import {alias} from 'ember-computed'; import ModalComponent from 'ghost-admin/components/modals/base'; import {invokeAction} from 'ember-invoke-action'; export default ModalComponent.extend({ submitting: false, subscriber: alias('model'), actions: { confirm() { this.set('submitting', true); invokeAction(this, 'confirm').finally(() => { this.set('submitting', false); }); } } });
slugGenerator: injectService(), cards: [], // for apps atoms: [], // for apps toolbar: [], // for apps apiRoot: ghostPaths().apiRoot, assetPath: ghostPaths().assetRoot, init() { this._super(...arguments); window.onbeforeunload = () => { return this.get('hasDirtyAttributes') ? this.unloadDirtyMessage() : null; }; }, shouldFocusTitle: alias('model.isNew'), shouldFocusEditor: false, autoSave: observer('model.scratch', function () { // Don't save just because we swapped out models if (this.get('model.isDraft') && !this.get('model.isNew')) { let autoSaveId, saveOptions, timedSaveId; saveOptions = { silent: true, backgroundSave: true }; timedSaveId = run.throttle(this, 'send', 'save', saveOptions, 60000, false);
import Model from 'ember-data/model' import attr from 'ember-data/attr' import { belongsTo } from 'ember-data/relationships' import { alias } from 'ember-computed' export default Model.extend({ actor: belongsTo('user'), githubId: attr('string'), type: attr('string'), repo: attr(), payload: attr(), public: attr('boolean'), createdAt: attr('date'), importedAt: attr('date'), updatedAt: attr('date'), created_at: alias('createdAt') })
import ModalComponent from 'ghost-admin/components/modals/base'; import {alias} from 'ember-computed'; import {invokeAction} from 'ember-invoke-action'; import {task} from 'ember-concurrency'; export default ModalComponent.extend({ theme: alias('model.theme'), download: alias('model.download'), deleteTheme: task(function* () { try { yield invokeAction(this, 'confirm'); } finally { this.send('closeModal'); } }).drop(), actions: { confirm() { this.get('deleteTheme').perform(); } } });
import injectService from 'ember-service/inject'; import $ from 'jquery'; import {isBlank} from 'ember-utils'; // ember-cli-shims doesn't export these const {Handlebars} = Ember; export default Component.extend({ tagName: 'li', classNames: ['gh-posts-list-item'], classNameBindings: ['active'], post: null, active: false, isFeatured: alias('post.featured'), isPage: alias('post.page'), isPublished: equal('post.status', 'published'), isScheduled: equal('post.status', 'scheduled'), ghostPaths: injectService(), authorName: computed('post.author.name', 'post.author.email', function () { return this.get('post.author.name') || this.get('post.author.email'); }), authorAvatar: computed('post.author.image', function () { return this.get('post.author.image') || `${this.get('ghostPaths.assetRoot')}/img/user-image.png`; }), authorAvatarBackground: computed('authorAvatar', function () {
* @module Component * @extends Ember.Component */ export default Component.extend({ classNames: ['code-theme-selector'], classNameBindings: ['themeClass'], /** * @property codeTheme * @type Ember.Service */ codeTheme: service(), /** * Returns the current code theme's class name. * * @property themeClass * @type String */ themeClass: alias('codeTheme.className'), /** * Fires on click. Toggles the code theme. * * @method click */ click() { get(this, 'codeTheme').toggle(); } });
return baseSet.filterBy('activated', true); }), /** * Computed props for generating aggregation params * used to query on behalf of data-stat components * resultant objects used by aggregator service */ currectQueryParams: computed(...QUERY_PARAMS, function() { const filters = getProperties(this, ...this.queryParams); return Object.freeze(filters); }), aggParamsBase: computed('currectQueryParams', function() { return Object.assign({aggBy: 'count'}, get(this, 'currectQueryParams')); }), grantCountParams: alias('aggParamsBase'), sumCostParams: computed('aggParamsBase', function() { return Object.assign({aggMethod: 'sum', aggOn: 'totalCost'}, get(this, 'aggParamsBase')); }), avgCostParams: computed('aggParamsBase', function() { return Object.assign({aggMethod: 'avg', aggOn: 'totalCost'}, get(this, 'aggParamsBase')); }), stdCostParams: computed('aggParamsBase', function() { return Object.assign({aggMethod: 'stdDevSamp', aggOn: 'totalCost'}, get(this, 'aggParamsBase')); }), actions: { /* toggles filter activation state @ search-filter-modal component */ toggleActivation(filterProps) { // reset filter before turning it inactive if ( get(this, filterProps.filterAttr) ) {
import Controller from 'ember-controller'; import {alias, filter} from 'ember-computed'; import injectService from 'ember-service/inject'; export default Controller.extend({ showInviteUserModal: false, users: alias('model'), session: injectService(), activeUsers: filter('users', function (user) { return /^active|warn-[1-4]|locked$/.test(user.get('status')); }), invitedUsers: filter('users', function (user) { let status = user.get('status'); return status === 'invited' || status === 'invited-pending'; }), actions: { toggleInviteUserModal() { this.toggleProperty('showInviteUserModal'); } } });
import ModalComponent from 'ghost-admin/components/modals/base'; import {alias} from 'ember-computed'; import {invokeAction} from 'ember-invoke-action'; import {task} from 'ember-concurrency'; export default ModalComponent.extend({ user: alias('model'), suspendUser: task(function* () { try { yield invokeAction(this, 'confirm'); } finally { this.send('closeModal'); } }).drop(), actions: { confirm() { return this.get('suspendUser').perform(); } } });
// application // must be kept for Route.reopen logic import Controller from 'ember-controller'; import { alias } from 'ember-computed'; export default Controller.extend({ currentRoute: alias('target.currentPath') });
return get(this, '_dataManager') || APIDataManager.create(); } return get(this, '_dataManager') || ArrayDataManager.create(); } }), didReceiveAttrs() { set(this, 'dataManager.content', this.getAttr('content') || get(this, 'content')); if (get(this, 'modelName')) { Ember.bind(this, 'dataManager.modelName', 'modelName'); Ember.bind(this, 'dataManager.store', 'store'); } this._super(...arguments); }, filteringHandler: alias('dataManager.filteringHandler'), sortingHandler: alias('dataManager.sortingHandler'), paginatingHandler: alias('dataManager.paginatingHandler'), page: alias('paginatingHandler.page'), pageSize: alias('paginatingHandler.pageSize'), managedContent: alias('dataManager.managedContent'), propertiesList: computed( 'properties.@each{label,key}', 'sortingHandler.sortKeys.@each.{key,descending}', function() { let properties = get(this, 'properties'); let sortings = get(this, 'sortingHandler.sortKeys');
import moment from 'moment'; import computed from 'ember-computed'; import Component from 'ember-component'; export default Component.extend({ days: computed.alias('forecast'), displayDate: computed('weather.weatherForecast.currently.time', function () { return moment.unix(this.get('weather.weatherForecast.currently.time')).format('MMM DD'); }) });
import Controller from 'ember-controller'; import injectController from 'ember-controller/inject'; import {alias} from 'ember-computed'; export default Controller.extend({ appsController: injectController('settings.apps'), slack: alias('appsController.model.slack.firstObject') });
import {alias} from 'ember-computed'; import injectService from 'ember-service/inject'; import ModalComponent from 'ghost-admin/components/modals/base'; import {task} from 'ember-concurrency'; export default ModalComponent.extend({ post: alias('model.post'), onSuccess: alias('model.onSuccess'), notifications: injectService(), routing: injectService('-routing'), _deletePost() { let post = this.get('post'); // definitely want to clear the data store and post of any unsaved, // client-generated tags post.updateTags(); return post.destroyRecord(); }, _success() { // clear any previous error messages this.get('notifications').closeAlerts('post.delete'); // trigger the success action if (this.get('onSuccess')) { this.get('onSuccess')(); }
*/ optionLabelPath: 'label', /** * A path to fetch the value for each option. If null, will return the object. * * @type {String} */ optionValuePath: null, /** * The current selection * * @type {Object} */ selected: computed.alias('value'), /** * The options to render in the list * * @type {Array[Object]} */ options: computed.reads('collection'), selectionOptions: computed('value', 'selected', 'options.[]', 'multiple', { get() { let { selected, options, optionValuePath, multiple } = this.getProperties('selected', 'options', 'optionValuePath', 'multiple'); if (multiple) { if (!Ember.isArray(selected)) {
import ModalComponent from 'ghost-admin/components/modals/base'; import computed, {alias} from 'ember-computed'; import {invokeAction} from 'ember-invoke-action'; import {task} from 'ember-concurrency'; export default ModalComponent.extend({ tag: alias('model'), postInflection: computed('tag.count.posts', function () { return this.get('tag.count.posts') > 1 ? 'posts' : 'post'; }), deleteTag: task(function* () { try { yield invokeAction(this, 'confirm'); } finally { this.send('closeModal'); } }).drop(), actions: { confirm() { this.get('deleteTag').perform(); } } });
import Controller from 'ember-controller'; import {empty} from 'ember-computed'; import injectService from 'ember-service/inject'; import {task} from 'ember-concurrency'; import {isInvalidError} from 'ember-ajax/errors'; import {alias} from 'ember-computed'; export default Controller.extend({ ghostPaths: injectService(), ajax: injectService(), notifications: injectService(), settings: injectService(), model: alias('settings.slack.firstObject'), testNotificationDisabled: empty('model.url'), save: task(function* () { let slack = this.get('model'); let settings = this.get('settings'); try { yield slack.validate(); settings.get('slack').clear().pushObject(slack); return yield settings.save(); } catch (error) { if (error) { this.get('notifications').showAPIError(error); throw error; } }
import {alias} from 'ember-computed'; import injectService from 'ember-service/inject'; import ModalComponent from 'ghost-admin/components/modals/base'; export default ModalComponent.extend({ submitting: false, post: alias('model'), notifications: injectService(), routing: injectService('-routing'), _deletePost() { let post = this.get('post'); // definitely want to clear the data store and post of any unsaved, // client-generated tags post.updateTags(); return post.destroyRecord(); }, _success() { // clear any previous error messages this.get('notifications').closeAlerts('post.delete'); // redirect to content screen this.get('routing').transitionTo('posts'); },
import injectService from 'ember-service/inject'; import injectController from 'ember-controller/inject'; import {htmlSafe} from 'ember-string'; import run from 'ember-runloop'; import DS from 'ember-data'; const {Errors} = DS; export default Controller.extend({ notifications: injectService(), two: injectController('setup/two'), errors: Errors.create(), hasValidated: emberA(), users: '', ownerEmail: alias('two.email'), submitting: false, usersArray: computed('users', function () { let errors = this.get('errors'); let users = this.get('users').split('\n').filter(function (email) { return email.trim().length > 0; }); // remove "no users to invite" error if we have users if (users.uniq().length > 0 && errors.get('users.length') === 1) { if (errors.get('users.firstObject').message.match(/no users/i)) { errors.remove('users'); } }
/** A service that is used for fetching mentions within a body of text. @property mentionFetcher @type Ember.Service */ mentionFetcher: service(), /** Returns whether or not the current user can edit the current comment. @property canEdit @type Boolean */ canEdit: alias('currentUserIsCommentAuthor'), /** Returns the comment author's ID. @property commentAuthorId @type Number */ commentAuthorId: alias('comment.user.id'), /** Returns the current user's ID. @property currentUserId @type Number */
import Component from 'ember-component'; import injectService from 'ember-service/inject'; import {alias} from 'ember-computed'; export default Component.extend({ tagName: 'section', classNames: ['gh-upgrade-notification'], upgradeNotification: injectService('upgrade-notification'), message: alias('upgradeNotification.content') });
import Controller from 'ember-controller'; import {alias} from 'ember-computed'; import injectService from 'ember-service/inject'; import injectController from 'ember-controller/inject'; export default Controller.extend({ showDeleteTagModal: false, tag: alias('model'), isMobile: alias('tagsController.isMobile'), applicationController: injectController('application'), tagsController: injectController('settings.tags'), notifications: injectService(), _saveTagProperty(propKey, newValue) { let tag = this.get('tag'); let currentValue = tag.get(propKey); newValue = newValue.trim(); // Quit if there was no change if (newValue === currentValue) { return; } tag.set(propKey, newValue); // TODO: This is required until .validate/.save mark fields as validated tag.get('hasValidated').addObject(propKey);
import Component from 'ember-component'; import computed, {alias, readOnly} from 'ember-computed'; import run from 'ember-runloop'; import ValidationState from 'ghost-admin/mixins/validation-state'; import SortableItem from 'ember-sortable/mixins/sortable-item'; export default Component.extend(ValidationState, SortableItem, { classNames: 'gh-blognav-item', classNameBindings: ['errorClass', 'navItem.isNew::gh-blognav-item--sortable'], new: false, handle: '.gh-blognav-grab', model: alias('navItem'), errors: readOnly('navItem.errors'), errorClass: computed('hasError', function () { if (this.get('hasError')) { return 'gh-blognav-item--error'; } }), keyPress(event) { // enter key if (event.keyCode === 13 && this.get('navItem.isNew')) { event.preventDefault(); run.scheduleOnce('actions', this, function () { this.send('addItem'); }); } },