Cleaned up and re-organised tag and new tag routes/controllers

no issue

- removed unused `<GhTagsManagementContainer>` component and related `isMobile` CPs
- un-nested `tag` and `tag.new` routes
  - nested routes in Ember are used for nested UI but these are both separate screens
  - removes usage of `selectedTag` property in favour of using Ember's built-in model handling
  - removed unnecessary `tags/new` controller
  - sets up `tag.new` route which extends the `tag` route to avoid duplicate code
This commit is contained in:
Kevin Ansfield 2019-12-09 17:44:16 +00:00
parent ccaece5e8d
commit 5c0cfca479
15 changed files with 33 additions and 147 deletions

View File

@ -102,7 +102,7 @@ export default Component.extend({
if (selected.category === 'Tags') {
let id = selected.id.replace('tag.', '');
this.router.transitionTo('tags.tag', id);
this.router.transitionTo('tag', id);
}
},

View File

@ -12,7 +12,6 @@ const {Handlebars} = Ember;
export default Component.extend({
feature: service(),
config: service(),
mediaQueries: service(),
tag: null,
@ -28,8 +27,6 @@ export default Component.extend({
scratchMetaTitle: boundOneWay('tag.metaTitle'),
scratchMetaDescription: boundOneWay('tag.metaDescription'),
isMobile: reads('mediaQueries.maxWidth600'),
title: computed('tag.isNew', function () {
if (this.get('tag.isNew')) {
return 'New tag';

View File

@ -1,59 +0,0 @@
import Component from '@ember/component';
import {computed} from '@ember/object';
import {equal, reads} from '@ember/object/computed';
import {isBlank} from '@ember/utils';
import {inject as service} from '@ember/service';
export default Component.extend({
mediaQueries: service(),
classNames: ['view-container', 'tags-container'],
classNameBindings: ['isMobile'],
tags: null,
selectedTag: null,
isMobile: reads('mediaQueries.maxWidth600'),
isEmpty: equal('tags.length', 0),
displaySettingsPane: computed('isEmpty', 'selectedTag', 'isMobile', function () {
let isEmpty = this.isEmpty;
let selectedTag = this.selectedTag;
let isMobile = this.isMobile;
// always display settings pane for blank-slate on mobile
if (isMobile && isEmpty) {
return true;
}
// display list if no tag is selected on mobile
if (isMobile && isBlank(selectedTag)) {
return false;
}
// default to displaying settings pane
return true;
}),
init() {
this._super(...arguments);
this.mediaQueries.on('change', this, this._fireMobileChangeActions);
},
willDestroyElement() {
this._super(...arguments);
this.mediaQueries.off('change', this, this._fireMobileChangeActions);
},
_fireMobileChangeActions(key, value) {
if (key === 'maxWidth600') {
let leftMobileAction = this.leftMobile;
this.set('isMobile', value);
if (!value && leftMobileAction) {
leftMobileAction();
}
}
}
});

View File

@ -1,4 +1,4 @@
import Controller, {inject as controller} from '@ember/controller';
import Controller from '@ember/controller';
import windowProxy from 'ghost-admin/utils/window-proxy';
import {alias} from '@ember/object/computed';
import {inject as service} from '@ember/service';
@ -6,14 +6,12 @@ import {slugify} from '@tryghost/string';
import {task} from 'ember-concurrency';
export default Controller.extend({
tagsController: controller('tags'),
notifications: service(),
router: service(),
showDeleteTagModal: false,
tag: alias('model'),
isMobile: alias('tagsController.isMobile'),
actions: {
setProperty(propKey, value) {
@ -27,6 +25,7 @@ export default Controller.extend({
deleteTag() {
return this._deleteTag();
},
save() {
return this.save.perform();
},
@ -104,7 +103,7 @@ export default Controller.extend({
try {
let savedTag = yield tag.save();
// replace 'new' route with 'tag' route
this.replaceRoute('tags.tag', savedTag);
this.replaceRoute('tag', savedTag);
// update the URL if the slug changed
if (!isNewTag) {
@ -140,7 +139,7 @@ export default Controller.extend({
let currentRoute = this.router.currentRouteName || '';
if (currentRoute.match(/^tags/)) {
this.transitionToRoute('tags.index');
this.transitionToRoute('tags');
}
},

View File

@ -1,15 +1,13 @@
import Controller, {inject as controller} from '@ember/controller';
import Controller from '@ember/controller';
import {alias, sort} from '@ember/object/computed';
import {computed} from '@ember/object';
export default Controller.extend({
tagController: controller('tags.tag'),
queryParams: ['type'],
type: 'public',
tags: alias('model'),
selectedTag: alias('tagController.tag'),
filteredTags: computed('tags.@each.isNew', 'type', function () {
return this.tags.filter((tag) => {

View File

@ -35,10 +35,9 @@ Router.map(function () {
this.route('user', {path: ':user_slug'});
});
this.route('tags', function () {
this.route('tag', {path: ':tag_slug'});
this.route('new');
});
this.route('tags');
this.route('tag.new', {path: '/tags/new'});
this.route('tag', {path: '/tags/:tag_slug'});
this.route('settings.general', {path: '/settings/general'});
this.route('settings.labs', {path: '/settings/labs'});
@ -61,7 +60,6 @@ Router.map(function () {
this.route('members', function () {
this.route('import');
});
this.route('member.new', {path: '/members/new'});
this.route('member', {path: '/members/:member_id'});

View File

@ -20,25 +20,17 @@ export default AuthenticatedRoute.extend(CurrentUserSettings, {
},
model(params) {
return this.store.queryRecord('tag', {slug: params.tag_slug});
if (params.tag_slug) {
return this.store.queryRecord('tag', {slug: params.tag_slug});
} else {
return this.store.createRecord('tag');
}
},
serialize(model) {
return {tag_slug: model.get('slug')};
},
setupController() {
this._super(...arguments);
},
// reset the model so that mobile screens react to an empty selectedTag
deactivate() {
this._super(...arguments);
let {controller} = this;
controller.model.rollbackAttributes();
this.set('controller.model', null);
},
actions: {
save() {
this.controller.send('save');
@ -46,7 +38,7 @@ export default AuthenticatedRoute.extend(CurrentUserSettings, {
},
showUnsavedChangesModal(transition) {
if (transition.from && transition.from.name.match(/^tags\.tag/) && transition.targetName) {
if (transition.from && transition.from.name.match(/^tag$|^tag\.new$/) && transition.targetName) {
let {controller} = this;
if (!controller.tag.isDeleted && controller.tag.hasDirtyAttributes) {

View File

@ -0,0 +1,6 @@
import TagRoute from '../tag';
export default TagRoute.extend({
controllerName: 'tag',
templateName: 'tag'
});

View File

@ -42,7 +42,7 @@ export default AuthenticatedRoute.extend(CurrentUserSettings, ShortcutsRoute, {
actions: {
newTag() {
this.transitionTo('tags.new');
this.transitionTo('tag.new');
}
},

View File

@ -1,44 +0,0 @@
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
import {isEmpty} from '@ember/utils';
import {inject as service} from '@ember/service';
export default AuthenticatedRoute.extend({
router: service(),
controllerName: 'tags.tag',
templateName: 'tags/tag',
init() {
this._super(...arguments);
this.router.on('routeWillChange', (transition) => {
this.showUnsavedChangesModal(transition);
});
},
model() {
return this.store.createRecord('tag');
},
// reset the model so that mobile screens react to an empty selectedTag
deactivate() {
this._super(...arguments);
let {controller} = this;
controller.model.rollbackAttributes();
controller.set('model', null);
},
showUnsavedChangesModal(transition) {
if (transition.from && transition.from.name.match(/^tags\.new/) && transition.targetName) {
let {controller} = this;
let isUnchanged = isEmpty(Object.keys(controller.tag.changedAttributes()));
if (!controller.tag.isDeleted && !isUnchanged) {
transition.abort();
controller.send('toggleUnsavedChangesModal', transition);
return;
}
}
}
});

View File

@ -1,4 +1,4 @@
{{#link-to "tags.tag" tag class="gh-list-data gh-tag-list-title" title="Edit tag"}}
{{#link-to "tag" tag class="gh-list-data gh-tag-list-title" title="Edit tag"}}
<h3 class="gh-tag-list-name">
{{this.tag.name}}
</h3>
@ -9,7 +9,7 @@
{{/if}}
{{/link-to}}
{{#link-to "tags.tag" tag class="gh-list-data middarkgrey f8 gh-tag-list-slug gh-list-cellwidth-10" title="Edit tag"}}
{{#link-to "tag" tag class="gh-list-data middarkgrey f8 gh-tag-list-slug gh-list-cellwidth-10" title="Edit tag"}}
<span title="{{this.slug}}">{{this.slug}}</span>
{{/link-to}}
@ -18,12 +18,12 @@
<span class="nowrap">{{this.postsLabel}}</span>
{{/link-to}}
{{else}}
{{#link-to "tags.tag" tag class="gh-list-data gh-tag-list-posts-count gh-list-cellwidth-10" title="Edit tag"}}
{{#link-to "tag" tag class="gh-list-data gh-tag-list-posts-count gh-list-cellwidth-10" title="Edit tag"}}
<span class="nowrap f8 midlightgrey">{{this.postsLabel}}</span>
{{/link-to}}
{{/if}}
{{#link-to "tags.tag" tag class="gh-list-data gh-list-cellwidth-min gh-tag-list-chevron" title="Edit tag"}}
{{#link-to "tag" tag class="gh-list-data gh-list-cellwidth-min gh-tag-list-chevron" title="Edit tag"}}
<div class="flex items-center justify-end w-100 h-100">
<span class="nr2">{{svg-jar "arrow-right" class="w6 h6 fill-midgrey pa1"}}</span>
</div>

View File

@ -2,9 +2,9 @@
<form class="mb15">
<GhCanvasHeader class="gh-canvas-header">
<h2 class="gh-canvas-title" data-test-screen-title>
{{#link-to "tags.index" data-test-link="tags-back"}}Tags{{/link-to}}
{{#link-to "tags" data-test-link="tags-back"}}Tags{{/link-to}}
<span>{{svg-jar "arrow-right"}}</span>
{{if tag.name tag.name "New tag"}}
{{if tag.isNew "New tag" tag.name}}
</h2>
<section class="view-actions">
{{gh-task-button task=save type="button" class="gh-btn gh-btn-blue gh-btn-icon" data-test-button="save"}}

View File

@ -2,7 +2,7 @@
<header class="gh-canvas-header">
<h2 class="gh-canvas-title" data-test-screen-title>Tags</h2>
<section class="view-actions">
{{#link-to "tags.new" class="gh-btn gh-btn-green"}}<span>New tag</span>{{/link-to}}
{{#link-to "tag.new" class="gh-btn gh-btn-green"}}<span>New tag</span>{{/link-to}}
</section>
</header>

View File

@ -1,4 +1,3 @@
{{#unless selectedTag}}
<section class="gh-canvas tags-view">
<GhCanvasHeader class="gh-canvas-header tags-header">
<h2 class="gh-canvas-title" data-test-screen-title>Tags</h2>
@ -7,7 +6,7 @@
<button class="gh-btn {{if (eq type "public") "gh-btn-group-selected"}}" {{action "changeType" "public"}}><span>Public tags</span></button>
<button class="gh-btn {{if (eq type "internal") "gh-btn-group-selected"}}" {{action "changeType" "internal"}}><span>Internal tags</span></button>
</div>
{{#link-to "tags.new" class="gh-btn gh-btn-green"}}<span>New tag</span>{{/link-to}}
{{#link-to "tag.new" class="gh-btn gh-btn-green"}}<span>New tag</span>{{/link-to}}
</section>
</GhCanvasHeader>
<section class="content-list">
@ -37,7 +36,7 @@
<div class="no-posts">
{{svg-jar "tags-placeholder" class="gh-tags-placeholder"}}
<h3>You haven't created any {{type}} tags yet!</h3>
{{#link-to "tags.new" class="gh-btn gh-btn-green gh-btn-lg"}}
{{#link-to "tag.new" class="gh-btn gh-btn-green gh-btn-lg"}}
<span>Create a new tag</span>
{{/link-to}}
</div>
@ -46,5 +45,5 @@
</ol>
</section>
</section>
{{/unless}}
{{outlet}}