feedback (see commit description for details)

* fill blank space when no theme is selected
* animate row's height in themes/components list when selecting, and hide children list
* show warning when you move to a different page and have unsaved changes
* refactor `adminCustomizeThemes.show` controller
* allow collapsing/expanding children lists
* fix a bug when adding components to a theme (changed the way it works slightly)
* a bunch of other minor things
This commit is contained in:
OsamaSayegh 2018-09-06 21:56:00 +03:00 committed by Sam
parent a4f057a589
commit ca28548762
15 changed files with 372 additions and 208 deletions

View File

@ -1,32 +1,136 @@
import { default as computed } from "ember-addons/ember-computed-decorators";
import {
default as computed,
observes
} from "ember-addons/ember-computed-decorators";
const MAX_COMPONENTS = 4;
export default Ember.Component.extend({
childrenExpanded: false,
classNames: ["themes-list-item"],
classNameBindings: ["theme.active:active"],
classNameBindings: ["theme.selected:selected"],
hasComponents: Em.computed.gt("children.length", 0),
hasMore: Em.computed.gt("moreCount", 0),
displayComponents: Em.computed.and("hasComponents", "theme.isActive"),
displayHasMore: Em.computed.gt("theme.childThemes.length", MAX_COMPONENTS),
click(e) {
if (!$(e.target).hasClass("others-count")) {
this.navigateToTheme();
}
},
init() {
this._super(...arguments);
this.scheduleAnimation();
},
@observes("theme.selected")
triggerAnimation() {
this.animate();
},
scheduleAnimation() {
Ember.run.schedule("afterRender", () => {
this.animate(true);
});
},
animate(isInitial) {
const $container = this.$();
const $list = this.$(".components-list");
if ($list.length === 0 || Ember.testing) {
return;
}
const duration = 300;
if (this.get("theme.selected")) {
this.collapseComponentsList($container, $list, duration);
} else if (!isInitial) {
this.expandComponentsList($container, $list, duration);
}
},
@computed(
"theme.component",
"theme.childThemes.@each.name",
"theme.childThemes.length"
"theme.childThemes.length",
"childrenExpanded"
)
children() {
const theme = this.get("theme");
const children = theme.get("childThemes");
let children = theme.get("childThemes");
if (theme.get("component") || !children) {
return [];
}
return children.slice(0, MAX_COMPONENTS).map(t => t.get("name"));
children = this.get("childrenExpanded")
? children
: children.slice(0, MAX_COMPONENTS);
return children.map(t => t.get("name"));
},
@computed("theme.childThemes.length", "theme.component", "children.length")
moreCount(childrenCount, component) {
if (component || !childrenCount) {
@computed(
"theme.childThemes.length",
"theme.component",
"childrenExpanded",
"children.length"
)
moreCount(childrenCount, component, expanded) {
if (component || !childrenCount || expanded) {
return 0;
}
return childrenCount - MAX_COMPONENTS;
},
expandComponentsList($container, $list, duration) {
$container.css("height", `${$container.height()}px`);
$list.css("display", "");
$container.animate(
{
height: `${$container.height() + $list.outerHeight(true)}px`
},
{
duration,
done: () => {
$list.css("display", "");
$container.css("height", "");
}
}
);
$list.animate(
{
opacity: 1
},
{
duration
}
);
},
collapseComponentsList($container, $list, duration) {
$container.animate(
{
height: `${$container.height() - $list.outerHeight(true)}px`
},
{
duration,
done: () => {
$list.css("display", "none");
$container.css("height", "");
}
}
);
$list.animate(
{
opacity: 0
},
{
duration
}
);
},
actions: {
toggleChildrenExpanded() {
this.toggleProperty("childrenExpanded");
}
}
});

View File

@ -1,7 +1,7 @@
import { THEMES, COMPONENTS } from "admin/models/theme";
import { default as computed } from "ember-addons/ember-computed-decorators";
const NUM_ENTRIES = 8;
const MAX_LIST_HEIGHT = 700;
export default Ember.Component.extend({
THEMES: THEMES,
@ -63,15 +63,24 @@ export default Ember.Component.extend({
},
didRender() {
let height = -1;
this.$(".themes-list-item")
.slice(0, NUM_ENTRIES)
.each(function() {
height += $(this).outerHeight();
});
if (height >= 485 && height <= 800) {
this.$(".themes-list-container").css("max-height", `${height}px`);
this._super(...arguments);
// hide scrollbar
const $container = this.$(".themes-list-container");
const containerNode = $container[0];
if (containerNode) {
const width = containerNode.offsetWidth - containerNode.clientWidth;
$container.css("width", `calc(100% + ${width}px)`);
}
let height = -1;
Array.from(this.$(".themes-list-item")).forEach(node => {
const nodeHeight = $(node).outerHeight();
if (height + nodeHeight <= MAX_LIST_HEIGHT) {
height += nodeHeight;
}
});
$container.css("max-height", `${height}px`);
},
actions: {
@ -79,6 +88,11 @@ export default Ember.Component.extend({
if (newTab !== this.get("currentTab")) {
this.set("currentTab", newTab);
}
},
navigateToTheme(theme) {
Em.getOwner(this)
.lookup("router:main")
.transitionTo("adminCustomizeThemes.show", theme);
}
}
});

View File

@ -5,8 +5,10 @@ import {
} from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({
maximized: false,
section: null,
currentTarget: 0,
maximized: false,
previewUrl: url("model.id", "/admin/themes/%@/preview"),
editRouteName: "adminCustomizeThemes.edit",
@ -86,8 +88,6 @@ export default Ember.Controller.extend({
return this.get("model").hasEdited(target);
},
currentTarget: 0,
setTargetName: function(name) {
const target = this.get("targets").find(t => t.name === name);
this.set("currentTarget", target && target.id);
@ -152,21 +152,20 @@ export default Ember.Controller.extend({
});
},
previewUrl: url("model.id", "/admin/themes/%@/preview"),
@computed("maximized")
maximizeIcon(maximized) {
return maximized ? "compress" : "expand";
},
maximizeIcon: function() {
return this.get("maximized") ? "compress" : "expand";
}.property("maximized"),
@computed("model.isSaving")
saveButtonText(isSaving) {
return isSaving ? I18n.t("saving") : I18n.t("admin.customize.save");
},
saveButtonText: function() {
return this.get("model.isSaving")
? I18n.t("saving")
: I18n.t("admin.customize.save");
}.property("model.isSaving"),
saveDisabled: function() {
return !this.get("model.changed") || this.get("model.isSaving");
}.property("model.changed", "model.isSaving"),
@computed("model.changed", "model.isSaving")
saveDisabled(changed, isSaving) {
return !changed || isSaving;
},
actions: {
save() {

View File

@ -9,106 +9,65 @@ import ThemeSettings from "admin/models/theme-settings";
import { THEMES, COMPONENTS } from "admin/models/theme";
const THEME_UPLOAD_VAR = 2;
const SETTINGS_TYPE_ID = 5;
export default Ember.Controller.extend({
editRouteName: "adminCustomizeThemes.edit",
@observes("allowChildThemes")
setSelectedThemeId() {
const available = this.get("selectableChildThemes");
if (
!this.get("selectedChildThemeId") &&
available &&
available.length > 0
) {
this.set("selectedChildThemeId", available[0].get("id"));
}
},
downloadUrl: url("model.id", "/admin/themes/%@"),
previewUrl: url("model.id", "/admin/themes/%@/preview"),
addButtonDisabled: Em.computed.empty("selectedChildThemeId"),
@computed("model", "allThemes", "model.component")
parentThemes(model, allThemes) {
if (!model.get("component")) {
return null;
}
let parents = allThemes.filter(theme =>
const parents = allThemes.filter(theme =>
_.contains(theme.get("childThemes"), model)
);
return parents.length === 0 ? null : parents;
},
@computed("model.theme_fields.@each")
hasEditedFields(fields) {
return fields.any(
f => !Em.isBlank(f.value) && f.type_id !== SETTINGS_TYPE_ID
);
},
@computed("model.theme_fields.@each")
editedDescriptions(fields) {
let descriptions = [];
let description = target => {
let current = fields.filter(
field => field.target === target && !Em.isBlank(field.value)
);
if (current.length > 0) {
let text = I18n.t("admin.customize.theme." + target);
let localized = current.map(f =>
I18n.t("admin.customize.theme." + f.name + ".text")
);
return text + ": " + localized.join(" , ");
}
};
@computed("model.editedFields")
editedFieldsFormatted(fields) {
const descriptions = [];
["common", "desktop", "mobile"].forEach(target => {
descriptions.push(description(target));
const fields = this.editedFieldsForTarget(target);
if (fields.length < 1) {
return;
}
let resultString = I18n.t("admin.customize.theme." + target);
const formattedFields = fields
.map(f => I18n.t("admin.customize.theme." + f.name + ".text"))
.join(" , ");
resultString += `: ${formattedFields}`;
descriptions.push(resultString);
});
return descriptions.reject(d => Em.isBlank(d));
return descriptions;
},
previewUrl: url("model.id", "/admin/themes/%@/preview"),
@computed("colorSchemeId", "model.color_scheme_id")
colorSchemeChanged(colorSchemeId, existingId) {
colorSchemeId = colorSchemeId === null ? null : parseInt(colorSchemeId);
return colorSchemeId !== existingId;
},
@computed(
"availableChildThemes",
"model.childThemes.@each",
"model",
"allowChildThemes"
)
selectableChildThemes(available, childThemes, allowChildThemes) {
if (!allowChildThemes && (!childThemes || childThemes.length === 0)) {
return null;
@computed("availableChildThemes", "model.childThemes.@each", "model")
selectableChildThemes(available, childThemes) {
if (available) {
const themes = !childThemes
? available
: available.filter(theme => childThemes.indexOf(theme) === -1);
return themes.length === 0 ? null : themes;
}
let themes = [];
available.forEach(t => {
if (!childThemes || childThemes.indexOf(t) === -1) {
themes.push(t);
}
});
return themes.length === 0 ? null : themes;
},
@computed("allThemes", "allThemes.length", "model.component", "model")
availableChildThemes(allThemes, count, component) {
if (count === 1 || component) {
return null;
@computed("allThemes", "model.component", "model")
availableChildThemes(allThemes) {
if (!this.get("model.component")) {
const themeId = this.get("model.id");
return allThemes.filter(
theme => theme.get("id") !== themeId && theme.get("component")
);
}
const themeId = this.get("model.id");
let themes = [];
allThemes.forEach(theme => {
if (themeId !== theme.get("id") && theme.get("component")) {
themes.push(theme);
}
});
return themes;
},
@computed("model.component")
@ -137,8 +96,11 @@ export default Ember.Controller.extend({
hasSettings(settings) {
return settings.length > 0;
},
downloadUrl: url("model.id", "/admin/themes/%@"),
editedFieldsForTarget(target) {
return this.get("model.editedFields").filter(
field => field.target === target
);
},
commitSwitchType() {
const model = this.get("model");
@ -146,7 +108,6 @@ export default Ember.Controller.extend({
model.set("component", newValue);
if (newValue) {
// component
this.set("parentController.currentTab", COMPONENTS);
} else {
this.set("parentController.currentTab", THEMES);
@ -166,8 +127,8 @@ export default Ember.Controller.extend({
});
this.get("parentController.model.content").forEach(theme => {
const children = Array.from(theme.get("childThemes"));
const rawChildren = Array.from(theme.get("child_themes") || []);
const children = _.toArray(theme.get("childThemes"));
const rawChildren = _.toArray(theme.get("child_themes") || []);
const index = children ? children.indexOf(model) : -1;
if (index > -1) {
children.splice(index, 1);
@ -181,7 +142,14 @@ export default Ember.Controller.extend({
})
.catch(popupAjaxError);
},
transitionToEditRoute() {
this.transitionToRoute(
"adminCustomizeThemes.edit",
this.get("model.id"),
"common",
"scss"
);
},
actions: {
updateToLatest() {
this.set("updatingRemote", true);
@ -238,25 +206,17 @@ export default Ember.Controller.extend({
},
editTheme() {
let edit = () =>
this.transitionToRoute(
this.get("editRouteName"),
this.get("model.id"),
"common",
"scss"
);
if (this.get("model.remote_theme")) {
bootbox.confirm(
I18n.t("admin.customize.theme.edit_confirm"),
result => {
if (result) {
edit();
this.transitionToEditRoute();
}
}
);
} else {
edit();
this.transitionToEditRoute();
}
},

View File

@ -6,9 +6,13 @@ const THEME_UPLOAD_VAR = 2;
export const THEMES = "themes";
export const COMPONENTS = "components";
const SETTINGS_TYPE_ID = 5;
const Theme = RestModel.extend({
FIELDS_IDS: [0, 1],
isActive: Em.computed.or("default", "user_selectable"),
isPendingUpdates: Em.computed.gt("remote_theme.commits_behind", 0),
hasEditedFields: Em.computed.gt("editedFields.length", 0),
@computed("theme_fields")
themeFields(fields) {
@ -43,9 +47,11 @@ const Theme = RestModel.extend({
);
},
@computed("remote_theme", "remote_theme.commits_behind")
isPendingUpdates(remote, commitsBehind) {
return remote && commitsBehind && commitsBehind > 0;
@computed("theme_fields.@each")
editedFields(fields) {
return fields.filter(
field => !Em.isBlank(field.value) && field.type_id !== SETTINGS_TYPE_ID
);
},
getKey(field) {

View File

@ -35,5 +35,29 @@ export default Ember.Route.extend({
controller.setTargetName(wrapper.target || "common");
controller.set("fieldName", wrapper.field_name || "scss");
this.controllerFor("adminCustomizeThemes").set("editingTheme", true);
this.set("shouldAlertUnsavedChanges", true);
},
actions: {
willTransition(transition) {
if (
this.get("controller.model.changed") &&
this.get("shouldAlertUnsavedChanges") &&
transition.intent.name !== this.routeName
) {
transition.abort();
bootbox.confirm(
I18n.t("admin.customize.theme.unsaved_changes_alert"),
I18n.t("admin.customize.theme.discard"),
I18n.t("admin.customize.theme.stay"),
result => {
if (!result) {
this.set("shouldAlertUnsavedChanges", false);
transition.retry();
}
}
);
}
}
}
});

View File

@ -1,5 +1,25 @@
const externalResources = [
{
key: "admin.customize.theme.beginners_guide_title",
link: "https://meta.discourse.org/t/91966",
icon: "book"
},
{
key: "admin.customize.theme.developers_guide_title",
link: "https://meta.discourse.org/t/93648",
icon: "book"
},
{
key: "admin.customize.theme.browse_themes",
link: "https://meta.discourse.org/c/theme",
icon: "paint-brush"
}
];
export default Ember.Route.extend({
setupController() {
setupController(controller, model) {
this._super(...arguments);
this.controllerFor("adminCustomizeThemes").set("editingTheme", false);
controller.set("externalResources", externalResources);
}
});

View File

@ -37,9 +37,11 @@ export default Ember.Route.extend({
},
handleHighlight(theme) {
this.get("controller.allThemes").forEach(t => t.set("active", false));
this.get("controller.allThemes")
.filter(t => t.get("selected"))
.forEach(t => t.set("selected", false));
if (theme) {
theme.set("active", true);
theme.set("selected", true);
}
},

View File

@ -1,4 +1,4 @@
{{#link-to 'adminCustomizeThemes.show' theme replace=true}}
<div class="inner-wrapper">
{{plugin-outlet name="admin-customize-themes-list-item" connectorTagName='span' args=(hash theme=theme)}}
<div class="info">
@ -7,28 +7,38 @@
</span>
<span class="icons">
{{#if theme.default}}
{{d-icon "check" class="default-indicator" title="admin.customize.theme.default_theme_tooltip"}}
{{/if}}
{{#if theme.isPendingUpdates}}
{{d-icon "refresh" title="admin.customize.theme.updates_available_tooltip" class="light-grey-icon"}}
{{/if}}
{{#if theme.isBroken}}
{{d-icon "exclamation-circle" class="broken-indicator" title="admin.customize.theme.broken_theme_tooltip"}}
{{/if}}
{{#unless theme.selected}}
{{#if theme.default}}
{{d-icon "check" class="default-indicator" title="admin.customize.theme.default_theme_tooltip"}}
{{/if}}
{{#if theme.isPendingUpdates}}
{{d-icon "refresh" title="admin.customize.theme.updates_available_tooltip" class="light-grey-icon"}}
{{/if}}
{{#if theme.isBroken}}
{{d-icon "exclamation-circle" class="broken-indicator" title="admin.customize.theme.broken_theme_tooltip"}}
{{/if}}
{{else}}
{{d-icon "caret-right"}}
{{/unless}}
</span>
</div>
{{#if hasComponents}}
{{#if displayComponents}}
<div class="components-list">
{{#each children as |child|}}
<span class="component">
{{child}}
</span>
{{/each}}
{{#if hasMore}}
<span class="others-count">{{I18n "admin.customize.theme.and_x_more" count=moreCount}}</span>
{{#if displayHasMore}}
<span {{action "toggleChildrenExpanded"}} class="others-count">
{{#if childrenExpanded}}
{{I18n "admin.customize.theme.collapse"}}
{{else}}
{{I18n "admin.customize.theme.and_x_more" count=moreCount}}
{{/if}}
</span>
{{/if}}
</div>
{{/if}}
{{/link-to}}
</div>

View File

@ -7,16 +7,16 @@
</div>
</div>
<div class="themes-list-container" style="max-height: 485px;">
<div class="themes-list-container" style="max-height: 450px;">
{{#if hasThemes}}
{{#if componentsTabActive}}
{{#each themesList as |theme|}}
{{themes-list-item theme=theme}}
{{themes-list-item theme=theme navigateToTheme=(action "navigateToTheme" theme)}}
{{/each}}
{{else}}
{{#if hasUserThemes}}
{{#each userThemes as |theme|}}
{{themes-list-item theme=theme}}
{{themes-list-item theme=theme navigateToTheme=(action "navigateToTheme" theme)}}
{{/each}}
{{#if hasInactiveThemes}}
@ -28,7 +28,7 @@
{{#if hasInactiveThemes}}
{{#each inactiveThemes as |theme|}}
{{themes-list-item theme=theme}}
{{themes-list-item theme=theme navigateToTheme=(action "navigateToTheme" theme)}}
{{/each}}
{{/if}}
{{/if}}

View File

@ -0,0 +1,11 @@
<div class="themes-intro">
<h1>{{I18n "admin.customize.theme.themes_intro"}}</h1>
<div class="external-resources">
{{#each externalResources as |resource|}}
<a href={{resource.link}} class="external-link" target="_blank">
{{d-icon resource.icon}}
{{I18n resource.key}}
</a>
{{/each}}
</div>
</div>

View File

@ -52,11 +52,11 @@
<div class="control-unit">
<div class="mini-title">{{i18n "admin.customize.theme.css_html"}}</div>
{{#if hasEditedFields}}
{{#if model.hasEditedFields}}
<div class="description">{{i18n "admin.customize.theme.custom_sections"}}</div>
<ul>
{{#each editedDescriptions as |desc|}}
<li>{{desc}}</li>
{{#each editedFieldsFormatted as |field|}}
<li>{{field}}</li>
{{/each}}
</ul>
{{else}}
@ -127,24 +127,17 @@
{{#if availableChildThemes}}
<div class="control-unit">
<div class="mini-title">{{i18n "admin.customize.theme.theme_components"}}</div>
{{#unless model.childThemes.length}}
<div class="description">
<label class='checkbox-label'>
{{input type="checkbox" checked=allowChildThemes}}
{{i18n "admin.customize.theme.child_themes_check"}}
</label>
</div>
{{else}}
<ul class='removable-list'>
{{#each model.childThemes as |child|}}
<li>{{#link-to 'adminCustomizeThemes.show' child replace=true class='col'}}{{child.name}}{{/link-to}} {{d-button action="removeChildTheme" actionParam=child class="btn-small cancel-edit col" icon="times"}}</li>
{{/each}}
</ul>
{{/unless}}
{{#if model.childThemes.length}}
<ul class='removable-list'>
{{#each model.childThemes as |child|}}
<li>{{#link-to 'adminCustomizeThemes.show' child replace=true class='col'}}{{child.name}}{{/link-to}} {{d-button action="removeChildTheme" actionParam=child class="btn-small cancel-edit col" icon="times"}}</li>
{{/each}}
</ul>
{{/if}}
{{#if selectableChildThemes}}
<div class="description">
{{combo-box forceEscape=true filterable=true content=selectableChildThemes value=selectedChildThemeId}}
{{#d-button action="addChildTheme" icon="plus"}}{{i18n "admin.customize.theme.add"}}{{/d-button}}
{{combo-box forceEscape=true filterable=true content=selectableChildThemes value=selectedChildThemeId none="admin.customize.theme.select_component"}}
{{#d-button action="addChildTheme" icon="plus" disabled=addButtonDisabled class="add-component-button"}}{{i18n "admin.customize.theme.add"}}{{/d-button}}
</div>
{{/if}}
</div>

View File

@ -59,6 +59,18 @@
}
.admin-customize.admin-customize-themes {
.themes-intro {
float: right;
width: 34%;
margin-right: 20%;
margin-top: 60px;
.external-link {
display: block;
margin-bottom: 5px;
}
}
.customize-themes-header {
border-bottom: 1px solid $primary-low;
padding-bottom: 8px;
@ -158,12 +170,15 @@
float: left;
width: 70%;
}
.add-component-button {
vertical-align: middle;
}
.themes-list {
border-right: 1px solid $primary-low;
border-bottom: 1px solid $primary-low;
float: left;
width: 28%;
overflow: hidden;
}
.themes-list-header {
@ -180,8 +195,7 @@
&.active {
font-weight: bold;
color: $secondary;
background-color: $tertiary;
color: $tertiary;
}
&:not(.active) {
@ -195,18 +209,10 @@
}
.themes-list-container {
max-height: 485px;
overflow-y: auto;
overflow-y: scroll;
box-sizing: content-box;
width: 100%; /* overridden in javascript to hide scrollbar */
&::-webkit-scrollbar-track {
background-color: $secondary;
}
&::-webkit-scrollbar {
width: 5px;
}
&::-webkit-scrollbar-thumb {
background-color: $primary-low;
}
.themes-list-item:last-child {
border-bottom: none;
}
@ -216,22 +222,47 @@
display: flex;
border-left: 1px solid $primary-low;
&:not(.inactive-indicator):not(.active):hover {
&.inactive-indicator {
border-right: 0;
border-left: 0;
font-weight: bold;
color: $primary-medium;
span.empty {
padding-left: 5px;
padding-top: 15px;
}
}
&:not(.inactive-indicator):not(.selected):hover {
background-color: $tertiary-low;
.component {
border-color: $primary-low-mid;
}
}
&.active {
&.selected {
color: $secondary;
background-color: $tertiary;
.fa {
color: inherit;
}
}
&:not(.selected) {
.broken-indicator {
color: $danger;
}
.fa {
opacity: 0.7;
}
.default-indicator {
color: $success;
}
}
.light-grey-icon {
color: $primary-medium;
}
.info {
overflow: hidden;
font-weight: bold;
@ -253,6 +284,9 @@
font-size: $font-down-1;
align-items: baseline;
.others-count:hover {
text-decoration: underline;
}
.component {
display: flex;
padding: 3px 5px 3px 5px;
@ -262,37 +296,17 @@
margin-bottom: 5px;
}
}
&:not(.active) {
.broken-indicator {
color: $danger;
}
.default-indicator {
color: $success;
}
}
a {
.inner-wrapper {
padding: 10px;
}
&.inactive-indicator {
border-right: 0;
border-left: 0;
font-weight: bold;
color: $primary-medium;
span.empty {
padding-left: 5px;
padding-top: 15px;
}
cursor: pointer;
}
span.empty {
padding: 3px 10px 3px 10px;
}
a,
.inner-wrapper,
span.empty {
color: inherit;
width: 100%;

View File

@ -3191,7 +3191,6 @@ en:
import: "Import"
delete: "Delete"
delete_confirm: "Delete this theme?"
about: "Modify CSS stylesheets and HTML headers on the site. Add a customization to start."
color: "Color"
opacity: "Opacity"
copy: "Copy"
@ -3214,6 +3213,10 @@ en:
components: "Components"
theme_name: "Theme name"
component_name: "Component name"
themes_intro: "Select an existing theme or create a new one to get started"
beginners_guide_title: "Beginners guide to using Discourse Themes"
developers_guide_title: "Developers guide to Discourse Themes"
browse_themes: "Browse community themes"
import_theme: "Import Theme"
customize_desc: "Customize:"
title: "Themes"
@ -3245,6 +3248,7 @@ en:
default_theme_tooltip: "This theme is the site's default theme"
updates_available_tooltip: "Updates are available for this theme"
and_x_more: "and {{count}} more."
collapse: Collapse
uploads: "Uploads"
no_uploads: "You can upload assets associated with your theme such as fonts and images"
add_upload: "Add Upload"
@ -3256,7 +3260,10 @@ en:
no_overwrite: "Invalid variable name. Must not overwrite an existing variable."
must_be_unique: "Invalid variable name. Must be unique."
upload: "Upload"
child_themes_check: "Theme includes other child themes"
select_component: "Select a component..."
unsaved_changes_alert: "You haven't saved your changes yet, do you want to discard them and move on?"
discard: "Discard"
stay: "Stay"
css_html: "Custom CSS/HTML"
edit_css_html: "Edit CSS/HTML"
edit_css_html_help: "You have not edited any CSS or HTML"

View File

@ -62,7 +62,7 @@ componentTest("with children", {
beforeEach() {
this.set(
"theme",
Theme.create({ name: "Test", childThemes: childrenList })
Theme.create({ name: "Test", childThemes: childrenList, default: true })
);
},