From 9942fb337ea6a4fccd74614caddf241058e6c690 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Thu, 28 May 2020 13:35:53 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Improved=20performance=20of=20membe?= =?UTF-8?q?rs=20admin=20screens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no issue - removes the "old" members screens - swaps route names and links to point at the new members screens that were behind the experiments flag Why are the new screens faster? - only loads 50 members at once rather than every member in the database - loads pages of members in as-needed whilst scrolling - fetches member stats from the API rather than calculating locally - caches members list and stats data for 60 seconds to avoid re-fetching when navigating to/from the members list - moves search and filtering duties to the API rather than calculating locally --- .../app/components/gh-members-chart-old.hbs | 54 ---- .../app/components/gh-members-chart-old.js | 249 ------------------ .../components/gh-members-list-item-old.hbs | 35 --- .../components/gh-members-list-item-old.js | 8 - .../components/gh-members-no-members-old.hbs | 16 -- .../components/gh-members-no-members-old.js | 38 --- ghost/admin/app/components/gh-nav-menu.hbs | 15 +- ghost/admin/app/controllers/member-old.js | 139 ---------- ghost/admin/app/controllers/members-old.js | 182 ------------- .../app/controllers/members-old/import.js | 19 -- ghost/admin/app/router.js | 12 +- ghost/admin/app/routes/member-old.js | 73 ----- ghost/admin/app/routes/member-old/new.js | 6 - ghost/admin/app/routes/members-old.js | 45 ---- ghost/admin/app/routes/members-old/import.js | 4 - ghost/admin/app/templates/member-old.hbs | 109 -------- ghost/admin/app/templates/members-old.hbs | 99 ------- .../app/templates/members-old/import.hbs | 4 - ghost/admin/tests/acceptance/members-test.js | 2 +- 19 files changed, 9 insertions(+), 1100 deletions(-) delete mode 100644 ghost/admin/app/components/gh-members-chart-old.hbs delete mode 100644 ghost/admin/app/components/gh-members-chart-old.js delete mode 100644 ghost/admin/app/components/gh-members-list-item-old.hbs delete mode 100644 ghost/admin/app/components/gh-members-list-item-old.js delete mode 100644 ghost/admin/app/components/gh-members-no-members-old.hbs delete mode 100644 ghost/admin/app/components/gh-members-no-members-old.js delete mode 100644 ghost/admin/app/controllers/member-old.js delete mode 100644 ghost/admin/app/controllers/members-old.js delete mode 100644 ghost/admin/app/controllers/members-old/import.js delete mode 100644 ghost/admin/app/routes/member-old.js delete mode 100644 ghost/admin/app/routes/member-old/new.js delete mode 100644 ghost/admin/app/routes/members-old.js delete mode 100644 ghost/admin/app/routes/members-old/import.js delete mode 100644 ghost/admin/app/templates/member-old.hbs delete mode 100644 ghost/admin/app/templates/members-old.hbs delete mode 100644 ghost/admin/app/templates/members-old/import.hbs diff --git a/ghost/admin/app/components/gh-members-chart-old.hbs b/ghost/admin/app/components/gh-members-chart-old.hbs deleted file mode 100644 index 59467638d6..0000000000 --- a/ghost/admin/app/components/gh-members-chart-old.hbs +++ /dev/null @@ -1,54 +0,0 @@ -
- - {{!-- Chart title/filter graph --}} -
-
-

Total members

-
-
- - {{range.name}} - -
-
-
-
- -
-
- {{this.subData.startDateLabel}} - Today -
-
- - {{!-- Summary --}} -
-
-

Total Members

