diff --git a/.eslintrc.js b/.eslintrc.js index 393d7668f45..73a80c91254 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,48 +1,48 @@ module.exports = { - root: true, - parserOptions: { - ecmaVersion: 2017, - sourceType: 'module', - ecmaFeatures: { - experimentalObjectRestSpread: true, - }, + root: true, + parserOptions: { + ecmaVersion: 2017, + sourceType: 'module', + ecmaFeatures: { + experimentalObjectRestSpread: true, }, - plugins: ['ember', 'prettier'], - extends: ['eslint:recommended', 'plugin:ember/recommended', 'plugin:prettier/recommended'], - env: { - browser: true, - }, - rules: { - 'prettier/prettier': 'error', + }, + plugins: ['ember', 'prettier'], + extends: ['eslint:recommended', 'plugin:ember/recommended', 'plugin:prettier/recommended'], + env: { + browser: true, + }, + rules: { + 'prettier/prettier': 'error', - 'arrow-parens': 'off', - 'brace-style': 'off', - camelcase: 'off', - 'comma-dangle': 'off', - 'dot-notation': 'off', - 'operator-linebreak': 'off', + 'arrow-parens': 'off', + 'brace-style': 'off', + camelcase: 'off', + 'comma-dangle': 'off', + 'dot-notation': 'off', + 'operator-linebreak': 'off', + }, + overrides: [ + // node files + { + files: [ + '.eslintrc.js', + '.template-lintrc.js', + 'ember-cli-build.js', + 'testem.js', + 'blueprints/*/index.js', + 'config/**/*.js', + 'lib/*/index.js', + 'server/**/*.js', + ], + parserOptions: { + sourceType: 'script', + ecmaVersion: 2015, + }, + env: { + browser: false, + node: true, + }, }, - overrides: [ - // node files - { - files: [ - '.eslintrc.js', - '.template-lintrc.js', - 'ember-cli-build.js', - 'testem.js', - 'blueprints/*/index.js', - 'config/**/*.js', - 'lib/*/index.js', - 'server/**/*.js', - ], - parserOptions: { - sourceType: 'script', - ecmaVersion: 2015, - }, - env: { - browser: false, - node: true, - }, - }, - ], + ], }; diff --git a/.template-lintrc.js b/.template-lintrc.js index e5d16f8327a..1691cf83d5b 100644 --- a/.template-lintrc.js +++ b/.template-lintrc.js @@ -3,11 +3,11 @@ /* eslint-env node */ module.exports = { - extends: 'recommended', + extends: 'recommended', - rules: { - 'block-indentation': false, - 'img-alt-attributes': false, - 'triple-curlies': false, - }, + rules: { + 'img-alt-attributes': false, + 'triple-curlies': false, + 'html-comments': false, + }, }; diff --git a/.travis.yml b/.travis.yml index 4b41efa0acd..6c4a4797e32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,6 +59,7 @@ matrix: - npm ci before_script: skip script: + - npm run lint:hbs - npm run lint:js - npm run lint:deps - npm test diff --git a/app/adapters/api-token.js b/app/adapters/api-token.js index f956848b701..1c7e6f33e4e 100644 --- a/app/adapters/api-token.js +++ b/app/adapters/api-token.js @@ -1,17 +1,17 @@ import DS from 'ember-data'; export default DS.RESTAdapter.extend({ - namespace: 'api/v1/me', - pathForType() { - return 'tokens'; - }, - createRecord(store, type, snapshot) { - let data = {}; - let serializer = store.serializerFor(type.modelName); - let url = this.buildURL(type.modelName, null, snapshot, 'createRecord'); + namespace: 'api/v1/me', + pathForType() { + return 'tokens'; + }, + createRecord(store, type, snapshot) { + let data = {}; + let serializer = store.serializerFor(type.modelName); + let url = this.buildURL(type.modelName, null, snapshot, 'createRecord'); - serializer.serializeIntoHash(data, type, snapshot, { includeId: true }); + serializer.serializeIntoHash(data, type, snapshot, { includeId: true }); - return this.ajax(url, 'PUT', { data }); - }, + return this.ajax(url, 'PUT', { data }); + }, }); diff --git a/app/adapters/application.js b/app/adapters/application.js index 6858d92982c..7940faa0966 100644 --- a/app/adapters/application.js +++ b/app/adapters/application.js @@ -2,5 +2,5 @@ import DS from 'ember-data'; import AdapterFetch from 'ember-fetch/mixins/adapter-fetch'; export default DS.RESTAdapter.extend(AdapterFetch, { - namespace: 'api/v1', + namespace: 'api/v1', }); diff --git a/app/adapters/category-slug.js b/app/adapters/category-slug.js index cf88cff590c..2d55e5e32aa 100644 --- a/app/adapters/category-slug.js +++ b/app/adapters/category-slug.js @@ -4,8 +4,8 @@ import { underscore, decamelize } from '@ember/string'; import ApplicationAdapter from './application'; export default ApplicationAdapter.extend({ - pathForType(modelName) { - let decamelized = underscore(decamelize(modelName)); - return pluralize(decamelized); - }, + pathForType(modelName) { + let decamelized = underscore(decamelize(modelName)); + return pluralize(decamelized); + }, }); diff --git a/app/adapters/crate-owner-invite.js b/app/adapters/crate-owner-invite.js index 582f4eb1e25..ad99112db29 100644 --- a/app/adapters/crate-owner-invite.js +++ b/app/adapters/crate-owner-invite.js @@ -1,8 +1,8 @@ import DS from 'ember-data'; export default DS.RESTAdapter.extend({ - namespace: 'api/v1/me', - pathForType() { - return 'crate_owner_invitations'; - }, + namespace: 'api/v1/me', + pathForType() { + return 'crate_owner_invitations'; + }, }); diff --git a/app/adapters/crate.js b/app/adapters/crate.js index 20504968b1d..3e0f8cd9dfb 100644 --- a/app/adapters/crate.js +++ b/app/adapters/crate.js @@ -1,35 +1,35 @@ import ApplicationAdapter from './application'; export default ApplicationAdapter.extend({ - follow(id) { - return this.ajax(this.urlForFollowAction(id), 'PUT'); - }, + follow(id) { + return this.ajax(this.urlForFollowAction(id), 'PUT'); + }, - inviteOwner(id, username) { - return this.ajax(this.urlForOwnerAction(id), 'PUT', { - data: { - owners: [username], - }, - }); - }, + inviteOwner(id, username) { + return this.ajax(this.urlForOwnerAction(id), 'PUT', { + data: { + owners: [username], + }, + }); + }, - removeOwner(id, username) { - return this.ajax(this.urlForOwnerAction(id), 'DELETE', { - data: { - owners: [username], - }, - }); - }, + removeOwner(id, username) { + return this.ajax(this.urlForOwnerAction(id), 'DELETE', { + data: { + owners: [username], + }, + }); + }, - unfollow(id) { - return this.ajax(this.urlForFollowAction(id), 'DELETE'); - }, + unfollow(id) { + return this.ajax(this.urlForFollowAction(id), 'DELETE'); + }, - urlForFollowAction(id) { - return `${this.buildURL('crate', id)}/follow`; - }, + urlForFollowAction(id) { + return `${this.buildURL('crate', id)}/follow`; + }, - urlForOwnerAction(id) { - return `${this.buildURL('crate', id)}/owners`; - }, + urlForOwnerAction(id) { + return `${this.buildURL('crate', id)}/owners`; + }, }); diff --git a/app/adapters/dependency.js b/app/adapters/dependency.js index bf6c5db25af..9e2d5a086ed 100644 --- a/app/adapters/dependency.js +++ b/app/adapters/dependency.js @@ -1,13 +1,13 @@ import ApplicationAdapter from './application'; export default ApplicationAdapter.extend({ - query(store, type, query) { - if (!query.reverse) { - return this._super(...arguments); - } - delete query.reverse; - let { crate } = query; - delete query.crate; - return this.ajax(`/${this.urlPrefix()}/crates/${crate.get('id')}/reverse_dependencies`, 'GET', { data: query }); - }, + query(store, type, query) { + if (!query.reverse) { + return this._super(...arguments); + } + delete query.reverse; + let { crate } = query; + delete query.crate; + return this.ajax(`/${this.urlPrefix()}/crates/${crate.get('id')}/reverse_dependencies`, 'GET', { data: query }); + }, }); diff --git a/app/adapters/team.js b/app/adapters/team.js index 8f4738e298b..e92de43a614 100644 --- a/app/adapters/team.js +++ b/app/adapters/team.js @@ -1,8 +1,8 @@ import ApplicationAdapter from './application'; export default ApplicationAdapter.extend({ - queryRecord(store, type, query) { - let url = this.urlForFindRecord(query.team_id, 'team'); - return this.ajax(url, 'GET'); - }, + queryRecord(store, type, query) { + let url = this.urlForFindRecord(query.team_id, 'team'); + return this.ajax(url, 'GET'); + }, }); diff --git a/app/adapters/user.js b/app/adapters/user.js index ba343fc4cfd..0517c69951d 100644 --- a/app/adapters/user.js +++ b/app/adapters/user.js @@ -1,16 +1,16 @@ import ApplicationAdapter from './application'; export default ApplicationAdapter.extend({ - stats(id) { - return this.ajax(this.urlForStatsAction(id), 'GET'); - }, + stats(id) { + return this.ajax(this.urlForStatsAction(id), 'GET'); + }, - urlForStatsAction(id) { - return `${this.buildURL('user', id)}/stats`; - }, + urlForStatsAction(id) { + return `${this.buildURL('user', id)}/stats`; + }, - queryRecord(store, type, query) { - let url = this.urlForFindRecord(query.user_id, 'user'); - return this.ajax(url, 'GET'); - }, + queryRecord(store, type, query) { + let url = this.urlForFindRecord(query.user_id, 'user'); + return this.ajax(url, 'GET'); + }, }); diff --git a/app/app.js b/app/app.js index ffb39911076..ddd13a0ff68 100644 --- a/app/app.js +++ b/app/app.js @@ -5,9 +5,9 @@ import loadInitializers from 'ember-load-initializers'; import config from './config/environment'; const App = Application.extend({ - modulePrefix: config.modulePrefix, - podModulePrefix: config.podModulePrefix, - Resolver, + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix, + Resolver, }); loadInitializers(App, config.modulePrefix); diff --git a/app/components/api-token-row.js b/app/components/api-token-row.js index 5a8066ceea9..eb8255a63ef 100644 --- a/app/components/api-token-row.js +++ b/app/components/api-token-row.js @@ -2,44 +2,44 @@ import Component from '@ember/component'; import { empty, or } from '@ember/object/computed'; export default Component.extend({ - emptyName: empty('api_token.name'), - disableCreate: or('api_token.isSaving', 'emptyName'), - serverError: null, + emptyName: empty('api_token.name'), + disableCreate: or('api_token.isSaving', 'emptyName'), + serverError: null, - didInsertElement() { - if (this.get('api_token.isNew')) { - this.$('input').focus(); + didInsertElement() { + if (this.get('api_token.isNew')) { + this.$('input').focus(); + } + }, + + actions: { + async saveToken() { + try { + await this.api_token.save(); + this.set('serverError', null); + } catch (err) { + let msg; + if (err.errors && err.errors[0] && err.errors[0].detail) { + msg = `An error occurred while saving this token, ${err.errors[0].detail}`; + } else { + msg = 'An unknown error occurred while saving this token'; } + this.set('serverError', msg); + } }, - actions: { - async saveToken() { - try { - await this.api_token.save(); - this.set('serverError', null); - } catch (err) { - let msg; - if (err.errors && err.errors[0] && err.errors[0].detail) { - msg = `An error occurred while saving this token, ${err.errors[0].detail}`; - } else { - msg = 'An unknown error occurred while saving this token'; - } - this.set('serverError', msg); - } - }, - - async revokeToken() { - try { - await this.api_token.destroyRecord(); - } catch (err) { - let msg; - if (err.errors && err.errors[0] && err.errors[0].detail) { - msg = `An error occurred while revoking this token, ${err.errors[0].detail}`; - } else { - msg = 'An unknown error occurred while revoking this token'; - } - this.set('serverError', msg); - } - }, + async revokeToken() { + try { + await this.api_token.destroyRecord(); + } catch (err) { + let msg; + if (err.errors && err.errors[0] && err.errors[0].detail) { + msg = `An error occurred while revoking this token, ${err.errors[0].detail}`; + } else { + msg = 'An unknown error occurred while revoking this token'; + } + this.set('serverError', msg); + } }, + }, }); diff --git a/app/components/badge-appveyor.js b/app/components/badge-appveyor.js index fc25c203810..72e52f54162 100644 --- a/app/components/badge-appveyor.js +++ b/app/components/badge-appveyor.js @@ -3,40 +3,38 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - - id: alias('badge.attributes.id'), - repository: alias('badge.attributes.repository'), - - imageUrl: computed('badge.attributes.id', function() { - let id = this.get('badge.attributes.id'); - let branch = this.branch; - if (id !== undefined && id !== null) { - return `https://ci.appveyor.com/api/projects/status/${id}/branch/${branch}?svg=true`; - } else { - let service = this.service; - let repository = this.repository; - - return `https://ci.appveyor.com/api/projects/status/${service}/${repository}?svg=true&branch=${branch}`; - } - }), - - branch: computed('badge.attributes.branch', function() { - return this.get('badge.attributes.branch') || 'master'; - }), - - projectName: computed('badge.attributes.project_name', function() { - return ( - this.get('badge.attributes.project_name') || this.get('badge.attributes.repository').replace(/[_.]/g, '-') - ); - }), - - service: computed('badge.attributes.service', function() { - return this.get('badge.attributes.service') || 'github'; - }), - - text: computed('badge', function() { - return `Appveyor build status for the ${this.branch} branch`; - }), + tagName: 'span', + classNames: ['badge'], + + id: alias('badge.attributes.id'), + repository: alias('badge.attributes.repository'), + + imageUrl: computed('badge.attributes.id', function() { + let id = this.get('badge.attributes.id'); + let branch = this.branch; + if (id !== undefined && id !== null) { + return `https://ci.appveyor.com/api/projects/status/${id}/branch/${branch}?svg=true`; + } else { + let service = this.service; + let repository = this.repository; + + return `https://ci.appveyor.com/api/projects/status/${service}/${repository}?svg=true&branch=${branch}`; + } + }), + + branch: computed('badge.attributes.branch', function() { + return this.get('badge.attributes.branch') || 'master'; + }), + + projectName: computed('badge.attributes.project_name', function() { + return this.get('badge.attributes.project_name') || this.get('badge.attributes.repository').replace(/[_.]/g, '-'); + }), + + service: computed('badge.attributes.service', function() { + return this.get('badge.attributes.service') || 'github'; + }), + + text: computed('badge', function() { + return `Appveyor build status for the ${this.branch} branch`; + }), }); diff --git a/app/components/badge-azure-devops.js b/app/components/badge-azure-devops.js index 89335afd9f1..16dd7b1a3e6 100644 --- a/app/components/badge-azure-devops.js +++ b/app/components/badge-azure-devops.js @@ -3,14 +3,14 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - project: alias('badge.attributes.project'), - pipeline: alias('badge.attributes.pipeline'), - build: computed('badge.attributes.build', function() { - return this.get('badge.attributes.build') || '1'; - }), - text: computed('pipeline', function() { - return `Azure Devops build status for the ${this.pipeline} pipeline`; - }), + tagName: 'span', + classNames: ['badge'], + project: alias('badge.attributes.project'), + pipeline: alias('badge.attributes.pipeline'), + build: computed('badge.attributes.build', function() { + return this.get('badge.attributes.build') || '1'; + }), + text: computed('pipeline', function() { + return `Azure Devops build status for the ${this.pipeline} pipeline`; + }), }); diff --git a/app/components/badge-circle-ci.js b/app/components/badge-circle-ci.js index 0af66e4acb9..f3d40695892 100644 --- a/app/components/badge-circle-ci.js +++ b/app/components/badge-circle-ci.js @@ -3,13 +3,13 @@ import { alias } from '@ember/object/computed'; import Component from '@ember/component'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - repository: alias('badge.attributes.repository'), - branch: computed('badge.attributes.branch', function() { - return encodeURIComponent(this.get('badge.attributes.branch') || 'master'); - }), - text: computed('branch', function() { - return `Circle CI build status for the ${this.branch} branch`; - }), + tagName: 'span', + classNames: ['badge'], + repository: alias('badge.attributes.repository'), + branch: computed('badge.attributes.branch', function() { + return encodeURIComponent(this.get('badge.attributes.branch') || 'master'); + }), + text: computed('branch', function() { + return `Circle CI build status for the ${this.branch} branch`; + }), }); diff --git a/app/components/badge-cirrus-ci.js b/app/components/badge-cirrus-ci.js index 62a3db4e328..93229669396 100644 --- a/app/components/badge-cirrus-ci.js +++ b/app/components/badge-cirrus-ci.js @@ -3,13 +3,13 @@ import { alias } from '@ember/object/computed'; import Component from '@ember/component'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - repository: alias('badge.attributes.repository'), - branch: computed('badge.attributes.branch', function() { - return encodeURIComponent(this.get('badge.attributes.branch') || 'master'); - }), - text: computed('branch', function() { - return `Cirrus CI build status for the ${this.branch} branch`; - }), + tagName: 'span', + classNames: ['badge'], + repository: alias('badge.attributes.repository'), + branch: computed('badge.attributes.branch', function() { + return encodeURIComponent(this.get('badge.attributes.branch') || 'master'); + }), + text: computed('branch', function() { + return `Cirrus CI build status for the ${this.branch} branch`; + }), }); diff --git a/app/components/badge-codecov.js b/app/components/badge-codecov.js index caa3429194a..90f30bb6201 100644 --- a/app/components/badge-codecov.js +++ b/app/components/badge-codecov.js @@ -3,16 +3,16 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - repository: alias('badge.attributes.repository'), - branch: computed('badge.attributes.branch', function() { - return this.get('badge.attributes.branch') || 'master'; - }), - service: computed('badge.attributes.service', function() { - return this.get('badge.attributes.service') || 'github'; - }), - text: computed('branch', function() { - return `CodeCov coverage status for the ${this.branch} branch`; - }), + tagName: 'span', + classNames: ['badge'], + repository: alias('badge.attributes.repository'), + branch: computed('badge.attributes.branch', function() { + return this.get('badge.attributes.branch') || 'master'; + }), + service: computed('badge.attributes.service', function() { + return this.get('badge.attributes.service') || 'github'; + }), + text: computed('branch', function() { + return `CodeCov coverage status for the ${this.branch} branch`; + }), }); diff --git a/app/components/badge-coveralls.js b/app/components/badge-coveralls.js index 8596f9f77ba..ee4dfaf17e5 100644 --- a/app/components/badge-coveralls.js +++ b/app/components/badge-coveralls.js @@ -3,16 +3,16 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - repository: alias('badge.attributes.repository'), - branch: computed('badge.attributes.branch', function() { - return this.get('badge.attributes.branch') || 'master'; - }), - service: computed('badge.attributes.service', function() { - return this.get('badge.attributes.service') || 'github'; - }), - text: computed('branch', function() { - return `Coveralls coverage status for the ${this.branch} branch`; - }), + tagName: 'span', + classNames: ['badge'], + repository: alias('badge.attributes.repository'), + branch: computed('badge.attributes.branch', function() { + return this.get('badge.attributes.branch') || 'master'; + }), + service: computed('badge.attributes.service', function() { + return this.get('badge.attributes.service') || 'github'; + }), + text: computed('branch', function() { + return `Coveralls coverage status for the ${this.branch} branch`; + }), }); diff --git a/app/components/badge-gitlab.js b/app/components/badge-gitlab.js index 98d5f1fae86..e3e00cf27e1 100644 --- a/app/components/badge-gitlab.js +++ b/app/components/badge-gitlab.js @@ -3,13 +3,13 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - repository: alias('badge.attributes.repository'), - branch: computed('badge.attributes.branch', function() { - return this.get('badge.attributes.branch') || 'master'; - }), - text: computed('badge', function() { - return `GitLab build status for the ${this.branch} branch`; - }), + tagName: 'span', + classNames: ['badge'], + repository: alias('badge.attributes.repository'), + branch: computed('badge.attributes.branch', function() { + return this.get('badge.attributes.branch') || 'master'; + }), + text: computed('badge', function() { + return `GitLab build status for the ${this.branch} branch`; + }), }); diff --git a/app/components/badge-is-it-maintained-issue-resolution.js b/app/components/badge-is-it-maintained-issue-resolution.js index a131e01868b..67c3b5252ff 100644 --- a/app/components/badge-is-it-maintained-issue-resolution.js +++ b/app/components/badge-is-it-maintained-issue-resolution.js @@ -3,10 +3,10 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - repository: alias('badge.attributes.repository'), - text: computed('badge', function() { - return `Is It Maintained average time to resolve an issue`; - }), + tagName: 'span', + classNames: ['badge'], + repository: alias('badge.attributes.repository'), + text: computed('badge', function() { + return `Is It Maintained average time to resolve an issue`; + }), }); diff --git a/app/components/badge-is-it-maintained-open-issues.js b/app/components/badge-is-it-maintained-open-issues.js index 5695dcca856..813a0e60428 100644 --- a/app/components/badge-is-it-maintained-open-issues.js +++ b/app/components/badge-is-it-maintained-open-issues.js @@ -3,10 +3,10 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - repository: alias('badge.attributes.repository'), - text: computed('badge', function() { - return `Is It Maintained percentage of issues still open`; - }), + tagName: 'span', + classNames: ['badge'], + repository: alias('badge.attributes.repository'), + text: computed('badge', function() { + return `Is It Maintained percentage of issues still open`; + }), }); diff --git a/app/components/badge-maintenance.js b/app/components/badge-maintenance.js index 70473376ae0..327b0bd769b 100644 --- a/app/components/badge-maintenance.js +++ b/app/components/badge-maintenance.js @@ -3,30 +3,30 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - escapedStatus: computed('badge', function() { - return this.get('badge.attributes.status').replace(/-/g, '--'); - }), - none: computed('badge', function() { - return this.get('badge.attributes.status') === 'none' || !this.get('badge.attributes.status'); - }), - status: alias('badge.attributes.status'), - color: computed('badge', function() { - switch (this.get('badge.attributes.status')) { - case 'actively-developed': - return 'brightgreen'; - case 'passively-maintained': - return 'yellowgreen'; - case 'as-is': - return 'yellow'; - case 'experimental': - return 'blue'; - case 'looking-for-maintainer': - return 'orange'; - case 'deprecated': - return 'red'; - } - }), - text: 'Maintenance intention for this crate', + tagName: 'span', + classNames: ['badge'], + escapedStatus: computed('badge', function() { + return this.get('badge.attributes.status').replace(/-/g, '--'); + }), + none: computed('badge', function() { + return this.get('badge.attributes.status') === 'none' || !this.get('badge.attributes.status'); + }), + status: alias('badge.attributes.status'), + color: computed('badge', function() { + switch (this.get('badge.attributes.status')) { + case 'actively-developed': + return 'brightgreen'; + case 'passively-maintained': + return 'yellowgreen'; + case 'as-is': + return 'yellow'; + case 'experimental': + return 'blue'; + case 'looking-for-maintainer': + return 'orange'; + case 'deprecated': + return 'red'; + } + }), + text: 'Maintenance intention for this crate', }); diff --git a/app/components/badge-travis-ci.js b/app/components/badge-travis-ci.js index a4562265e16..3650c7951b0 100644 --- a/app/components/badge-travis-ci.js +++ b/app/components/badge-travis-ci.js @@ -3,13 +3,13 @@ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; export default Component.extend({ - tagName: 'span', - classNames: ['badge'], - repository: alias('badge.attributes.repository'), - branch: computed('badge.attributes.branch', function() { - return this.get('badge.attributes.branch') || 'master'; - }), - text: computed('branch', function() { - return `Travis CI build status for the ${this.branch} branch`; - }), + tagName: 'span', + classNames: ['badge'], + repository: alias('badge.attributes.repository'), + branch: computed('badge.attributes.branch', function() { + return this.get('badge.attributes.branch') || 'master'; + }), + text: computed('branch', function() { + return `Travis CI build status for the ${this.branch} branch`; + }), }); diff --git a/app/components/crate-badge.js b/app/components/crate-badge.js index 7b1f8feaafb..30e30257d65 100644 --- a/app/components/crate-badge.js +++ b/app/components/crate-badge.js @@ -2,19 +2,19 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; export default Component.extend({ - classNames: ['vers'], + classNames: ['vers'], - tagName: 'span', + tagName: 'span', - version: computed('crate.max_version', function() { - return this.get('crate.max_version').replace('-', '--'); - }), + version: computed('crate.max_version', function() { + return this.get('crate.max_version').replace('-', '--'); + }), - color: computed('crate.max_version', function() { - if (this.get('crate.max_version')[0] == '0') { - return 'orange'; - } else { - return 'blue'; - } - }), + color: computed('crate.max_version', function() { + if (this.get('crate.max_version')[0] == '0') { + return 'orange'; + } else { + return 'blue'; + } + }), }); diff --git a/app/components/crate-readme.js b/app/components/crate-readme.js index 9aa88e6ab7f..513647ec05a 100644 --- a/app/components/crate-readme.js +++ b/app/components/crate-readme.js @@ -1,11 +1,11 @@ import Component from '@ember/component'; export default Component.extend({ - rendered: '', - didRender() { - this._super(...arguments); - this.$('pre > code').each(function() { - window.Prism.highlightElement(this); - }); - }, + rendered: '', + didRender() { + this._super(...arguments); + this.$('pre > code').each(function() { + window.Prism.highlightElement(this); + }); + }, }); diff --git a/app/components/crate-row.js b/app/components/crate-row.js index e395f9f98e3..84b9ce752bc 100644 --- a/app/components/crate-row.js +++ b/app/components/crate-row.js @@ -1,7 +1,7 @@ import Component from '@ember/component'; export default Component.extend({ - classNames: ['crate', 'row'], + classNames: ['crate', 'row'], - 'data-test-crate-row': true, + 'data-test-crate-row': true, }); diff --git a/app/components/download-graph.js b/app/components/download-graph.js index 56c1bf2f7f0..3682d29e246 100644 --- a/app/components/download-graph.js +++ b/app/components/download-graph.js @@ -4,174 +4,174 @@ import Component from '@ember/component'; const COLORS = ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#92c5de', '#4393c3', '#2166ac', '#053061']; export default Component.extend({ - classNames: 'graph-data', - resizeHandler: undefined, - - didInsertElement() { - this._super(...arguments); - - this.resizeHandler = () => this.rerender(); - window.addEventListener('resize', this.resizeHandler, false); - document.addEventListener('googleChartsLoaded', this.resizeHandler, false); - }, - - willDestroyElement() { - window.removeEventListener('resize', this.resizeHandler); - document.removeEventListener('googleChartsLoaded', this.resizeHandler); - }, - - didRender() { - this._super(...arguments); - - let data = this.data; - - let subarray_length = (data[1] || []).length; - - // Start at 1 to skip the date element in the 0th - // location in the array. - for (let k = 1; k < subarray_length; k++) { - let on = false; - - // Start at 1 because the 0th entry in the array - // is an array of version numbers. - // - // End before the last element is reached because we never - // want to change the last element. - for (let i = 1; i < data.length - 1; i++) { - // k + 1 because the first entry in the array is the date - let value = data[i][k]; - - // If we are "off" and are looking at a zero - // replace the data at this point with `null`. - // - // Null tells google.visualization to stop drawing - // the line altogether. - if (!on && value === 0) { - data[i][k] = null; - } - - // If we are off and the value is not zero, we - // need to turn back on. (keep the value the same though) - else if (!on && value !== 0) { - on = true; - - // We previously wrote a null into data[i - 1][k + 1], - // so to make the graph look pretty, we'll switch it back - // to the zero that it was before. - if (i >= 2) { - data[i - 1][k] = 0; - } - } - // If we are on and the value is zero, turn off - // but keep the zero in the array - else if (on && value === 0) { - on = false; - } - } + classNames: 'graph-data', + resizeHandler: undefined, + + didInsertElement() { + this._super(...arguments); + + this.resizeHandler = () => this.rerender(); + window.addEventListener('resize', this.resizeHandler, false); + document.addEventListener('googleChartsLoaded', this.resizeHandler, false); + }, + + willDestroyElement() { + window.removeEventListener('resize', this.resizeHandler); + document.removeEventListener('googleChartsLoaded', this.resizeHandler); + }, + + didRender() { + this._super(...arguments); + + let data = this.data; + + let subarray_length = (data[1] || []).length; + + // Start at 1 to skip the date element in the 0th + // location in the array. + for (let k = 1; k < subarray_length; k++) { + let on = false; + + // Start at 1 because the 0th entry in the array + // is an array of version numbers. + // + // End before the last element is reached because we never + // want to change the last element. + for (let i = 1; i < data.length - 1; i++) { + // k + 1 because the first entry in the array is the date + let value = data[i][k]; + + // If we are "off" and are looking at a zero + // replace the data at this point with `null`. + // + // Null tells google.visualization to stop drawing + // the line altogether. + if (!on && value === 0) { + data[i][k] = null; } - let show = data && window.google && window.googleChartsLoaded; - this.element.style.display = show ? '' : 'none'; - if (!show) { - return; + // If we are off and the value is not zero, we + // need to turn back on. (keep the value the same though) + else if (!on && value !== 0) { + on = true; + + // We previously wrote a null into data[i - 1][k + 1], + // so to make the graph look pretty, we'll switch it back + // to the zero that it was before. + if (i >= 2) { + data[i - 1][k] = 0; + } } + // If we are on and the value is zero, turn off + // but keep the zero in the array + else if (on && value === 0) { + on = false; + } + } + } - let myData = window.google.visualization.arrayToDataTable(data); - - let dateFmt = new window.google.visualization.DateFormat({ - pattern: 'LLL d, yyyy', - }); - dateFmt.format(myData, 0); - - // Create a formatter to use for daily download numbers - let numberFormatWhole = new window.google.visualization.NumberFormat({ - pattern: '#,##0', - }); - - // Create a formatter to use for 7-day average numbers - let numberFormatDecimal = new window.google.visualization.NumberFormat({ - pattern: '#,##0.0', - }); - - // use a DataView to calculate an x-day moving average - let days = 7; - let view = new window.google.visualization.DataView(myData); - let moving_avg_func_for_col = function(col) { - return function(dt, row) { - // For the last rows (the *first* days, remember, the dataset is - // backwards), we cannot calculate the avg. of previous days. - if (row >= dt.getNumberOfRows() - days) { - return null; - } - - let total = 0; - for (let i = days; i > 0; i--) { - total += dt.getValue(row + i, col); - } - let avg = total / days; - return { - v: avg, - f: numberFormatDecimal.formatValue(avg), - }; - }; - }; + let show = data && window.google && window.googleChartsLoaded; + this.element.style.display = show ? '' : 'none'; + if (!show) { + return; + } - let columns = [0]; // 0 = datetime - let seriesOption = {}; - let [headers] = data; - // Walk over the headers/colums in reverse order, as the newest version - // is at the end, but in the UI we want it at the top of the chart legend. - - range(headers.length - 1, 0, -1).forEach((dataCol, i) => { - // Set the number format for the colum in the data table. - numberFormatWhole.format(myData, dataCol); - columns.push(dataCol); // add the column itself - columns.push({ - // add a 'calculated' column, the moving average - type: 'number', - label: `${headers[dataCol]} ${days}-day avg.`, - calc: moving_avg_func_for_col(dataCol), - }); - // Note: while the columns start with index 1 (because 0 is the time - // axis), the series configuration starts with index 0. - seriesOption[i * 2] = { - type: 'scatter', - color: COLORS[i % COLORS.length], - pointSize: 3, - pointShape: 'square', - }; - seriesOption[i * 2 + 1] = { - type: 'area', - color: COLORS[i % COLORS.length], - lineWidth: 2, - curveType: 'function', - visibleInLegend: false, - }; - }); - view.setColumns(columns); - - let chart = new window.google.visualization.ComboChart(this.element); - chart.draw(view, { - chartArea: { left: 85, width: '77%', height: '80%' }, - hAxis: { - minorGridlines: { count: 8 }, - }, - vAxis: { - minorGridlines: { count: 5 }, - viewWindow: { min: 0 }, - }, - isStacked: true, - focusTarget: 'category', - seriesType: 'scatter', - series: seriesOption, - }); - }, + let myData = window.google.visualization.arrayToDataTable(data); + + let dateFmt = new window.google.visualization.DateFormat({ + pattern: 'LLL d, yyyy', + }); + dateFmt.format(myData, 0); + + // Create a formatter to use for daily download numbers + let numberFormatWhole = new window.google.visualization.NumberFormat({ + pattern: '#,##0', + }); + + // Create a formatter to use for 7-day average numbers + let numberFormatDecimal = new window.google.visualization.NumberFormat({ + pattern: '#,##0.0', + }); + + // use a DataView to calculate an x-day moving average + let days = 7; + let view = new window.google.visualization.DataView(myData); + let moving_avg_func_for_col = function(col) { + return function(dt, row) { + // For the last rows (the *first* days, remember, the dataset is + // backwards), we cannot calculate the avg. of previous days. + if (row >= dt.getNumberOfRows() - days) { + return null; + } + + let total = 0; + for (let i = days; i > 0; i--) { + total += dt.getValue(row + i, col); + } + let avg = total / days; + return { + v: avg, + f: numberFormatDecimal.formatValue(avg), + }; + }; + }; + + let columns = [0]; // 0 = datetime + let seriesOption = {}; + let [headers] = data; + // Walk over the headers/colums in reverse order, as the newest version + // is at the end, but in the UI we want it at the top of the chart legend. + + range(headers.length - 1, 0, -1).forEach((dataCol, i) => { + // Set the number format for the colum in the data table. + numberFormatWhole.format(myData, dataCol); + columns.push(dataCol); // add the column itself + columns.push({ + // add a 'calculated' column, the moving average + type: 'number', + label: `${headers[dataCol]} ${days}-day avg.`, + calc: moving_avg_func_for_col(dataCol), + }); + // Note: while the columns start with index 1 (because 0 is the time + // axis), the series configuration starts with index 0. + seriesOption[i * 2] = { + type: 'scatter', + color: COLORS[i % COLORS.length], + pointSize: 3, + pointShape: 'square', + }; + seriesOption[i * 2 + 1] = { + type: 'area', + color: COLORS[i % COLORS.length], + lineWidth: 2, + curveType: 'function', + visibleInLegend: false, + }; + }); + view.setColumns(columns); + + let chart = new window.google.visualization.ComboChart(this.element); + chart.draw(view, { + chartArea: { left: 85, width: '77%', height: '80%' }, + hAxis: { + minorGridlines: { count: 8 }, + }, + vAxis: { + minorGridlines: { count: 5 }, + viewWindow: { min: 0 }, + }, + isStacked: true, + focusTarget: 'category', + seriesType: 'scatter', + series: seriesOption, + }); + }, }); function range(start, end, step) { - let array = []; - for (let i = start; i !== end; i += step) { - array.push(i); - } - return array; + let array = []; + for (let i = start; i !== end; i += step) { + array.push(i); + } + return array; } diff --git a/app/components/email-input.js b/app/components/email-input.js index 0c95afdae2e..641f6434c8b 100644 --- a/app/components/email-input.js +++ b/app/components/email-input.js @@ -5,108 +5,109 @@ import { inject as service } from '@ember/service'; import ajax from 'ember-fetch/ajax'; export default Component.extend({ - flashMessages: service(), + flashMessages: service(), - type: '', - value: '', - isEditing: false, - user: null, - disableSave: empty('user.email'), - notValidEmail: false, - prevEmail: '', - emailIsNull: computed('user.email', function() { - let email = this.get('user.email'); - return email == null; - }), - emailNotVerified: computed('user.{email,email_verified}', function() { - let email = this.get('user.email'); - let verified = this.get('user.email_verified'); + type: '', + value: '', + isEditing: false, + user: null, + disableSave: empty('user.email'), + notValidEmail: false, + prevEmail: '', + emailIsNull: computed('user.email', function() { + let email = this.get('user.email'); + return email == null; + }), + emailNotVerified: computed('user.{email,email_verified}', function() { + let email = this.get('user.email'); + let verified = this.get('user.email_verified'); - return email != null && !verified; - }), - isError: false, - emailError: '', - disableResend: false, - resendButtonText: computed('disableResend', 'user.email_verification_sent', function() { - if (this.disableResend) { - return 'Sent!'; - } else if (this.get('user.email_verification_sent')) { - return 'Resend'; - } else { - return 'Send verification email'; - } - }), + return email != null && !verified; + }), + isError: false, + emailError: '', + disableResend: false, + resendButtonText: computed('disableResend', 'user.email_verification_sent', function() { + if (this.disableResend) { + return 'Sent!'; + } else if (this.get('user.email_verification_sent')) { + return 'Resend'; + } else { + return 'Send verification email'; + } + }), - actions: { - editEmail() { - let email = this.value; - let isEmailNull = function(email) { - return email == null; - }; + actions: { + editEmail() { + let email = this.value; + let isEmailNull = function(email) { + return email == null; + }; - this.set('emailIsNull', isEmailNull(email)); - this.set('isEditing', true); - this.set('prevEmail', this.value); - }, + this.set('emailIsNull', isEmailNull(email)); + this.set('isEditing', true); + this.set('prevEmail', this.value); + }, - saveEmail() { - let userEmail = this.value; - let user = this.user; + saveEmail() { + let userEmail = this.value; + let user = this.user; - let emailIsProperFormat = function(userEmail) { - let regExp = /^\S+@\S+\.\S+$/; - return regExp.test(userEmail); - }; + let emailIsProperFormat = function(userEmail) { + let regExp = /^\S+@\S+\.\S+$/; + return regExp.test(userEmail); + }; - if (!emailIsProperFormat(userEmail)) { - this.set('notValidEmail', true); - return; - } + if (!emailIsProperFormat(userEmail)) { + this.set('notValidEmail', true); + return; + } - user.set('email', userEmail); - user.save() - .then(() => { - this.set('serverError', null); - this.set('user.email_verification_sent', true); - this.set('user.email_verified', false); - }) - .catch(err => { - let msg; - if (err.errors && err.errors[0] && err.errors[0].detail) { - msg = `An error occurred while saving this email, ${err.errors[0].detail}`; - } else { - msg = 'An unknown error occurred while saving this email.'; - } - this.set('serverError', msg); - this.set('isError', true); - this.set('emailError', `Error in saving email: ${msg}`); - }); + user.set('email', userEmail); + user + .save() + .then(() => { + this.set('serverError', null); + this.set('user.email_verification_sent', true); + this.set('user.email_verified', false); + }) + .catch(err => { + let msg; + if (err.errors && err.errors[0] && err.errors[0].detail) { + msg = `An error occurred while saving this email, ${err.errors[0].detail}`; + } else { + msg = 'An unknown error occurred while saving this email.'; + } + this.set('serverError', msg); + this.set('isError', true); + this.set('emailError', `Error in saving email: ${msg}`); + }); - this.set('isEditing', false); - this.set('notValidEmail', false); - this.set('disableResend', false); - }, + this.set('isEditing', false); + this.set('notValidEmail', false); + this.set('disableResend', false); + }, - cancelEdit() { - this.set('isEditing', false); - this.set('value', this.prevEmail); - }, + cancelEdit() { + this.set('isEditing', false); + this.set('value', this.prevEmail); + }, - async resendEmail() { - let user = this.user; + async resendEmail() { + let user = this.user; - try { - await ajax(`/api/v1/users/${user.id}/resend`, { method: 'PUT' }); - this.set('disableResend', true); - } catch (error) { - if (error.payload) { - this.set('isError', true); - this.set('emailError', `Error in resending message: ${error.payload.errors[0].detail}`); - } else { - this.set('isError', true); - this.set('emailError', 'Unknown error in resending message'); - } - } - }, + try { + await ajax(`/api/v1/users/${user.id}/resend`, { method: 'PUT' }); + this.set('disableResend', true); + } catch (error) { + if (error.payload) { + this.set('isError', true); + this.set('emailError', `Error in resending message: ${error.payload.errors[0].detail}`); + } else { + this.set('isError', true); + this.set('emailError', 'Unknown error in resending message'); + } + } }, + }, }); diff --git a/app/components/flash-message.js b/app/components/flash-message.js index 27567632a98..ef807af025a 100644 --- a/app/components/flash-message.js +++ b/app/components/flash-message.js @@ -3,10 +3,10 @@ import { readOnly } from '@ember/object/computed'; import { inject as service } from '@ember/service'; export default Component.extend({ - flashMessages: service(), - message: readOnly('flashMessages.message'), + flashMessages: service(), + message: readOnly('flashMessages.message'), - elementId: 'flash', - tagName: 'p', - classNameBindings: ['message:shown'], + elementId: 'flash', + tagName: 'p', + classNameBindings: ['message:shown'], }); diff --git a/app/components/google-jsapi.js b/app/components/google-jsapi.js index db35067b8ab..50feacf7e41 100644 --- a/app/components/google-jsapi.js +++ b/app/components/google-jsapi.js @@ -1,26 +1,26 @@ import Component from '@ember/component'; function createEvent(name) { - let event = document.createEvent('Event'); - event.initEvent(name, true, true); - return event; + let event = document.createEvent('Event'); + event.initEvent(name, true, true); + return event; } export default Component.extend({ - tagName: '', + tagName: '', - didInsertElement() { - let script = document.createElement('script'); - script.onload = () => { - window.google.load('visualization', '1.0', { - packages: ['corechart'], - callback() { - window.googleChartsLoaded = true; - document.dispatchEvent(createEvent('googleChartsLoaded')); - }, - }); - }; - document.body.appendChild(script); - script.src = 'https://www.google.com/jsapi'; - }, + didInsertElement() { + let script = document.createElement('script'); + script.onload = () => { + window.google.load('visualization', '1.0', { + packages: ['corechart'], + callback() { + window.googleChartsLoaded = true; + document.dispatchEvent(createEvent('googleChartsLoaded')); + }, + }); + }; + document.body.appendChild(script); + script.src = 'https://www.google.com/jsapi'; + }, }); diff --git a/app/components/pending-owner-invite-row.js b/app/components/pending-owner-invite-row.js index c330822d0b3..0fe78fc1cfa 100644 --- a/app/components/pending-owner-invite-row.js +++ b/app/components/pending-owner-invite-row.js @@ -1,42 +1,42 @@ import Component from '@ember/component'; export default Component.extend({ - isAccepted: false, - isDeclined: false, - isError: false, - inviteError: 'default error message', + isAccepted: false, + isDeclined: false, + isError: false, + inviteError: 'default error message', - actions: { - async acceptInvitation(invite) { - invite.set('accepted', true); + actions: { + async acceptInvitation(invite) { + invite.set('accepted', true); - try { - await invite.save(); - this.set('isAccepted', true); - } catch (error) { - this.set('isError', true); - if (error.payload) { - this.set('inviteError', `Error in accepting invite: ${error.payload.errors[0].detail}`); - } else { - this.set('inviteError', 'Error in accepting invite'); - } - } - }, + try { + await invite.save(); + this.set('isAccepted', true); + } catch (error) { + this.set('isError', true); + if (error.payload) { + this.set('inviteError', `Error in accepting invite: ${error.payload.errors[0].detail}`); + } else { + this.set('inviteError', 'Error in accepting invite'); + } + } + }, - async declineInvitation(invite) { - invite.set('accepted', false); + async declineInvitation(invite) { + invite.set('accepted', false); - try { - await invite.save(); - this.set('isDeclined', true); - } catch (error) { - this.set('isError', true); - if (error.payload) { - this.set('inviteError', `Error in declining invite: ${error.payload.errors[0].detail}`); - } else { - this.set('inviteError', 'Error in declining invite'); - } - } - }, + try { + await invite.save(); + this.set('isDeclined', true); + } catch (error) { + this.set('isError', true); + if (error.payload) { + this.set('inviteError', `Error in declining invite: ${error.payload.errors[0].detail}`); + } else { + this.set('inviteError', 'Error in declining invite'); + } + } }, + }, }); diff --git a/app/components/rl-dropdown-container.js b/app/components/rl-dropdown-container.js index e12592c5384..909d64a8b78 100644 --- a/app/components/rl-dropdown-container.js +++ b/app/components/rl-dropdown-container.js @@ -3,5 +3,5 @@ import Component from '@ember/component'; import DropdownComponentMixin from '../mixins/rl-dropdown-component'; export default Component.extend(DropdownComponentMixin, { - classNameBindings: ['dropdownExpanded'], + classNameBindings: ['dropdownExpanded'], }); diff --git a/app/components/rl-dropdown-toggle.js b/app/components/rl-dropdown-toggle.js index 049f3f4235c..380db2f7846 100644 --- a/app/components/rl-dropdown-toggle.js +++ b/app/components/rl-dropdown-toggle.js @@ -4,39 +4,39 @@ import { computed } from '@ember/object'; import RlDropdownContainer from './rl-dropdown-container'; export default Component.extend({ - classNames: ['rl-dropdown-toggle'], + classNames: ['rl-dropdown-toggle'], - tagName: 'button', + tagName: 'button', - attributeBindings: ['type', 'role', 'disabled'], + attributeBindings: ['type', 'role', 'disabled'], - type: computed('tagName', function() { - return this.tagName === 'button' ? 'button' : null; - }), + type: computed('tagName', function() { + return this.tagName === 'button' ? 'button' : null; + }), - role: computed('tagName', function() { - return this.tagName === 'a' ? 'button' : null; - }), + role: computed('tagName', function() { + return this.tagName === 'a' ? 'button' : null; + }), - dropdownContainer: computed(function() { - return this.nearestOfType(RlDropdownContainer); - }), + dropdownContainer: computed(function() { + return this.nearestOfType(RlDropdownContainer); + }), - action: 'toggleDropdown', + action: 'toggleDropdown', - propagateClicks: true, + propagateClicks: true, - disabled: false, + disabled: false, - click(event) { - if (!this.disabled) { - let propagateClicks = this.propagateClicks; + click(event) { + if (!this.disabled) { + let propagateClicks = this.propagateClicks; - this.dropdownContainer.send(this.action); + this.dropdownContainer.send(this.action); - if (propagateClicks === false || propagateClicks === 'false') { - event.stopPropagation(); - } - } - }, + if (propagateClicks === false || propagateClicks === 'false') { + event.stopPropagation(); + } + } + }, }); diff --git a/app/components/rl-dropdown.js b/app/components/rl-dropdown.js index 2c6934290b3..be9b398f7a7 100644 --- a/app/components/rl-dropdown.js +++ b/app/components/rl-dropdown.js @@ -6,35 +6,35 @@ import $ from 'jquery'; import RlDropdownContainer from './rl-dropdown-container'; export default Component.extend({ - classNames: ['rl-dropdown'], - classNameBindings: ['isExpanded:open'], + classNames: ['rl-dropdown'], + classNameBindings: ['isExpanded:open'], - dropdownContainer: computed(function() { - return this.nearestOfType(RlDropdownContainer); - }), + dropdownContainer: computed(function() { + return this.nearestOfType(RlDropdownContainer); + }), - isExpanded: alias('dropdownContainer.dropdownExpanded'), + isExpanded: alias('dropdownContainer.dropdownExpanded'), - closeOnChildClick: false, + closeOnChildClick: false, - propagateClicks: true, + propagateClicks: true, - click(event) { - let closeOnChildClick = this.closeOnChildClick; - let propagateClicks = this.propagateClicks; - let $target = $(event.target); - let $c = this.$(); + click(event) { + let closeOnChildClick = this.closeOnChildClick; + let propagateClicks = this.propagateClicks; + let $target = $(event.target); + let $c = this.$(); - if ($target !== $c) { - if ((closeOnChildClick === true || closeOnChildClick === 'true') && $target.closest($c).length) { - this.set('isExpanded', false); - } else if (closeOnChildClick && $target.closest(closeOnChildClick, $c).length) { - this.set('isExpanded', false); - } - } + if ($target !== $c) { + if ((closeOnChildClick === true || closeOnChildClick === 'true') && $target.closest($c).length) { + this.set('isExpanded', false); + } else if (closeOnChildClick && $target.closest(closeOnChildClick, $c).length) { + this.set('isExpanded', false); + } + } - if (propagateClicks === false || propagateClicks === 'false') { - event.stopPropagation(); - } - }, + if (propagateClicks === false || propagateClicks === 'false') { + event.stopPropagation(); + } + }, }); diff --git a/app/components/user-avatar.js b/app/components/user-avatar.js index ee6b8249b56..ef98e9af231 100644 --- a/app/components/user-avatar.js +++ b/app/components/user-avatar.js @@ -3,28 +3,28 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; export default Component.extend({ - size: 'small', - user: null, - attributeBindings: ['src', 'width', 'height', 'alt'], - tagName: 'img', + size: 'small', + user: null, + attributeBindings: ['src', 'width', 'height', 'alt'], + tagName: 'img', - width: computed('size', function() { - if (this.size === 'small') { - return 22; - } else if (this.size === 'medium-small') { - return 32; - } else { - return 85; // medium - } - }), + width: computed('size', function() { + if (this.size === 'small') { + return 22; + } else if (this.size === 'medium-small') { + return 32; + } else { + return 85; // medium + } + }), - height: readOnly('width'), + height: readOnly('width'), - alt: computed('user', function() { - return `${this.get('user.name')} (${this.get('user.login')})`; - }), + alt: computed('user', function() { + return `${this.get('user.name')} (${this.get('user.login')})`; + }), - src: computed('size', 'user', function() { - return `${this.get('user.avatar')}&s=${this.width * 2}`; - }), + src: computed('size', 'user', function() { + return `${this.get('user.avatar')}&s=${this.width * 2}`; + }), }); diff --git a/app/components/user-link.js b/app/components/user-link.js index 814fbb7f6f7..37cfd84baea 100644 --- a/app/components/user-link.js +++ b/app/components/user-link.js @@ -2,13 +2,13 @@ import { readOnly } from '@ember/object/computed'; import Component from '@ember/component'; export default Component.extend({ - user: null, - attributeBindings: ['title', 'href'], - tagName: 'a', + user: null, + attributeBindings: ['title', 'href'], + tagName: 'a', - title: readOnly('user.login'), + title: readOnly('user.login'), - // TODO replace this with a link to a native crates.io profile - // page when they exist. - href: readOnly('user.url'), + // TODO replace this with a link to a native crates.io profile + // page when they exist. + href: readOnly('user.url'), }); diff --git a/app/components/validated-input.js b/app/components/validated-input.js index bdea206ce91..f40807b8f63 100644 --- a/app/components/validated-input.js +++ b/app/components/validated-input.js @@ -3,36 +3,36 @@ import Component from '@ember/component'; import { defineProperty } from '@ember/object'; export default Component.extend({ - classNames: ['validated-input'], - classNameBindings: ['showErrorClass:has-error', 'isValid:has-success'], - model: null, - value: null, - type: 'text', - valuePath: '', - placeholder: '', - validation: null, - showValidations: false, - didValidate: false, + classNames: ['validated-input'], + classNameBindings: ['showErrorClass:has-error', 'isValid:has-success'], + model: null, + value: null, + type: 'text', + valuePath: '', + placeholder: '', + validation: null, + showValidations: false, + didValidate: false, - notValidating: not('validation.isValidating').readOnly(), - hasContent: notEmpty('value').readOnly(), - hasWarnings: notEmpty('validation.warnings').readOnly(), - isValid: and('hasContent', 'validation.isTruelyValid').readOnly(), - shouldDisplayValidations: or('showValidations', 'didValidate', 'hasContent').readOnly(), + notValidating: not('validation.isValidating').readOnly(), + hasContent: notEmpty('value').readOnly(), + hasWarnings: notEmpty('validation.warnings').readOnly(), + isValid: and('hasContent', 'validation.isTruelyValid').readOnly(), + shouldDisplayValidations: or('showValidations', 'didValidate', 'hasContent').readOnly(), - showErrorClass: and('notValidating', 'showErrorMessage', 'hasContent', 'validation').readOnly(), - showErrorMessage: and('shouldDisplayValidations', 'validation.isInvalid').readOnly(), + showErrorClass: and('notValidating', 'showErrorMessage', 'hasContent', 'validation').readOnly(), + showErrorMessage: and('shouldDisplayValidations', 'validation.isInvalid').readOnly(), - init() { - this._super(...arguments); - let valuePath = this.valuePath; + init() { + this._super(...arguments); + let valuePath = this.valuePath; - defineProperty(this, 'validation', readOnly(`model.validations.attrs.${valuePath}`)); - defineProperty(this, 'value', alias(`model.${valuePath}`)); - }, + defineProperty(this, 'validation', readOnly(`model.validations.attrs.${valuePath}`)); + defineProperty(this, 'value', alias(`model.${valuePath}`)); + }, - focusOut() { - this._super(...arguments); - this.set('showValidations', true); - }, + focusOut() { + this._super(...arguments); + this.set('showValidations', true); + }, }); diff --git a/app/controllers/application.js b/app/controllers/application.js index f7ccf93eaf4..8d8216d7424 100644 --- a/app/controllers/application.js +++ b/app/controllers/application.js @@ -5,31 +5,31 @@ import { EKMixin, keyDown, keyPress } from 'ember-keyboard'; import { on } from '@ember/object/evented'; export default Controller.extend(EKMixin, { - search: service(), - searchQuery: oneWay('search.q'), - session: service(), + search: service(), + searchQuery: oneWay('search.q'), + session: service(), - keyboardActivated: true, + keyboardActivated: true, - focusSearch: on(keyDown('KeyS'), keyPress('KeyS'), keyDown('shift+KeyS'), function(event) { - if (event.ctrlKey || event.altKey || event.metaKey) { - return; - } + focusSearch: on(keyDown('KeyS'), keyPress('KeyS'), keyDown('shift+KeyS'), function(event) { + if (event.ctrlKey || event.altKey || event.metaKey) { + return; + } - if (document.activeElement === document.body) { - event.preventDefault(); - document.querySelector('#cargo-desktop-search').focus(); - } - }), + if (document.activeElement === document.body) { + event.preventDefault(); + document.querySelector('#cargo-desktop-search').focus(); + } + }), - actions: { - search() { - this.transitionToRoute('search', { - queryParams: { - q: this.searchQuery, - page: 1, - }, - }); + actions: { + search() { + this.transitionToRoute('search', { + queryParams: { + q: this.searchQuery, + page: 1, }, + }); }, + }, }); diff --git a/app/controllers/catch-all.js b/app/controllers/catch-all.js index 4e5ecb1f2b9..2005430f146 100644 --- a/app/controllers/catch-all.js +++ b/app/controllers/catch-all.js @@ -1,9 +1,9 @@ import Controller from '@ember/controller'; export default Controller.extend({ - actions: { - search(query) { - return this.transitionToRoute('search', { queryParams: { q: query } }); - }, + actions: { + search(query) { + return this.transitionToRoute('search', { queryParams: { q: query } }); }, + }, }); diff --git a/app/controllers/categories.js b/app/controllers/categories.js index 56ce1b6feb2..625c2e9529d 100644 --- a/app/controllers/categories.js +++ b/app/controllers/categories.js @@ -5,14 +5,14 @@ import { computed } from '@ember/object'; import PaginationMixin from '../mixins/pagination'; export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page', 'sort'], - page: '1', - per_page: 100, - sort: 'alpha', + queryParams: ['page', 'per_page', 'sort'], + page: '1', + per_page: 100, + sort: 'alpha', - totalItems: readOnly('model.meta.total'), + totalItems: readOnly('model.meta.total'), - currentSortBy: computed('sort', function() { - return this.sort === 'crates' ? '# Crates' : 'Alphabetical'; - }), + currentSortBy: computed('sort', function() { + return this.sort === 'crates' ? '# Crates' : 'Alphabetical'; + }), }); diff --git a/app/controllers/category/index.js b/app/controllers/category/index.js index 2e4d091ac1a..b74e744555b 100644 --- a/app/controllers/category/index.js +++ b/app/controllers/category/index.js @@ -5,24 +5,24 @@ import { computed } from '@ember/object'; import PaginationMixin from '../../mixins/pagination'; export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page', 'sort'], - page: '1', - per_page: 10, - sort: 'recent-downloads', + queryParams: ['page', 'per_page', 'sort'], + page: '1', + per_page: 10, + sort: 'recent-downloads', - totalItems: readOnly('model.meta.total'), + totalItems: readOnly('model.meta.total'), - category: null, + category: null, - currentSortBy: computed('sort', function() { - if (this.sort === 'downloads') { - return 'All-Time Downloads'; - } else if (this.sort === 'alpha') { - return 'Alphabetical'; - } else if (this.get('sort') === 'recent-updates') { - return 'Recent Updates'; - } else { - return 'Recent Downloads'; - } - }), + currentSortBy: computed('sort', function() { + if (this.sort === 'downloads') { + return 'All-Time Downloads'; + } else if (this.sort === 'alpha') { + return 'Alphabetical'; + } else if (this.get('sort') === 'recent-updates') { + return 'Recent Updates'; + } else { + return 'Recent Downloads'; + } + }), }); diff --git a/app/controllers/crate/owners.js b/app/controllers/crate/owners.js index bfdab8da2c6..3f56a4d472f 100644 --- a/app/controllers/crate/owners.js +++ b/app/controllers/crate/owners.js @@ -1,51 +1,51 @@ import Controller from '@ember/controller'; export default Controller.extend({ - crate: null, - error: false, - invited: false, - removed: false, - username: '', - - actions: { - async addOwner() { - this.set('error', false); - this.set('invited', false); - - const username = this.username; - - if (!username) { - this.set('error', 'Please enter a username'); - return false; - } - - try { - await this.crate.inviteOwner(username); - this.set('invited', `An invite has been sent to ${username}`); - } catch (error) { - if (error.payload) { - this.set('error', `Error sending invite: ${error.payload.errors[0].detail}`); - } else { - this.set('error', 'Error sending invite'); - } - } - }, - - async removeOwner(user) { - this.set('removed', false); - - try { - await this.crate.removeOwner(user.get('login')); - this.set('removed', `User ${user.get('login')} removed as crate owner`); - - this.get('crate.owner_user').removeObject(user); - } catch (error) { - if (error.payload) { - this.set('removed', `Error removing owner: ${error.payload.errors[0].detail}`); - } else { - this.set('removed', 'Error removing owner'); - } - } - }, + crate: null, + error: false, + invited: false, + removed: false, + username: '', + + actions: { + async addOwner() { + this.set('error', false); + this.set('invited', false); + + const username = this.username; + + if (!username) { + this.set('error', 'Please enter a username'); + return false; + } + + try { + await this.crate.inviteOwner(username); + this.set('invited', `An invite has been sent to ${username}`); + } catch (error) { + if (error.payload) { + this.set('error', `Error sending invite: ${error.payload.errors[0].detail}`); + } else { + this.set('error', 'Error sending invite'); + } + } }, + + async removeOwner(user) { + this.set('removed', false); + + try { + await this.crate.removeOwner(user.get('login')); + this.set('removed', `User ${user.get('login')} removed as crate owner`); + + this.get('crate.owner_user').removeObject(user); + } catch (error) { + if (error.payload) { + this.set('removed', `Error removing owner: ${error.payload.errors[0].detail}`); + } else { + this.set('removed', 'Error removing owner'); + } + } + }, + }, }); diff --git a/app/controllers/crate/reverse-dependencies.js b/app/controllers/crate/reverse-dependencies.js index cc668f1f0ef..ab3aafb5a9c 100644 --- a/app/controllers/crate/reverse-dependencies.js +++ b/app/controllers/crate/reverse-dependencies.js @@ -4,10 +4,10 @@ import { readOnly } from '@ember/object/computed'; import PaginationMixin from '../../mixins/pagination'; export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page'], - page: '1', - per_page: 10, - crate: null, + queryParams: ['page', 'per_page'], + page: '1', + per_page: 10, + crate: null, - totalItems: readOnly('model.meta.total'), + totalItems: readOnly('model.meta.total'), }); diff --git a/app/controllers/crate/version.js b/app/controllers/crate/version.js index 5aefab120dc..685cd18110c 100644 --- a/app/controllers/crate/version.js +++ b/app/controllers/crate/version.js @@ -12,190 +12,188 @@ const NUM_VERSIONS = 5; const PromiseArray = ArrayProxy.extend(PromiseProxyMixin); export default Controller.extend({ - session: service(), - - isDownloading: false, - - downloadsContext: computed('requestedVersion', 'model', 'crate', function() { - return this.requestedVersion ? this.model : this.crate; - }), - downloads: alias('downloadsContext.version_downloads'), - extraDownloads: alias('downloads.content.meta.extra_downloads'), - - fetchingFollowing: true, - following: false, - currentVersion: alias('model'), - requestedVersion: null, - keywords: alias('crate.keywords'), - categories: alias('crate.categories'), - badges: alias('crate.badges'), - isOwner: computed('crate.owner_user', 'session.currentUser.id', function() { - return this.get('crate.owner_user').findBy('id', this.get('session.currentUser.id')); - }), - notYankedOrIsOwner: computed('model', 'crate.owner_user', 'session.currentUser.id', function() { - return ( - !this.get('model').yanked || this.get('crate.owner_user').findBy('id', this.get('session.currentUser.id')) - ); - }), - - sortedVersions: readOnly('crate.versions'), - - smallSortedVersions: computed('sortedVersions', function() { - return this.sortedVersions.slice(0, NUM_VERSIONS); - }), - - hasMoreVersions: gt('sortedVersions.length', NUM_VERSIONS), - - displayedAuthors: computed('currentVersion.authors.[]', function() { - return PromiseArray.create({ - promise: this.get('currentVersion.authors').then(authors => { - let ret = authors.slice(); - let others = authors.get('meta'); - for (let i = 0; i < others.names.length; i++) { - ret.push({ name: others.names[i] }); - } - return ret; - }), - }); - }), - - anyKeywords: gt('keywords.length', 0), - anyCategories: gt('categories.length', 0), - - currentDependencies: computed('currentVersion.dependencies', function() { - let deps = this.get('currentVersion.dependencies'); - - if (deps === null) { - return []; + session: service(), + + isDownloading: false, + + downloadsContext: computed('requestedVersion', 'model', 'crate', function() { + return this.requestedVersion ? this.model : this.crate; + }), + downloads: alias('downloadsContext.version_downloads'), + extraDownloads: alias('downloads.content.meta.extra_downloads'), + + fetchingFollowing: true, + following: false, + currentVersion: alias('model'), + requestedVersion: null, + keywords: alias('crate.keywords'), + categories: alias('crate.categories'), + badges: alias('crate.badges'), + isOwner: computed('crate.owner_user', 'session.currentUser.id', function() { + return this.get('crate.owner_user').findBy('id', this.get('session.currentUser.id')); + }), + notYankedOrIsOwner: computed('model', 'crate.owner_user', 'session.currentUser.id', function() { + return !this.get('model').yanked || this.get('crate.owner_user').findBy('id', this.get('session.currentUser.id')); + }), + + sortedVersions: readOnly('crate.versions'), + + smallSortedVersions: computed('sortedVersions', function() { + return this.sortedVersions.slice(0, NUM_VERSIONS); + }), + + hasMoreVersions: gt('sortedVersions.length', NUM_VERSIONS), + + displayedAuthors: computed('currentVersion.authors.[]', function() { + return PromiseArray.create({ + promise: this.get('currentVersion.authors').then(authors => { + let ret = authors.slice(); + let others = authors.get('meta'); + for (let i = 0; i < others.names.length; i++) { + ret.push({ name: others.names[i] }); } - - return PromiseArray.create({ - promise: deps.then(deps => { - return deps.filter(dep => dep.get('kind') !== 'dev').uniqBy('crate_id'); - }), - }); - }), - - currentDevDependencies: computed('currentVersion.dependencies', function() { - let deps = this.get('currentVersion.dependencies'); - if (deps === null) { - return []; - } - return PromiseArray.create({ - promise: deps.then(deps => { - return deps.filterBy('kind', 'dev'); - }), - }); - }), - - downloadData: computed('downloads', 'extraDownloads', 'requestedVersion', function() { - let downloads = this.downloads; - if (!downloads) { - return; - } - - let extra = this.extraDownloads || []; - - let dates = {}; - let versions = []; - for (let i = 0; i < 90; i++) { - let now = moment().subtract(i, 'days'); - dates[now.format('MMM D')] = { date: now, cnt: {} }; - } - - downloads.forEach(d => { - let version_id = d.get('version.id'); - let key = moment(d.get('date')) - .utc() - .format('MMM D'); - if (dates[key]) { - let prev = dates[key].cnt[version_id] || 0; - dates[key].cnt[version_id] = prev + d.get('downloads'); - } - }); - - extra.forEach(d => { - let key = moment(d.date) - .utc() - .format('MMM D'); - if (dates[key]) { - let prev = dates[key].cnt[null] || 0; - dates[key].cnt[null] = prev + d.downloads; - } - }); - if (this.requestedVersion) { - versions.push(this.model.getProperties('id', 'num')); - } else { - this.smallSortedVersions.forEach(version => { - versions.push(version.getProperties('id', 'num')); - }); - } - if (extra.length > 0) { - versions.push({ - id: null, - num: 'Other', - }); - } - - let headers = ['Date']; - versions.sort(b => b.num).reverse(); - for (let i = 0; i < versions.length; i++) { - headers.push(versions[i].num); - } - let data = [headers]; - for (let date in dates) { - let row = [dates[date].date.toDate()]; - for (let i = 0; i < versions.length; i++) { - row.push(dates[date].cnt[versions[i].id] || 0); - } - data.push(row); - } - - return data; - }), - - toggleClipboardProps(isSuccess) { - this.setProperties({ - showSuccess: isSuccess, - showNotification: true, - }); - later( - this, - () => { - this.set('showNotification', false); - }, - 2000, - ); + return ret; + }), + }); + }), + + anyKeywords: gt('keywords.length', 0), + anyCategories: gt('categories.length', 0), + + currentDependencies: computed('currentVersion.dependencies', function() { + let deps = this.get('currentVersion.dependencies'); + + if (deps === null) { + return []; + } + + return PromiseArray.create({ + promise: deps.then(deps => { + return deps.filter(dep => dep.get('kind') !== 'dev').uniqBy('crate_id'); + }), + }); + }), + + currentDevDependencies: computed('currentVersion.dependencies', function() { + let deps = this.get('currentVersion.dependencies'); + if (deps === null) { + return []; + } + return PromiseArray.create({ + promise: deps.then(deps => { + return deps.filterBy('kind', 'dev'); + }), + }); + }), + + downloadData: computed('downloads', 'extraDownloads', 'requestedVersion', function() { + let downloads = this.downloads; + if (!downloads) { + return; + } + + let extra = this.extraDownloads || []; + + let dates = {}; + let versions = []; + for (let i = 0; i < 90; i++) { + let now = moment().subtract(i, 'days'); + dates[now.format('MMM D')] = { date: now, cnt: {} }; + } + + downloads.forEach(d => { + let version_id = d.get('version.id'); + let key = moment(d.get('date')) + .utc() + .format('MMM D'); + if (dates[key]) { + let prev = dates[key].cnt[version_id] || 0; + dates[key].cnt[version_id] = prev + d.get('downloads'); + } + }); + + extra.forEach(d => { + let key = moment(d.date) + .utc() + .format('MMM D'); + if (dates[key]) { + let prev = dates[key].cnt[null] || 0; + dates[key].cnt[null] = prev + d.downloads; + } + }); + if (this.requestedVersion) { + versions.push(this.model.getProperties('id', 'num')); + } else { + this.smallSortedVersions.forEach(version => { + versions.push(version.getProperties('id', 'num')); + }); + } + if (extra.length > 0) { + versions.push({ + id: null, + num: 'Other', + }); + } + + let headers = ['Date']; + versions.sort(b => b.num).reverse(); + for (let i = 0; i < versions.length; i++) { + headers.push(versions[i].num); + } + let data = [headers]; + for (let date in dates) { + let row = [dates[date].date.toDate()]; + for (let i = 0; i < versions.length; i++) { + row.push(dates[date].cnt[versions[i].id] || 0); + } + data.push(row); + } + + return data; + }), + + toggleClipboardProps(isSuccess) { + this.setProperties({ + showSuccess: isSuccess, + showNotification: true, + }); + later( + this, + () => { + this.set('showNotification', false); + }, + 2000, + ); + }, + + actions: { + copySuccess(event) { + event.clearSelection(); + this.toggleClipboardProps(true); }, - actions: { - copySuccess(event) { - event.clearSelection(); - this.toggleClipboardProps(true); - }, - - copyError() { - this.toggleClipboardProps(false); - }, + copyError() { + this.toggleClipboardProps(false); + }, - toggleFollow() { - this.set('fetchingFollowing', true); + toggleFollow() { + this.set('fetchingFollowing', true); - let crate = this.crate; - let op = this.toggleProperty('following') ? crate.follow() : crate.unfollow(); + let crate = this.crate; + let op = this.toggleProperty('following') ? crate.follow() : crate.unfollow(); - return op.finally(() => this.set('fetchingFollowing', false)); - }, + return op.finally(() => this.set('fetchingFollowing', false)); }, - - report: observer('crate.readme', function() { - if (typeof document === 'undefined') { - return; - } - setTimeout(() => { - let e = document.createEvent('CustomEvent'); - e.initCustomEvent('hashchange', true, true); - window.dispatchEvent(e); - }); - }), + }, + + report: observer('crate.readme', function() { + if (typeof document === 'undefined') { + return; + } + setTimeout(() => { + let e = document.createEvent('CustomEvent'); + e.initCustomEvent('hashchange', true, true); + window.dispatchEvent(e); + }); + }), }); diff --git a/app/controllers/crates.js b/app/controllers/crates.js index dbfc0e8ff74..e07b3662aba 100644 --- a/app/controllers/crates.js +++ b/app/controllers/crates.js @@ -5,24 +5,24 @@ import { computed } from '@ember/object'; import PaginationMixin from '../mixins/pagination'; export default Controller.extend(PaginationMixin, { - queryParams: ['letter', 'page', 'per_page', 'sort'], - letter: null, - page: '1', - per_page: 10, - sort: 'alpha', - alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), + queryParams: ['letter', 'page', 'per_page', 'sort'], + letter: null, + page: '1', + per_page: 10, + sort: 'alpha', + alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), - totalItems: readOnly('model.meta.total'), + totalItems: readOnly('model.meta.total'), - currentSortBy: computed('sort', function() { - if (this.sort === 'downloads') { - return 'All-Time Downloads'; - } else if (this.sort === 'recent-downloads') { - return 'Recent Downloads'; - } else if (this.get('sort') === 'recent-updates') { - return 'Recent Updates'; - } else { - return 'Alphabetical'; - } - }), + currentSortBy: computed('sort', function() { + if (this.sort === 'downloads') { + return 'All-Time Downloads'; + } else if (this.sort === 'recent-downloads') { + return 'Recent Downloads'; + } else if (this.get('sort') === 'recent-updates') { + return 'Recent Updates'; + } else { + return 'Alphabetical'; + } + }), }); diff --git a/app/controllers/dashboard.js b/app/controllers/dashboard.js index 12bc169d9a7..81b6fbfb9b6 100644 --- a/app/controllers/dashboard.js +++ b/app/controllers/dashboard.js @@ -6,51 +6,51 @@ import ajax from 'ember-fetch/ajax'; const TO_SHOW = 5; export default Controller.extend({ - init() { - this._super(...arguments); - - this.loadingMore = false; - this.hasMore = false; - this.myCrates = A(); - this.myFollowing = A(); - this.myFeed = A(); - this.myStats = 0; - }, - - visibleCrates: computed('myCrates.[]', function() { - return this.myCrates.slice(0, TO_SHOW); - }), - - visibleFollowing: computed('myFollowing.[]', function() { - return this.myFollowing.slice(0, TO_SHOW); - }), - - visibleStats: computed('myStats', function() { - return this.myStats; - }), - - hasMoreCrates: computed('myCrates.[]', function() { - return this.get('myCrates.length') > TO_SHOW; - }), - - hasMoreFollowing: computed('myFollowing.[]', function() { - return this.get('myFollowing.length') > TO_SHOW; - }), - - actions: { - async loadMore() { - this.set('loadingMore', true); - let page = this.myFeed.length / 10 + 1; - - try { - let data = await ajax(`/api/v1/me/updates?page=${page}`); - let versions = data.versions.map(version => this.store.push(this.store.normalize('version', version))); - - this.myFeed.pushObjects(versions); - this.set('hasMore', data.meta.more); - } finally { - this.set('loadingMore', false); - } - }, + init() { + this._super(...arguments); + + this.loadingMore = false; + this.hasMore = false; + this.myCrates = A(); + this.myFollowing = A(); + this.myFeed = A(); + this.myStats = 0; + }, + + visibleCrates: computed('myCrates.[]', function() { + return this.myCrates.slice(0, TO_SHOW); + }), + + visibleFollowing: computed('myFollowing.[]', function() { + return this.myFollowing.slice(0, TO_SHOW); + }), + + visibleStats: computed('myStats', function() { + return this.myStats; + }), + + hasMoreCrates: computed('myCrates.[]', function() { + return this.get('myCrates.length') > TO_SHOW; + }), + + hasMoreFollowing: computed('myFollowing.[]', function() { + return this.get('myFollowing.length') > TO_SHOW; + }), + + actions: { + async loadMore() { + this.set('loadingMore', true); + let page = this.myFeed.length / 10 + 1; + + try { + let data = await ajax(`/api/v1/me/updates?page=${page}`); + let versions = data.versions.map(version => this.store.push(this.store.normalize('version', version))); + + this.myFeed.pushObjects(versions); + this.set('hasMore', data.meta.more); + } finally { + this.set('loadingMore', false); + } }, + }, }); diff --git a/app/controllers/index.js b/app/controllers/index.js index fc283920743..6d057737714 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -6,26 +6,26 @@ import ajax from 'ember-fetch/ajax'; import { task } from 'ember-concurrency'; export default Controller.extend({ - model: readOnly('dataTask.lastSuccessful.value'), + model: readOnly('dataTask.lastSuccessful.value'), - hasData: computed('dataTask.{lastSuccessful,isRunning}', function() { - return this.get('dataTask.lastSuccessful') || !this.get('dataTask.isRunning'); - }), + hasData: computed('dataTask.{lastSuccessful,isRunning}', function() { + return this.get('dataTask.lastSuccessful') || !this.get('dataTask.isRunning'); + }), - dataTask: task(function*() { - let data = yield ajax('/api/v1/summary'); + dataTask: task(function*() { + let data = yield ajax('/api/v1/summary'); - addCrates(this.store, data.new_crates); - addCrates(this.store, data.most_downloaded); - addCrates(this.store, data.just_updated); - addCrates(this.store, data.most_recently_downloaded); + addCrates(this.store, data.new_crates); + addCrates(this.store, data.most_downloaded); + addCrates(this.store, data.just_updated); + addCrates(this.store, data.most_recently_downloaded); - return data; - }).drop(), + return data; + }).drop(), }); function addCrates(store, crates) { - for (let i = 0; i < crates.length; i++) { - crates[i] = store.push(store.normalize('crate', crates[i])); - } + for (let i = 0; i < crates.length; i++) { + crates[i] = store.push(store.normalize('crate', crates[i])); + } } diff --git a/app/controllers/install.js b/app/controllers/install.js index f57d8814168..7366e369a8f 100644 --- a/app/controllers/install.js +++ b/app/controllers/install.js @@ -1,14 +1,14 @@ import Controller from '@ember/controller'; function link(target) { - return `https://static.rust-lang.org/cargo-dist/cargo-nightly-${target}.tar.gz`; + return `https://static.rust-lang.org/cargo-dist/cargo-nightly-${target}.tar.gz`; } export default Controller.extend({ - linux64: link('x86_64-unknown-linux-gnu'), - linux32: link('i686-unknown-linux-gnu'), - mac64: link('x86_64-apple-darwin'), - mac32: link('i686-apple-darwin'), - win64: link('x86_64-pc-windows-gnu'), - win32: link('i686-pc-windows-gnu'), + linux64: link('x86_64-unknown-linux-gnu'), + linux32: link('i686-unknown-linux-gnu'), + mac64: link('x86_64-apple-darwin'), + mac32: link('i686-apple-darwin'), + win64: link('x86_64-pc-windows-gnu'), + win32: link('i686-pc-windows-gnu'), }); diff --git a/app/controllers/keyword/index.js b/app/controllers/keyword/index.js index aadd8fb66c9..d952fb40812 100644 --- a/app/controllers/keyword/index.js +++ b/app/controllers/keyword/index.js @@ -5,22 +5,22 @@ import { computed } from '@ember/object'; import PaginationMixin from '../../mixins/pagination'; export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page', 'sort'], - page: '1', - per_page: 10, - sort: 'recent-downloads', + queryParams: ['page', 'per_page', 'sort'], + page: '1', + per_page: 10, + sort: 'recent-downloads', - totalItems: readOnly('model.meta.total'), + totalItems: readOnly('model.meta.total'), - currentSortBy: computed('sort', function() { - if (this.sort === 'downloads') { - return 'All-Time Downloads'; - } else if (this.sort === 'alpha') { - return 'Alphabetical'; - } else if (this.get('sort') === 'recent-updates') { - return 'Recent Updates'; - } else { - return 'Recent Downloads'; - } - }), + currentSortBy: computed('sort', function() { + if (this.sort === 'downloads') { + return 'All-Time Downloads'; + } else if (this.sort === 'alpha') { + return 'Alphabetical'; + } else if (this.get('sort') === 'recent-updates') { + return 'Recent Updates'; + } else { + return 'Recent Downloads'; + } + }), }); diff --git a/app/controllers/keywords.js b/app/controllers/keywords.js index a23839aec12..4dec3969e28 100644 --- a/app/controllers/keywords.js +++ b/app/controllers/keywords.js @@ -5,14 +5,14 @@ import { computed } from '@ember/object'; import PaginationMixin from '../mixins/pagination'; export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page', 'sort'], - page: '1', - per_page: 10, - sort: 'crates', + queryParams: ['page', 'per_page', 'sort'], + page: '1', + per_page: 10, + sort: 'crates', - totalItems: readOnly('model.meta.total'), + totalItems: readOnly('model.meta.total'), - currentSortBy: computed('sort', function() { - return this.sort === 'crates' ? '# Crates' : 'Alphabetical'; - }), + currentSortBy: computed('sort', function() { + return this.sort === 'crates' ? '# Crates' : 'Alphabetical'; + }), }); diff --git a/app/controllers/me/crates.js b/app/controllers/me/crates.js index fd9c716d1b8..dc52b917c91 100644 --- a/app/controllers/me/crates.js +++ b/app/controllers/me/crates.js @@ -7,22 +7,22 @@ import PaginationMixin from '../../mixins/pagination'; // TODO: reduce duplicatoin with controllers/crates export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page', 'sort'], - page: '1', - per_page: 10, - sort: 'alpha', + queryParams: ['page', 'per_page', 'sort'], + page: '1', + per_page: 10, + sort: 'alpha', - totalItems: readOnly('model.meta.total'), + totalItems: readOnly('model.meta.total'), - currentSortBy: computed('sort', function() { - if (this.sort === 'downloads') { - return 'All-Time Downloads'; - } else if (this.sort === 'recent-downloads') { - return 'Recent Downloads'; - } else if (this.get('sort') === 'recent-updates') { - return 'Recent Updates'; - } else { - return 'Alphabetical'; - } - }), + currentSortBy: computed('sort', function() { + if (this.sort === 'downloads') { + return 'All-Time Downloads'; + } else if (this.sort === 'recent-downloads') { + return 'Recent Downloads'; + } else if (this.get('sort') === 'recent-updates') { + return 'Recent Updates'; + } else { + return 'Alphabetical'; + } + }), }); diff --git a/app/controllers/me/following.js b/app/controllers/me/following.js index ad74cc201ab..4d97fde6b61 100644 --- a/app/controllers/me/following.js +++ b/app/controllers/me/following.js @@ -7,14 +7,14 @@ import PaginationMixin from '../../mixins/pagination'; // TODO: reduce duplicatoin with controllers/me/crates export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page', 'sort'], - page: '1', - per_page: 10, - sort: 'alpha', + queryParams: ['page', 'per_page', 'sort'], + page: '1', + per_page: 10, + sort: 'alpha', - totalItems: readOnly('model.meta.total'), + totalItems: readOnly('model.meta.total'), - currentSortBy: computed('sort', function() { - return this.sort === 'downloads' ? 'Downloads' : 'Alphabetical'; - }), + currentSortBy: computed('sort', function() { + return this.sort === 'downloads' ? 'Downloads' : 'Alphabetical'; + }), }); diff --git a/app/controllers/me/index.js b/app/controllers/me/index.js index 875806bc5c9..a3edf82124e 100644 --- a/app/controllers/me/index.js +++ b/app/controllers/me/index.js @@ -3,23 +3,23 @@ import { sort, filterBy, notEmpty } from '@ember/object/computed'; import { inject as service } from '@ember/service'; export default Controller.extend({ - // eslint-disable-next-line ember/avoid-leaking-state-in-ember-objects - tokenSort: ['created_at:desc'], + // eslint-disable-next-line ember/avoid-leaking-state-in-ember-objects + tokenSort: ['created_at:desc'], - sortedTokens: sort('model.api_tokens', 'tokenSort'), + sortedTokens: sort('model.api_tokens', 'tokenSort'), - flashMessages: service(), + flashMessages: service(), - isResetting: false, + isResetting: false, - newTokens: filterBy('model.api_tokens', 'isNew', true), - disableCreate: notEmpty('newTokens'), + newTokens: filterBy('model.api_tokens', 'isNew', true), + disableCreate: notEmpty('newTokens'), - actions: { - startNewToken() { - this.store.createRecord('api-token', { - created_at: new Date(Date.now() + 2000), - }); - }, + actions: { + startNewToken() { + this.store.createRecord('api-token', { + created_at: new Date(Date.now() + 2000), + }); }, + }, }); diff --git a/app/controllers/search.js b/app/controllers/search.js index 4fc8564f512..4c08b873454 100644 --- a/app/controllers/search.js +++ b/app/controllers/search.js @@ -8,43 +8,43 @@ import { task } from 'ember-concurrency'; import PaginationMixin from '../mixins/pagination'; export default Controller.extend(PaginationMixin, { - search: service(), - queryParams: ['q', 'page', 'per_page', 'sort'], - q: alias('search.q'), - page: '1', - per_page: 10, - - model: readOnly('dataTask.lastSuccessful.value'), - - hasData: computed('dataTask.{lastSuccessful,isRunning}', function() { - return this.get('dataTask.lastSuccessful') || !this.get('dataTask.isRunning'); - }), - - firstResultPending: computed('dataTask.{lastSuccessful,isRunning}', function() { - return !this.get('dataTask.lastSuccessful') && this.get('dataTask.isRunning'); - }), - - totalItems: readOnly('model.meta.total'), - - currentSortBy: computed('sort', function() { - if (this.sort === 'downloads') { - return 'All-Time Downloads'; - } else if (this.sort === 'recent-downloads') { - return 'Recent Downloads'; - } else if (this.get('sort') === 'recent-updates') { - return 'Recent Updates'; - } else { - return 'Relevance'; - } - }), - - hasItems: bool('totalItems'), - - dataTask: task(function*(params) { - if (params.q !== null) { - params.q = params.q.trim(); - } - - return yield this.store.query('crate', params); - }).drop(), + search: service(), + queryParams: ['q', 'page', 'per_page', 'sort'], + q: alias('search.q'), + page: '1', + per_page: 10, + + model: readOnly('dataTask.lastSuccessful.value'), + + hasData: computed('dataTask.{lastSuccessful,isRunning}', function() { + return this.get('dataTask.lastSuccessful') || !this.get('dataTask.isRunning'); + }), + + firstResultPending: computed('dataTask.{lastSuccessful,isRunning}', function() { + return !this.get('dataTask.lastSuccessful') && this.get('dataTask.isRunning'); + }), + + totalItems: readOnly('model.meta.total'), + + currentSortBy: computed('sort', function() { + if (this.sort === 'downloads') { + return 'All-Time Downloads'; + } else if (this.sort === 'recent-downloads') { + return 'Recent Downloads'; + } else if (this.get('sort') === 'recent-updates') { + return 'Recent Updates'; + } else { + return 'Relevance'; + } + }), + + hasItems: bool('totalItems'), + + dataTask: task(function*(params) { + if (params.q !== null) { + params.q = params.q.trim(); + } + + return yield this.store.query('crate', params); + }).drop(), }); diff --git a/app/controllers/team.js b/app/controllers/team.js index 8d36c2bfe56..96fd125d032 100644 --- a/app/controllers/team.js +++ b/app/controllers/team.js @@ -5,22 +5,22 @@ import { computed } from '@ember/object'; import PaginationMixin from '../mixins/pagination'; export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page', 'sort'], - page: '1', - per_page: 10, - sort: 'alpha', + queryParams: ['page', 'per_page', 'sort'], + page: '1', + per_page: 10, + sort: 'alpha', - totalItems: readOnly('model.crates.meta.total'), + totalItems: readOnly('model.crates.meta.total'), - currentSortBy: computed('sort', function() { - if (this.sort === 'downloads') { - return 'All-Time Downloads'; - } else if (this.sort === 'recent-downloads') { - return 'Recent Downloads'; - } else if (this.get('sort') === 'recent-updates') { - return 'Recent Updates'; - } else { - return 'Alphabetical'; - } - }), + currentSortBy: computed('sort', function() { + if (this.sort === 'downloads') { + return 'All-Time Downloads'; + } else if (this.sort === 'recent-downloads') { + return 'Recent Downloads'; + } else if (this.get('sort') === 'recent-updates') { + return 'Recent Updates'; + } else { + return 'Alphabetical'; + } + }), }); diff --git a/app/controllers/user.js b/app/controllers/user.js index 08b51995c2d..9afafbfc9a2 100644 --- a/app/controllers/user.js +++ b/app/controllers/user.js @@ -6,22 +6,22 @@ import PaginationMixin from '../mixins/pagination'; // TODO: reduce duplication with controllers/crates export default Controller.extend(PaginationMixin, { - queryParams: ['page', 'per_page', 'sort'], - page: '1', - per_page: 10, - sort: 'alpha', + queryParams: ['page', 'per_page', 'sort'], + page: '1', + per_page: 10, + sort: 'alpha', - totalItems: readOnly('model.crates.meta.total'), + totalItems: readOnly('model.crates.meta.total'), - currentSortBy: computed('sort', function() { - if (this.sort === 'downloads') { - return 'All-Time Downloads'; - } else if (this.sort === 'recent-downloads') { - return 'Recent Downloads'; - } else if (this.get('sort') === 'recent-updates') { - return 'Recent Updates'; - } else { - return 'Alphabetical'; - } - }), + currentSortBy: computed('sort', function() { + if (this.sort === 'downloads') { + return 'All-Time Downloads'; + } else if (this.sort === 'recent-downloads') { + return 'Recent Downloads'; + } else if (this.get('sort') === 'recent-updates') { + return 'Recent Updates'; + } else { + return 'Alphabetical'; + } + }), }); diff --git a/app/helpers/format-crate-size.js b/app/helpers/format-crate-size.js index 2f8beb53809..f0103c11d44 100644 --- a/app/helpers/format-crate-size.js +++ b/app/helpers/format-crate-size.js @@ -1,11 +1,11 @@ import { helper } from '@ember/component/helper'; export function formatCrateSize(sizeInBytes) { - if (sizeInBytes < 100000) { - return +(sizeInBytes / 1000).toFixed(2) + ' kB'; - } else { - return +(sizeInBytes / 1000000).toFixed(2) + ' MB'; - } + if (sizeInBytes < 100000) { + return +(sizeInBytes / 1000).toFixed(2) + ' kB'; + } else { + return +(sizeInBytes / 1000000).toFixed(2) + ' MB'; + } } export default helper(formatCrateSize); diff --git a/app/helpers/format-email.js b/app/helpers/format-email.js index 11ff4b1b1a6..4852ab98ee1 100644 --- a/app/helpers/format-email.js +++ b/app/helpers/format-email.js @@ -5,16 +5,16 @@ import Ember from 'ember'; const escape = Ember.Handlebars.Utils.escapeExpression; export function formatEmail(email) { - let formatted = email.match(/^(.*?)\s*(?:<(.*)>)?$/); - let ret = ''; + let formatted = email.match(/^(.*?)\s*(?:<(.*)>)?$/); + let ret = ''; - ret += escape(formatted[1]); + ret += escape(formatted[1]); - if (formatted[2]) { - ret = `${ret}`; - } + if (formatted[2]) { + ret = `${ret}`; + } - return htmlSafe(ret); + return htmlSafe(ret); } export default helper(params => formatEmail(params[0])); diff --git a/app/helpers/format-num.js b/app/helpers/format-num.js index a5f3e4589d8..54fff2d67cd 100644 --- a/app/helpers/format-num.js +++ b/app/helpers/format-num.js @@ -1,22 +1,22 @@ import { helper } from '@ember/component/helper'; export function formatNum(value) { - if (value === 0) { - return '0'; - } + if (value === 0) { + return '0'; + } - let ret = ''; - let cnt = 0; - while (value > 0) { - if (cnt > 0 && cnt % 3 === 0) { - ret = `,${ret}`; - cnt = 0; - } - ret = (value % 10) + ret; - cnt += 1; - value = Math.floor(value / 10); + let ret = ''; + let cnt = 0; + while (value > 0) { + if (cnt > 0 && cnt % 3 === 0) { + ret = `,${ret}`; + cnt = 0; } - return ret; + ret = (value % 10) + ret; + cnt += 1; + value = Math.floor(value / 10); + } + return ret; } export default helper(params => formatNum(params[0])); diff --git a/app/helpers/format-req.js b/app/helpers/format-req.js index 22e79f9b492..2e3740ea71a 100644 --- a/app/helpers/format-req.js +++ b/app/helpers/format-req.js @@ -1,6 +1,6 @@ import { helper } from '@ember/component/helper'; export default helper(function(params) { - let [req] = params; - return req === '*' ? '' : req; + let [req] = params; + return req === '*' ? '' : req; }); diff --git a/app/helpers/truncate-text.js b/app/helpers/truncate-text.js index b42feaa0714..029dde80fbe 100644 --- a/app/helpers/truncate-text.js +++ b/app/helpers/truncate-text.js @@ -1,12 +1,12 @@ import { helper } from '@ember/component/helper'; export default helper(function(params) { - let [value] = params; - if (!value) { - return value; - } - if (value.length > 200) { - return `${value.slice(0, 200)} ...`; - } + let [value] = params; + if (!value) { return value; + } + if (value.length > 200) { + return `${value.slice(0, 200)} ...`; + } + return value; }); diff --git a/app/initializers/hashchange.js b/app/initializers/hashchange.js index d852ecf7f0a..13c14f5ac0d 100644 --- a/app/initializers/hashchange.js +++ b/app/initializers/hashchange.js @@ -1,55 +1,55 @@ function decodeFragmentValue(hash) { - try { - return decodeURIComponent(hash.slice(1)); - } catch (_) { - return ''; - } + try { + return decodeURIComponent(hash.slice(1)); + } catch (_) { + return ''; + } } function findElementByFragmentName(document, name) { - if (name === '') { - return; - } + if (name === '') { + return; + } - return document.getElementById(name) || document.getElementsByName(name)[0]; + return document.getElementById(name) || document.getElementsByName(name)[0]; } function hashchange() { - if (document.querySelector(':target')) { - return; - } + if (document.querySelector(':target')) { + return; + } - const hash = decodeFragmentValue(location.hash); - const target = findElementByFragmentName(document, `user-content-${hash}`); - if (target) { - target.scrollIntoView(); - } + const hash = decodeFragmentValue(location.hash); + const target = findElementByFragmentName(document, `user-content-${hash}`); + if (target) { + target.scrollIntoView(); + } } export function initialize() { - if (typeof window === 'undefined' || typeof window.addEventListener === 'undefined') { - // Don't run this initializer under FastBoot - return; - } - window.addEventListener('hashchange', hashchange); + if (typeof window === 'undefined' || typeof window.addEventListener === 'undefined') { + // Don't run this initializer under FastBoot + return; + } + window.addEventListener('hashchange', hashchange); - // If clicking on a link to the same fragment as currently in the address bar, - // hashchange won't be fired, so we need to manually trigger rescroll. - document.addEventListener('click', function(event) { - if (event.target.tagName !== 'A') { - return; - } - if (this.href === location.href && location.hash.length > 1) { - setTimeout(function() { - if (!event.defaultPrevented) { - hashchange(); - } - }); + // If clicking on a link to the same fragment as currently in the address bar, + // hashchange won't be fired, so we need to manually trigger rescroll. + document.addEventListener('click', function(event) { + if (event.target.tagName !== 'A') { + return; + } + if (this.href === location.href && location.hash.length > 1) { + setTimeout(function() { + if (!event.defaultPrevented) { + hashchange(); } - }); + }); + } + }); } export default { - name: 'app.hashchange', - initialize, + name: 'app.hashchange', + initialize, }; diff --git a/app/initializers/set-global-promise.js b/app/initializers/set-global-promise.js index 972f5dad550..20a20415742 100644 --- a/app/initializers/set-global-promise.js +++ b/app/initializers/set-global-promise.js @@ -1,9 +1,9 @@ import RSVP from 'rsvp'; export function initialize() { - // async/await is using window.Promise by default and we want async/await to - // use RSVP instead which is properly integrated with Ember's runloop - window.Promise = RSVP.Promise; + // async/await is using window.Promise by default and we want async/await to + // use RSVP instead which is properly integrated with Ember's runloop + window.Promise = RSVP.Promise; } export default { initialize }; diff --git a/app/mixins/authenticated-route.js b/app/mixins/authenticated-route.js index ffa174be15b..d599c648495 100644 --- a/app/mixins/authenticated-route.js +++ b/app/mixins/authenticated-route.js @@ -2,12 +2,12 @@ import Mixin from '@ember/object/mixin'; import { inject as service } from '@ember/service'; export default Mixin.create({ - flashMessages: service(), - session: service(), + flashMessages: service(), + session: service(), - beforeModel(transition) { - return this.session.checkCurrentUser(transition, () => { - this.flashMessages.queue('Please log in to proceed'); - }); - }, + beforeModel(transition) { + return this.session.checkCurrentUser(transition, () => { + this.flashMessages.queue('Please log in to proceed'); + }); + }, }); diff --git a/app/mixins/pagination.js b/app/mixins/pagination.js index fd271e11ada..70706b51421 100644 --- a/app/mixins/pagination.js +++ b/app/mixins/pagination.js @@ -5,71 +5,71 @@ import { computed } from '@ember/object'; const VIEWABLE_PAGES = 9; export default Mixin.create({ - // Gives page numbers to the surrounding 9 pages. - pages: computed('currentPage', 'availablePages', function() { - let pages = []; - let currentPage = this.currentPage; - let availablePages = this.availablePages; - let lowerBound = 0; - let upperBound = 0; + // Gives page numbers to the surrounding 9 pages. + pages: computed('currentPage', 'availablePages', function() { + let pages = []; + let currentPage = this.currentPage; + let availablePages = this.availablePages; + let lowerBound = 0; + let upperBound = 0; - // Always show the same number of pages even if we're - // at the beginning or at the end of the list. - if (availablePages - currentPage < Math.ceil(VIEWABLE_PAGES / 2)) { - lowerBound = Math.max(0, availablePages - VIEWABLE_PAGES); - upperBound = availablePages; - } else if (currentPage <= Math.ceil(VIEWABLE_PAGES / 2)) { - lowerBound = 0; - upperBound = Math.min(availablePages, VIEWABLE_PAGES); - } else { - lowerBound = currentPage - Math.ceil(VIEWABLE_PAGES / 2); - upperBound = currentPage + Math.floor(VIEWABLE_PAGES / 2); - } - for (let i = lowerBound; i < upperBound; i++) { - pages.push(i + 1); - } - return pages; - }), + // Always show the same number of pages even if we're + // at the beginning or at the end of the list. + if (availablePages - currentPage < Math.ceil(VIEWABLE_PAGES / 2)) { + lowerBound = Math.max(0, availablePages - VIEWABLE_PAGES); + upperBound = availablePages; + } else if (currentPage <= Math.ceil(VIEWABLE_PAGES / 2)) { + lowerBound = 0; + upperBound = Math.min(availablePages, VIEWABLE_PAGES); + } else { + lowerBound = currentPage - Math.ceil(VIEWABLE_PAGES / 2); + upperBound = currentPage + Math.floor(VIEWABLE_PAGES / 2); + } + for (let i = lowerBound; i < upperBound; i++) { + pages.push(i + 1); + } + return pages; + }), - currentPage: computed('selectedPage', function() { - return parseInt(this.selectedPage, 10) || 1; - }), + currentPage: computed('selectedPage', function() { + return parseInt(this.selectedPage, 10) || 1; + }), - currentPageStart: computed('currentPage', 'itemsPerPage', 'totalItems', function() { - if (this.totalItems === 0) { - return 0; - } - return (this.currentPage - 1) * this.itemsPerPage + 1; - }), + currentPageStart: computed('currentPage', 'itemsPerPage', 'totalItems', function() { + if (this.totalItems === 0) { + return 0; + } + return (this.currentPage - 1) * this.itemsPerPage + 1; + }), - currentPageEnd: computed('currentPage', 'itemsPerPage', 'totalItems', function() { - return Math.min(this.currentPage * this.itemsPerPage, this.totalItems); - }), + currentPageEnd: computed('currentPage', 'itemsPerPage', 'totalItems', function() { + return Math.min(this.currentPage * this.itemsPerPage, this.totalItems); + }), - nextPage: computed('currentPage', 'availablePages', function() { - let nextPage = this.currentPage + 1; - let availablePages = this.availablePages; - if (nextPage <= availablePages) { - return nextPage; - } else { - return this.currentPage; - } - }), + nextPage: computed('currentPage', 'availablePages', function() { + let nextPage = this.currentPage + 1; + let availablePages = this.availablePages; + if (nextPage <= availablePages) { + return nextPage; + } else { + return this.currentPage; + } + }), - prevPage: computed('currentPage', function() { - let prevPage = this.currentPage - 1; - if (prevPage > 0) { - return prevPage; - } else { - return this.currentPage; - } - }), + prevPage: computed('currentPage', function() { + let prevPage = this.currentPage - 1; + if (prevPage > 0) { + return prevPage; + } else { + return this.currentPage; + } + }), - availablePages: computed('totalItems', 'itemsPerPage', function() { - return Math.ceil(this.totalItems / this.itemsPerPage || 1); - }), + availablePages: computed('totalItems', 'itemsPerPage', function() { + return Math.ceil(this.totalItems / this.itemsPerPage || 1); + }), - // wire up these ember-style variables to the expected query parameters - itemsPerPage: readOnly('per_page'), - selectedPage: readOnly('page'), + // wire up these ember-style variables to the expected query parameters + itemsPerPage: readOnly('per_page'), + selectedPage: readOnly('page'), }); diff --git a/app/mixins/rl-dropdown-component.js b/app/mixins/rl-dropdown-component.js index 677c7bee5cb..1d9adf352d5 100644 --- a/app/mixins/rl-dropdown-component.js +++ b/app/mixins/rl-dropdown-component.js @@ -5,97 +5,97 @@ import { bind, later } from '@ember/runloop'; import $ from 'jquery'; export default Mixin.create({ - init() { - this._super(...arguments); + init() { + this._super(...arguments); - this.set('boundClickoutHandler', bind(this, this.clickoutHandler)); - this.set('boundEscapeHandler', bind(this, this.escapeHandler)); - }, - - onOpen() {}, - onClose() {}, + this.set('boundClickoutHandler', bind(this, this.clickoutHandler)); + this.set('boundEscapeHandler', bind(this, this.escapeHandler)); + }, - dropdownExpanded: false, + onOpen() {}, + onClose() {}, - dropdownToggleSelector: '.rl-dropdown-toggle', + dropdownExpanded: false, - dropdownSelector: '.rl-dropdown', + dropdownToggleSelector: '.rl-dropdown-toggle', - closingEventNamespace: 'rl-dropdown', + dropdownSelector: '.rl-dropdown', - closeOnEscape: true, + closingEventNamespace: 'rl-dropdown', - actions: { - toggleDropdown() { - this.toggleProperty('dropdownExpanded'); + closeOnEscape: true, - if (this.dropdownExpanded) { - this.onOpen(); - } else { - this.onClose(); - } - }, + actions: { + toggleDropdown() { + this.toggleProperty('dropdownExpanded'); - openDropdown() { - this.set('dropdownExpanded', true); - this.onOpen(); - }, + if (this.dropdownExpanded) { + this.onOpen(); + } else { + this.onClose(); + } + }, - closeDropdown() { - this.set('dropdownExpanded', false); - this.onClose(); - }, + openDropdown() { + this.set('dropdownExpanded', true); + this.onOpen(); }, - manageClosingEvents: on( - 'didInsertElement', - observer('dropdownExpanded', function() { - let namespace = this.closingEventNamespace; - let clickEventName = `click.${namespace}`; - let focusEventName = `focusin.${namespace}`; - let touchEventName = `touchstart.${namespace}`; - let escapeEventName = `keydown.${namespace}`; - let component = this; - let $document = $(document); - - if (this.dropdownExpanded) { - /* Add clickout handler with 1ms delay, to allow opening the dropdown + closeDropdown() { + this.set('dropdownExpanded', false); + this.onClose(); + }, + }, + + manageClosingEvents: on( + 'didInsertElement', + observer('dropdownExpanded', function() { + let namespace = this.closingEventNamespace; + let clickEventName = `click.${namespace}`; + let focusEventName = `focusin.${namespace}`; + let touchEventName = `touchstart.${namespace}`; + let escapeEventName = `keydown.${namespace}`; + let component = this; + let $document = $(document); + + if (this.dropdownExpanded) { + /* Add clickout handler with 1ms delay, to allow opening the dropdown * by clicking e.g. a checkbox and binding to dropdownExpanded, without * having the handler close the dropdown immediately. */ - later(() => { - $document.bind(clickEventName, { component }, component.boundClickoutHandler); - $document.bind(focusEventName, { component }, component.boundClickoutHandler); - $document.bind(touchEventName, { component }, component.boundClickoutHandler); - }, 1); - - if (this.closeOnEscape) { - $document.bind(escapeEventName, { component }, component.boundEscapeHandler); - } - } else { - $document.unbind(clickEventName, component.boundClickoutHandler); - $document.unbind(focusEventName, component.boundClickoutHandler); - $document.unbind(touchEventName, component.boundClickoutHandler); - $document.unbind(escapeEventName, component.boundEscapeHandler); - } - }), - ), - - unbindClosingEvents: on('willDestroyElement', function() { - let namespace = this.closingEventNamespace; - let $document = $(document); - - $document.unbind(`click.${namespace}`, this.boundClickoutHandler); - $document.unbind(`focusin.${namespace}`, this.boundClickoutHandler); - $document.unbind(`touchstart.${namespace}`, this.boundClickoutHandler); - $document.unbind(`keydown.${namespace}`, this.boundEscapeHandler); + later(() => { + $document.bind(clickEventName, { component }, component.boundClickoutHandler); + $document.bind(focusEventName, { component }, component.boundClickoutHandler); + $document.bind(touchEventName, { component }, component.boundClickoutHandler); + }, 1); + + if (this.closeOnEscape) { + $document.bind(escapeEventName, { component }, component.boundEscapeHandler); + } + } else { + $document.unbind(clickEventName, component.boundClickoutHandler); + $document.unbind(focusEventName, component.boundClickoutHandler); + $document.unbind(touchEventName, component.boundClickoutHandler); + $document.unbind(escapeEventName, component.boundEscapeHandler); + } }), + ), + + unbindClosingEvents: on('willDestroyElement', function() { + let namespace = this.closingEventNamespace; + let $document = $(document); - clickoutHandler(event) { - let { component } = event.data; - let $c = component.$(); - let $target = $(event.target); + $document.unbind(`click.${namespace}`, this.boundClickoutHandler); + $document.unbind(`focusin.${namespace}`, this.boundClickoutHandler); + $document.unbind(`touchstart.${namespace}`, this.boundClickoutHandler); + $document.unbind(`keydown.${namespace}`, this.boundEscapeHandler); + }), - /* There is an issue when the click triggered a dom change in the + clickoutHandler(event) { + let { component } = event.data; + let $c = component.$(); + let $target = $(event.target); + + /* There is an issue when the click triggered a dom change in the * dropdown that unloaded the target element. The ancestry of the target * can no longer be determined. We can check if html is still an ancestor * to determine if this has happened. The safe option then seems to be to @@ -103,21 +103,21 @@ export default Mixin.create({ * should have closed, seems to be less bad for usability than occasionaly * closing the dropdown when it should not have closed. */ - if ( - component.get('dropdownExpanded') && - $target.closest('html').length && - !( - $target.closest($c.find(component.get('dropdownToggleSelector'))).length || - $target.closest($c.find(component.get('dropdownSelector'))).length - ) - ) { - component.send('closeDropdown'); - } - }, - - escapeHandler(event) { - if (event.keyCode === 27) { - event.data.component.send('closeDropdown'); - } - }, + if ( + component.get('dropdownExpanded') && + $target.closest('html').length && + !( + $target.closest($c.find(component.get('dropdownToggleSelector'))).length || + $target.closest($c.find(component.get('dropdownSelector'))).length + ) + ) { + component.send('closeDropdown'); + } + }, + + escapeHandler(event) { + if (event.keyCode === 27) { + event.data.component.send('closeDropdown'); + } + }, }); diff --git a/app/models/api-token.js b/app/models/api-token.js index 2d9e01ca6d6..b4f95ea61ec 100644 --- a/app/models/api-token.js +++ b/app/models/api-token.js @@ -1,8 +1,8 @@ import DS from 'ember-data'; export default DS.Model.extend({ - name: DS.attr('string'), - token: DS.attr('string'), - created_at: DS.attr('date'), - last_used_at: DS.attr('date'), + name: DS.attr('string'), + token: DS.attr('string'), + created_at: DS.attr('date'), + last_used_at: DS.attr('date'), }); diff --git a/app/models/category-slug.js b/app/models/category-slug.js index ee38d510b21..100f88069c0 100644 --- a/app/models/category-slug.js +++ b/app/models/category-slug.js @@ -1,6 +1,6 @@ import DS from 'ember-data'; export default DS.Model.extend({ - slug: DS.attr('string'), - description: DS.attr('string'), + slug: DS.attr('string'), + description: DS.attr('string'), }); diff --git a/app/models/category.js b/app/models/category.js index 235eb0ad27b..cfc787f806c 100644 --- a/app/models/category.js +++ b/app/models/category.js @@ -1,14 +1,14 @@ import DS from 'ember-data'; export default DS.Model.extend({ - category: DS.attr('string'), - slug: DS.attr('string'), - description: DS.attr('string'), - created_at: DS.attr('date'), - crates_cnt: DS.attr('number'), + category: DS.attr('string'), + slug: DS.attr('string'), + description: DS.attr('string'), + created_at: DS.attr('date'), + crates_cnt: DS.attr('number'), - subcategories: DS.attr(), - parent_categories: DS.attr(), + subcategories: DS.attr(), + parent_categories: DS.attr(), - crates: DS.hasMany('crate', { async: true }), + crates: DS.hasMany('crate', { async: true }), }); diff --git a/app/models/crate-owner-invite.js b/app/models/crate-owner-invite.js index b17385aacda..d1fb018f7dd 100644 --- a/app/models/crate-owner-invite.js +++ b/app/models/crate-owner-invite.js @@ -1,9 +1,9 @@ import DS from 'ember-data'; export default DS.Model.extend({ - invited_by_username: DS.attr('string'), - crate_name: DS.attr('string'), - crate_id: DS.attr('number'), - created_at: DS.attr('date'), - accepted: DS.attr('boolean', { defaultValue: false }), + invited_by_username: DS.attr('string'), + crate_name: DS.attr('string'), + crate_id: DS.attr('number'), + created_at: DS.attr('date'), + accepted: DS.attr('boolean', { defaultValue: false }), }); diff --git a/app/models/crate.js b/app/models/crate.js index f020f19355a..19c057c4c46 100644 --- a/app/models/crate.js +++ b/app/models/crate.js @@ -2,54 +2,54 @@ import { map, sort } from '@ember/object/computed'; import DS from 'ember-data'; export default DS.Model.extend({ - name: DS.attr('string'), - downloads: DS.attr('number'), - recent_downloads: DS.attr('number'), - created_at: DS.attr('date'), - updated_at: DS.attr('date'), - max_version: DS.attr('string'), - - description: DS.attr('string'), - homepage: DS.attr('string'), - wiki: DS.attr('string'), - mailing_list: DS.attr('string'), - issues: DS.attr('string'), - documentation: DS.attr('string'), - repository: DS.attr('string'), - exact_match: DS.attr('boolean'), - - versions: DS.hasMany('versions', { async: true }), - badges: DS.attr(), - enhanced_badges: map('badges', badge => ({ - ...badge, - component_name: `badge-${badge.badge_type}`, - })), - - // eslint-disable-next-line ember/avoid-leaking-state-in-ember-objects - badge_sort: ['badge_type'], - annotated_badges: sort('enhanced_badges', 'badge_sort'), - - owners: DS.hasMany('users', { async: true }), - owner_team: DS.hasMany('teams', { async: true }), - owner_user: DS.hasMany('users', { async: true }), - version_downloads: DS.hasMany('version-download', { async: true }), - keywords: DS.hasMany('keywords', { async: true }), - categories: DS.hasMany('categories', { async: true }), - reverse_dependencies: DS.hasMany('dependency', { async: true }), - - follow() { - return this.store.adapterFor('crate').follow(this.id); - }, - - inviteOwner(username) { - return this.store.adapterFor('crate').inviteOwner(this.id, username); - }, - - removeOwner(username) { - return this.store.adapterFor('crate').removeOwner(this.id, username); - }, - - unfollow() { - return this.store.adapterFor('crate').unfollow(this.id); - }, + name: DS.attr('string'), + downloads: DS.attr('number'), + recent_downloads: DS.attr('number'), + created_at: DS.attr('date'), + updated_at: DS.attr('date'), + max_version: DS.attr('string'), + + description: DS.attr('string'), + homepage: DS.attr('string'), + wiki: DS.attr('string'), + mailing_list: DS.attr('string'), + issues: DS.attr('string'), + documentation: DS.attr('string'), + repository: DS.attr('string'), + exact_match: DS.attr('boolean'), + + versions: DS.hasMany('versions', { async: true }), + badges: DS.attr(), + enhanced_badges: map('badges', badge => ({ + ...badge, + component_name: `badge-${badge.badge_type}`, + })), + + // eslint-disable-next-line ember/avoid-leaking-state-in-ember-objects + badge_sort: ['badge_type'], + annotated_badges: sort('enhanced_badges', 'badge_sort'), + + owners: DS.hasMany('users', { async: true }), + owner_team: DS.hasMany('teams', { async: true }), + owner_user: DS.hasMany('users', { async: true }), + version_downloads: DS.hasMany('version-download', { async: true }), + keywords: DS.hasMany('keywords', { async: true }), + categories: DS.hasMany('categories', { async: true }), + reverse_dependencies: DS.hasMany('dependency', { async: true }), + + follow() { + return this.store.adapterFor('crate').follow(this.id); + }, + + inviteOwner(username) { + return this.store.adapterFor('crate').inviteOwner(this.id, username); + }, + + removeOwner(username) { + return this.store.adapterFor('crate').removeOwner(this.id, username); + }, + + unfollow() { + return this.store.adapterFor('crate').unfollow(this.id); + }, }); diff --git a/app/models/dependency.js b/app/models/dependency.js index add3fbc0efe..9cccd5d7d54 100644 --- a/app/models/dependency.js +++ b/app/models/dependency.js @@ -4,14 +4,14 @@ import Inflector from 'ember-inflector'; Inflector.inflector.irregular('dependency', 'dependencies'); export default DS.Model.extend({ - version: DS.belongsTo('version', { - async: false, - }), - crate_id: DS.attr('string'), - req: DS.attr('string'), - optional: DS.attr('boolean'), - default_features: DS.attr('boolean'), - features: DS.attr({ defaultValue: () => [] }), - kind: DS.attr('string'), - downloads: DS.attr('number'), + version: DS.belongsTo('version', { + async: false, + }), + crate_id: DS.attr('string'), + req: DS.attr('string'), + optional: DS.attr('boolean'), + default_features: DS.attr('boolean'), + features: DS.attr({ defaultValue: () => [] }), + kind: DS.attr('string'), + downloads: DS.attr('number'), }); diff --git a/app/models/keyword.js b/app/models/keyword.js index d32a54d8983..a55b15bca86 100644 --- a/app/models/keyword.js +++ b/app/models/keyword.js @@ -1,9 +1,9 @@ import DS from 'ember-data'; export default DS.Model.extend({ - keyword: DS.attr('string'), - created_at: DS.attr('date'), - crates_cnt: DS.attr('number'), + keyword: DS.attr('string'), + created_at: DS.attr('date'), + crates_cnt: DS.attr('number'), - crates: DS.hasMany('crate', { async: true }), + crates: DS.hasMany('crate', { async: true }), }); diff --git a/app/models/team.js b/app/models/team.js index a993e5b42e5..80b4a6bb782 100644 --- a/app/models/team.js +++ b/app/models/team.js @@ -2,16 +2,16 @@ import { computed } from '@ember/object'; import DS from 'ember-data'; export default DS.Model.extend({ - email: DS.attr('string'), - name: DS.attr('string'), - login: DS.attr('string'), - api_token: DS.attr('string'), - avatar: DS.attr('string'), - url: DS.attr('string'), - kind: DS.attr('string'), - org_name: computed('login', function() { - let login = this.login; - let login_split = login.split(':'); - return login_split[1]; - }), + email: DS.attr('string'), + name: DS.attr('string'), + login: DS.attr('string'), + api_token: DS.attr('string'), + avatar: DS.attr('string'), + url: DS.attr('string'), + kind: DS.attr('string'), + org_name: computed('login', function() { + let login = this.login; + let login_split = login.split(':'); + return login_split[1]; + }), }); diff --git a/app/models/user.js b/app/models/user.js index 9bab18b285d..0bcbdcbce71 100644 --- a/app/models/user.js +++ b/app/models/user.js @@ -1,16 +1,16 @@ import DS from 'ember-data'; export default DS.Model.extend({ - email: DS.attr('string'), - email_verified: DS.attr('boolean'), - email_verification_sent: DS.attr('boolean'), - name: DS.attr('string'), - login: DS.attr('string'), - avatar: DS.attr('string'), - url: DS.attr('string'), - kind: DS.attr('string'), + email: DS.attr('string'), + email_verified: DS.attr('boolean'), + email_verification_sent: DS.attr('boolean'), + name: DS.attr('string'), + login: DS.attr('string'), + avatar: DS.attr('string'), + url: DS.attr('string'), + kind: DS.attr('string'), - stats() { - return this.store.adapterFor('user').stats(this.id); - }, + stats() { + return this.store.adapterFor('user').stats(this.id); + }, }); diff --git a/app/models/version-download.js b/app/models/version-download.js index a8f0c25f1e5..fc15938974c 100644 --- a/app/models/version-download.js +++ b/app/models/version-download.js @@ -1,9 +1,9 @@ import DS from 'ember-data'; export default DS.Model.extend({ - version: DS.belongsTo('version', { - async: false, - }), - downloads: DS.attr('number'), - date: DS.attr('date'), + version: DS.belongsTo('version', { + async: false, + }), + downloads: DS.attr('number'), + date: DS.attr('date'), }); diff --git a/app/models/version.js b/app/models/version.js index e5888831c48..504ba240d93 100644 --- a/app/models/version.js +++ b/app/models/version.js @@ -2,24 +2,24 @@ import { computed } from '@ember/object'; import DS from 'ember-data'; export default DS.Model.extend({ - num: DS.attr('string'), - dl_path: DS.attr('string'), - readme_path: DS.attr('string'), - created_at: DS.attr('date'), - updated_at: DS.attr('date'), - downloads: DS.attr('number'), - yanked: DS.attr('boolean'), - license: DS.attr('string'), + num: DS.attr('string'), + dl_path: DS.attr('string'), + readme_path: DS.attr('string'), + created_at: DS.attr('date'), + updated_at: DS.attr('date'), + downloads: DS.attr('number'), + yanked: DS.attr('boolean'), + license: DS.attr('string'), - crate: DS.belongsTo('crate', { - async: false, - }), - authors: DS.hasMany('users', { async: true }), - dependencies: DS.hasMany('dependency', { async: true }), - version_downloads: DS.hasMany('version-download', { async: true }), + crate: DS.belongsTo('crate', { + async: false, + }), + authors: DS.hasMany('users', { async: true }), + dependencies: DS.hasMany('dependency', { async: true }), + version_downloads: DS.hasMany('version-download', { async: true }), - crateName: computed('crate', function() { - return this.belongsTo('crate').id(); - }), - crate_size: DS.attr('number'), + crateName: computed('crate', function() { + return this.belongsTo('crate').id(); + }), + crate_size: DS.attr('number'), }); diff --git a/app/router.js b/app/router.js index 01eb2bbeace..969fbfc156b 100644 --- a/app/router.js +++ b/app/router.js @@ -3,52 +3,52 @@ import config from './config/environment'; import RouterScroll from 'ember-router-scroll'; const Router = EmberRouter.extend(RouterScroll, { - location: config.locationType, - rootURL: config.rootURL, + location: config.locationType, + rootURL: config.rootURL, }); Router.map(function() { - this.route('logout'); - this.route('login'); - this.route('github-login', { path: 'github_login' }); - this.route('github-authorize', { path: '/authorize/github' }); - this.route('crates'); - this.route('crate', { path: '/crates/:crate_id' }, function() { - this.route('download'); - this.route('versions'); - this.route('version', { path: '/:version_num' }); + this.route('logout'); + this.route('login'); + this.route('github-login', { path: 'github_login' }); + this.route('github-authorize', { path: '/authorize/github' }); + this.route('crates'); + this.route('crate', { path: '/crates/:crate_id' }, function() { + this.route('download'); + this.route('versions'); + this.route('version', { path: '/:version_num' }); - this.route('reverse-dependencies', { path: 'reverse_dependencies' }); + this.route('reverse-dependencies', { path: 'reverse_dependencies' }); - this.route('owners'); + this.route('owners'); - // Well-known routes - this.route('docs'); - this.route('repo'); - }); - this.route('me', function() { - this.route('crates'); - this.route('following'); - this.route('pending-invites'); - }); - this.route('user', { path: '/users/:user_id' }); - this.route('install'); - this.route('search'); - this.route('dashboard'); - this.route('keywords'); - this.route('keyword', { path: '/keywords/:keyword_id' }, function() { - this.route('index', { path: '/' }); - }); - this.route('categories'); - this.route('category', { path: '/categories/:category_id' }, function() { - this.route('index', { path: '/' }); - }); - this.route('category-slugs', { path: 'category_slugs' }); - this.route('team', { path: '/teams/:team_id' }); - this.route('policies'); - this.route('confirm', { path: '/confirm/:email_token' }); + // Well-known routes + this.route('docs'); + this.route('repo'); + }); + this.route('me', function() { + this.route('crates'); + this.route('following'); + this.route('pending-invites'); + }); + this.route('user', { path: '/users/:user_id' }); + this.route('install'); + this.route('search'); + this.route('dashboard'); + this.route('keywords'); + this.route('keyword', { path: '/keywords/:keyword_id' }, function() { + this.route('index', { path: '/' }); + }); + this.route('categories'); + this.route('category', { path: '/categories/:category_id' }, function() { + this.route('index', { path: '/' }); + }); + this.route('category-slugs', { path: 'category_slugs' }); + this.route('team', { path: '/teams/:team_id' }); + this.route('policies'); + this.route('confirm', { path: '/confirm/:email_token' }); - this.route('catch-all', { path: '*path' }); + this.route('catch-all', { path: '*path' }); }); export default Router; diff --git a/app/routes/application.js b/app/routes/application.js index 61cc50b7307..b295f018340 100644 --- a/app/routes/application.js +++ b/app/routes/application.js @@ -2,16 +2,16 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default Route.extend({ - flashMessages: service(), - session: service(), + flashMessages: service(), + session: service(), - beforeModel() { - this.session.loadUser(); - }, + beforeModel() { + this.session.loadUser(); + }, - actions: { - didTransition() { - this.flashMessages.step(); - }, + actions: { + didTransition() { + this.flashMessages.step(); }, + }, }); diff --git a/app/routes/categories.js b/app/routes/categories.js index 99a581cdfe8..9e21dfc5809 100644 --- a/app/routes/categories.js +++ b/app/routes/categories.js @@ -1,12 +1,12 @@ import Route from '@ember/routing/route'; export default Route.extend({ - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - return this.store.query('category', params); - }, + model(params) { + return this.store.query('category', params); + }, }); diff --git a/app/routes/category-slugs.js b/app/routes/category-slugs.js index ea695cfe049..ab314b37f43 100644 --- a/app/routes/category-slugs.js +++ b/app/routes/category-slugs.js @@ -1,12 +1,12 @@ import Route from '@ember/routing/route'; export default Route.extend({ - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - return this.store.query('category-slug', params); - }, + model(params) { + return this.store.query('category-slug', params); + }, }); diff --git a/app/routes/category.js b/app/routes/category.js index f36246439e6..bd106c48fb9 100644 --- a/app/routes/category.js +++ b/app/routes/category.js @@ -2,14 +2,14 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default Route.extend({ - flashMessages: service(), + flashMessages: service(), - model(params) { - return this.store.find('category', params.category_id).catch(e => { - if (e.errors.some(e => e.detail === 'Not Found')) { - this.flashMessages.queue(`Category '${params.category_id}' does not exist`); - return this.replaceWith('index'); - } - }); - }, + model(params) { + return this.store.find('category', params.category_id).catch(e => { + if (e.errors.some(e => e.detail === 'Not Found')) { + this.flashMessages.queue(`Category '${params.category_id}' does not exist`); + return this.replaceWith('index'); + } + }); + }, }); diff --git a/app/routes/category/index.js b/app/routes/category/index.js index c1bc4378f8d..1b347b13303 100644 --- a/app/routes/category/index.js +++ b/app/routes/category/index.js @@ -1,19 +1,19 @@ import Route from '@ember/routing/route'; export default Route.extend({ - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - params.category = this.paramsFor('category').category_id; - return this.store.query('crate', params); - }, + model(params) { + params.category = this.paramsFor('category').category_id; + return this.store.query('crate', params); + }, - setupController(controller) { - this._super(...arguments); - let category = this.modelFor('category'); - controller.set('category', category); - }, + setupController(controller) { + this._super(...arguments); + let category = this.modelFor('category'); + controller.set('category', category); + }, }); diff --git a/app/routes/confirm.js b/app/routes/confirm.js index 9280e88d483..67405995bb9 100644 --- a/app/routes/confirm.js +++ b/app/routes/confirm.js @@ -3,14 +3,14 @@ import { inject as service } from '@ember/service'; import ajax from 'ember-fetch/ajax'; export default Route.extend({ - flashMessages: service(), - session: service(), + flashMessages: service(), + session: service(), - async model(params) { - try { - await ajax(`/api/v1/confirm/${params.email_token}`, { method: 'PUT', body: '{}' }); + async model(params) { + try { + await ajax(`/api/v1/confirm/${params.email_token}`, { method: 'PUT', body: '{}' }); - /* We need this block to reload the user model from the database, + /* We need this block to reload the user model from the database, without which if we haven't submitted another GET /me after clicking the link and before checking their account info page, the user will still see that their email has not yet been @@ -20,19 +20,19 @@ export default Route.extend({ Suggestions of a more ideomatic way to fix/test this are welcome! */ - if (this.get('session.isLoggedIn')) { - ajax('/api/v1/me').then(response => { - this.session.set('currentUser', this.store.push(this.store.normalize('user', response.user))); - }); - } - } catch (error) { - if (error.payload) { - this.flashMessages.queue(`Error in email confirmation: ${error.payload.errors[0].detail}`); - return this.replaceWith('index'); - } else { - this.flashMessages.queue(`Unknown error in email confirmation`); - return this.replaceWith('index'); - } - } - }, + if (this.get('session.isLoggedIn')) { + ajax('/api/v1/me').then(response => { + this.session.set('currentUser', this.store.push(this.store.normalize('user', response.user))); + }); + } + } catch (error) { + if (error.payload) { + this.flashMessages.queue(`Error in email confirmation: ${error.payload.errors[0].detail}`); + return this.replaceWith('index'); + } else { + this.flashMessages.queue(`Unknown error in email confirmation`); + return this.replaceWith('index'); + } + } + }, }); diff --git a/app/routes/crate.js b/app/routes/crate.js index f3ca47726d7..145f005e13d 100644 --- a/app/routes/crate.js +++ b/app/routes/crate.js @@ -2,35 +2,35 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default Route.extend({ - flashMessages: service(), + flashMessages: service(), - model(params) { - return this.store.find('crate', params.crate_id).catch(e => { - if (e.errors.some(e => e.detail === 'Not Found')) { - this.flashMessages.show(`Crate '${params.crate_id}' does not exist`); - return; - } - }); - }, + model(params) { + return this.store.find('crate', params.crate_id).catch(e => { + if (e.errors.some(e => e.detail === 'Not Found')) { + this.flashMessages.show(`Crate '${params.crate_id}' does not exist`); + return; + } + }); + }, - afterModel(model) { - if (model && typeof model.get === 'function') { - this.setHeadTags(model); - } - }, + afterModel(model) { + if (model && typeof model.get === 'function') { + this.setHeadTags(model); + } + }, - setHeadTags(model) { - let headTags = [ - { - type: 'meta', - tagId: 'meta-description-tag', - attrs: { - name: 'description', - content: model.get('description') || 'A package for Rust.', - }, - }, - ]; + setHeadTags(model) { + let headTags = [ + { + type: 'meta', + tagId: 'meta-description-tag', + attrs: { + name: 'description', + content: model.get('description') || 'A package for Rust.', + }, + }, + ]; - this.set('headTags', headTags); - }, + this.set('headTags', headTags); + }, }); diff --git a/app/routes/crate/docs.js b/app/routes/crate/docs.js index 7bceb06433e..2579eb95e9e 100644 --- a/app/routes/crate/docs.js +++ b/app/routes/crate/docs.js @@ -2,20 +2,20 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default Route.extend({ - flashMessages: service(), + flashMessages: service(), - redirect() { - let crate = this.modelFor('crate'); + redirect() { + let crate = this.modelFor('crate'); - let documentation = crate.get('documentation'); - if (documentation) { - window.location = documentation; - } else { - // Redirect to the crate's main page and show a flash error if - // no documentation is found - let message = 'Crate does not supply a documentation URL'; - this.flashMessages.queue(message); - this.replaceWith('crate', crate); - } - }, + let documentation = crate.get('documentation'); + if (documentation) { + window.location = documentation; + } else { + // Redirect to the crate's main page and show a flash error if + // no documentation is found + let message = 'Crate does not supply a documentation URL'; + this.flashMessages.queue(message); + this.replaceWith('crate', crate); + } + }, }); diff --git a/app/routes/crate/index.js b/app/routes/crate/index.js index fdf2da0a21f..18fdbb182b1 100644 --- a/app/routes/crate/index.js +++ b/app/routes/crate/index.js @@ -1,6 +1,6 @@ import VersionRoute from './version'; export default VersionRoute.extend({ - controllerName: 'crate.version', - templateName: 'crate/version', + controllerName: 'crate.version', + templateName: 'crate/version', }); diff --git a/app/routes/crate/owners.js b/app/routes/crate/owners.js index ac698aa6eb3..3809c391aa6 100644 --- a/app/routes/crate/owners.js +++ b/app/routes/crate/owners.js @@ -1,9 +1,9 @@ import Route from '@ember/routing/route'; export default Route.extend({ - setupController(controller) { - this._super(...arguments); - let crate = this.modelFor('crate'); - controller.set('crate', crate); - }, + setupController(controller) { + this._super(...arguments); + let crate = this.modelFor('crate'); + controller.set('crate', crate); + }, }); diff --git a/app/routes/crate/repo.js b/app/routes/crate/repo.js index 2a340521387..8ff337aadf5 100644 --- a/app/routes/crate/repo.js +++ b/app/routes/crate/repo.js @@ -2,20 +2,20 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default Route.extend({ - flashMessages: service(), + flashMessages: service(), - redirect() { - let crate = this.modelFor('crate'); + redirect() { + let crate = this.modelFor('crate'); - let repository = crate.get('repository'); - if (repository) { - window.location = repository; - } else { - // Redirect to the crate's main page and show a flash error if - // no repository is found - let message = 'Crate does not supply a repository URL'; - this.flashMessages.queue(message); - this.replaceWith('crate', crate); - } - }, + let repository = crate.get('repository'); + if (repository) { + window.location = repository; + } else { + // Redirect to the crate's main page and show a flash error if + // no repository is found + let message = 'Crate does not supply a repository URL'; + this.flashMessages.queue(message); + this.replaceWith('crate', crate); + } + }, }); diff --git a/app/routes/crate/reverse-dependencies.js b/app/routes/crate/reverse-dependencies.js index 0f869a2569e..4a2c6d059f5 100644 --- a/app/routes/crate/reverse-dependencies.js +++ b/app/routes/crate/reverse-dependencies.js @@ -1,20 +1,20 @@ import Route from '@ember/routing/route'; export default Route.extend({ - queryParams: { - page: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + }, - model(params) { - params.reverse = true; - params.crate = this.modelFor('crate'); + model(params) { + params.reverse = true; + params.crate = this.modelFor('crate'); - return this.store.query('dependency', params); - }, + return this.store.query('dependency', params); + }, - setupController(controller) { - this._super(...arguments); - let crate = this.modelFor('crate'); - controller.set('crate', crate); - }, + setupController(controller) { + this._super(...arguments); + let crate = this.modelFor('crate'); + controller.set('crate', crate); + }, }); diff --git a/app/routes/crate/version.js b/app/routes/crate/version.js index b46a57fb226..86a6acf9395 100644 --- a/app/routes/crate/version.js +++ b/app/routes/crate/version.js @@ -6,122 +6,122 @@ import fetch from 'fetch'; import ajax from 'ember-fetch/ajax'; export default Route.extend({ - session: service(), + session: service(), - flashMessages: service(), + flashMessages: service(), - refreshAfterLogin: observer('session.isLoggedIn', function() { - this.refresh(); - }), + refreshAfterLogin: observer('session.isLoggedIn', function() { + this.refresh(); + }), - async model(params) { - const requestedVersion = params.version_num === 'all' ? '' : params.version_num; - const crate = this.modelFor('crate'); - const controller = this.controllerFor(this.routeName); - const maxVersion = crate.get('max_version'); + async model(params) { + const requestedVersion = params.version_num === 'all' ? '' : params.version_num; + const crate = this.modelFor('crate'); + const controller = this.controllerFor(this.routeName); + const maxVersion = crate.get('max_version'); - const isUnstableVersion = version => { - const versionLen = version.length; - let majorMinorPatchChars = 0; - let result = false; + const isUnstableVersion = version => { + const versionLen = version.length; + let majorMinorPatchChars = 0; + let result = false; - for (let i = 0; i < versionLen; i++) { - const char = version.charAt(i); + for (let i = 0; i < versionLen; i++) { + const char = version.charAt(i); - if (!isNaN(parseInt(char)) || char === '.') { - majorMinorPatchChars++; - } else { - break; - } - } - - if (versionLen !== majorMinorPatchChars) { - result = true; - } - - return result; - }; - - const fetchCrateDocumentation = () => { - if (!crate.get('documentation') || crate.get('documentation').substr(0, 16) === 'https://docs.rs/') { - let crateName = crate.get('name'); - let crateVersion = params.version_num; - ajax(`https://docs.rs/crate/${crateName}/${crateVersion}/builds.json`, { mode: 'cors' }).then(r => { - if (r.length > 0 && r[0].build_status === true) { - crate.set('documentation', `https://docs.rs/${crateName}/${crateVersion}/`); - } - }); - } - }; - - // Fallback to the crate's last stable version - // If `max_version` is `0.0.0` then all versions have been yanked - if (!requestedVersion && maxVersion !== '0.0.0') { - if (isUnstableVersion(maxVersion)) { - crate - .get('versions') - .then(versions => { - const latestStableVersion = versions.find(version => { - if (!isUnstableVersion(version.get('num')) && !version.get('yanked')) { - return version; - } - }); - - if (latestStableVersion == null) { - // If no stable version exists, fallback to `maxVersion` - params.version_num = maxVersion; - } else { - params.version_num = latestStableVersion.get('num'); - } - }) - .then(fetchCrateDocumentation); - } else { - params.version_num = maxVersion; - fetchCrateDocumentation(); - } + if (!isNaN(parseInt(char)) || char === '.') { + majorMinorPatchChars++; } else { - fetchCrateDocumentation(); - } - - controller.set('crate', crate); - controller.set('requestedVersion', requestedVersion); - controller.set('fetchingFollowing', true); - - if (this.get('session.currentUser')) { - ajax(`/api/v1/crates/${crate.get('name')}/following`) - .then(d => controller.set('following', d.following)) - .finally(() => controller.set('fetchingFollowing', false)); + break; } - - // Find version model - let versions = await crate.get('versions'); - - const version = versions.find(version => version.get('num') === params.version_num); - if (params.version_num && !version) { - this.flashMessages.queue(`Version '${params.version_num}' of crate '${crate.get('name')}' does not exist`); - } - - const result = version || versions.find(version => version.get('num') === maxVersion) || versions.objectAt(0); - - if (result.get('readme_path')) { - fetch(result.get('readme_path')) - .then(async r => { - if (r.ok) { - crate.set('readme', await r.text()); - } else { - crate.set('readme', null); - } - }) - .catch(() => { - crate.set('readme', null); - }); - } - - return result; - }, - - serialize(model) { - let version_num = model.get('num'); - return { version_num }; - }, + } + + if (versionLen !== majorMinorPatchChars) { + result = true; + } + + return result; + }; + + const fetchCrateDocumentation = () => { + if (!crate.get('documentation') || crate.get('documentation').substr(0, 16) === 'https://docs.rs/') { + let crateName = crate.get('name'); + let crateVersion = params.version_num; + ajax(`https://docs.rs/crate/${crateName}/${crateVersion}/builds.json`, { mode: 'cors' }).then(r => { + if (r.length > 0 && r[0].build_status === true) { + crate.set('documentation', `https://docs.rs/${crateName}/${crateVersion}/`); + } + }); + } + }; + + // Fallback to the crate's last stable version + // If `max_version` is `0.0.0` then all versions have been yanked + if (!requestedVersion && maxVersion !== '0.0.0') { + if (isUnstableVersion(maxVersion)) { + crate + .get('versions') + .then(versions => { + const latestStableVersion = versions.find(version => { + if (!isUnstableVersion(version.get('num')) && !version.get('yanked')) { + return version; + } + }); + + if (latestStableVersion == null) { + // If no stable version exists, fallback to `maxVersion` + params.version_num = maxVersion; + } else { + params.version_num = latestStableVersion.get('num'); + } + }) + .then(fetchCrateDocumentation); + } else { + params.version_num = maxVersion; + fetchCrateDocumentation(); + } + } else { + fetchCrateDocumentation(); + } + + controller.set('crate', crate); + controller.set('requestedVersion', requestedVersion); + controller.set('fetchingFollowing', true); + + if (this.get('session.currentUser')) { + ajax(`/api/v1/crates/${crate.get('name')}/following`) + .then(d => controller.set('following', d.following)) + .finally(() => controller.set('fetchingFollowing', false)); + } + + // Find version model + let versions = await crate.get('versions'); + + const version = versions.find(version => version.get('num') === params.version_num); + if (params.version_num && !version) { + this.flashMessages.queue(`Version '${params.version_num}' of crate '${crate.get('name')}' does not exist`); + } + + const result = version || versions.find(version => version.get('num') === maxVersion) || versions.objectAt(0); + + if (result.get('readme_path')) { + fetch(result.get('readme_path')) + .then(async r => { + if (r.ok) { + crate.set('readme', await r.text()); + } else { + crate.set('readme', null); + } + }) + .catch(() => { + crate.set('readme', null); + }); + } + + return result; + }, + + serialize(model) { + let version_num = model.get('num'); + return { version_num }; + }, }); diff --git a/app/routes/crates.js b/app/routes/crates.js index 17f7362a51f..b0968c8e54a 100644 --- a/app/routes/crates.js +++ b/app/routes/crates.js @@ -1,19 +1,19 @@ import Route from '@ember/routing/route'; export default Route.extend({ - queryParams: { - letter: { refreshModel: true }, - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + letter: { refreshModel: true }, + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - // The backend throws an error if the letter param is - // empty or null. - if (!params.letter) { - delete params.letter; - } + model(params) { + // The backend throws an error if the letter param is + // empty or null. + if (!params.letter) { + delete params.letter; + } - return this.store.query('crate', params); - }, + return this.store.query('crate', params); + }, }); diff --git a/app/routes/dashboard.js b/app/routes/dashboard.js index 8e13703b0c7..2883935b16e 100644 --- a/app/routes/dashboard.js +++ b/app/routes/dashboard.js @@ -5,34 +5,34 @@ import RSVP from 'rsvp'; import AuthenticatedRoute from '../mixins/authenticated-route'; export default Route.extend(AuthenticatedRoute, { - setupController(controller) { - this._super(...arguments); + setupController(controller) { + this._super(...arguments); - controller.set('myCrates', this.get('data.myCrates')); - controller.set('myFollowing', this.get('data.myFollowing')); - controller.set('myStats', this.get('data.myStats')); + controller.set('myCrates', this.get('data.myCrates')); + controller.set('myFollowing', this.get('data.myFollowing')); + controller.set('myStats', this.get('data.myStats')); - if (!controller.loadingMore) { - controller.set('myFeed', A()); - controller.send('loadMore'); - } - }, + if (!controller.loadingMore) { + controller.set('myFeed', A()); + controller.send('loadMore'); + } + }, - model() { - return this.get('session.currentUser'); - }, + model() { + return this.get('session.currentUser'); + }, - async afterModel(user) { - let myCrates = this.store.query('crate', { - user_id: user.get('id'), - }); + async afterModel(user) { + let myCrates = this.store.query('crate', { + user_id: user.get('id'), + }); - let myFollowing = this.store.query('crate', { - following: 1, - }); + let myFollowing = this.store.query('crate', { + following: 1, + }); - let myStats = user.stats(); + let myStats = user.stats(); - this.set('data', await RSVP.hash({ myCrates, myFollowing, myStats })); - }, + this.set('data', await RSVP.hash({ myCrates, myFollowing, myStats })); + }, }); diff --git a/app/routes/github-authorize.js b/app/routes/github-authorize.js index 0fcc44e5d58..4ee10cd9a18 100644 --- a/app/routes/github-authorize.js +++ b/app/routes/github-authorize.js @@ -16,22 +16,22 @@ import { serializeQueryParams } from 'ember-fetch/utils/serialize-query-params'; * @see `/login` route */ export default Route.extend({ - async beforeModel(transition) { - try { - let queryParams = serializeQueryParams(transition.queryParams); - let resp = await fetch(`/authorize?${queryParams}`); - let json = await resp.json(); - let item = JSON.stringify({ ok: resp.ok, data: json }); - if (window.opener) { - window.opener.github_response = item; - } - } catch (d) { - let item = JSON.stringify({ ok: false, data: d }); - if (window.opener) { - window.opener.github_response = item; - } - } finally { - window.close(); - } - }, + async beforeModel(transition) { + try { + let queryParams = serializeQueryParams(transition.queryParams); + let resp = await fetch(`/authorize?${queryParams}`); + let json = await resp.json(); + let item = JSON.stringify({ ok: resp.ok, data: json }); + if (window.opener) { + window.opener.github_response = item; + } + } catch (d) { + let item = JSON.stringify({ ok: false, data: d }); + if (window.opener) { + window.opener.github_response = item; + } + } finally { + window.close(); + } + }, }); diff --git a/app/routes/github-login.js b/app/routes/github-login.js index 8386a59318f..904e386725b 100644 --- a/app/routes/github-login.js +++ b/app/routes/github-login.js @@ -15,8 +15,8 @@ import ajax from 'ember-fetch/ajax'; * @see `github-authorize` route */ export default Route.extend({ - async beforeModel() { - let url = await ajax(`/authorize_url`); - window.location = url.url; - }, + async beforeModel() { + let url = await ajax(`/authorize_url`); + window.location = url.url; + }, }); diff --git a/app/routes/index.js b/app/routes/index.js index 44a52edf53a..f3502da44d8 100644 --- a/app/routes/index.js +++ b/app/routes/index.js @@ -1,19 +1,19 @@ import Route from '@ember/routing/route'; export default Route.extend({ - headTags() { - return [ - { - type: 'meta', - attrs: { - name: 'description', - content: 'cargo is the package manager and crate host for rust', - }, - }, - ]; - }, + headTags() { + return [ + { + type: 'meta', + attrs: { + name: 'description', + content: 'cargo is the package manager and crate host for rust', + }, + }, + ]; + }, - setupController(controller) { - controller.dataTask.perform(); - }, + setupController(controller) { + controller.dataTask.perform(); + }, }); diff --git a/app/routes/install.js b/app/routes/install.js index 006e9fece36..7c52f9ce3da 100644 --- a/app/routes/install.js +++ b/app/routes/install.js @@ -1,7 +1,7 @@ import Route from '@ember/routing/route'; export default Route.extend({ - redirect() { - window.location = 'https://doc.rust-lang.org/cargo/getting-started/installation.html'; - }, + redirect() { + window.location = 'https://doc.rust-lang.org/cargo/getting-started/installation.html'; + }, }); diff --git a/app/routes/keyword.js b/app/routes/keyword.js index 49056de679f..cc5dfa1dba0 100644 --- a/app/routes/keyword.js +++ b/app/routes/keyword.js @@ -2,14 +2,14 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default Route.extend({ - flashMessages: service(), + flashMessages: service(), - model({ keyword_id }) { - return this.store.find('keyword', keyword_id).catch(e => { - if (e.errors.some(e => e.detail === 'Not Found')) { - this.flashMessages.queue(`Keyword '${keyword_id}' does not exist`); - return this.replaceWith('index'); - } - }); - }, + model({ keyword_id }) { + return this.store.find('keyword', keyword_id).catch(e => { + if (e.errors.some(e => e.detail === 'Not Found')) { + this.flashMessages.queue(`Keyword '${keyword_id}' does not exist`); + return this.replaceWith('index'); + } + }); + }, }); diff --git a/app/routes/keyword/index.js b/app/routes/keyword/index.js index 9f8bcb5ba10..48f0e56588e 100644 --- a/app/routes/keyword/index.js +++ b/app/routes/keyword/index.js @@ -1,18 +1,18 @@ import Route from '@ember/routing/route'; export default Route.extend({ - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - params.keyword = this.modelFor('keyword').id; - return this.store.query('crate', params); - }, + model(params) { + params.keyword = this.modelFor('keyword').id; + return this.store.query('crate', params); + }, - setupController(controller) { - controller.set('keyword', this.modelFor('keyword')); - this._super(...arguments); - }, + setupController(controller) { + controller.set('keyword', this.modelFor('keyword')); + this._super(...arguments); + }, }); diff --git a/app/routes/keywords.js b/app/routes/keywords.js index 3f450f138c7..1027b4ac4f5 100644 --- a/app/routes/keywords.js +++ b/app/routes/keywords.js @@ -1,12 +1,12 @@ import Route from '@ember/routing/route'; export default Route.extend({ - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - return this.store.query('keyword', params); - }, + model(params) { + return this.store.query('keyword', params); + }, }); diff --git a/app/routes/login.js b/app/routes/login.js index 07ddf3fdab7..bed6ee39b3e 100644 --- a/app/routes/login.js +++ b/app/routes/login.js @@ -9,69 +9,69 @@ import { inject as service } from '@ember/service'; * @see `github-authorize` route */ export default Route.extend({ - flashMessages: service(), - session: service(), + flashMessages: service(), + session: service(), - beforeModel(transition) { - try { - localStorage.removeItem('github_response'); - } catch (e) { - // ignore error - } + beforeModel(transition) { + try { + localStorage.removeItem('github_response'); + } catch (e) { + // ignore error + } - window.github_response = undefined; - let windowDimensions = [ - 'width=1000', - 'height=450', - 'toolbar=0', - 'scrollbars=1', - 'status=1', - 'resizable=1', - 'location=1', - 'menuBar=0', - ].join(','); + window.github_response = undefined; + let windowDimensions = [ + 'width=1000', + 'height=450', + 'toolbar=0', + 'scrollbars=1', + 'status=1', + 'resizable=1', + 'location=1', + 'menuBar=0', + ].join(','); - let win = window.open('/github_login', 'Authorization', windowDimensions); - if (!win) { - return; - } + let win = window.open('/github_login', 'Authorization', windowDimensions); + if (!win) { + return; + } - // For the life of me I cannot figure out how to do this other than - // polling - let oauthInterval = window.setInterval(() => { - if (!win.closed) { - return; - } - window.clearInterval(oauthInterval); - let json = window.github_response; - window.github_response = undefined; - if (!json) { - return; - } + // For the life of me I cannot figure out how to do this other than + // polling + let oauthInterval = window.setInterval(() => { + if (!win.closed) { + return; + } + window.clearInterval(oauthInterval); + let json = window.github_response; + window.github_response = undefined; + if (!json) { + return; + } - let response = JSON.parse(json); - if (!response) { - return; - } + let response = JSON.parse(json); + if (!response) { + return; + } - let { data } = response; - if (data && data.errors) { - let error = `Failed to log in: ${data.errors[0].detail}`; - this.flashMessages.show(error); - return; - } else if (!response.ok) { - this.flashMessages.show('Failed to log in'); - return; - } + let { data } = response; + if (data && data.errors) { + let error = `Failed to log in: ${data.errors[0].detail}`; + this.flashMessages.show(error); + return; + } else if (!response.ok) { + this.flashMessages.show('Failed to log in'); + return; + } - let user = this.store.push(this.store.normalize('user', data.user)); - let transition = this.get('session.savedTransition'); - this.session.loginUser(user); - if (transition) { - transition.retry(); - } - }, 200); + let user = this.store.push(this.store.normalize('user', data.user)); + let transition = this.get('session.savedTransition'); + this.session.loginUser(user); + if (transition) { + transition.retry(); + } + }, 200); - transition.abort(); - }, + transition.abort(); + }, }); diff --git a/app/routes/logout.js b/app/routes/logout.js index f5e3e90c556..7fc5fd7bb30 100644 --- a/app/routes/logout.js +++ b/app/routes/logout.js @@ -4,13 +4,13 @@ import { inject as service } from '@ember/service'; import ajax from 'ember-fetch/ajax'; export default Route.extend({ - session: service(), + session: service(), - async activate() { - await ajax(`/logout`, { method: 'DELETE' }); - run(() => { - this.session.logoutUser(); - this.transitionTo('index'); - }); - }, + async activate() { + await ajax(`/logout`, { method: 'DELETE' }); + run(() => { + this.session.logoutUser(); + this.transitionTo('index'); + }); + }, }); diff --git a/app/routes/me/crates.js b/app/routes/me/crates.js index a793a754055..9d302af0c46 100644 --- a/app/routes/me/crates.js +++ b/app/routes/me/crates.js @@ -3,13 +3,13 @@ import Route from '@ember/routing/route'; import AuthenticatedRoute from '../../mixins/authenticated-route'; export default Route.extend(AuthenticatedRoute, { - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - params.user_id = this.get('session.currentUser.id'); - return this.store.query('crate', params); - }, + model(params) { + params.user_id = this.get('session.currentUser.id'); + return this.store.query('crate', params); + }, }); diff --git a/app/routes/me/following.js b/app/routes/me/following.js index 31966532829..3843fc2d622 100644 --- a/app/routes/me/following.js +++ b/app/routes/me/following.js @@ -3,13 +3,13 @@ import Route from '@ember/routing/route'; import AuthenticatedRoute from '../../mixins/authenticated-route'; export default Route.extend(AuthenticatedRoute, { - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - params.following = 1; - return this.store.query('crate', params); - }, + model(params) { + params.following = 1; + return this.store.query('crate', params); + }, }); diff --git a/app/routes/me/index.js b/app/routes/me/index.js index b205f67453d..7e0fb31bcbe 100644 --- a/app/routes/me/index.js +++ b/app/routes/me/index.js @@ -3,10 +3,10 @@ import Route from '@ember/routing/route'; import AuthenticatedRoute from '../../mixins/authenticated-route'; export default Route.extend(AuthenticatedRoute, { - model() { - return { - user: this.get('session.currentUser'), - api_tokens: this.store.findAll('api-token'), - }; - }, + model() { + return { + user: this.get('session.currentUser'), + api_tokens: this.store.findAll('api-token'), + }; + }, }); diff --git a/app/routes/me/pending-invites.js b/app/routes/me/pending-invites.js index 318ce3b8fe4..d8a5e77de76 100644 --- a/app/routes/me/pending-invites.js +++ b/app/routes/me/pending-invites.js @@ -3,7 +3,7 @@ import Route from '@ember/routing/route'; import AuthenticatedRoute from '../../mixins/authenticated-route'; export default Route.extend(AuthenticatedRoute, { - model() { - return this.store.findAll('crate-owner-invite'); - }, + model() { + return this.store.findAll('crate-owner-invite'); + }, }); diff --git a/app/routes/search.js b/app/routes/search.js index 8132c7235fc..62a8325e11d 100644 --- a/app/routes/search.js +++ b/app/routes/search.js @@ -1,19 +1,19 @@ import Route from '@ember/routing/route'; export default Route.extend({ - queryParams: { - q: { refreshModel: true }, - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + q: { refreshModel: true }, + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - // we need a model() implementation that changes, otherwise the setupController() hook - // is not called and we won't reload the results if a new query string is used - return params; - }, + model(params) { + // we need a model() implementation that changes, otherwise the setupController() hook + // is not called and we won't reload the results if a new query string is used + return params; + }, - setupController(controller, params) { - controller.dataTask.perform(params); - }, + setupController(controller, params) { + controller.dataTask.perform(params); + }, }); diff --git a/app/routes/team.js b/app/routes/team.js index a0c539e2157..48706381ad2 100644 --- a/app/routes/team.js +++ b/app/routes/team.js @@ -3,31 +3,31 @@ import { inject as service } from '@ember/service'; import RSVP from 'rsvp'; export default Route.extend({ - flashMessages: service(), + flashMessages: service(), - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - const { team_id } = params; + model(params) { + const { team_id } = params; - return this.store.queryRecord('team', { team_id }).then( - team => { - params.team_id = team.get('id'); - params.include_yanked = 'n'; - return RSVP.hash({ - crates: this.store.query('crate', params), - team, - }); - }, - e => { - if (e.errors.some(e => e.detail === 'Not Found')) { - this.flashMessages.queue(`Team '${params.team_id}' does not exist`); - return this.replaceWith('index'); - } - }, - ); - }, + return this.store.queryRecord('team', { team_id }).then( + team => { + params.team_id = team.get('id'); + params.include_yanked = 'n'; + return RSVP.hash({ + crates: this.store.query('crate', params), + team, + }); + }, + e => { + if (e.errors.some(e => e.detail === 'Not Found')) { + this.flashMessages.queue(`Team '${params.team_id}' does not exist`); + return this.replaceWith('index'); + } + }, + ); + }, }); diff --git a/app/routes/user.js b/app/routes/user.js index a47e3b258c8..10bbe8b292e 100644 --- a/app/routes/user.js +++ b/app/routes/user.js @@ -3,30 +3,30 @@ import { inject as service } from '@ember/service'; import RSVP from 'rsvp'; export default Route.extend({ - flashMessages: service(), + flashMessages: service(), - queryParams: { - page: { refreshModel: true }, - sort: { refreshModel: true }, - }, + queryParams: { + page: { refreshModel: true }, + sort: { refreshModel: true }, + }, - model(params) { - const { user_id } = params; - return this.store.queryRecord('user', { user_id }).then( - user => { - params.user_id = user.get('id'); - params.include_yanked = 'n'; - return RSVP.hash({ - crates: this.store.query('crate', params), - user, - }); - }, - e => { - if (e.errors.some(e => e.detail === 'Not Found')) { - this.flashMessages.queue(`User '${params.user_id}' does not exist`); - return this.replaceWith('index'); - } - }, - ); - }, + model(params) { + const { user_id } = params; + return this.store.queryRecord('user', { user_id }).then( + user => { + params.user_id = user.get('id'); + params.include_yanked = 'n'; + return RSVP.hash({ + crates: this.store.query('crate', params), + user, + }); + }, + e => { + if (e.errors.some(e => e.detail === 'Not Found')) { + this.flashMessages.queue(`User '${params.user_id}' does not exist`); + return this.replaceWith('index'); + } + }, + ); + }, }); diff --git a/app/serializers/api-token.js b/app/serializers/api-token.js index 52a9a49e870..449579d7e4c 100644 --- a/app/serializers/api-token.js +++ b/app/serializers/api-token.js @@ -1,7 +1,7 @@ import DS from 'ember-data'; export default DS.RESTSerializer.extend({ - payloadKeyFromModelName() { - return 'api_token'; - }, + payloadKeyFromModelName() { + return 'api_token'; + }, }); diff --git a/app/serializers/crate-owner-invite.js b/app/serializers/crate-owner-invite.js index 65bcb7e7cfe..724732be8b9 100644 --- a/app/serializers/crate-owner-invite.js +++ b/app/serializers/crate-owner-invite.js @@ -1,11 +1,11 @@ import DS from 'ember-data'; export default DS.RESTSerializer.extend({ - primaryKey: 'crate_id', - modelNameFromPayloadKey() { - return 'crate-owner-invite'; - }, - payloadKeyFromModelName() { - return 'crate_owner_invite'; - }, + primaryKey: 'crate_id', + modelNameFromPayloadKey() { + return 'crate-owner-invite'; + }, + payloadKeyFromModelName() { + return 'crate_owner_invite'; + }, }); diff --git a/app/serializers/crate.js b/app/serializers/crate.js index b8b9500e2d8..cde8d51c725 100644 --- a/app/serializers/crate.js +++ b/app/serializers/crate.js @@ -1,13 +1,13 @@ import DS from 'ember-data'; export default DS.RESTSerializer.extend({ - isNewSerializerAPI: true, + isNewSerializerAPI: true, - extractRelationships(modelClass, resourceHash) { - if (resourceHash.versions == null) { - delete resourceHash.versions; - } + extractRelationships(modelClass, resourceHash) { + if (resourceHash.versions == null) { + delete resourceHash.versions; + } - return this._super(...arguments); - }, + return this._super(...arguments); + }, }); diff --git a/app/serializers/dependency.js b/app/serializers/dependency.js index 865e3a63a4e..e03395aed0b 100644 --- a/app/serializers/dependency.js +++ b/app/serializers/dependency.js @@ -1,7 +1,7 @@ import DS from 'ember-data'; export default DS.RESTSerializer.extend({ - attrs: { - version: 'version_id', - }, + attrs: { + version: 'version_id', + }, }); diff --git a/app/serializers/version-download.js b/app/serializers/version-download.js index 48c5589a423..830917e2b9e 100644 --- a/app/serializers/version-download.js +++ b/app/serializers/version-download.js @@ -1,7 +1,7 @@ import DS from 'ember-data'; export default DS.RESTSerializer.extend({ - extractId(modelClass, resourceHash) { - return `${resourceHash.date}-${resourceHash.version}`; - }, + extractId(modelClass, resourceHash) { + return `${resourceHash.date}-${resourceHash.version}`; + }, }); diff --git a/app/services/flash-messages.js b/app/services/flash-messages.js index 62ff4826e35..e8f2568fe54 100644 --- a/app/services/flash-messages.js +++ b/app/services/flash-messages.js @@ -1,19 +1,19 @@ import Service from '@ember/service'; export default Service.extend({ - message: null, - _nextMessage: null, + message: null, + _nextMessage: null, - show(message) { - this.set('message', message); - }, + show(message) { + this.set('message', message); + }, - queue(message) { - this.set('_nextMessage', message); - }, + queue(message) { + this.set('_nextMessage', message); + }, - step() { - this.set('message', this._nextMessage); - this.set('_nextMessage', null); - }, + step() { + this.set('message', this._nextMessage); + this.set('_nextMessage', null); + }, }); diff --git a/app/services/search.js b/app/services/search.js index 47ff25937ce..89fb6aa8d73 100644 --- a/app/services/search.js +++ b/app/services/search.js @@ -1,5 +1,5 @@ import Service from '@ember/service'; export default Service.extend({ - q: null, + q: null, }); diff --git a/app/services/session.js b/app/services/session.js index 2eb60002234..9b9903f38b8 100644 --- a/app/services/session.js +++ b/app/services/session.js @@ -2,91 +2,91 @@ import Service, { inject as service } from '@ember/service'; import ajax from 'ember-fetch/ajax'; export default Service.extend({ - savedTransition: null, - abortedTransition: null, - isLoggedIn: false, - currentUser: null, - currentUserDetected: false, + savedTransition: null, + abortedTransition: null, + isLoggedIn: false, + currentUser: null, + currentUserDetected: false, - store: service(), - router: service(), + store: service(), + router: service(), - init() { - this._super(...arguments); - let isLoggedIn; - try { - isLoggedIn = localStorage.getItem('isLoggedIn') === '1'; - } catch (e) { - isLoggedIn = false; - } - this.set('isLoggedIn', isLoggedIn); - this.set('currentUser', null); - }, + init() { + this._super(...arguments); + let isLoggedIn; + try { + isLoggedIn = localStorage.getItem('isLoggedIn') === '1'; + } catch (e) { + isLoggedIn = false; + } + this.set('isLoggedIn', isLoggedIn); + this.set('currentUser', null); + }, - loginUser(user) { - this.set('isLoggedIn', true); - this.set('currentUser', user); - try { - localStorage.setItem('isLoggedIn', '1'); - } catch (e) { - // ignore error - } - }, + loginUser(user) { + this.set('isLoggedIn', true); + this.set('currentUser', user); + try { + localStorage.setItem('isLoggedIn', '1'); + } catch (e) { + // ignore error + } + }, - logoutUser() { - this.set('savedTransition', null); - this.set('abortedTransition', null); - this.set('isLoggedIn', null); - this.set('currentUser', null); + logoutUser() { + this.set('savedTransition', null); + this.set('abortedTransition', null); + this.set('isLoggedIn', null); + this.set('currentUser', null); - try { - localStorage.removeItem('isLoggedIn'); - } catch (e) { - // ignore error - } - }, + try { + localStorage.removeItem('isLoggedIn'); + } catch (e) { + // ignore error + } + }, - loadUser() { - if (this.isLoggedIn && !this.currentUser) { - this.fetchUser() - .catch(() => this.logoutUser()) - .finally(() => { - this.set('currentUserDetected', true); - let transition = this.abortedTransition; - if (transition) { - transition.retry(); - this.set('abortedTransition', null); - } - }); - } else { - this.set('currentUserDetected', true); - } - }, - - fetchUser() { - return ajax('/api/v1/me').then(response => { - this.set('currentUser', this.store.push(this.store.normalize('user', response.user))); + loadUser() { + if (this.isLoggedIn && !this.currentUser) { + this.fetchUser() + .catch(() => this.logoutUser()) + .finally(() => { + this.set('currentUserDetected', true); + let transition = this.abortedTransition; + if (transition) { + transition.retry(); + this.set('abortedTransition', null); + } }); - }, + } else { + this.set('currentUserDetected', true); + } + }, + + fetchUser() { + return ajax('/api/v1/me').then(response => { + this.set('currentUser', this.store.push(this.store.normalize('user', response.user))); + }); + }, - checkCurrentUser(transition, beforeRedirect) { - if (this.currentUser) { - return; - } + checkCurrentUser(transition, beforeRedirect) { + if (this.currentUser) { + return; + } - // The current user is loaded asynchronously, so if we haven't actually - // loaded the current user yet then we need to wait for it to be loaded. - // Once we've done that we can retry the transition and start the whole - // process over again! - if (!this.currentUserDetected) { - transition.abort(); - this.set('abortedTransition', transition); - } else { - this.set('savedTransition', transition); - if (beforeRedirect) { - beforeRedirect(); - } - return this.router.transitionTo('index'); - } - }, + // The current user is loaded asynchronously, so if we haven't actually + // loaded the current user yet then we need to wait for it to be loaded. + // Once we've done that we can retry the transition and start the whole + // process over again! + if (!this.currentUserDetected) { + transition.abort(); + this.set('abortedTransition', transition); + } else { + this.set('savedTransition', transition); + if (beforeRedirect) { + beforeRedirect(); + } + return this.router.transitionTo('index'); + } + }, }); diff --git a/app/templates/application.hbs b/app/templates/application.hbs index 883a6ea4d31..3cffa08ef8d 100644 --- a/app/templates/application.hbs +++ b/app/templates/application.hbs @@ -4,133 +4,133 @@ {{google-jsapi}}
Oops, that route doesn't exist!
- Perhaps a search of the site may help? + Perhaps a search of the site may help? - {{input type="text" class="search" - placeholder="Search" - value=search - enter="search" - required=true}} + {{input type="text" class="search" + placeholder="Search" + value=search + enter="search" + required=true}}
diff --git a/app/templates/categories.hbs b/app/templates/categories.hbs index f59c02996bb..b3ae63b6e5e 100644 --- a/app/templates/categories.hbs +++ b/app/templates/categories.hbs @@ -1,72 +1,72 @@ {{ title 'Categories' }}{{ category.description }}
+{{ category.description }}
~/.cargo/credentials
- with:
+ ~/.cargo/credentials
+ with:
- cargo login {{ api_token.token }}-
cargo login {{ api_token.token }}
We have sent a verification email to your address.
+ {{/if}} +Your email has not yet been verified.
+We have sent a verification email to your address.
- {{/if}} -Your email has not yet been verified.
-{{emailError}}
-{{emailError}}
+Success! You've been added as an owner of crate - {{#link-to 'crate' invite.crate_name}}{{invite.crate_name}}{{/link-to}}. -
- {{else if isDeclined}} -Declined. You have not been added as an owner of crate - {{#link-to 'crate' invite.crate_name}}{{invite.crate_name}}{{/link-to}}. -
- {{else}} + {{#if isAccepted }} ++ Success! You've been added as an owner of crate + {{#link-to 'crate' invite.crate_name}}{{invite.crate_name}}{{/link-to}}. +
+ {{else if isDeclined}} ++ Declined. You have not been added as an owner of crate + {{#link-to 'crate' invite.crate_name}}{{invite.crate_name}}{{/link-to}}. +
+ {{else}}Invited by: - {{#link-to 'user' invite.invited_by_username}} - {{invite.invited_by_username}} - {{/link-to}} -
-+ Invited by: + {{#link-to 'user' invite.invited_by_username}} + {{invite.invited_by_username}} + {{/link-to}} +
+{{inviteError}}
{{inviteError}}
-
- Redirecting you to {{model.documentation}}
…
+ Redirecting you to {{model.documentation}}
…
{{removed}}
-- This crate has been yanked, but it is still available for download for other crates that - may be depending on it. -
-- You may wish to {{#link-to 'crate.versions' crate}}view all versions{{/link-to}} to find - one that has not been yanked. -
- {{else}} -{{ crate.name }} = "{{ currentVersion.num }}"
- {{#if (is-clipboard-supported)}}
- {{#copy-button clipboardTarget="#crate-toml" success=(action 'copySuccess') error=(action 'copyError') title="Copy to clipboard"}}
- {{svg-jar "copy" alt="Copy to clipboard"}}
- {{/copy-button}}
- {{/if}}
- + This crate has been yanked, but it is still available for download for other crates that + may be depending on it. +
++ You may wish to {{#link-to 'crate.versions' crate}}view all versions{{/link-to}} to find + one that has not been yanked. +
+ {{else}} +{{ crate.name }} = "{{ currentVersion.num }}"
+ {{#if (is-clipboard-supported)}}
+ {{#copy-button clipboardTarget="#crate-toml" success=(action 'copySuccess') error=(action 'copyError') title="Copy to clipboard"}}
+ {{svg-jar "copy" alt="Copy to clipboard"}}
+ {{/copy-button}}
+ {{/if}}
+ {{ crate.description }}
-{{ crate.description }}
+{{ currentVersion.license }}
-{{ currentVersion.license }}
+- {{#link-to 'crate.owners' crate}} - Manage owners - {{/link-to}} -
- {{/if}} + {{#if isOwner}} ++ {{#link-to 'crate.owners' crate}} + Manage owners + {{/link-to}} +
+ {{/if}} -- {{model.stack}} + {{model.stack}}diff --git a/app/templates/index.hbs b/app/templates/index.hbs index 03c86a5ee81..c11be7b8882 100644 --- a/app/templates/index.hbs +++ b/app/templates/index.hbs @@ -1,63 +1,63 @@
- Redirecting you to https://doc.rust-lang.org/cargo/getting-started/installation.html
…
+ Redirecting you to https://doc.rust-lang.org/cargo/getting-started/installation.html
…
- If you want to use package commands from the command line, you will need to
- login with cargo login (token)
using one of the tokens listed below.
-
- When working in shared environments, supplying the token on the command line could
- expose it to prying eyes. To avoid this, enter cargo login
and supply your
- token when prompted.
-
+ If you want to use package commands from the command line, you will need to
+ login with cargo login (token)
using one of the tokens listed below.
+
+ When working in shared environments, supplying the token on the command line could
+ expose it to prying eyes. To avoid this, enter cargo login
and supply your
+ token when prompted.
+
You don't seem to have any pending invitations.
- {{/each}} -You don't seem to have any pending invitations.
+ {{/each}} +-In general, these policies are guidelines. Problems are often contextual, and -exceptional circumstances sometimes require exceptional measures. We plan to -continue to clarify and expand these rules over time as new circumstances -arise. If your problem is not described below, consider sending us an email. + In general, these policies are guidelines. Problems are often contextual, and + exceptional circumstances sometimes require exceptional measures. We plan to + continue to clarify and expand these rules over time as new circumstances + arise. If your problem is not described below, consider + sending us an email.
-We have a first-come, first-served policy on crate names. Upon publishing a -package, the publisher will be made owner of the package on Crates.io. + We have a first-come, first-served policy on crate names. Upon publishing a + package, the publisher will be made owner of the package on Crates.io.
-If someone wants to take over a package, and the previous owner agrees, the -existing maintainer can add them as an owner, and the new maintainer can remove -them. If necessary, the team may reach out to inactive maintainers and help -mediate the process of ownership transfer. + If someone wants to take over a package, and the previous owner agrees, the + existing maintainer can add them as an owner, and the new maintainer can remove + them. If necessary, the team may reach out to inactive maintainers and help + mediate the process of ownership transfer.
-Using an automated tool to claim ownership of a large number of package names -is not permitted. We reserve the right to block traffic or revoke ownership -of any package we determine to have been claimed by an automated tool. + Using an automated tool to claim ownership of a large number of package names + is not permitted. We reserve the right to block traffic or revoke ownership + of any package we determine to have been claimed by an automated tool.
-Many questions are specialized instances of a more general form: “Under what -circumstances can a package be removed from Crates.io?” + Many questions are specialized instances of a more general form: “Under what + circumstances can a package be removed from Crates.io?”
-The short version is that packages are first-come, first-served, and we won’t -attempt to get into policing what exactly makes a legitimate package. We will -do what the law requires us to do, and address flagrant violations of the Rust -Code of Conduct. + The short version is that packages are first-come, first-served, and we won’t + attempt to get into policing what exactly makes a legitimate package. We will + do what the law requires us to do, and address flagrant violations of the Rust + Code of Conduct.
-We do not have any policies to define 'squatting', and so will not hand over -ownership of a package for that reason. + We do not have any policies to define 'squatting', and so will not hand over + ownership of a package for that reason.
-For issues such as DMCA violations, trademark and copyright infringement, -Crates.io will respect Mozilla Legal’s decisions with regards to content that -is hosted. + For issues such as DMCA violations, trademark and copyright infringement, + Crates.io will respect Mozilla Legal’s decisions with regards to content that + is hosted.
-The Rust project has a Code -of Conduct which governs appropriate conduct for the Rust community. In -general, any content on Crates.io that violates the Code of Conduct may be -removed. Here, content can refer to but is not limited to: + The Rust project has a + Code of Conduct + which governs appropriate conduct for the Rust community. In + general, any content on Crates.io that violates the Code of Conduct may be + removed. Here, content can refer to but is not limited to:
-There are two important, related aspects: + There are two important, related aspects:
-Cargo and crates.io are projects that are governed by the Rust Programming -Language Team. Safety is one of the core principles of Rust, and to that end, -we would like to ensure that cargo and crates.io have secure implementations. -To learn more about disclosing security vulnerabilities, please reference the -Rust Security policy for -more details. + Cargo and crates.io are projects that are governed by the Rust Programming + Language Team. Safety is one of the core principles of Rust, and to that end, + we would like to ensure that cargo and crates.io have secure implementations. + To learn more about disclosing security vulnerabilities, please reference the + Rust Security policy for + more details.
-Thank you for taking the time to responsibly disclose any issues you find. + Thank you for taking the time to responsibly disclose any issues you find.
-Before resorting to crawling crates.io, you should first see if you are able to -gather the information you need from the -crates.io index, which is a public git repository containing the majority -of the information availble through our API. + Before resorting to crawling crates.io, you should first see if you are able to + gather the information you need from the + crates.io index, + which is a public git repository containing the majority + of the information availble through our API. -If the index does not have the information you need, we're also happy to -discuss solutions to your needs that don't require you to crawl the registry. -You can email us at help@crates.io. + If the index does not have the information you need, we're also happy to + discuss solutions to your needs that don't require you to crawl the registry. + You can email us at help@crates.io.
-We allow our API and website to be crawled by commercial crawlers such as -GoogleBot. At our discretion, we may choose to allow access to experimental -crawlers, as long as they limit their request rate to 1 request per second or -less. + We allow our API and website to be crawled by commercial crawlers such as + GoogleBot. At our discretion, we may choose to allow access to experimental + crawlers, as long as they limit their request rate to 1 request per second or + less.
-We also require all crawlers to provide a user-agent header that allows us to
-uniquely identify your bot. This allows us to more accurately monitor any
-impact your bot may have on our service. Providing a user agent that only
-identifies your HTTP client library (such as "request/0.9.1
") increases the
-likelihood that we will block your traffic.
+ We also require all crawlers to provide a user-agent header that allows us to
+ uniquely identify your bot. This allows us to more accurately monitor any
+ impact your bot may have on our service. Providing a user agent that only
+ identifies your HTTP client library (such as "request/0.9.1
") increases the
+ likelihood that we will block your traffic.
-It is recommended, but not required, to include contact information in your user
-agent. This allows us to contact you if we would like a change in your bot's
-behavior without having to block your traffic.
+ It is recommended, but not required, to include contact information in your user
+ agent. This allows us to contact you if we would like a change in your bot's
+ behavior without having to block your traffic.
-Bad: "User-Agent: reqwest/0.9.1
"
-Better: "User-Agent: my_bot
"
-Best: "User-Agent: my_bot (my_bot.com/info)
" or "User-Agent: my_bot (help@my_bot.com)
"
+ Bad: "User-Agent: reqwest/0.9.1
"
+ Better: "User-Agent: my_bot
"
+ Best: "User-Agent: my_bot (my_bot.com/info)
" or "User-Agent: my_bot (help@my_bot.com)
"
-We reserve the right to block traffic from any bot that we determine to be in -violation of this policy or causing an impact on the integrity of our service. + We reserve the right to block traffic from any bot that we determine to be in + violation of this policy or causing an impact on the integrity of our service.
diff --git a/app/templates/search.hbs b/app/templates/search.hbs index f261201d7e0..89282b73454 100644 --- a/app/templates/search.hbs +++ b/app/templates/search.hbs @@ -1,97 +1,97 @@ {{title (concat "Search Results for '" q "'")}}