Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Commit

Permalink
🎨 move theme activation to /themes endpoint
Browse files Browse the repository at this point in the history
requires TryGhost/Ghost#8093
- adds `theme.activate()` method and associated adapter method for activating themes rather than relying on `settings.activeTheme`
- minor refactors to the `modals/upload-theme` component to use a full theme model
  • Loading branch information
kevinansfield committed Mar 3, 2017
1 parent b12bcbf commit 914c63b
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 73 deletions.
13 changes: 13 additions & 0 deletions app/adapters/theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import ApplicationAdapter from './application';

export default ApplicationAdapter.extend({

activate(model) {
let url = `${this.buildURL('theme', model.get('id'))}activate/`;

return this.ajax(url, 'PUT', {data: {}}).then((data) => {
return this.store.pushPayload(data);
});
}

});
7 changes: 3 additions & 4 deletions app/components/gh-theme-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@ import get from 'ember-metal/get';
export default Component.extend({

themes: null,
activeTheme: null,

sortedThemes: computed('themes.[]', 'activeTheme', function () {
let activeTheme = get(this, 'activeTheme');
sortedThemes: computed('themes.@each.active', function () {
let themes = get(this, 'themes').map((t) => {
let theme = {};
let themePackage = get(t, 'package');

theme.model = t;
theme.name = get(t, 'name');
theme.label = themePackage ? `${themePackage.name}` : theme.name;
theme.version = themePackage ? `${themePackage.version}` : '1.0';
theme.package = themePackage;
theme.active = theme.name === activeTheme;
theme.active = get(t, 'active');
theme.isDeletable = !theme.active;

return theme;
Expand Down
19 changes: 11 additions & 8 deletions app/components/modals/upload-theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default ModalComponent.extend({
displayOverwriteWarning: false,

eventBus: injectService(),
store: injectService(),

hideUploader: or('theme', 'displayOverwriteWarning'),

Expand All @@ -29,9 +30,10 @@ export default ModalComponent.extend({
}),

themeName: computed('theme.{name,package.name}', function () {
let t = this.get('theme');
let themePackage = this.get('theme.package');
let name = this.get('theme.name');

return t.package ? `${t.package.name} - ${t.package.version}` : t.name;
return themePackage ? `${themePackage.name} - ${themePackage.version}` : name;
}),

currentThemeNames: mapBy('model.themes', 'name'),
Expand All @@ -43,13 +45,12 @@ export default ModalComponent.extend({

canActivateTheme: computed('theme', function () {
let theme = this.get('theme');
// TODO: do we still get theme.active back or do we need to check settings.activeTheme?
return theme && !theme.active;
return theme && !theme.get('active');
}),

actions: {
validateTheme(file) {
let themeName = file.name.replace(/\.zip$/, '').replace(/[^\w@.]/gi, '-');
let themeName = file.name.replace(/\.zip$/, '').replace(/[^\w@.]/gi, '-').toLowerCase();

let currentThemeNames = this.get('currentThemeNames');

Expand Down Expand Up @@ -94,16 +95,18 @@ export default ModalComponent.extend({
},

uploadSuccess(response) {
let [theme] = response.themes;
this.get('store').pushPayload(response);

let theme = this.get('store').peekRecord('theme', response.themes[0].name);

this.set('theme', theme);

if (get(theme, 'warnings.length') > 0) {
this.set('validationWarnings', theme.warnings);
this.set('validationWarnings', get(theme, 'warnings'));
}

// invoke the passed in confirm action
invokeAction(this, 'model.uploadSuccess', this.get('theme'));
invokeAction(this, 'model.uploadSuccess', theme);
},

uploadFailed(error) {
Expand Down
5 changes: 2 additions & 3 deletions app/controllers/settings/design.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,8 @@ export default Controller.extend(SettingsSaveMixin, {
navItem.set('url', url);
},

setTheme(theme) {
this.set('model.activeTheme', theme.name);
this.send('save');
activateTheme(theme) {
return theme.activate();
},

downloadTheme(theme) {
Expand Down
1 change: 0 additions & 1 deletion app/models/setting.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export default Model.extend(ValidationEngine, {
postsPerPage: attr('number'),
forceI18n: attr('boolean'),
permalinks: attr('string'),
activeTheme: attr('string'),
activeTimezone: attr('string', {defaultValue: 'Etc/UTC'}),
ghost_head: attr('string'),
ghost_foot: attr('string'),
Expand Down
9 changes: 8 additions & 1 deletion app/models/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,12 @@ import attr from 'ember-data/attr';

export default Model.extend({
name: attr('string'),
package: attr('raw')
package: attr('raw'),
active: attr('boolean'),
warnings: attr('raw'),

activate() {
let adapter = this.store.adapterFor(this.constructor.modelName);
return adapter.activate(this);
}
});
6 changes: 1 addition & 5 deletions app/routes/settings/design.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,8 @@ export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
return this._super(...arguments);
},

reloadThemes() {
return this.get('store').findAll('theme');
},

activateTheme(theme) {
return this.get('controller').send('setTheme', theme);
return this.get('controller').send('activateTheme', theme);
}
}
});
2 changes: 1 addition & 1 deletion app/templates/components/gh-theme-table.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
{{#if theme.active}}
<span class="gh-badge gh-badge-black apps-configured-action" data-test-theme-badge>Active</span>
{{else}}
<a href="#" {{action activateTheme theme}} class="apps-configured-action apps-configured-action-activate green-hover" data-test-theme-activate-button>
<a href="#" {{action activateTheme theme.model}} class="apps-configured-action apps-configured-action-activate green-hover" data-test-theme-activate-button>
Activate
</a>
{{/if}}
Expand Down
3 changes: 1 addition & 2 deletions app/templates/settings/design.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
<div class="gh-themes-container">
{{gh-theme-table
themes=themes
activeTheme=model.activeTheme
activateTheme=(action "setTheme")
activateTheme=(action "activateTheme")
downloadTheme=(action "downloadTheme")
deleteTheme=(action "deleteTheme")}}

Expand Down
1 change: 0 additions & 1 deletion app/templates/settings/design/uploadtheme.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{{gh-fullscreen-modal "upload-theme"
model=(hash
themes=model
uploadSuccess=(route-action 'reloadThemes')
activate=(route-action 'activateTheme')
)
close=(route-action "cancel")
Expand Down
7 changes: 7 additions & 0 deletions mirage/config/themes.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ export default function mockThemes(server) {

return new Response(204, {}, null);
});

server.put('/themes/:theme/activate/', function ({themes}, {params}) {
themes.all().update('active', false);
themes.findBy({name: params.theme}).update({active: true});

return themes.all();
});
}
10 changes: 0 additions & 10 deletions mirage/fixtures/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,6 @@ export default [
updated_at: '2015-10-27T17:39:58.280Z',
updated_by: 1
},
{
id: 8,
key: 'activeTheme',
value: 'casper',
type: 'theme',
created_at: '2013-11-25T14:48:11.000Z',
created_by: 1,
updated_at: '2015-10-27T17:39:58.284Z',
updated_by: 1
},
{
id: 9,
key: 'permalinks',
Expand Down
3 changes: 2 additions & 1 deletion mirage/fixtures/themes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export default [
package: {
name: 'Blog',
version: '1.0'
}
},
active: true
},
{
name: 'foo',
Expand Down
70 changes: 36 additions & 34 deletions tests/acceptance/settings/design-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -400,39 +400,40 @@ describe('Acceptance: Settings - Design', function () {

// theme upload handles validation warnings
andThen(() => {
server.post('/themes/upload/', function () {
return new Mirage.Response(200, {}, {
themes: [
server.post('/themes/upload/', function ({themes}) {
let theme = {
name: 'blackpalm',
package: {
name: 'BlackPalm',
version: '1.0.0'
}
};

themes.create(theme);

theme.warnings = [{
level: 'warning',
rule: 'Assets such as CSS & JS must use the <code>{{asset}}</code> helper',
details: '<p>The listed files should be included using the <code>{{asset}}</code> helper. For more information, please see the <a href="http://themes.ghost.org/docs/asset">asset helper documentation</a>.</p>',
failures: [
{
name: 'blackpalm',
package: {
name: 'BlackPalm',
version: '1.0.0'
},
warnings: [
{
level: 'warning',
rule: 'Assets such as CSS & JS must use the <code>{{asset}}</code> helper',
details: '<p>The listed files should be included using the <code>{{asset}}</code> helper. For more information, please see the <a href="http://themes.ghost.org/docs/asset">asset helper documentation</a>.</p>',
failures: [
{
ref: '/assets/dist/img/apple-touch-icon.png'
},
{
ref: '/assets/dist/img/favicon.ico'
},
{
ref: '/assets/dist/css/blackpalm.min.css'
},
{
ref: '/assets/dist/js/blackpalm.min.js'
}
],
code: 'GS030-ASSET-REQ'
}
]
ref: '/assets/dist/img/apple-touch-icon.png'
},
{
ref: '/assets/dist/img/favicon.ico'
},
{
ref: '/assets/dist/css/blackpalm.min.css'
},
{
ref: '/assets/dist/js/blackpalm.min.js'
}
]
],
code: 'GS030-ASSET-REQ'
}];

return new Mirage.Response(200, {}, {
themes: [theme]
});
});
});
Expand Down Expand Up @@ -461,6 +462,7 @@ describe('Acceptance: Settings - Design', function () {
// theme upload handles success then close
click(testSelector('upload-theme-button'));
fileUpload('.fullscreen-modal input[type="file"]', ['test'], {name: 'theme-1.zip', type: 'application/zip'});

andThen(() => {
expect(
find('.fullscreen-modal h1').text().trim(),
Expand All @@ -475,7 +477,7 @@ describe('Acceptance: Settings - Design', function () {
expect(
find(testSelector('theme-id')).length,
'number of themes in list grows after upload'
).to.equal(4);
).to.equal(5);

expect(
find(`${testSelector('theme-active', 'true')} ${testSelector('theme-title')}`).text().trim(),
Expand All @@ -492,7 +494,7 @@ describe('Acceptance: Settings - Design', function () {
expect(
find(testSelector('theme-id')).length,
'number of themes in list grows after upload and activate'
).to.equal(5);
).to.equal(6);

expect(
find(`${testSelector('theme-active', 'true')} ${testSelector('theme-title')}`).text().trim(),
Expand Down Expand Up @@ -546,7 +548,7 @@ describe('Acceptance: Settings - Design', function () {
expect(
find(testSelector('theme-id')).length,
'number of themes in list shrinks after delete'
).to.equal(4);
).to.equal(5);

expect(
find(testSelector('theme-title')).text(),
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/components/gh-theme-table-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Integration: Component: gh-theme-table', function() {

it('renders', function() {
this.set('themes', [
{name: 'Daring', package: {name: 'Daring', version: '0.1.4'}},
{name: 'Daring', package: {name: 'Daring', version: '0.1.4'}, active: true},
{name: 'casper', package: {name: 'Casper', version: '1.3.1'}},
{name: 'oscar-ghost-1.1.0', package: {name: 'Lanyon', version: '1.1.0'}},
{name: 'foo'}
Expand All @@ -24,7 +24,6 @@ describe('Integration: Component: gh-theme-table', function() {

this.render(hbs`{{gh-theme-table
themes=themes
activeTheme="Daring"
activateTheme=(action actionHandler)
downloadTheme=(action actionHandler)
deleteTheme=(action actionHandler)
Expand Down

0 comments on commit 914c63b

Please sign in to comment.