-
{{this.subData.totalSubs}}
-
-
- {{#if (eq this.range "all-time")}} -

All time signups

- {{else}} -

Signed up in the last {{this.range}} days

- {{/if}} -
{{this.subData.totalSubsInRange}}
-
-
-

Signed up today

-
{{this.subData.totalSubsToday}}
-
-
-
\ No newline at end of file diff --git a/ghost/admin/app/components/gh-members-chart-old.js b/ghost/admin/app/components/gh-members-chart-old.js deleted file mode 100644 index 6f8a4e7ac2..0000000000 --- a/ghost/admin/app/components/gh-members-chart-old.js +++ /dev/null @@ -1,249 +0,0 @@ -/* global Chart */ -import Component from '@ember/component'; -import moment from 'moment'; -import {computed, get} from '@ember/object'; -import {inject as service} from '@ember/service'; - -export default Component.extend({ - feature: service(), - members: null, - range: '30', - selectedRange: computed('range', function () { - const availableRange = this.get('availableRange'); - return availableRange.findBy('days', this.get('range')); - }), - availableRange: computed(function () { - return [ - { - name: '30 days', - days: '30' - }, - { - name: '90 days', - days: '90' - }, - { - name: '365 days', - days: '365' - }, - { - name: 'All time', - days: 'all-time' - } - ]; - }), - - subData: computed('members.[]', 'range', 'feature.nightShift', function () { - let isNightShiftEnabled = this.feature.nightShift; - let {members, range} = this; - let rangeInDays, rangeStartDate, rangeEndDate; - if (range === 'last-year') { - rangeStartDate = moment().startOf('year').subtract(1, 'year'); - rangeEndDate = moment().endOf('year').subtract(1, 'year').subtract(1, 'day'); - rangeInDays = rangeEndDate.diff(rangeStartDate, 'days'); - } else if (range === 'all-time') { - let firstMemberCreatedDate = members.length ? members.lastObject.get('createdAtUTC') : moment().subtract(365, 'days'); - rangeStartDate = moment(firstMemberCreatedDate); - rangeEndDate = moment(); - rangeInDays = rangeEndDate.diff(rangeStartDate, 'days'); - if (rangeInDays < 5) { - rangeStartDate = moment().subtract(6, 'days'); - rangeInDays = rangeEndDate.diff(rangeStartDate, 'days'); - } - let step = this.getTicksForRange(rangeInDays); - rangeInDays = Math.ceil(rangeInDays / step) * step; - rangeStartDate = moment().subtract(rangeInDays, 'days'); - } else { - rangeInDays = parseInt(range); - rangeStartDate = moment().subtract((rangeInDays), 'days'); - rangeEndDate = moment(); - } - let totalSubs = members.length || 0; - let totalSubsLastMonth = members.filter((member) => { - let isValid = moment(member.createdAtUTC).isSameOrAfter(rangeStartDate, 'day'); - return isValid; - }).length; - - let totalSubsToday = members.filter((member) => { - let isValid = moment(member.createdAtUTC).isSame(moment(), 'day'); - return isValid; - }).length; - - return { - startDateLabel: moment(rangeStartDate).format('MMM DD, YYYY'), - chartData: this.getChartData(members, moment(rangeStartDate), moment(rangeEndDate), isNightShiftEnabled), - totalSubs: totalSubs, - totalSubsToday: totalSubsToday, - totalSubsInRange: totalSubsLastMonth - }; - }), - - init() { - this._super(...arguments); - this.setChartJSDefaults(); - }, - - actions: { - changeDateRange(range) { - this.set('range', get(range, 'days')); - } - }, - - setChartJSDefaults() { - let isNightShiftEnabled = this.feature.nightShift; - Chart.defaults.LineWithLine = Chart.defaults.line; - Chart.controllers.LineWithLine = Chart.controllers.line.extend({ - draw: function (ease) { - Chart.controllers.line.prototype.draw.call(this, ease); - - if (this.chart.tooltip._active && this.chart.tooltip._active.length) { - var activePoint = this.chart.tooltip._active[0], - ctx = this.chart.ctx, - x = activePoint.tooltipPosition().x, - topY = this.chart.scales['y-axis-0'].top, - bottomY = this.chart.scales['y-axis-0'].bottom; - - // draw line - ctx.save(); - ctx.beginPath(); - ctx.moveTo(x, topY); - ctx.lineTo(x, bottomY); - ctx.lineWidth = 1; - ctx.strokeStyle = (isNightShiftEnabled ? 'rgba(62, 176, 239, 0.65)' : 'rgba(62, 176, 239, 0.8)'); - ctx.stroke(); - ctx.restore(); - } - } - }); - }, - - getTicksForRange(rangeInDays) { - if (rangeInDays <= 30) { - return 6; - } else if (rangeInDays <= 90) { - return 18; - } else { - return 24; - } - }, - - getChartData(members, startDate, endDate, isNightShiftEnabled) { - this.setChartJSDefaults(); - let dateFormat = 'MMM DD, YYYY'; - let monthData = []; - let dateLabel = []; - let rangeInDays = endDate.diff(startDate, 'days'); - for (var m = moment(startDate); m.isSameOrBefore(endDate, 'day'); m.add(1, 'days')) { - dateLabel.push(m.format(dateFormat)); - let membersTillDate = members.filter((member) => { - let isValid = moment(member.createdAtUTC).isSameOrBefore(m, 'day'); - return isValid; - }).length; - monthData.push(membersTillDate); - } - let maxTicksAllowed = this.getTicksForRange(rangeInDays); - return { - data: { - labels: dateLabel, - datasets: [{ - label: 'Total members', - cubicInterpolationMode: 'monotone', - data: monthData, - fill: false, - backgroundColor: 'rgba(62,176,239,.9)', - pointRadius: 0, - pointHitRadius: 10, - borderColor: 'rgba(62,176,239,.9)', - borderJoinStyle: 'round' - }] - }, - options: { - responsive: true, - maintainAspectRatio: false, - layout: { - padding: { - top: 5, // Needed otherwise the top dot is cut - right: 10, - bottom: 5, - left: 10 - } - }, - title: { - display: false - }, - tooltips: { - intersect: false, - mode: 'index', - displayColors: false, - backgroundColor: '#343f44', - xPadding: 7, - yPadding: 7, - cornerRadius: 5, - caretSize: 7, - caretPadding: 5, - bodyFontSize: 13, - titleFontStyle: 'normal', - titleFontColor: 'rgba(255, 255, 255, 0.7)', - titleMarginBottom: 4 - }, - hover: { - mode: 'index', - intersect: false, - animationDuration: 120 - }, - legend: { - display: false - }, - scales: { - xAxes: [{ - labelString: 'Date', - gridLines: { - drawTicks: false, - color: (isNightShiftEnabled ? '#333F44' : '#E5EFF5'), - zeroLineColor: (isNightShiftEnabled ? '#333F44' : '#E5EFF5') - }, - ticks: { - display: false, - maxRotation: 0, - minRotation: 0, - padding: 6, - autoSkip: false, - maxTicksLimit: 10, - callback: function (value, index, values) { - let step = (values.length - 1) / (maxTicksAllowed); - let steps = []; - for (let i = 0; i < maxTicksAllowed; i++) { - steps.push(Math.round(i * step)); - } - - if (index === 0) { - return value; - } - if (index === (values.length - 1)) { - return 'Today'; - } - - if (steps.includes(index)) { - return ''; - } - } - } - }], - yAxes: [{ - gridLines: { - drawTicks: false, - display: false, - drawBorder: false - }, - ticks: { - maxTicksLimit: 5, - fontColor: '#9baeb8', - padding: 8, - precision: 0 - } - }] - } - } - }; - } -}); diff --git a/ghost/admin/app/components/gh-members-list-item-old.hbs b/ghost/admin/app/components/gh-members-list-item-old.hbs deleted file mode 100644 index 4bd407c018..0000000000 --- a/ghost/admin/app/components/gh-members-list-item-old.hbs +++ /dev/null @@ -1,35 +0,0 @@ -
  • - -
    - -
    -

    {{or @member.name @member.email}}

    - {{#if @member.name}} -

    {{@member.email}}

    - {{/if}} -
    -
    -
    - - - {{#if @member.geolocation}} - {{#if (eq @member.geolocation.country_code "US")}} - {{@member.geolocation.region}}, US - {{else}} - {{@member.geolocation.country}} - {{/if}} - {{else}} - Unknown - {{/if}} - - - - {{moment-format @member.createdAtUTC "MMM DD, YYYY"}} ({{this.memberSince}}) - - - -
    - {{svg-jar "arrow-right" class="w6 h6 fill-midgrey pa1"}} -
    -
    -
  • \ No newline at end of file diff --git a/ghost/admin/app/components/gh-members-list-item-old.js b/ghost/admin/app/components/gh-members-list-item-old.js deleted file mode 100644 index 7d5c4a169d..0000000000 --- a/ghost/admin/app/components/gh-members-list-item-old.js +++ /dev/null @@ -1,8 +0,0 @@ -import Component from '@glimmer/component'; -import moment from 'moment'; - -export default class GhMembersListItemComponent extends Component { - get memberSince() { - return moment(this.args.member.createdAtUTC).from(moment()); - } -} diff --git a/ghost/admin/app/components/gh-members-no-members-old.hbs b/ghost/admin/app/components/gh-members-no-members-old.hbs deleted file mode 100644 index ffe7d10437..0000000000 --- a/ghost/admin/app/components/gh-members-no-members-old.hbs +++ /dev/null @@ -1,16 +0,0 @@ -
    - {{!--

    Get started with one of the following options

    --}} - - -
    - - Manually add a member - - - - Import members from CSV - -
    -
    \ No newline at end of file diff --git a/ghost/admin/app/components/gh-members-no-members-old.js b/ghost/admin/app/components/gh-members-no-members-old.js deleted file mode 100644 index 1eafbacdbb..0000000000 --- a/ghost/admin/app/components/gh-members-no-members-old.js +++ /dev/null @@ -1,38 +0,0 @@ -import Component from '@ember/component'; -import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; - -export default Component.extend({ - session: service(), - store: service(), - notifications: service(), - - actions: { - addYourself() { - return this.add.perform(); - } - }, - - add: task(function* () { - const member = this.store.createRecord('member', { - email: this.get('session.user.email'), - name: this.get('session.user.name') - }); - - try { - // NOTE: has to be before member.save() is performed otherwise component is - // destroyed before notification is shown - this.notifications.showNotification('Member added'.htmlSafe(), - { - description: 'You\'ve successfully added yourself as a member.' - } - ); - - return yield member.save(); - } catch (error) { - if (error) { - this.notifications.showAPIError(error, {key: 'member.save'}); - } - } - }).drop() -}); diff --git a/ghost/admin/app/components/gh-nav-menu.hbs b/ghost/admin/app/components/gh-nav-menu.hbs index 81005cc8d0..464de9d212 100644 --- a/ghost/admin/app/components/gh-nav-menu.hbs +++ b/ghost/admin/app/components/gh-nav-menu.hbs @@ -71,17 +71,12 @@ {{/if}} {{#if (and this.feature.members (gh-user-can-admin this.session.user))}}
  • - {{svg-jar "members"}}Members + {{#if (eq this.router.currentRouteName "members.index")}} + {{svg-jar "members"}}Members + {{else}} + {{svg-jar "members"}}Members + {{/if}}
  • - {{#if this.config.enableDeveloperExperiments}} -
  • - {{#if (eq this.router.currentRouteName "members.index")}} - {{svg-jar "members"}}Members (dev) - {{else}} - {{svg-jar "members"}}Members (dev) - {{/if}} -
  • - {{/if}} {{/if}}
  • {{svg-jar "staff"}}Staff
  • diff --git a/ghost/admin/app/controllers/member-old.js b/ghost/admin/app/controllers/member-old.js deleted file mode 100644 index 3a845aac81..0000000000 --- a/ghost/admin/app/controllers/member-old.js +++ /dev/null @@ -1,139 +0,0 @@ -import Controller from '@ember/controller'; -import EmberObject from '@ember/object'; -import boundOneWay from 'ghost-admin/utils/bound-one-way'; -import moment from 'moment'; -import {alias} from '@ember/object/computed'; -import {computed, defineProperty} from '@ember/object'; -import {inject as controller} from '@ember/controller'; -import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; - -const SCRATCH_PROPS = ['name', 'email', 'note']; - -export default Controller.extend({ - members: controller('members-old'), - session: service(), - dropdown: service(), - notifications: service(), - router: service(), - store: service(), - - showImpersonateMemberModal: false, - - member: alias('model'), - - scratchMember: computed('member', function () { - let scratchMember = EmberObject.create({member: this.member}); - SCRATCH_PROPS.forEach(prop => defineProperty(scratchMember, prop, boundOneWay(`member.${prop}`))); - return scratchMember; - }), - - subscribedAt: computed('member.createdAtUTC', function () { - let memberSince = moment(this.member.createdAtUTC).from(moment()); - let createdDate = moment(this.member.createdAtUTC).format('MMM DD, YYYY'); - return `${createdDate} (${memberSince})`; - }), - - actions: { - setProperty(propKey, value) { - this._saveMemberProperty(propKey, value); - }, - - toggleDeleteMemberModal() { - this.toggleProperty('showDeleteMemberModal'); - }, - - toggleImpersonateMemberModal() { - this.toggleProperty('showImpersonateMemberModal'); - }, - - save() { - return this.save.perform(); - }, - - deleteMember() { - return this.member.destroyRecord().then(() => { - return this.transitionToRoute('members-old'); - }, (error) => { - return this.notifications.showAPIError(error, {key: 'member.delete'}); - }); - }, - - toggleUnsavedChangesModal(transition) { - let leaveTransition = this.leaveScreenTransition; - - if (!transition && this.showUnsavedChangesModal) { - this.set('leaveScreenTransition', null); - this.set('showUnsavedChangesModal', false); - return; - } - - if (!leaveTransition || transition.targetName === leaveTransition.targetName) { - this.set('leaveScreenTransition', transition); - - // if a save is running, wait for it to finish then transition - if (this.save.isRunning) { - return this.save.last.then(() => { - transition.retry(); - }); - } - - // we genuinely have unsaved data, show the modal - this.set('showUnsavedChangesModal', true); - } - }, - - leaveScreen() { - this.member.rollbackAttributes(); - return this.leaveScreenTransition.retry(); - } - }, - - save: task(function* () { - let {member, scratchMember} = this; - - // if Cmd+S is pressed before the field loses focus make sure we're - // saving the intended property values - let scratchProps = scratchMember.getProperties(SCRATCH_PROPS); - member.setProperties(scratchProps); - - try { - yield member.save(); - member.updateLabels(); - // replace 'member.new' route with 'member' route - this.replaceRoute('member-old', member); - - return member; - } catch (error) { - if (error) { - this.notifications.showAPIError(error, {key: 'member.save'}); - } - } - }).drop(), - - fetchMember: task(function* (memberId) { - this.set('isLoading', true); - - let member = yield this.store.findRecord('member', memberId, { - reload: true - }); - - this.set('member', member); - this.set('isLoading', false); - }), - - _saveMemberProperty(propKey, newValue) { - let currentValue = this.member.get(propKey); - - if (newValue) { - newValue = newValue.trim(); - } - - // avoid modifying empty values and triggering inadvertant unsaved changes modals - if (newValue !== false && !newValue && !currentValue) { - return; - } - - this.member.set(propKey, newValue); - } -}); diff --git a/ghost/admin/app/controllers/members-old.js b/ghost/admin/app/controllers/members-old.js deleted file mode 100644 index ad0c52d034..0000000000 --- a/ghost/admin/app/controllers/members-old.js +++ /dev/null @@ -1,182 +0,0 @@ -import Controller from '@ember/controller'; -import ghostPaths from 'ghost-admin/utils/ghost-paths'; -import moment from 'moment'; -import {computed} from '@ember/object'; -import {get} from '@ember/object'; -import {pluralize} from 'ember-inflector'; -import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; - -/* eslint-disable ghost/ember/alias-model-in-controller */ -export default Controller.extend({ - store: service(), - - queryParams: ['label'], - - label: null, - members: null, - searchText: '', - modalLabel: null, - showLabelModal: false, - - _hasLoadedLabels: false, - _availableLabels: null, - - init() { - this._super(...arguments); - this.set('members', this.store.peekAll('member')); - this._availableLabels = this.store.peekAll('label'); - }, - - showLoader: computed('filteredMembers.length', 'fetchMembers.isRunning', function () { - return (!this.get('filteredMembers.length') && this.get('fetchMembers.isRunning')); - }), - - listHeader: computed('selectedLabel', 'searchText', function () { - let {searchText, selectedLabel, filteredMembers} = this; - if (searchText) { - return 'Search result'; - } - if (this.fetchMembers.lastSuccessful) { - let count = pluralize(filteredMembers.length, 'member'); - if (selectedLabel && selectedLabel.slug) { - if (filteredMembers.length > 1) { - return `${count} match current filter`; - } else { - return `${count} matches current filter`; - } - } - return count; - } - return 'Loading...'; - }), - - showingAll: computed('label', 'searchText', function () { - let {searchText, label} = this; - - return !searchText && !label; - }), - - availableLabels: computed('_availableLabels.@each.isNew', function () { - let labels = this._availableLabels - .filter(label => !label.get('isNew')) - .filter(label => label.get('id') !== null) - .sort((labelA, labelB) => labelA.name.localeCompare(labelB.name, undefined, {ignorePunctuation: true})); - let options = labels.toArray(); - - options.unshiftObject({name: 'All labels', slug: null}); - - return options; - }), - - selectedLabel: computed('label', 'availableLabels', function () { - let label = this.get('label'); - let labels = this.get('availableLabels'); - - return labels.findBy('slug', label); - }), - - labelModalData: computed('modalLabel', 'availableLabels', function () { - let label = this.get('modalLabel'); - let labels = this.get('availableLabels'); - - return { - label, - labels - }; - }), - - filteredMembers: computed('members.@each.{name,email}', 'searchText', 'label', function () { - let {members, searchText, label} = this; - searchText = searchText.toLowerCase(); - - let filtered = members.filter((member) => { - if (!searchText) { - return true; - } - - let {name, email} = member; - return (name && name.toLowerCase().indexOf(searchText) >= 0) - || (email && email.toLowerCase().indexOf(searchText) >= 0); - }).filter((member) => { - if (!label) { - return true; - } - return !!member.labels.find((_label) => { - return _label.slug === label; - }); - }).sort((a, b) => { - return b.get('createdAtUTC').valueOf() - a.get('createdAtUTC').valueOf(); - }); - - return filtered; - }), - - actions: { - exportData() { - let exportUrl = ghostPaths().url.api('members/csv'); - let downloadURL = `${exportUrl}?limit=all`; - let iframe = document.getElementById('iframeDownload'); - - if (!iframe) { - iframe = document.createElement('iframe'); - iframe.id = 'iframeDownload'; - iframe.style.display = 'none'; - document.body.append(iframe); - } - iframe.setAttribute('src', downloadURL); - }, - changeLabel(label, e) { - if (e) { - e.preventDefault(); - e.stopPropagation(); - } - this.set('label', get(label, 'slug')); - }, - addLabel(e) { - if (e) { - e.preventDefault(); - e.stopPropagation(); - } - const newLabel = this.store.createRecord('label'); - this.set('modalLabel', newLabel); - this.toggleProperty('showLabelModal'); - }, - editLabel(label, e) { - if (e) { - e.preventDefault(); - e.stopPropagation(); - } - let labels = this.get('availableLabels'); - - let modalLabel = labels.findBy('slug', label); - this.set('modalLabel', modalLabel); - this.toggleProperty('showLabelModal'); - }, - toggleLabelModal() { - this.toggleProperty('showLabelModal'); - } - }, - - fetchMembers: task(function* () { - let newFetchDate = new Date(); - - if (this._hasFetchedAll) { - // fetch any records modified since last fetch - yield this.store.query('member', { - limit: 'all', - filter: `updated_at:>='${moment.utc(this._lastFetchDate).format('YYYY-MM-DD HH:mm:ss')}'`, - order: 'created_at desc' - }); - } else { - // fetch all records - yield this.store.query('member', { - limit: 'all', - order: 'created_at desc' - }); - this._hasFetchedAll = true; - } - - this._lastFetchDate = newFetchDate; - }) -}); diff --git a/ghost/admin/app/controllers/members-old/import.js b/ghost/admin/app/controllers/members-old/import.js deleted file mode 100644 index 9a18fdcd6d..0000000000 --- a/ghost/admin/app/controllers/members-old/import.js +++ /dev/null @@ -1,19 +0,0 @@ -import Controller from '@ember/controller'; -import {inject as controller} from '@ember/controller'; -import {inject as service} from '@ember/service'; - -/* eslint-disable ghost/ember/alias-model-in-controller */ -export default Controller.extend({ - members: controller('members-old'), - router: service(), - - actions: { - fetchNewMembers() { - this.members.fetchMembers.perform(); - }, - - close() { - this.router.transitionTo('members-old'); - } - } -}); diff --git a/ghost/admin/app/router.js b/ghost/admin/app/router.js index 67eaa40cf6..4698992320 100644 --- a/ghost/admin/app/router.js +++ b/ghost/admin/app/router.js @@ -61,17 +61,11 @@ Router.map(function () { this.route('settings.integrations.unsplash', {path: '/settings/integrations/unsplash'}); this.route('settings.integrations.zapier', {path: '/settings/integrations/zapier'}); - this.route('members', {path: '/members-dev'}, function () { + this.route('members', function () { this.route('import'); }); - this.route('member.new', {path: '/members-dev/new'}); - this.route('member', {path: '/members-dev/:member_id'}); - - this.route('members-old', {path: '/members'}, function () { - this.route('import'); - }); - this.route('member-old.new', {path: '/members/new'}); - this.route('member-old', {path: '/members/:member_id'}); + this.route('member.new', {path: '/members/new'}); + this.route('member', {path: '/members/:member_id'}); this.route('error404', {path: '/*path'}); }); diff --git a/ghost/admin/app/routes/member-old.js b/ghost/admin/app/routes/member-old.js deleted file mode 100644 index f3f14e9dfb..0000000000 --- a/ghost/admin/app/routes/member-old.js +++ /dev/null @@ -1,73 +0,0 @@ -import AuthenticatedRoute from 'ghost-admin/routes/authenticated'; -import CurrentUserSettings from 'ghost-admin/mixins/current-user-settings'; -import {inject as service} from '@ember/service'; - -export default AuthenticatedRoute.extend(CurrentUserSettings, { - router: service(), - - _requiresBackgroundRefresh: true, - - init() { - this._super(...arguments); - this.router.on('routeWillChange', (transition) => { - this.showUnsavedChangesModal(transition); - }); - }, - - beforeModel() { - this._super(...arguments); - return this.get('session.user') - .then(this.transitionAuthor()); - }, - - model(params) { - this._requiresBackgroundRefresh = false; - - if (params.member_id) { - return this.store.findRecord('member', params.member_id, {reload: true}); - } else { - return this.store.createRecord('member'); - } - }, - - setupController(controller, member) { - this._super(...arguments); - if (this._requiresBackgroundRefresh) { - controller.fetchMember.perform(member.get('id')); - } - }, - - deactivate() { - this._super(...arguments); - - // clean up newly created records and revert unsaved changes to existing - this.controller.member.rollbackAttributes(); - - this._requiresBackgroundRefresh = true; - }, - - actions: { - save() { - this.controller.send('save'); - } - }, - - titleToken() { - return this.controller.get('member.name'); - }, - - showUnsavedChangesModal(transition) { - if (transition.from && transition.from.name === this.routeName && transition.targetName) { - let {controller} = this; - - // member.changedAttributes is always true for new members but number of changed attrs is reliable - let isChanged = Object.keys(controller.member.changedAttributes()).length > 0; - - if (!controller.member.isDeleted && isChanged) { - transition.abort(); - controller.send('toggleUnsavedChangesModal', transition); - return; - } - } - } -}); diff --git a/ghost/admin/app/routes/member-old/new.js b/ghost/admin/app/routes/member-old/new.js deleted file mode 100644 index c0acdcf7ce..0000000000 --- a/ghost/admin/app/routes/member-old/new.js +++ /dev/null @@ -1,6 +0,0 @@ -import MemberRoute from '../member-old'; - -export default MemberRoute.extend({ - controllerName: 'member-old', - templateName: 'member-old' -}); diff --git a/ghost/admin/app/routes/members-old.js b/ghost/admin/app/routes/members-old.js deleted file mode 100644 index cff6e62174..0000000000 --- a/ghost/admin/app/routes/members-old.js +++ /dev/null @@ -1,45 +0,0 @@ -import AuthenticatedRoute from 'ghost-admin/routes/authenticated'; -import {inject as service} from '@ember/service'; - -export default AuthenticatedRoute.extend({ - config: service(), - - queryParams: { - label: {refreshModel: true} - }, - - // redirect to posts screen if: - // - TODO: members is disabled? - // - logged in user isn't owner/admin - beforeModel() { - this._super(...arguments); - - return this.session.user.then((user) => { - if (!user.isOwnerOrAdmin) { - return this.transitionTo('home'); - } - }); - }, - - // trigger a background load of labels for filter dropdown - setupController(controller) { - this._super(...arguments); - controller.fetchMembers.perform(); - if (!controller._hasLoadedLabels) { - this.store.query('label', {limit: 'all'}).then(() => { - controller._hasLoadedLabels = true; - }); - } - }, - - deactivate() { - this._super(...arguments); - this.controller.modalLabel && this.controller.modalLabel.rollbackAttributes(); - }, - buildRouteInfoMetadata() { - return { - titleToken: 'Members' - }; - } - -}); diff --git a/ghost/admin/app/routes/members-old/import.js b/ghost/admin/app/routes/members-old/import.js deleted file mode 100644 index 6c74252aa1..0000000000 --- a/ghost/admin/app/routes/members-old/import.js +++ /dev/null @@ -1,4 +0,0 @@ -import Route from '@ember/routing/route'; - -export default Route.extend({ -}); diff --git a/ghost/admin/app/templates/member-old.hbs b/ghost/admin/app/templates/member-old.hbs deleted file mode 100644 index 7695ab7b56..0000000000 --- a/ghost/admin/app/templates/member-old.hbs +++ /dev/null @@ -1,109 +0,0 @@ -
    - -

    - Members - {{svg-jar "arrow-right"}} - {{#if this.member.isNew}} - New member - {{else}} - {{or this.member.name this.member.email}} - {{/if}} -

    - -
    - {{#if this.session.user.isOwner}} - {{#unless this.member.isNew}} - - {{/unless}} - {{/if}} - - -
    -
    - -
    -
    - {{#if (or this.member.name this.member.email)}} - - {{else}} -
    - N -
    - {{/if}} -
    -

    - {{or this.member.name this.member.email}} -

    -

    - {{#if (and this.member.name this.member.email)}} - {{this.member.email}} - {{/if}} -

    - {{#unless this.member.isNew}} -

    - {{#if this.member.geolocation}} - {{#if (eq this.member.geolocation.country_code "US")}} - {{this.member.geolocation.region}}, US - {{else}} - {{this.member.geolocation.country}} - {{/if}} - {{else}} - Unknown location - {{/if}} - – Created on {{this.subscribedAt}} -

    - {{/unless}} -
    -
    - - - - - {{#unless this.member.isNew}} - - {{/unless}} -
    - -{{#if this.showUnsavedChangesModal}} - -{{/if}} - -{{#if this.showDeleteMemberModal}} - -{{/if}} - -{{#if this.showImpersonateMemberModal}} - -{{/if}} diff --git a/ghost/admin/app/templates/members-old.hbs b/ghost/admin/app/templates/members-old.hbs deleted file mode 100644 index 15c9236978..0000000000 --- a/ghost/admin/app/templates/members-old.hbs +++ /dev/null @@ -1,99 +0,0 @@ -
    - -

    Members

    -
    - - - - - - {{svg-jar "settings"}} - - - - -
  • - - Import members - -
  • -
  • - - Export all members - -
  • -
    -
    - New member -
    -
    - {{#if this.showLoader}} -
    - -
    - {{else}} -
    - {{#if this.filteredMembers}} - {{#if this.showingAll}} -
    - -
    - {{/if}} - {{/if}} -
    -
      - {{#if this.filteredMembers}} -
    1. -
      {{listHeader}}
      -
      Location
      -
      Created
      -
      -
    2. - - - - {{else}} -
    3. -
      - {{svg-jar "members-placeholder" class="gh-members-placeholder"}} - {{#if this.showingAll}} -

      No members yet

      - - {{else}} -

      No members match the current filter

      - {{/if}} -
      -
    4. - {{/if}} -
    -
    -
    - {{/if}} -
    - -{{outlet}} - -{{#if this.showLabelModal}} - -{{/if}} \ No newline at end of file diff --git a/ghost/admin/app/templates/members-old/import.hbs b/ghost/admin/app/templates/members-old/import.hbs deleted file mode 100644 index 47dbdbc281..0000000000 --- a/ghost/admin/app/templates/members-old/import.hbs +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/ghost/admin/tests/acceptance/members-test.js b/ghost/admin/tests/acceptance/members-test.js index fc34d42e38..601abf9889 100644 --- a/ghost/admin/tests/acceptance/members-test.js +++ b/ghost/admin/tests/acceptance/members-test.js @@ -53,7 +53,7 @@ describe('Acceptance: Members', function () { await click('[data-test-nav="members"]'); expect(currentURL()).to.equal('/members'); - expect(currentRouteName()).to.equal('members-old.index'); + expect(currentRouteName()).to.equal('members.index'); expect(find('[data-test-screen-title]')).to.have.text('Members'); });