From ca28b2742eeb6c5c8251baccc74070a92a48b755 Mon Sep 17 00:00:00 2001 From: Josh Justice Date: Fri, 30 Aug 2019 06:07:13 -0400 Subject: [PATCH 1/8] Set tab width to 2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce4b06699b..ab06740047 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "private": true, "prettier": { "printWidth": 120, - "tabWidth": 4, + "tabWidth": 2, "singleQuote": true, "trailingComma": "all" } From 396c0ebc94fa243f3f35ed58c26031dd1fe9d0df Mon Sep 17 00:00:00 2001 From: Josh Justice Date: Fri, 30 Aug 2019 06:07:58 -0400 Subject: [PATCH 2/8] Format to 2 spaces for tabs --- .eslintrc.js | 86 +- .template-lintrc.js | 12 +- app/adapters/api-token.js | 22 +- app/adapters/application.js | 2 +- app/adapters/category-slug.js | 8 +- app/adapters/crate-owner-invite.js | 8 +- app/adapters/crate.js | 52 +- app/adapters/dependency.js | 18 +- app/adapters/team.js | 8 +- app/adapters/user.js | 20 +- app/app.js | 6 +- app/components/api-token-row.js | 70 +- app/components/badge-appveyor.js | 70 +- app/components/badge-azure-devops.js | 20 +- app/components/badge-circle-ci.js | 18 +- app/components/badge-cirrus-ci.js | 18 +- app/components/badge-codecov.js | 24 +- app/components/badge-coveralls.js | 24 +- app/components/badge-gitlab.js | 18 +- ...badge-is-it-maintained-issue-resolution.js | 12 +- .../badge-is-it-maintained-open-issues.js | 12 +- app/components/badge-maintenance.js | 52 +- app/components/badge-travis-ci.js | 18 +- app/components/crate-badge.js | 24 +- app/components/crate-readme.js | 14 +- app/components/crate-row.js | 4 +- app/components/download-graph.js | 324 ++++---- app/components/email-input.js | 183 ++--- app/components/flash-message.js | 10 +- app/components/google-jsapi.js | 36 +- app/components/pending-owner-invite-row.js | 66 +- app/components/rl-dropdown-container.js | 2 +- app/components/rl-dropdown-toggle.js | 48 +- app/components/rl-dropdown.js | 48 +- app/components/user-avatar.js | 40 +- app/components/user-link.js | 14 +- app/components/validated-input.js | 54 +- app/controllers/application.js | 42 +- app/controllers/catch-all.js | 8 +- app/controllers/categories.js | 16 +- app/controllers/category/index.js | 34 +- app/controllers/crate/owners.js | 92 +-- app/controllers/crate/reverse-dependencies.js | 10 +- app/controllers/crate/version.js | 356 ++++----- app/controllers/crates.js | 36 +- app/controllers/dashboard.js | 92 +-- app/controllers/index.js | 30 +- app/controllers/install.js | 14 +- app/controllers/keyword/index.js | 32 +- app/controllers/keywords.js | 16 +- app/controllers/me/crates.js | 32 +- app/controllers/me/following.js | 16 +- app/controllers/me/index.js | 26 +- app/controllers/search.js | 78 +- app/controllers/team.js | 32 +- app/controllers/user.js | 32 +- app/helpers/format-crate-size.js | 10 +- app/helpers/format-email.js | 14 +- app/helpers/format-num.js | 28 +- app/helpers/format-req.js | 4 +- app/helpers/truncate-text.js | 14 +- app/initializers/hashchange.js | 74 +- app/initializers/set-global-promise.js | 6 +- app/mixins/authenticated-route.js | 14 +- app/mixins/pagination.js | 118 +-- app/mixins/rl-dropdown-component.js | 182 ++--- app/models/api-token.js | 8 +- app/models/category-slug.js | 4 +- app/models/category.js | 16 +- app/models/crate-owner-invite.js | 10 +- app/models/crate.js | 100 +-- app/models/dependency.js | 20 +- app/models/keyword.js | 8 +- app/models/team.js | 24 +- app/models/user.js | 22 +- app/models/version-download.js | 10 +- app/models/version.js | 36 +- app/router.js | 78 +- app/routes/application.js | 18 +- app/routes/categories.js | 14 +- app/routes/category-slugs.js | 14 +- app/routes/category.js | 18 +- app/routes/category/index.js | 26 +- app/routes/confirm.js | 42 +- app/routes/crate.js | 54 +- app/routes/crate/docs.js | 28 +- app/routes/crate/index.js | 4 +- app/routes/crate/owners.js | 10 +- app/routes/crate/repo.js | 28 +- app/routes/crate/reverse-dependencies.js | 26 +- app/routes/crate/version.js | 220 ++--- app/routes/crates.js | 26 +- app/routes/dashboard.js | 46 +- app/routes/github-authorize.js | 36 +- app/routes/github-login.js | 8 +- app/routes/index.js | 28 +- app/routes/install.js | 6 +- app/routes/keyword.js | 18 +- app/routes/keyword/index.js | 24 +- app/routes/keywords.js | 14 +- app/routes/login.js | 114 +-- app/routes/logout.js | 16 +- app/routes/me/crates.js | 16 +- app/routes/me/following.js | 16 +- app/routes/me/index.js | 12 +- app/routes/me/pending-invites.js | 6 +- app/routes/search.js | 26 +- app/routes/team.js | 48 +- app/routes/user.js | 48 +- app/serializers/api-token.js | 6 +- app/serializers/crate-owner-invite.js | 14 +- app/serializers/crate.js | 14 +- app/serializers/dependency.js | 6 +- app/serializers/version-download.js | 6 +- app/services/flash-messages.js | 24 +- app/services/search.js | 2 +- app/services/session.js | 156 ++-- config/coverage.js | 4 +- config/environment.js | 102 +-- config/manifest.js | 38 +- config/targets.js | 20 +- ember-cli-build.js | 94 +-- mirage/config.js | 558 +++++++------ mirage/factories/category.js | 24 +- mirage/factories/crate.js | 56 +- mirage/factories/version.js | 40 +- mirage/fixtures/categories.js | 52 +- mirage/fixtures/crates.js | 755 +++++++++--------- mirage/fixtures/dependencies.js | 66 +- mirage/fixtures/keywords.js | 12 +- mirage/fixtures/teams.js | 28 +- mirage/fixtures/users.js | 48 +- mirage/fixtures/version-downloads.js | 30 +- mirage/fixtures/versions.js | 606 +++++++------- mirage/scenarios/default.js | 2 +- mirage/serializers/application.js | 36 +- mirage/serializers/crate.js | 54 +- mirage/serializers/version.js | 42 +- testem.js | 20 +- tests/acceptance/categories-test.js | 82 +- tests/acceptance/crate-test.js | 392 ++++----- tests/acceptance/crates-test.js | 118 +-- tests/acceptance/front-page-test.js | 52 +- tests/acceptance/keyword-test.js | 28 +- tests/acceptance/search-test.js | 122 +-- tests/acceptance/team-page-test.js | 64 +- tests/acceptance/user-page-test.js | 64 +- tests/axe-config.js | 8 +- tests/helpers/setup-mirage.js | 18 +- tests/unit/controllers/crate/version-test.js | 50 +- tests/unit/helpers/format-crate-size-test.js | 24 +- tests/unit/helpers/format-email-test.js | 22 +- tests/unit/helpers/format-num-test.js | 10 +- tests/unit/mixins/pagination-test.js | 12 +- 154 files changed, 4121 insertions(+), 4129 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 393d7668f4..73a80c9125 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 e5d16f8327..de1deb105f 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: { + 'block-indentation': false, + 'img-alt-attributes': false, + 'triple-curlies': false, + }, }; diff --git a/app/adapters/api-token.js b/app/adapters/api-token.js index f956848b70..1c7e6f33e4 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 6858d92982..7940faa096 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 cf88cff590..2d55e5e32a 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 582f4eb1e2..ad99112db2 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 20504968b1..3e0f8cd9df 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 bf6c5db25a..9e2d5a086e 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 8f4738e298..e92de43a61 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 ba343fc4cf..0517c69951 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 ffb3991107..ddd13a0ff6 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 5a8066ceea..eb8255a63e 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 fc25c20381..72e52f5416 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 89335afd9f..16dd7b1a3e 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 0af66e4acb..f3d4069589 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 62a3db4e32..9322966939 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 caa3429194..90f30bb620 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 8596f9f77b..ee4dfaf17e 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 98d5f1fae8..e3e00cf27e 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 a131e01868..67c3b5252f 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 5695dcca85..813a0e6042 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 70473376ae..327b0bd769 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 a4562265e1..3650c7951b 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 7b1f8feaaf..30e30257d6 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 9aa88e6ab7..513647ec05 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 e395f9f98e..84b9ce752b 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 56c1bf2f7f..3682d29e24 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 0c95afdae2..641f6434c8 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 27567632a9..ef807af025 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 db35067b8a..50feacf7e4 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 c330822d0b..0fe78fc1cf 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 e12592c538..909d64a8b7 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 049f3f4235..380db2f784 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 2c6934290b..be9b398f7a 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 ee6b8249b5..ef98e9af23 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 814fbb7f6f..37cfd84bae 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 bdea206ce9..f40807b8f6 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 f7ccf93eaf..8d8216d742 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 4e5ecb1f2b..2005430f14 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 56ce1b6feb..625c2e9529 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 2e4d091ac1..b74e744555 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 bfdab8da2c..3f56a4d472 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 cc668f1f0e..ab3aafb5a9 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 5aefab120d..685cd18110 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 dbfc0e8ff7..e07b3662ab 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 12bc169d9a..81b6fbfb9b 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 fc28392074..6d05773771 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 f57d881416..7366e369a8 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 aadd8fb66c..d952fb4081 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 a23839aec1..4dec3969e2 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 fd9c716d1b..dc52b917c9 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 ad74cc201a..4d97fde6b6 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 875806bc5c..a3edf82124 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 4fc8564f51..4c08b87345 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 8d36c2bfe5..96fd125d03 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 08b51995c2..9afafbfc9a 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 2f8beb5380..f0103c11d4 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 11ff4b1b1a..4852ab98ee 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 a5f3e4589d..54fff2d67c 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 22e79f9b49..2e3740ea71 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 b42feaa071..029dde80fb 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 d852ecf7f0..13c14f5ac0 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 972f5dad55..20a2041574 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 ffa174be15..d599c64849 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 fd271e11ad..70706b5142 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 677c7bee5c..1d9adf352d 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 2d9e01ca6d..b4f95ea61e 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 ee38d510b2..100f88069c 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 235eb0ad27..cfc787f806 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 b17385aacd..d1fb018f7d 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 f020f19355..19c057c4c4 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 add3fbc0ef..9cccd5d7d5 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 d32a54d898..a55b15bca8 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 a993e5b42e..80b4a6bb78 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 9bab18b285..0bcbdcbce7 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 a8f0c25f1e..fc15938974 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 e5888831c4..504ba240d9 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 01eb2bbeac..969fbfc156 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 61cc50b730..b295f01834 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 99a581cdfe..9e21dfc580 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 ea695cfe04..ab314b37f4 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 f36246439e..bd106c48fb 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 c1bc4378f8..1b347b1330 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 9280e88d48..67405995bb 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 f3ca47726d..145f005e13 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 7bceb06433..2579eb95e9 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 fdf2da0a21..18fdbb182b 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 ac698aa6eb..3809c391aa 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 2a34052138..8ff337aadf 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 0f869a2569..4a2c6d059f 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 b46a57fb22..86a6acf939 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 17f7362a51..b0968c8e54 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 8e13703b0c..2883935b16 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 0fcc44e5d5..4ee10cd9a1 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 8386a59318..904e386725 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 44a52edf53..f3502da44d 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 006e9fece3..7c52f9ce3d 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 49056de679..cc5dfa1dba 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 9f8bcb5ba1..48f0e56588 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 3f450f138c..1027b4ac4f 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 07ddf3fdab..bed6ee39b3 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 f5e3e90c55..7fc5fd7bb3 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 a793a75405..9d302af0c4 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 3196653282..3843fc2d62 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 b205f67453..7e0fb31bcb 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 318ce3b8fe..d8a5e77de7 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 8132c7235f..62a8325e11 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 a0c539e215..48706381ad 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 a47e3b258c..10bbe8b292 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 52a9a49e87..449579d7e4 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 65bcb7e7cf..724732be8b 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 b8b9500e2d..cde8d51c72 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 865e3a63a4..e03395aed0 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 48c5589a42..830917e2b9 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 62ff4826e3..e8f2568fe5 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 47ff25937c..89fb6aa8d7 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 2eb6000223..9b9903f38b 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/config/coverage.js b/config/coverage.js index 133a5c502b..01fca3c604 100644 --- a/config/coverage.js +++ b/config/coverage.js @@ -1,4 +1,4 @@ module.exports = { - parallel: true, - reporters: ['json', 'lcov'], + parallel: true, + reporters: ['json', 'lcov'], }; diff --git a/config/environment.js b/config/environment.js index 55a356a27c..7681acac19 100644 --- a/config/environment.js +++ b/config/environment.js @@ -1,63 +1,63 @@ 'use strict'; module.exports = function(environment) { - let ENV = { - modulePrefix: 'cargo', - environment, - rootURL: '/', - locationType: 'router-scroll', - historySupportMiddleware: true, - EmberENV: { - FEATURES: { - // Here you can enable experimental features on an ember canary build - // e.g. 'with-controller': true - }, - EXTEND_PROTOTYPES: { - // Prevent Ember Data from overriding Date.parse. - Date: false, - }, - }, - - APP: { - // Here you can pass flags/options to your application instance - // when it is created - }, + let ENV = { + modulePrefix: 'cargo', + environment, + rootURL: '/', + locationType: 'router-scroll', + historySupportMiddleware: true, + EmberENV: { + FEATURES: { + // Here you can enable experimental features on an ember canary build + // e.g. 'with-controller': true + }, + EXTEND_PROTOTYPES: { + // Prevent Ember Data from overriding Date.parse. + Date: false, + }, + }, + + APP: { + // Here you can pass flags/options to your application instance + // when it is created + }, + }; + + if (environment === 'development') { + // ENV.APP.LOG_RESOLVER = true; + // ENV.APP.LOG_ACTIVE_GENERATION = true; + // ENV.APP.LOG_TRANSITIONS = true; + // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; + // ENV.APP.LOG_VIEW_LOOKUPS = true; + ENV['ember-a11y-testing'] = { + componentOptions: { + turnAuditOff: true, + }, }; + } - if (environment === 'development') { - // ENV.APP.LOG_RESOLVER = true; - // ENV.APP.LOG_ACTIVE_GENERATION = true; - // ENV.APP.LOG_TRANSITIONS = true; - // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; - // ENV.APP.LOG_VIEW_LOOKUPS = true; - ENV['ember-a11y-testing'] = { - componentOptions: { - turnAuditOff: true, - }, - }; - } - - if (environment === 'test') { - // Testem prefers this... - ENV.locationType = 'none'; + if (environment === 'test') { + // Testem prefers this... + ENV.locationType = 'none'; - // keep test console output quieter - ENV.APP.LOG_ACTIVE_GENERATION = false; - ENV.APP.LOG_VIEW_LOOKUPS = false; + // keep test console output quieter + ENV.APP.LOG_ACTIVE_GENERATION = false; + ENV.APP.LOG_VIEW_LOOKUPS = false; - ENV.APP.rootElement = '#ember-testing'; - ENV.APP.autoboot = false; - } + ENV.APP.rootElement = '#ember-testing'; + ENV.APP.autoboot = false; + } - if (environment === 'production') { - // here you can enable a production-specific feature + if (environment === 'production') { + // here you can enable a production-specific feature - // Heroku Git Hash support - if (process.env.SOURCE_VERSION) { - let hash = process.env.SOURCE_VERSION.substr(0, 7); - ENV['ember-cli-app-version'] = { version: hash }; - } + // Heroku Git Hash support + if (process.env.SOURCE_VERSION) { + let hash = process.env.SOURCE_VERSION.substr(0, 7); + ENV['ember-cli-app-version'] = { version: hash }; } + } - return ENV; + return ENV; }; diff --git a/config/manifest.js b/config/manifest.js index c3a8e22882..157de48b45 100644 --- a/config/manifest.js +++ b/config/manifest.js @@ -1,23 +1,23 @@ 'use strict'; module.exports = function(/* environment, appConfig */) { - return { - name: 'crates.io: Rust Package Registry', - short_name: 'crates.io', - description: 'crates.io is the default crate host for Rust.', - start_url: '/', - display: 'standalone', - background_color: '#3b6837', - theme_color: '#f9f7ec', - icons: [ - { - src: 'cargo.png', - sizes: '227x227', - type: 'image/png', - }, - ], - ms: { - tileColor: '#3b6837', - }, - }; + return { + name: 'crates.io: Rust Package Registry', + short_name: 'crates.io', + description: 'crates.io is the default crate host for Rust.', + start_url: '/', + display: 'standalone', + background_color: '#3b6837', + theme_color: '#f9f7ec', + icons: [ + { + src: 'cargo.png', + sizes: '227x227', + type: 'image/png', + }, + ], + ms: { + tileColor: '#3b6837', + }, + }; }; diff --git a/config/targets.js b/config/targets.js index f78c1e9dae..dcde5b9d7d 100644 --- a/config/targets.js +++ b/config/targets.js @@ -1,12 +1,12 @@ module.exports = { - browsers: [ - // These are the browsers we actually are attempting to support: - 'last 2 Chrome versions', - 'last 1 Firefox version', - 'Firefox ESR', - 'last 1 Safari version', - 'last 1 iOS version', - 'last 1 Edge version', - 'last 1 UCAndroid version', - ], + browsers: [ + // These are the browsers we actually are attempting to support: + 'last 2 Chrome versions', + 'last 1 Firefox version', + 'Firefox ESR', + 'last 1 Safari version', + 'last 1 iOS version', + 'last 1 Edge version', + 'last 1 UCAndroid version', + ], }; diff --git a/ember-cli-build.js b/ember-cli-build.js index 53551c2c1b..1361574be2 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -3,54 +3,54 @@ const EmberApp = require('ember-cli/lib/broccoli/ember-app'); module.exports = function(defaults) { - const highlightedLanguages = [ - 'bash', - 'clike', - 'glsl', - 'go', - 'ini', - 'javascript', - 'json', - 'markup', - 'protobuf', - 'ruby', - 'rust', - 'scss', - 'sql', - 'yaml', - ]; + const highlightedLanguages = [ + 'bash', + 'clike', + 'glsl', + 'go', + 'ini', + 'javascript', + 'json', + 'markup', + 'protobuf', + 'ruby', + 'rust', + 'scss', + 'sql', + 'yaml', + ]; - let app = new EmberApp(defaults, { - babel6: { - plugins: ['transform-object-rest-spread'], - }, - 'ember-prism': { - theme: 'twilight', - components: highlightedLanguages, - }, - sassOptions: { - includePaths: ['node_modules/normalize.css'], - }, - fingerprint: { - extensions: ['js', 'css', 'png', 'jpg', 'gif', 'map', 'svg', 'ttf', 'woff', 'woff2'], - }, - }); + let app = new EmberApp(defaults, { + babel6: { + plugins: ['transform-object-rest-spread'], + }, + 'ember-prism': { + theme: 'twilight', + components: highlightedLanguages, + }, + sassOptions: { + includePaths: ['node_modules/normalize.css'], + }, + fingerprint: { + extensions: ['js', 'css', 'png', 'jpg', 'gif', 'map', 'svg', 'ttf', 'woff', 'woff2'], + }, + }); - // Use `app.import` to add additional libraries to the generated - // output files. - // - // If you need to use different assets in different - // environments, specify an object as the first parameter. That - // object's keys should be the environment name and the values - // should be the asset to use in that environment. - // - // If the library that you are including contains AMD or ES6 - // modules that you would like to import into your application - // please specify an object with the list of modules as keys - // along with the exports of each module as its value. - app.import('node_modules/timekeeper/lib/timekeeper.js', { - using: [{ transformation: 'cjs', as: 'timekeeper' }], - }); + // Use `app.import` to add additional libraries to the generated + // output files. + // + // If you need to use different assets in different + // environments, specify an object as the first parameter. That + // object's keys should be the environment name and the values + // should be the asset to use in that environment. + // + // If the library that you are including contains AMD or ES6 + // modules that you would like to import into your application + // please specify an object with the list of modules as keys + // along with the exports of each module as its value. + app.import('node_modules/timekeeper/lib/timekeeper.js', { + using: [{ transformation: 'cjs', as: 'timekeeper' }], + }); - return app.toTree(); + return app.toTree(); }; diff --git a/mirage/config.js b/mirage/config.js index b638593a4c..1dea65e0af 100644 --- a/mirage/config.js +++ b/mirage/config.js @@ -1,309 +1,307 @@ import Response from 'ember-cli-mirage/response'; export default function() { - // Used by ember-cli-code-coverage - this.passthrough('/write-coverage'); - - this.namespace = '/api/v1'; - - this.get('/summary', function(schema) { - let crates = schema.crates.all(); - - let just_updated = crates.sort((a, b) => compareIsoDates(b.updated_at, a.updated_at)).slice(0, 10); - let most_downloaded = crates.sort((a, b) => b.downloads - a.downloads).slice(0, 10); - let new_crates = crates.sort((a, b) => compareIsoDates(b.created_at, a.created_at)).slice(0, 10); - let most_recently_downloaded = crates.sort((a, b) => b.recent_downloads - a.recent_downloads).slice(0, 10); - - let num_crates = crates.length; - let num_downloads = crates.models.reduce((sum, crate) => sum + crate.downloads, 0); - - let popular_categories = schema.categories - .all() - .sort((a, b) => b.crates_cnt - a.crates_cnt) - .slice(0, 10); - let popular_keywords = schema.keywords - .all() - .sort((a, b) => b.crates_cnt - a.crates_cnt) - .slice(0, 10); - - return { - just_updated: this.serialize(just_updated).crates.map(it => ({ ...it, versions: null })), - most_downloaded: this.serialize(most_downloaded).crates.map(it => ({ ...it, versions: null })), - new_crates: this.serialize(new_crates).crates.map(it => ({ ...it, versions: null })), - most_recently_downloaded: this.serialize(most_recently_downloaded).crates.map(it => ({ - ...it, - versions: null, - })), - num_crates, - num_downloads, - popular_categories: this.serialize(popular_categories).categories, - popular_keywords: this.serialize(popular_keywords).keywords, - }; + // Used by ember-cli-code-coverage + this.passthrough('/write-coverage'); + + this.namespace = '/api/v1'; + + this.get('/summary', function(schema) { + let crates = schema.crates.all(); + + let just_updated = crates.sort((a, b) => compareIsoDates(b.updated_at, a.updated_at)).slice(0, 10); + let most_downloaded = crates.sort((a, b) => b.downloads - a.downloads).slice(0, 10); + let new_crates = crates.sort((a, b) => compareIsoDates(b.created_at, a.created_at)).slice(0, 10); + let most_recently_downloaded = crates.sort((a, b) => b.recent_downloads - a.recent_downloads).slice(0, 10); + + let num_crates = crates.length; + let num_downloads = crates.models.reduce((sum, crate) => sum + crate.downloads, 0); + + let popular_categories = schema.categories + .all() + .sort((a, b) => b.crates_cnt - a.crates_cnt) + .slice(0, 10); + let popular_keywords = schema.keywords + .all() + .sort((a, b) => b.crates_cnt - a.crates_cnt) + .slice(0, 10); + + return { + just_updated: this.serialize(just_updated).crates.map(it => ({ ...it, versions: null })), + most_downloaded: this.serialize(most_downloaded).crates.map(it => ({ ...it, versions: null })), + new_crates: this.serialize(new_crates).crates.map(it => ({ ...it, versions: null })), + most_recently_downloaded: this.serialize(most_recently_downloaded).crates.map(it => ({ + ...it, + versions: null, + })), + num_crates, + num_downloads, + popular_categories: this.serialize(popular_categories).categories, + popular_keywords: this.serialize(popular_keywords).keywords, + }; + }); + + this.get('/crates', function(schema, request) { + const { start, end } = pageParams(request); + + let crates = schema.crates.all(); + + if (request.queryParams.letter) { + let letter = request.queryParams.letter.toLowerCase(); + crates = crates.filter(crate => crate.id[0].toLowerCase() === letter); + } + + if (request.queryParams.q) { + let q = request.queryParams.q.toLowerCase(); + crates = crates.filter(crate => crate.id.toLowerCase().indexOf(q) !== -1); + } + + if (request.queryParams.user_id) { + let userId = parseInt(request.queryParams.user_id, 10); + crates = crates.filter(crate => (crate._owner_users || []).indexOf(userId) !== -1); + } + + if (request.queryParams.team_id) { + let teamId = parseInt(request.queryParams.team_id, 10); + crates = crates.filter(crate => (crate._owner_teams || []).indexOf(teamId) !== -1); + } + + if (request.queryParams.sort === 'alpha') { + crates = crates.sort((a, b) => compareStrings(a.id.toLowerCase(), b.id.toLowerCase())); + } + + return withMeta(this.serialize(crates.slice(start, end)), { total: crates.length }); + }); + + this.get('/crates/:crate_id', function(schema, request) { + let crateId = request.params.crate_id; + let crate = schema.crates.find(crateId); + let categories = schema.categories.all().filter(category => (crate.categories || []).indexOf(category.id) !== -1); + let keywords = schema.keywords.all().filter(keyword => (crate.keywords || []).indexOf(keyword.id) !== -1); + let versions = schema.versions + .all() + .filter(version => (crate.versions || []).indexOf(parseInt(version.id, 10)) !== -1); + + return { + ...this.serialize(crate), + ...this.serialize(categories), + ...this.serialize(keywords), + ...this.serialize(versions), + }; + }); + + this.get('/crates/:crate_id/following', (/* schema, request */) => { + // TODO + }); + + this.get('/crates/:crate_id/versions', (schema, request) => { + let crate = request.params.crate_id; + return schema.versions.where({ crate }).sort((a, b) => compareIsoDates(b.created_at, a.created_at)); + }); + + this.get('/crates/:crate_id/:version_num/authors', (schema, request) => { + let crate = request.params.crate_id; + let num = request.params.version_num; + let version = schema.versions.findBy({ crate, num }); + return { meta: { names: version._authors }, users: [] }; + }); + + this.get('/crates/:crate_id/:version_num/dependencies', (schema, request) => { + let crate = request.params.crate_id; + let num = request.params.version_num; + let version_id = schema.versions.findBy({ crate, num }).id; + return schema.dependencies.where({ version_id }); + }); + + this.get('/crates/:crate_id/:version_num/downloads', function(schema, request) { + let crateId = request.params.crate_id; + let versionNum = request.params.version_num; + let versionId = schema.versions.findBy({ crate: crateId, num: versionNum }).id; + return schema.versionDownloads.where({ version: versionId }); + }); + + this.get('/crates/:crate_id/owner_user', function(schema, request) { + let crateId = request.params.crate_id; + let crate = schema.crates.find(crateId); + let users = schema.users.find(crate._owner_users); + + let response = this.serialize(users); + + response.users.forEach(user => { + user.kind = 'user'; }); - this.get('/crates', function(schema, request) { - const { start, end } = pageParams(request); - - let crates = schema.crates.all(); - - if (request.queryParams.letter) { - let letter = request.queryParams.letter.toLowerCase(); - crates = crates.filter(crate => crate.id[0].toLowerCase() === letter); - } - - if (request.queryParams.q) { - let q = request.queryParams.q.toLowerCase(); - crates = crates.filter(crate => crate.id.toLowerCase().indexOf(q) !== -1); - } - - if (request.queryParams.user_id) { - let userId = parseInt(request.queryParams.user_id, 10); - crates = crates.filter(crate => (crate._owner_users || []).indexOf(userId) !== -1); - } - - if (request.queryParams.team_id) { - let teamId = parseInt(request.queryParams.team_id, 10); - crates = crates.filter(crate => (crate._owner_teams || []).indexOf(teamId) !== -1); - } - - if (request.queryParams.sort === 'alpha') { - crates = crates.sort((a, b) => compareStrings(a.id.toLowerCase(), b.id.toLowerCase())); - } - - return withMeta(this.serialize(crates.slice(start, end)), { total: crates.length }); - }); - - this.get('/crates/:crate_id', function(schema, request) { - let crateId = request.params.crate_id; - let crate = schema.crates.find(crateId); - let categories = schema.categories - .all() - .filter(category => (crate.categories || []).indexOf(category.id) !== -1); - let keywords = schema.keywords.all().filter(keyword => (crate.keywords || []).indexOf(keyword.id) !== -1); - let versions = schema.versions - .all() - .filter(version => (crate.versions || []).indexOf(parseInt(version.id, 10)) !== -1); - - return { - ...this.serialize(crate), - ...this.serialize(categories), - ...this.serialize(keywords), - ...this.serialize(versions), - }; - }); - - this.get('/crates/:crate_id/following', (/* schema, request */) => { - // TODO - }); - - this.get('/crates/:crate_id/versions', (schema, request) => { - let crate = request.params.crate_id; - return schema.versions.where({ crate }).sort((a, b) => compareIsoDates(b.created_at, a.created_at)); - }); - - this.get('/crates/:crate_id/:version_num/authors', (schema, request) => { - let crate = request.params.crate_id; - let num = request.params.version_num; - let version = schema.versions.findBy({ crate, num }); - return { meta: { names: version._authors }, users: [] }; - }); - - this.get('/crates/:crate_id/:version_num/dependencies', (schema, request) => { - let crate = request.params.crate_id; - let num = request.params.version_num; - let version_id = schema.versions.findBy({ crate, num }).id; - return schema.dependencies.where({ version_id }); - }); - - this.get('/crates/:crate_id/:version_num/downloads', function(schema, request) { - let crateId = request.params.crate_id; - let versionNum = request.params.version_num; - let versionId = schema.versions.findBy({ crate: crateId, num: versionNum }).id; - return schema.versionDownloads.where({ version: versionId }); - }); - - this.get('/crates/:crate_id/owner_user', function(schema, request) { - let crateId = request.params.crate_id; - let crate = schema.crates.find(crateId); - let users = schema.users.find(crate._owner_users); - - let response = this.serialize(users); - - response.users.forEach(user => { - user.kind = 'user'; - }); - - return response; - }); - - this.get('/crates/:crate_id/owner_team', function(schema, request) { - let crateId = request.params.crate_id; - let crate = schema.crates.find(crateId); - let teams = schema.teams.find(crate._owner_teams); - - let response = this.serialize(teams); - - response.teams.forEach(team => { - team.kind = 'team'; - }); - - return response; - }); - - this.get('/crates/:crate_id/reverse_dependencies', function(schema, request) { - let { start, end } = pageParams(request); - - let crate = request.params.crate_id; - let allDependencies = schema.dependencies.where({ crate_id: crate }); - let dependencies = allDependencies.slice(start, end); - let total = allDependencies.length; - - let versions = schema.versions.find(dependencies.models.map(it => it.version_id)); - - return { - ...this.serialize(dependencies), - ...this.serialize(versions), - meta: { total }, - }; - }); - - this.get('/crates/:crate_id/downloads', function(schema, request) { - let crateId = request.params.crate_id; - let crate = schema.crates.find(crateId); - let versionDownloads = schema.versionDownloads - .all() - .filter(it => crate.versions.indexOf(parseInt(it.version, 10)) !== -1); - - return withMeta(this.serialize(versionDownloads), { extra_downloads: crate._extra_downloads }); - }); - - this.get('/categories', function(schema, request) { - let { start, end } = pageParams(request); - - let allCategories = schema.categories.all().sort((a, b) => compareStrings(a.category, b.category)); - let categories = allCategories.slice(start, end); - let total = allCategories.length; - - return withMeta(this.serialize(categories), { total }); - }); - - this.get('/categories/:category_id', function(schema, request) { - let catId = request.params.category_id; - let category = schema.categories.find(catId); - return category ? category : notFound(); - }); - - this.get('/category_slugs', function(schema) { - let allCategories = schema.categories.all().sort((a, b) => compareStrings(a.category, b.category)); - return { - category_slugs: this.serialize(allCategories).categories.map(cat => ({ - id: cat.id, - slug: cat.slug, - description: cat.description, - })), - }; - }); - - this.get('/keywords', function(schema, request) { - let { start, end } = pageParams(request); - - let allKeywords = schema.keywords.all().sort((a, b) => a.crates_cnt - b.crates_cnt); - let keywords = allKeywords.slice(start, end); - let total = allKeywords.length; - - return withMeta(this.serialize(keywords), { total }); - }); - - this.get('/keywords/:keyword_id', (schema, request) => { - let keywordId = request.params.keyword_id; - let keyword = schema.keywords.find(keywordId); - return keyword ? keyword : notFound(); - }); - - this.get('/teams/:team_id', (schema, request) => { - let login = request.params.team_id; - let team = schema.teams.findBy({ login }); - return team ? team : notFound(); - }); - - this.get('/users/:user_id', (schema, request) => { - let login = request.params.user_id; - let user = schema.users.findBy({ login }); - return user ? user : notFound(); - }); - - this.put('/crates/:crate_id/owners', (schema, request) => { - const crateId = request.params.crate_id; - const crate = schema.crates.find(crateId); - - if (!crate) { - return notFound(); - } + return response; + }); - const body = JSON.parse(request.requestBody); - const [ownerId] = body.owners; - const user = schema.users.findBy({ login: ownerId }); + this.get('/crates/:crate_id/owner_team', function(schema, request) { + let crateId = request.params.crate_id; + let crate = schema.crates.find(crateId); + let teams = schema.teams.find(crate._owner_teams); - if (!user) { - return notFound(); - } + let response = this.serialize(teams); - return { ok: true }; + response.teams.forEach(team => { + team.kind = 'team'; }); - this.delete('/crates/:crate_id/owners', (schema, request) => { - const crateId = request.params.crate_id; - const crate = schema.crates.find(crateId); - - if (!crate) { - return notFound(); - } - - const body = JSON.parse(request.requestBody); - const [ownerId] = body.owners; - const user = schema.users.findBy({ login: ownerId }); - - if (!user) { - return notFound(); - } - - return {}; - }); + return response; + }); + + this.get('/crates/:crate_id/reverse_dependencies', function(schema, request) { + let { start, end } = pageParams(request); + + let crate = request.params.crate_id; + let allDependencies = schema.dependencies.where({ crate_id: crate }); + let dependencies = allDependencies.slice(start, end); + let total = allDependencies.length; + + let versions = schema.versions.find(dependencies.models.map(it => it.version_id)); + + return { + ...this.serialize(dependencies), + ...this.serialize(versions), + meta: { total }, + }; + }); + + this.get('/crates/:crate_id/downloads', function(schema, request) { + let crateId = request.params.crate_id; + let crate = schema.crates.find(crateId); + let versionDownloads = schema.versionDownloads + .all() + .filter(it => crate.versions.indexOf(parseInt(it.version, 10)) !== -1); + + return withMeta(this.serialize(versionDownloads), { extra_downloads: crate._extra_downloads }); + }); + + this.get('/categories', function(schema, request) { + let { start, end } = pageParams(request); + + let allCategories = schema.categories.all().sort((a, b) => compareStrings(a.category, b.category)); + let categories = allCategories.slice(start, end); + let total = allCategories.length; + + return withMeta(this.serialize(categories), { total }); + }); + + this.get('/categories/:category_id', function(schema, request) { + let catId = request.params.category_id; + let category = schema.categories.find(catId); + return category ? category : notFound(); + }); + + this.get('/category_slugs', function(schema) { + let allCategories = schema.categories.all().sort((a, b) => compareStrings(a.category, b.category)); + return { + category_slugs: this.serialize(allCategories).categories.map(cat => ({ + id: cat.id, + slug: cat.slug, + description: cat.description, + })), + }; + }); + + this.get('/keywords', function(schema, request) { + let { start, end } = pageParams(request); + + let allKeywords = schema.keywords.all().sort((a, b) => a.crates_cnt - b.crates_cnt); + let keywords = allKeywords.slice(start, end); + let total = allKeywords.length; + + return withMeta(this.serialize(keywords), { total }); + }); + + this.get('/keywords/:keyword_id', (schema, request) => { + let keywordId = request.params.keyword_id; + let keyword = schema.keywords.find(keywordId); + return keyword ? keyword : notFound(); + }); + + this.get('/teams/:team_id', (schema, request) => { + let login = request.params.team_id; + let team = schema.teams.findBy({ login }); + return team ? team : notFound(); + }); + + this.get('/users/:user_id', (schema, request) => { + let login = request.params.user_id; + let user = schema.users.findBy({ login }); + return user ? user : notFound(); + }); + + this.put('/crates/:crate_id/owners', (schema, request) => { + const crateId = request.params.crate_id; + const crate = schema.crates.find(crateId); + + if (!crate) { + return notFound(); + } + + const body = JSON.parse(request.requestBody); + const [ownerId] = body.owners; + const user = schema.users.findBy({ login: ownerId }); + + if (!user) { + return notFound(); + } + + return { ok: true }; + }); + + this.delete('/crates/:crate_id/owners', (schema, request) => { + const crateId = request.params.crate_id; + const crate = schema.crates.find(crateId); + + if (!crate) { + return notFound(); + } + + const body = JSON.parse(request.requestBody); + const [ownerId] = body.owners; + const user = schema.users.findBy({ login: ownerId }); + + if (!user) { + return notFound(); + } + + return {}; + }); } function notFound() { - return new Response( - 404, - { 'Content-Type': 'application/json' }, - { - errors: [{ detail: 'Not Found' }], - }, - ); + return new Response( + 404, + { 'Content-Type': 'application/json' }, + { + errors: [{ detail: 'Not Found' }], + }, + ); } function pageParams(request) { - const { queryParams } = request; + const { queryParams } = request; - const page = parseInt(queryParams.page || '1'); - const perPage = parseInt(queryParams.per_page || '10'); + const page = parseInt(queryParams.page || '1'); + const perPage = parseInt(queryParams.per_page || '10'); - const start = (page - 1) * perPage; - const end = start + perPage; + const start = (page - 1) * perPage; + const end = start + perPage; - return { page, perPage, start, end }; + return { page, perPage, start, end }; } function withMeta(response, meta) { - response.meta = meta; - return response; + response.meta = meta; + return response; } function compareStrings(a, b) { - return a < b ? -1 : a > b ? 1 : 0; + return a < b ? -1 : a > b ? 1 : 0; } function compareIsoDates(a, b) { - let aDate = new Date(a); - let bDate = new Date(b); - return aDate < bDate ? -1 : aDate > bDate ? 1 : 0; + let aDate = new Date(a); + let bDate = new Date(b); + return aDate < bDate ? -1 : aDate > bDate ? 1 : 0; } diff --git a/mirage/factories/category.js b/mirage/factories/category.js index 5dc4cb902b..c2f55a0f54 100644 --- a/mirage/factories/category.js +++ b/mirage/factories/category.js @@ -2,19 +2,19 @@ import { Factory, faker } from 'ember-cli-mirage'; import { dasherize } from '@ember/string'; export default Factory.extend({ - category(i) { - return `Category ${i}`; - }, + category(i) { + return `Category ${i}`; + }, - id() { - return dasherize(this.category); - }, + id() { + return dasherize(this.category); + }, - slug() { - return dasherize(this.category); - }, + slug() { + return dasherize(this.category); + }, - description: () => faker.lorem.sentence(), - created_at: () => faker.date.past(), - crates_cnt: () => faker.random.number({ max: 5000 }), + description: () => faker.lorem.sentence(), + created_at: () => faker.date.past(), + crates_cnt: () => faker.random.number({ max: 5000 }), }); diff --git a/mirage/factories/crate.js b/mirage/factories/crate.js index bbf5ef4143..8d8b2c6a1d 100644 --- a/mirage/factories/crate.js +++ b/mirage/factories/crate.js @@ -1,37 +1,37 @@ import { Factory, trait, faker } from 'ember-cli-mirage'; export default Factory.extend({ - id(i) { - return `crate-${i}`; - }, + id(i) { + return `crate-${i}`; + }, - name() { - return this.id; - }, + name() { + return this.id; + }, - description: () => faker.lorem.sentence(), - downloads: () => faker.random.number({ max: 10000 }), - documentation: () => faker.internet.url(), - homepage: () => faker.internet.url(), - repository: () => faker.internet.url(), - max_version: () => faker.system.semver(), + description: () => faker.lorem.sentence(), + downloads: () => faker.random.number({ max: 10000 }), + documentation: () => faker.internet.url(), + homepage: () => faker.internet.url(), + repository: () => faker.internet.url(), + max_version: () => faker.system.semver(), - created_at: () => faker.date.past(), - updated_at() { - return faker.date.between(this.created_at, new Date()); - }, + created_at: () => faker.date.past(), + updated_at() { + return faker.date.between(this.created_at, new Date()); + }, - badges: () => [], - categories: () => [], - keywords: () => [], - versions: () => [], - _extra_downloads: () => [], - _owner_teams: () => [], - _owner_users: () => [], + badges: () => [], + categories: () => [], + keywords: () => [], + versions: () => [], + _extra_downloads: () => [], + _owner_teams: () => [], + _owner_users: () => [], - withVersion: trait({ - afterCreate(crate, server) { - server.create('version', { crate: crate.id }); - }, - }), + withVersion: trait({ + afterCreate(crate, server) { + server.create('version', { crate: crate.id }); + }, + }), }); diff --git a/mirage/factories/version.js b/mirage/factories/version.js index 781c6e57ab..e1cdbd6db5 100644 --- a/mirage/factories/version.js +++ b/mirage/factories/version.js @@ -1,31 +1,31 @@ import { Factory, faker } from 'ember-cli-mirage'; export default Factory.extend({ - id: i => i, + id: i => i, - // crate: '...', + // crate: '...', - num: () => faker.system.semver(), + num: () => faker.system.semver(), - created_at: () => faker.date.past(), - updated_at() { - return faker.date.between(this.created_at, new Date()); - }, + created_at: () => faker.date.past(), + updated_at() { + return faker.date.between(this.created_at, new Date()); + }, - yanked: false, - license: () => faker.hacker.abbreviation(), + yanked: false, + license: () => faker.hacker.abbreviation(), - dl_path() { - return `/api/v1/crates/${this.crate}/${this.num}/download`; - }, + dl_path() { + return `/api/v1/crates/${this.crate}/${this.num}/download`; + }, - downloads: () => faker.random.number({ max: 10000 }), - features: () => {}, - _authors: () => [], + downloads: () => faker.random.number({ max: 10000 }), + features: () => {}, + _authors: () => [], - afterCreate(version, server) { - let crate = server.schema.crates.find(version.crate); - crate.update({ versions: crate.versions.concat(parseInt(version.id, 10)) }); - }, - crate_size: () => faker.random.number({ max: 10000000 }), + afterCreate(version, server) { + let crate = server.schema.crates.find(version.crate); + crate.update({ versions: crate.versions.concat(parseInt(version.id, 10)) }); + }, + crate_size: () => faker.random.number({ max: 10000000 }), }); diff --git a/mirage/fixtures/categories.js b/mirage/fixtures/categories.js index 6e6433a28d..c2f62272f5 100644 --- a/mirage/fixtures/categories.js +++ b/mirage/fixtures/categories.js @@ -1,29 +1,29 @@ /* eslint-disable quotes */ export default [ - { - category: 'API bindings', - crates_cnt: 0, - created_at: '2017-01-20T14:51:49Z', - description: - 'Idiomatic wrappers of specific APIs for convenient access from Rust. Includes HTTP API wrappers as well. Non-idiomatic or unsafe bindings can be found in External FFI bindings.', - id: 'api-bindings', - slug: 'api-bindings', - }, - { - category: 'Algorithms', - crates_cnt: 1, - created_at: '2017-01-20T14:51:49Z', - description: 'Rust implementations of core algorithms such as hashing, sorting, searching, and more.', - id: 'algorithms', - slug: 'algorithms', - }, - { - category: 'Asynchronous', - crates_cnt: 3910, - created_at: '2017-01-20T14:51:49Z', - description: - 'Crates to help you deal with events independently of the main program flow, using techniques like futures, promises, waiting, or eventing.', - id: 'asynchronous', - slug: 'asynchronous', - }, + { + category: 'API bindings', + crates_cnt: 0, + created_at: '2017-01-20T14:51:49Z', + description: + 'Idiomatic wrappers of specific APIs for convenient access from Rust. Includes HTTP API wrappers as well. Non-idiomatic or unsafe bindings can be found in External FFI bindings.', + id: 'api-bindings', + slug: 'api-bindings', + }, + { + category: 'Algorithms', + crates_cnt: 1, + created_at: '2017-01-20T14:51:49Z', + description: 'Rust implementations of core algorithms such as hashing, sorting, searching, and more.', + id: 'algorithms', + slug: 'algorithms', + }, + { + category: 'Asynchronous', + crates_cnt: 3910, + created_at: '2017-01-20T14:51:49Z', + description: + 'Crates to help you deal with events independently of the main program flow, using techniques like futures, promises, waiting, or eventing.', + id: 'asynchronous', + slug: 'asynchronous', + }, ]; diff --git a/mirage/fixtures/crates.js b/mirage/fixtures/crates.js index e1d009be14..b2290e9dce 100644 --- a/mirage/fixtures/crates.js +++ b/mirage/fixtures/crates.js @@ -1,381 +1,380 @@ /* eslint-disable quotes */ export default [ - { - badges: [ - { - badge_type: 'maintenance', - attributes: { - value: 'actively-developed', - }, - }, - ], - categories: [], - created_at: '2014-12-08T02:08:06Z', - description: 'A high-level, Rust idiomatic wrapper around nanomsg.', - documentation: 'https://github.com/thehydroimpulse/nanomsg.rs', - downloads: 3888, - recent_downloads: 800, - homepage: 'https://github.com/thehydroimpulse/nanomsg.rs', - id: 'nanomsg', - keywords: ['network'], - max_version: '0.7.0-alpha', - name: 'nanomsg', - repository: 'https://github.com/thehydroimpulse/nanomsg.rs', - updated_at: '2016-12-28T08:40:00Z', - versions: [40906, 40905, 28431, 21273, 18445, 17384, 13574, 9014, 8236, 7190, 4944, 940, 924], - _extra_downloads: [ - { - date: '2017-02-02', - downloads: 41, - }, - { - date: '2017-02-07', - downloads: 14, - }, - ], - _owner_teams: [1, 303], - _owner_users: [2, 303], - }, - { - created_at: '2015-02-27T11:52:13Z', - description: - 'Yo dawg, use Rust to generate Rust, right in your Rust. (See\n`external_mixin` to use scripting languages.)\n', - documentation: 'https://github.com/huonw/external_mixin#rust_mixin', - downloads: 477, - recent_downloads: 100, - exact_match: true, - homepage: 'https://github.com/huonw/external_mixin', - id: 'rust_mixin', - keywords: ['rust', 'plugin', 'code-generation'], - max_version: '0.0.1', - name: 'rust_mixin', - repository: 'https://github.com/huonw/external_mixin', - updated_at: '2015-02-27T11:52:13Z', - badges: [ - { - attributes: { - project: 'robertohuertasm/github-oss', - pipeline: 'microserver', - build: '2', - }, - badge_type: 'azure-devops', - }, - { - attributes: { - repository: 'huonw/external_mixin', - }, - badge_type: 'appveyor', - }, - { - attributes: { - branch: 'master', - repository: 'huonw/external_mixin', - }, - badge_type: 'travis-ci', - }, - { - attributes: { - branch: 'master', - repository: 'huonw/external_mixin', - }, - badge_type: 'gitlab', - }, - { - attributes: { - repository: 'huonw/external_mixin', - }, - badge_type: 'is-it-maintained-issue-resolution', - }, - { - attributes: { - repository: 'huonw/external_mixin', - }, - badge_type: 'is-it-maintained-open-issues', - }, - { - attributes: { - branch: 'master', - repository: 'huonw/external_mixin', - }, - badge_type: 'codecov', - }, - { - attributes: { - branch: 'master', - repository: 'huonw/external_mixin', - }, - badge_type: 'coveralls', - }, - ], - versions: null, - }, - { - created_at: '2015-02-27T11:51:58Z', - description: - 'Use your favourite interpreted language to generate your Rust, right\nin your Rust. Supports Python, Ruby and shell (`sh`) out of the box,\nwith an extensible macro to support any others. (See `rust_mixin` to\nbe able to use your all-time favourite language to generate your Rust.)\n', - documentation: 'https://github.com/huonw/external_mixin#external_mixin', - downloads: 497, - recent_downloads: 497, - homepage: 'https://github.com/huonw/external_mixin', - id: 'external_mixin', - keywords: ['python', 'ruby', 'shell', 'plugin', 'code-generation'], - max_version: '0.0.1', - name: 'external_mixin', - repository: 'https://github.com/huonw/external_mixin', - updated_at: '2015-02-27T11:51:58Z', - versions: null, - }, - { - created_at: '2015-02-27T11:51:40Z', - description: 'Backing library for `rust_mixin` and `external_mixin` to keep them\nDRY.\n', - documentation: 'https://github.com/huonw/external_mixin#external_mixin_base', - downloads: 989, - recent_downloads: 0, - homepage: 'https://github.com/huonw/external_mixin', - id: 'external_mixin_umbrella', - keywords: ['plugin', 'code-generation'], - max_version: '0.0.2', - name: 'external_mixin_umbrella', - repository: 'https://github.com/huonw/external_mixin', - updated_at: '2015-02-27T11:52:30Z', - versions: null, - }, - { - created_at: '2015-10-10T15:26:24Z', - description: - 'Adds String based inflections for Rust. Snake, kebab, camel, sentence, class, title, upper, and lower cases as well as ordinalize, deordinalize, demodulize, and foreign key are supported as both traits and pure functions acting on String types.\n', - documentation: 'http://whatisinternet.github.io/inflector/doc/inflector/', - downloads: 57, - recent_downloads: 1, - homepage: 'https://github.com/whatisinternet/inflector', - id: 'Inflector', - keywords: ['string', 'case', 'camel', 'snake', 'inflection'], - max_version: '0.1.6', - name: 'Inflector', - repository: 'https://github.com/whatisinternet/inflector', - updated_at: '2015-10-27T01:51:42Z', - versions: null, - }, - { - created_at: '2015-05-21T17:43:38Z', - description: 'Client for the ElasticSearch REST API', - documentation: 'http://benashford.github.io/rs-es/rs_es/index.html', - downloads: 321, - recent_downloads: 21, - homepage: null, - id: 'rs-es', - keywords: ['elasticsearch', 'elastic'], - max_version: '0.1.17', - name: 'rs-es', - repository: 'https://github.com/benashford/rs-es', - updated_at: '2015-09-09T15:34:50Z', - versions: null, - }, - { - created_at: '2014-11-21T05:12:08Z', - description: 'A (mostly) pure-Rust implementation of various common cryptographic algorithms.', - documentation: null, - downloads: 21573, - recent_downloads: 2000, - homepage: 'https://github.com/DaGenix/rust-crypto/', - id: 'rust-crypto', - keywords: ['Crypto', 'MD5', 'Sha1', 'Sha2', 'AES'], - max_version: '0.2.34', - name: 'rust-crypto', - repository: 'https://github.com/DaGenix/rust-crypto/', - updated_at: '2015-10-29T01:16:17Z', - versions: null, - }, - { - created_at: '2015-03-20T13:46:04Z', - description: - 'This library provides HTSlib bindings and a high level Rust API for reading and writing BAM files.', - documentation: null, - downloads: 485, - recent_downloads: 85, - homepage: null, - id: 'rust-htslib', - keywords: ['htslib', 'bam', 'bioinformatics', 'pileup', 'sequencing'], - max_version: '0.5.2', - name: 'rust-htslib', - repository: 'https://github.com/rust-bio/rust-htslib.git', - updated_at: '2015-11-11T00:10:43Z', - versions: null, - }, - { - badges: [ - { - badge_type: 'maintenance', - attributes: { - status: 'actively-developed', - }, - }, - ], - created_at: '2014-11-23T09:01:21Z', - description: 'A Kinetic protocol library written in Rust', - documentation: 'https://icorderi.github.io/kinetic-rust/doc/kinetic/', - downloads: 225, - recent_downloads: 125, - homepage: 'https://icorderi.github.io/icorderi/kinetic-rust', - id: 'kinetic-rust', - keywords: ['Protocol', 'Kinetic', 'Storage'], - max_version: '0.0.16', - name: 'kinetic-rust', - repository: 'https://github.com/icorderi/kinetic-rust/', - updated_at: '2015-04-21T00:15:49Z', - versions: null, - }, - { - created_at: '2014-11-29T17:51:55Z', - description: 'Rustless is a REST-like API micro-framework for Rust.', - documentation: null, - downloads: 554, - recent_downloads: 500, - homepage: 'https://github.com/rustless/rustless', - id: 'rustless', - keywords: ['api', 'web', 'hyper', 'iron', 'rest'], - max_version: '0.8.0', - name: 'rustless', - repository: 'https://crates.io/crates/rustless', - updated_at: '2015-10-31T11:49:29Z', - versions: null, - }, - { - created_at: '2014-12-05T20:20:39Z', - description: 'A generic serialization/deserialization framework', - documentation: 'https://serde-rs.github.io/serde/serde/serde/index.html', - downloads: 50854, - recent_downloads: 854, - homepage: null, - id: 'serde', - keywords: ['serde', 'serialization'], - max_version: '0.6.1', - name: 'serde', - repository: 'https://github.com/serde-rs/serde', - updated_at: '2015-10-18T03:10:21Z', - versions: null, - }, - { - created_at: '2015-08-26T13:50:58Z', - description: 'Send cypher queries to a neo4j database', - documentation: 'http://livioribeiro.github.io/rusted_cypher/rusted_cypher/', - downloads: 156, - recent_downloads: 54, - homepage: 'https://github.com/livioribeiro/rusted-cypher', - id: 'rusted_cypher', - keywords: ['neo4j', 'database', 'query', 'cypher', 'graph'], - max_version: '0.7.1', - name: 'rusted_cypher', - repository: 'https://github.com/livioribeiro/rusted-cypher', - updated_at: '2015-11-07T17:26:55Z', - versions: null, - }, - { - created_at: '2015-01-02T20:54:04Z', - description: - 'An (incomplete) port of zlib to Rust. The decompressor works, but the compressor has not yet been ported.', - documentation: null, - downloads: 223, - recent_downloads: 23, - homepage: null, - id: 'zlib', - keywords: [], - max_version: '0.0.1', - name: 'zlib', - repository: null, - updated_at: '2015-01-02T20:54:04Z', - versions: null, - }, - { - created_at: '2015-05-08T19:34:16Z', - description: - 'A light HTTP framework, with some REST-like features and the ambition of being simple, modular and non-intrusive.', - documentation: 'http://ogeon.github.io/docs/rustful/master/rustful/index.html', - downloads: 576, - recent_downloads: 76, - homepage: null, - id: 'rustful', - keywords: ['web', 'rest', 'framework', 'http', 'routing'], - max_version: '0.5.0', - name: 'rustful', - repository: 'https://github.com/Ogeon/rustful', - updated_at: '2015-09-19T21:10:27Z', - versions: null, - }, - { - created_at: '2014-11-24T02:34:44Z', - description: 'A native PostgreSQL driver', - documentation: 'https://sfackler.github.io/rust-postgres/doc/v0.10.1/postgres', - downloads: 13449, - recent_downloads: 13, - homepage: null, - id: 'postgres', - keywords: ['database', 'sql'], - max_version: '0.10.1', - name: 'postgres', - repository: 'https://github.com/sfackler/rust-postgres', - updated_at: '2015-11-08T00:48:59Z', - versions: null, - }, - { - created_at: '2014-11-21T00:20:47Z', - description: 'Automatic property based testing with shrinking.', - documentation: 'http://burntsushi.net/rustdoc/quickcheck/', - downloads: 19271, - recent_downloads: 143, - homepage: 'https://github.com/BurntSushi/quickcheck', - id: 'quickcheck', - keywords: ['testing', 'quickcheck', 'property', 'shrinking', 'fuzz'], - max_version: '0.2.24', - name: 'quickcheck', - repository: 'https://github.com/BurntSushi/quickcheck', - updated_at: '2015-09-20T21:53:38Z', - versions: null, - }, - { - created_at: '2014-11-21T00:21:04Z', - description: 'A macro attribute for quickcheck.', - documentation: 'http://burntsushi.net/rustdoc/quickcheck/', - downloads: 3796, - recent_downloads: 768, - homepage: 'https://github.com/BurntSushi/quickcheck', - id: 'quickcheck_macros', - keywords: ['testing', 'quickcheck', 'property', 'shrinking', 'fuzz'], - max_version: '0.2.24', - name: 'quickcheck_macros', - repository: 'https://github.com/BurntSushi/quickcheck', - updated_at: '2015-09-20T21:53:57Z', - versions: null, - }, - { - created_at: '2015-08-25T19:15:35Z', - description: - 'Lexical analysers generator for Rust, written in Rust (crate dedicated to rumblebars, divergences written by Nicolas Cherel)', - documentation: null, - downloads: 109, - recent_downloads: 0, - homepage: 'https://github.com/nicolas-cherel/rustlex', - id: 'nc_rustlex', - keywords: ['lexer', 'lexical', 'analyser', 'generator'], - max_version: '0.3.1', - name: 'nc_rustlex', - repository: 'https://github.com/nicolas-cherel/rustlex', - updated_at: '2015-08-25T19:15:35Z', - versions: null, - }, - { - created_at: '2015-01-17T17:47:52Z', - description: 'A byte-oriented, zero-copy, parser combinators library', - documentation: 'http://rust.unhandledexpression.com/nom/', - downloads: 5169, - recent_downloads: 69, - homepage: null, - id: 'nom', - keywords: ['parser', 'parser-combinators', 'parsing', 'streaming', 'bit'], - max_version: '1.0.1', - name: 'nom', - repository: 'https://github.com/Geal/nom', - updated_at: '2015-11-22T22:00:41Z', - versions: null, - }, + { + badges: [ + { + badge_type: 'maintenance', + attributes: { + value: 'actively-developed', + }, + }, + ], + categories: [], + created_at: '2014-12-08T02:08:06Z', + description: 'A high-level, Rust idiomatic wrapper around nanomsg.', + documentation: 'https://github.com/thehydroimpulse/nanomsg.rs', + downloads: 3888, + recent_downloads: 800, + homepage: 'https://github.com/thehydroimpulse/nanomsg.rs', + id: 'nanomsg', + keywords: ['network'], + max_version: '0.7.0-alpha', + name: 'nanomsg', + repository: 'https://github.com/thehydroimpulse/nanomsg.rs', + updated_at: '2016-12-28T08:40:00Z', + versions: [40906, 40905, 28431, 21273, 18445, 17384, 13574, 9014, 8236, 7190, 4944, 940, 924], + _extra_downloads: [ + { + date: '2017-02-02', + downloads: 41, + }, + { + date: '2017-02-07', + downloads: 14, + }, + ], + _owner_teams: [1, 303], + _owner_users: [2, 303], + }, + { + created_at: '2015-02-27T11:52:13Z', + description: + 'Yo dawg, use Rust to generate Rust, right in your Rust. (See\n`external_mixin` to use scripting languages.)\n', + documentation: 'https://github.com/huonw/external_mixin#rust_mixin', + downloads: 477, + recent_downloads: 100, + exact_match: true, + homepage: 'https://github.com/huonw/external_mixin', + id: 'rust_mixin', + keywords: ['rust', 'plugin', 'code-generation'], + max_version: '0.0.1', + name: 'rust_mixin', + repository: 'https://github.com/huonw/external_mixin', + updated_at: '2015-02-27T11:52:13Z', + badges: [ + { + attributes: { + project: 'robertohuertasm/github-oss', + pipeline: 'microserver', + build: '2', + }, + badge_type: 'azure-devops', + }, + { + attributes: { + repository: 'huonw/external_mixin', + }, + badge_type: 'appveyor', + }, + { + attributes: { + branch: 'master', + repository: 'huonw/external_mixin', + }, + badge_type: 'travis-ci', + }, + { + attributes: { + branch: 'master', + repository: 'huonw/external_mixin', + }, + badge_type: 'gitlab', + }, + { + attributes: { + repository: 'huonw/external_mixin', + }, + badge_type: 'is-it-maintained-issue-resolution', + }, + { + attributes: { + repository: 'huonw/external_mixin', + }, + badge_type: 'is-it-maintained-open-issues', + }, + { + attributes: { + branch: 'master', + repository: 'huonw/external_mixin', + }, + badge_type: 'codecov', + }, + { + attributes: { + branch: 'master', + repository: 'huonw/external_mixin', + }, + badge_type: 'coveralls', + }, + ], + versions: null, + }, + { + created_at: '2015-02-27T11:51:58Z', + description: + 'Use your favourite interpreted language to generate your Rust, right\nin your Rust. Supports Python, Ruby and shell (`sh`) out of the box,\nwith an extensible macro to support any others. (See `rust_mixin` to\nbe able to use your all-time favourite language to generate your Rust.)\n', + documentation: 'https://github.com/huonw/external_mixin#external_mixin', + downloads: 497, + recent_downloads: 497, + homepage: 'https://github.com/huonw/external_mixin', + id: 'external_mixin', + keywords: ['python', 'ruby', 'shell', 'plugin', 'code-generation'], + max_version: '0.0.1', + name: 'external_mixin', + repository: 'https://github.com/huonw/external_mixin', + updated_at: '2015-02-27T11:51:58Z', + versions: null, + }, + { + created_at: '2015-02-27T11:51:40Z', + description: 'Backing library for `rust_mixin` and `external_mixin` to keep them\nDRY.\n', + documentation: 'https://github.com/huonw/external_mixin#external_mixin_base', + downloads: 989, + recent_downloads: 0, + homepage: 'https://github.com/huonw/external_mixin', + id: 'external_mixin_umbrella', + keywords: ['plugin', 'code-generation'], + max_version: '0.0.2', + name: 'external_mixin_umbrella', + repository: 'https://github.com/huonw/external_mixin', + updated_at: '2015-02-27T11:52:30Z', + versions: null, + }, + { + created_at: '2015-10-10T15:26:24Z', + description: + 'Adds String based inflections for Rust. Snake, kebab, camel, sentence, class, title, upper, and lower cases as well as ordinalize, deordinalize, demodulize, and foreign key are supported as both traits and pure functions acting on String types.\n', + documentation: 'http://whatisinternet.github.io/inflector/doc/inflector/', + downloads: 57, + recent_downloads: 1, + homepage: 'https://github.com/whatisinternet/inflector', + id: 'Inflector', + keywords: ['string', 'case', 'camel', 'snake', 'inflection'], + max_version: '0.1.6', + name: 'Inflector', + repository: 'https://github.com/whatisinternet/inflector', + updated_at: '2015-10-27T01:51:42Z', + versions: null, + }, + { + created_at: '2015-05-21T17:43:38Z', + description: 'Client for the ElasticSearch REST API', + documentation: 'http://benashford.github.io/rs-es/rs_es/index.html', + downloads: 321, + recent_downloads: 21, + homepage: null, + id: 'rs-es', + keywords: ['elasticsearch', 'elastic'], + max_version: '0.1.17', + name: 'rs-es', + repository: 'https://github.com/benashford/rs-es', + updated_at: '2015-09-09T15:34:50Z', + versions: null, + }, + { + created_at: '2014-11-21T05:12:08Z', + description: 'A (mostly) pure-Rust implementation of various common cryptographic algorithms.', + documentation: null, + downloads: 21573, + recent_downloads: 2000, + homepage: 'https://github.com/DaGenix/rust-crypto/', + id: 'rust-crypto', + keywords: ['Crypto', 'MD5', 'Sha1', 'Sha2', 'AES'], + max_version: '0.2.34', + name: 'rust-crypto', + repository: 'https://github.com/DaGenix/rust-crypto/', + updated_at: '2015-10-29T01:16:17Z', + versions: null, + }, + { + created_at: '2015-03-20T13:46:04Z', + description: 'This library provides HTSlib bindings and a high level Rust API for reading and writing BAM files.', + documentation: null, + downloads: 485, + recent_downloads: 85, + homepage: null, + id: 'rust-htslib', + keywords: ['htslib', 'bam', 'bioinformatics', 'pileup', 'sequencing'], + max_version: '0.5.2', + name: 'rust-htslib', + repository: 'https://github.com/rust-bio/rust-htslib.git', + updated_at: '2015-11-11T00:10:43Z', + versions: null, + }, + { + badges: [ + { + badge_type: 'maintenance', + attributes: { + status: 'actively-developed', + }, + }, + ], + created_at: '2014-11-23T09:01:21Z', + description: 'A Kinetic protocol library written in Rust', + documentation: 'https://icorderi.github.io/kinetic-rust/doc/kinetic/', + downloads: 225, + recent_downloads: 125, + homepage: 'https://icorderi.github.io/icorderi/kinetic-rust', + id: 'kinetic-rust', + keywords: ['Protocol', 'Kinetic', 'Storage'], + max_version: '0.0.16', + name: 'kinetic-rust', + repository: 'https://github.com/icorderi/kinetic-rust/', + updated_at: '2015-04-21T00:15:49Z', + versions: null, + }, + { + created_at: '2014-11-29T17:51:55Z', + description: 'Rustless is a REST-like API micro-framework for Rust.', + documentation: null, + downloads: 554, + recent_downloads: 500, + homepage: 'https://github.com/rustless/rustless', + id: 'rustless', + keywords: ['api', 'web', 'hyper', 'iron', 'rest'], + max_version: '0.8.0', + name: 'rustless', + repository: 'https://crates.io/crates/rustless', + updated_at: '2015-10-31T11:49:29Z', + versions: null, + }, + { + created_at: '2014-12-05T20:20:39Z', + description: 'A generic serialization/deserialization framework', + documentation: 'https://serde-rs.github.io/serde/serde/serde/index.html', + downloads: 50854, + recent_downloads: 854, + homepage: null, + id: 'serde', + keywords: ['serde', 'serialization'], + max_version: '0.6.1', + name: 'serde', + repository: 'https://github.com/serde-rs/serde', + updated_at: '2015-10-18T03:10:21Z', + versions: null, + }, + { + created_at: '2015-08-26T13:50:58Z', + description: 'Send cypher queries to a neo4j database', + documentation: 'http://livioribeiro.github.io/rusted_cypher/rusted_cypher/', + downloads: 156, + recent_downloads: 54, + homepage: 'https://github.com/livioribeiro/rusted-cypher', + id: 'rusted_cypher', + keywords: ['neo4j', 'database', 'query', 'cypher', 'graph'], + max_version: '0.7.1', + name: 'rusted_cypher', + repository: 'https://github.com/livioribeiro/rusted-cypher', + updated_at: '2015-11-07T17:26:55Z', + versions: null, + }, + { + created_at: '2015-01-02T20:54:04Z', + description: + 'An (incomplete) port of zlib to Rust. The decompressor works, but the compressor has not yet been ported.', + documentation: null, + downloads: 223, + recent_downloads: 23, + homepage: null, + id: 'zlib', + keywords: [], + max_version: '0.0.1', + name: 'zlib', + repository: null, + updated_at: '2015-01-02T20:54:04Z', + versions: null, + }, + { + created_at: '2015-05-08T19:34:16Z', + description: + 'A light HTTP framework, with some REST-like features and the ambition of being simple, modular and non-intrusive.', + documentation: 'http://ogeon.github.io/docs/rustful/master/rustful/index.html', + downloads: 576, + recent_downloads: 76, + homepage: null, + id: 'rustful', + keywords: ['web', 'rest', 'framework', 'http', 'routing'], + max_version: '0.5.0', + name: 'rustful', + repository: 'https://github.com/Ogeon/rustful', + updated_at: '2015-09-19T21:10:27Z', + versions: null, + }, + { + created_at: '2014-11-24T02:34:44Z', + description: 'A native PostgreSQL driver', + documentation: 'https://sfackler.github.io/rust-postgres/doc/v0.10.1/postgres', + downloads: 13449, + recent_downloads: 13, + homepage: null, + id: 'postgres', + keywords: ['database', 'sql'], + max_version: '0.10.1', + name: 'postgres', + repository: 'https://github.com/sfackler/rust-postgres', + updated_at: '2015-11-08T00:48:59Z', + versions: null, + }, + { + created_at: '2014-11-21T00:20:47Z', + description: 'Automatic property based testing with shrinking.', + documentation: 'http://burntsushi.net/rustdoc/quickcheck/', + downloads: 19271, + recent_downloads: 143, + homepage: 'https://github.com/BurntSushi/quickcheck', + id: 'quickcheck', + keywords: ['testing', 'quickcheck', 'property', 'shrinking', 'fuzz'], + max_version: '0.2.24', + name: 'quickcheck', + repository: 'https://github.com/BurntSushi/quickcheck', + updated_at: '2015-09-20T21:53:38Z', + versions: null, + }, + { + created_at: '2014-11-21T00:21:04Z', + description: 'A macro attribute for quickcheck.', + documentation: 'http://burntsushi.net/rustdoc/quickcheck/', + downloads: 3796, + recent_downloads: 768, + homepage: 'https://github.com/BurntSushi/quickcheck', + id: 'quickcheck_macros', + keywords: ['testing', 'quickcheck', 'property', 'shrinking', 'fuzz'], + max_version: '0.2.24', + name: 'quickcheck_macros', + repository: 'https://github.com/BurntSushi/quickcheck', + updated_at: '2015-09-20T21:53:57Z', + versions: null, + }, + { + created_at: '2015-08-25T19:15:35Z', + description: + 'Lexical analysers generator for Rust, written in Rust (crate dedicated to rumblebars, divergences written by Nicolas Cherel)', + documentation: null, + downloads: 109, + recent_downloads: 0, + homepage: 'https://github.com/nicolas-cherel/rustlex', + id: 'nc_rustlex', + keywords: ['lexer', 'lexical', 'analyser', 'generator'], + max_version: '0.3.1', + name: 'nc_rustlex', + repository: 'https://github.com/nicolas-cherel/rustlex', + updated_at: '2015-08-25T19:15:35Z', + versions: null, + }, + { + created_at: '2015-01-17T17:47:52Z', + description: 'A byte-oriented, zero-copy, parser combinators library', + documentation: 'http://rust.unhandledexpression.com/nom/', + downloads: 5169, + recent_downloads: 69, + homepage: null, + id: 'nom', + keywords: ['parser', 'parser-combinators', 'parsing', 'streaming', 'bit'], + max_version: '1.0.1', + name: 'nom', + repository: 'https://github.com/Geal/nom', + updated_at: '2015-11-22T22:00:41Z', + versions: null, + }, ]; diff --git a/mirage/fixtures/dependencies.js b/mirage/fixtures/dependencies.js index bd3e7b3e36..9f7cb4a839 100644 --- a/mirage/fixtures/dependencies.js +++ b/mirage/fixtures/dependencies.js @@ -1,36 +1,36 @@ /* eslint-disable quotes */ export default [ - { - crate_id: 'libc', - default_features: true, - features: '', - id: 146231, - kind: 'normal', - optional: false, - req: '^0.2.18', - target: null, - version_id: 40905, - }, - { - crate_id: 'nanomsg-sys', - default_features: true, - features: '', - id: 146232, - kind: 'normal', - optional: false, - req: '^0.6.1', - target: null, - version_id: 40905, - }, - { - crate_id: 'nanomsg', - default_features: true, - features: '', - id: 90880, - kind: 'normal', - optional: false, - req: '^0.5.0', - target: null, - version_id: 28674, - }, + { + crate_id: 'libc', + default_features: true, + features: '', + id: 146231, + kind: 'normal', + optional: false, + req: '^0.2.18', + target: null, + version_id: 40905, + }, + { + crate_id: 'nanomsg-sys', + default_features: true, + features: '', + id: 146232, + kind: 'normal', + optional: false, + req: '^0.6.1', + target: null, + version_id: 40905, + }, + { + crate_id: 'nanomsg', + default_features: true, + features: '', + id: 90880, + kind: 'normal', + optional: false, + req: '^0.5.0', + target: null, + version_id: 28674, + }, ]; diff --git a/mirage/fixtures/keywords.js b/mirage/fixtures/keywords.js index 231b818733..2285b073d4 100644 --- a/mirage/fixtures/keywords.js +++ b/mirage/fixtures/keywords.js @@ -1,9 +1,9 @@ /* eslint-disable quotes */ export default [ - { - crates_cnt: 38, - created_at: '2014-11-23T06:47:40Z', - id: 'network', - keyword: 'network', - }, + { + crates_cnt: 38, + created_at: '2014-11-23T06:47:40Z', + id: 'network', + keyword: 'network', + }, ]; diff --git a/mirage/fixtures/teams.js b/mirage/fixtures/teams.js index f13fe486a0..aabb1a35ba 100644 --- a/mirage/fixtures/teams.js +++ b/mirage/fixtures/teams.js @@ -1,17 +1,17 @@ /* eslint-disable quotes */ export default [ - { - avatar: 'https://avatars.githubusercontent.com/u/565790?v=3', - id: 1, - login: 'github:org:thehydroimpulse', - name: 'thehydroimpulseteam', - url: 'https://github.com/org_test', - }, - { - avatar: 'https://avatars.githubusercontent.com/u/9447137?v=3', - id: 303, - login: 'github:org:blabaere', - name: 'Team Benoît Labaere', - url: 'https://github.com/blabaere', - }, + { + avatar: 'https://avatars.githubusercontent.com/u/565790?v=3', + id: 1, + login: 'github:org:thehydroimpulse', + name: 'thehydroimpulseteam', + url: 'https://github.com/org_test', + }, + { + avatar: 'https://avatars.githubusercontent.com/u/9447137?v=3', + id: 303, + login: 'github:org:blabaere', + name: 'Team Benoît Labaere', + url: 'https://github.com/blabaere', + }, ]; diff --git a/mirage/fixtures/users.js b/mirage/fixtures/users.js index 83b1b4365d..0c57699a95 100644 --- a/mirage/fixtures/users.js +++ b/mirage/fixtures/users.js @@ -1,27 +1,27 @@ /* eslint-disable quotes */ export default [ - { - avatar: 'https://avatars0.githubusercontent.com/u/9447137?v=3', - email: null, - id: 303, - login: 'blabaere', - name: 'Benoît Labaere', - url: 'https://github.com/blabaere', - }, - { - avatar: 'https://avatars.githubusercontent.com/u/565790?v=3', - email: 'dnfagnan@gmail.com', - id: 2, - login: 'thehydroimpulse', - name: 'Daniel Fagnan', - url: 'https://github.com/thehydroimpulse', - }, - { - avatar: 'https://avatars3.githubusercontent.com/u/1179195?v=3', - email: 'iain@fastmail.com', - id: 10982, - login: 'iain8', - name: 'Iain Buchanan', - url: 'https://github.com/iain8', - }, + { + avatar: 'https://avatars0.githubusercontent.com/u/9447137?v=3', + email: null, + id: 303, + login: 'blabaere', + name: 'Benoît Labaere', + url: 'https://github.com/blabaere', + }, + { + avatar: 'https://avatars.githubusercontent.com/u/565790?v=3', + email: 'dnfagnan@gmail.com', + id: 2, + login: 'thehydroimpulse', + name: 'Daniel Fagnan', + url: 'https://github.com/thehydroimpulse', + }, + { + avatar: 'https://avatars3.githubusercontent.com/u/1179195?v=3', + email: 'iain@fastmail.com', + id: 10982, + login: 'iain8', + name: 'Iain Buchanan', + url: 'https://github.com/iain8', + }, ]; diff --git a/mirage/fixtures/version-downloads.js b/mirage/fixtures/version-downloads.js index f7a144d14a..eaeccc264c 100644 --- a/mirage/fixtures/version-downloads.js +++ b/mirage/fixtures/version-downloads.js @@ -1,18 +1,18 @@ /* eslint-disable quotes */ export default [ - { - date: '2017-02-10T00:00:00Z', - downloads: 2, - version: 40905, - }, - { - date: '2017-02-10T00:00:00Z', - downloads: 1, - version: 18445, - }, - { - date: '2017-02-11T00:00:00Z', - downloads: 1, - version: 40905, - }, + { + date: '2017-02-10T00:00:00Z', + downloads: 2, + version: 40905, + }, + { + date: '2017-02-10T00:00:00Z', + downloads: 1, + version: 18445, + }, + { + date: '2017-02-11T00:00:00Z', + downloads: 1, + version: 40905, + }, ]; diff --git a/mirage/fixtures/versions.js b/mirage/fixtures/versions.js index 667d44de11..34969b7faf 100644 --- a/mirage/fixtures/versions.js +++ b/mirage/fixtures/versions.js @@ -1,308 +1,308 @@ /* eslint-disable quotes */ export default [ - { - crate: 'nanomsg', - created_at: '2016-12-27T08:40:00Z', - dl_path: '/api/v1/crates/nanomsg/0.7.0-alpha.1/download', - downloads: 260, - features: { - bundled: ['nanomsg-sys/bundled'], - }, - id: 40906, - num: '0.7.0-alpha.1', - updated_at: '2016-12-27T08:40:00Z', - yanked: false, - license: 'MIT', - crate_size: 912355, - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], + { + crate: 'nanomsg', + created_at: '2016-12-27T08:40:00Z', + dl_path: '/api/v1/crates/nanomsg/0.7.0-alpha.1/download', + downloads: 260, + features: { + bundled: ['nanomsg-sys/bundled'], }, - { - crate: 'nanomsg', - created_at: '2016-12-27T08:40:00Z', - dl_path: '/api/v1/crates/nanomsg/0.6.1/download', - downloads: 260, - features: { - bundled: ['nanomsg-sys/bundled'], - }, - id: 40905, - num: '0.6.1', - crate_size: 8123545, - updated_at: '2016-12-27T08:40:00Z', - yanked: false, - license: 'Apache-2.0', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2016-06-10T20:03:55Z', - dl_path: '/api/v1/crates/nanomsg/0.6.0/download', - downloads: 904, - features: {}, - id: 28431, - num: '0.6.0', - updated_at: '2016-06-10T20:03:55Z', - yanked: false, - license: 'Apache-2.0', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2016-01-24T22:07:58Z', - dl_path: '/api/v1/crates/nanomsg/0.5.0/download', - downloads: 1217, - features: {}, - id: 21273, - num: '0.5.0', - updated_at: '2016-01-24T22:07:58Z', - yanked: false, - license: 'MIT/Apache-2.0', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2015-11-23T12:10:09Z', - dl_path: '/api/v1/crates/nanomsg/0.4.2/download', - downloads: 318, - features: {}, - id: 18445, - num: '0.4.2', - updated_at: '2015-12-16T00:01:56Z', - yanked: false, - license: 'MIT', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2015-10-29T22:13:45Z', - dl_path: '/api/v1/crates/nanomsg/0.4.1/download', - downloads: 168, - features: {}, - id: 17384, - num: '0.4.1', - updated_at: '2015-12-11T23:54:29Z', - yanked: false, - license: 'MIT', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2015-07-23T05:54:44Z', - dl_path: '/api/v1/crates/nanomsg/0.4.0/download', - downloads: 311, - features: {}, - id: 13574, - num: '0.4.0', - updated_at: '2015-12-11T23:54:29Z', - yanked: false, - license: 'MIT', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2015-04-18T20:45:03Z', - dl_path: '/api/v1/crates/nanomsg/0.3.4/download', - downloads: 237, - features: {}, - id: 9014, - num: '0.3.4', - updated_at: '2015-12-15T00:03:39Z', - yanked: false, - license: 'MIT', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2015-04-06T18:57:47Z', - dl_path: '/api/v1/crates/nanomsg/0.3.3/download', - downloads: 99, - features: {}, - id: 8236, - num: '0.3.3', - updated_at: '2015-12-11T23:54:29Z', - yanked: false, - license: 'MIT', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2015-03-26T06:51:10Z', - dl_path: '/api/v1/crates/nanomsg/0.3.2/download', - downloads: 98, - features: {}, - id: 7190, - num: '0.3.2', - updated_at: '2015-12-11T23:54:29Z', - yanked: false, - license: 'Apache-2.0', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2015-02-12T20:20:32Z', - dl_path: '/api/v1/crates/nanomsg/0.3.1/download', - downloads: 95, - features: {}, - id: 4944, - num: '0.3.1', - updated_at: '2015-12-11T23:54:29Z', - yanked: false, - license: 'MIT/Apache-2.0', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2014-12-08T16:21:01Z', - dl_path: '/api/v1/crates/nanomsg/0.3.0/download', - downloads: 102, - features: {}, - id: 940, - num: '0.3.0', - updated_at: '2015-12-11T23:54:29Z', - yanked: false, - license: 'MIT', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'nanomsg', - created_at: '2014-12-08T02:08:06Z', - dl_path: '/api/v1/crates/nanomsg/0.2.0/download', - downloads: 79, - features: {}, - id: 924, - num: '0.2.0', - updated_at: '2015-12-11T23:54:29Z', - yanked: false, - license: 'MIT', - _authors: [ - 'Daniel Fagnan ', - 'Jason E. Aten', - 'David C. Bishop', - 'Dennis Lawler', - 'Zachary Tong', - 'Dan Burkert', - 'Benoît Labaere ', - 'Chip Collier', - ], - }, - { - crate: 'unicorn-rpc', - created_at: '2014-12-08T02:08:06Z', - dl_path: '/api/v1/crates/unicorn-rpc/0.2.0/download', - downloads: 79, - features: {}, - id: 28674, - num: '0.2.0', - updated_at: '2015-12-11T23:54:29Z', - yanked: false, - license: 'MIT', - _authors: ['David C. Bishop'], + id: 40906, + num: '0.7.0-alpha.1', + updated_at: '2016-12-27T08:40:00Z', + yanked: false, + license: 'MIT', + crate_size: 912355, + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2016-12-27T08:40:00Z', + dl_path: '/api/v1/crates/nanomsg/0.6.1/download', + downloads: 260, + features: { + bundled: ['nanomsg-sys/bundled'], }, + id: 40905, + num: '0.6.1', + crate_size: 8123545, + updated_at: '2016-12-27T08:40:00Z', + yanked: false, + license: 'Apache-2.0', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2016-06-10T20:03:55Z', + dl_path: '/api/v1/crates/nanomsg/0.6.0/download', + downloads: 904, + features: {}, + id: 28431, + num: '0.6.0', + updated_at: '2016-06-10T20:03:55Z', + yanked: false, + license: 'Apache-2.0', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2016-01-24T22:07:58Z', + dl_path: '/api/v1/crates/nanomsg/0.5.0/download', + downloads: 1217, + features: {}, + id: 21273, + num: '0.5.0', + updated_at: '2016-01-24T22:07:58Z', + yanked: false, + license: 'MIT/Apache-2.0', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2015-11-23T12:10:09Z', + dl_path: '/api/v1/crates/nanomsg/0.4.2/download', + downloads: 318, + features: {}, + id: 18445, + num: '0.4.2', + updated_at: '2015-12-16T00:01:56Z', + yanked: false, + license: 'MIT', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2015-10-29T22:13:45Z', + dl_path: '/api/v1/crates/nanomsg/0.4.1/download', + downloads: 168, + features: {}, + id: 17384, + num: '0.4.1', + updated_at: '2015-12-11T23:54:29Z', + yanked: false, + license: 'MIT', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2015-07-23T05:54:44Z', + dl_path: '/api/v1/crates/nanomsg/0.4.0/download', + downloads: 311, + features: {}, + id: 13574, + num: '0.4.0', + updated_at: '2015-12-11T23:54:29Z', + yanked: false, + license: 'MIT', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2015-04-18T20:45:03Z', + dl_path: '/api/v1/crates/nanomsg/0.3.4/download', + downloads: 237, + features: {}, + id: 9014, + num: '0.3.4', + updated_at: '2015-12-15T00:03:39Z', + yanked: false, + license: 'MIT', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2015-04-06T18:57:47Z', + dl_path: '/api/v1/crates/nanomsg/0.3.3/download', + downloads: 99, + features: {}, + id: 8236, + num: '0.3.3', + updated_at: '2015-12-11T23:54:29Z', + yanked: false, + license: 'MIT', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2015-03-26T06:51:10Z', + dl_path: '/api/v1/crates/nanomsg/0.3.2/download', + downloads: 98, + features: {}, + id: 7190, + num: '0.3.2', + updated_at: '2015-12-11T23:54:29Z', + yanked: false, + license: 'Apache-2.0', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2015-02-12T20:20:32Z', + dl_path: '/api/v1/crates/nanomsg/0.3.1/download', + downloads: 95, + features: {}, + id: 4944, + num: '0.3.1', + updated_at: '2015-12-11T23:54:29Z', + yanked: false, + license: 'MIT/Apache-2.0', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2014-12-08T16:21:01Z', + dl_path: '/api/v1/crates/nanomsg/0.3.0/download', + downloads: 102, + features: {}, + id: 940, + num: '0.3.0', + updated_at: '2015-12-11T23:54:29Z', + yanked: false, + license: 'MIT', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'nanomsg', + created_at: '2014-12-08T02:08:06Z', + dl_path: '/api/v1/crates/nanomsg/0.2.0/download', + downloads: 79, + features: {}, + id: 924, + num: '0.2.0', + updated_at: '2015-12-11T23:54:29Z', + yanked: false, + license: 'MIT', + _authors: [ + 'Daniel Fagnan ', + 'Jason E. Aten', + 'David C. Bishop', + 'Dennis Lawler', + 'Zachary Tong', + 'Dan Burkert', + 'Benoît Labaere ', + 'Chip Collier', + ], + }, + { + crate: 'unicorn-rpc', + created_at: '2014-12-08T02:08:06Z', + dl_path: '/api/v1/crates/unicorn-rpc/0.2.0/download', + downloads: 79, + features: {}, + id: 28674, + num: '0.2.0', + updated_at: '2015-12-11T23:54:29Z', + yanked: false, + license: 'MIT', + _authors: ['David C. Bishop'], + }, ]; diff --git a/mirage/scenarios/default.js b/mirage/scenarios/default.js index 6336d953b8..5031608679 100644 --- a/mirage/scenarios/default.js +++ b/mirage/scenarios/default.js @@ -1,3 +1,3 @@ export default function(server) { - server.loadFixtures(); + server.loadFixtures(); } diff --git a/mirage/serializers/application.js b/mirage/serializers/application.js index 1a966912ef..29c7196b5e 100644 --- a/mirage/serializers/application.js +++ b/mirage/serializers/application.js @@ -1,26 +1,26 @@ import { ActiveModelSerializer } from 'ember-cli-mirage'; export default ActiveModelSerializer.extend({ - getHashForResource(resource) { - let isModel = this.isModel(resource); - let hash = ActiveModelSerializer.prototype.getHashForResource.apply(this, arguments); + getHashForResource(resource) { + let isModel = this.isModel(resource); + let hash = ActiveModelSerializer.prototype.getHashForResource.apply(this, arguments); - if (isModel) { - let links = this.links(resource); - if (links) { - hash[0].links = links; - } - } else { - for (let i = 0; i < hash[0].length && i < resource.models.length; i++) { - let links = this.links(resource.models[i]); - if (links) { - hash[0][i].links = links; - } - } + if (isModel) { + let links = this.links(resource); + if (links) { + hash[0].links = links; + } + } else { + for (let i = 0; i < hash[0].length && i < resource.models.length; i++) { + let links = this.links(resource.models[i]); + if (links) { + hash[0][i].links = links; } + } + } - return hash; - }, + return hash; + }, - links() {}, + links() {}, }); diff --git a/mirage/serializers/crate.js b/mirage/serializers/crate.js index 665f66bb37..940a8f3d27 100644 --- a/mirage/serializers/crate.js +++ b/mirage/serializers/crate.js @@ -1,32 +1,32 @@ import BaseSerializer from './application'; export default BaseSerializer.extend({ - attrs: [ - 'badges', - 'categories', - 'created_at', - 'description', - 'documentation', - 'downloads', - 'recent_downloads', - 'homepage', - 'id', - 'keywords', - 'links', - 'max_version', - 'name', - 'repository', - 'updated_at', - 'versions', - ], + attrs: [ + 'badges', + 'categories', + 'created_at', + 'description', + 'documentation', + 'downloads', + 'recent_downloads', + 'homepage', + 'id', + 'keywords', + 'links', + 'max_version', + 'name', + 'repository', + 'updated_at', + 'versions', + ], - links(crate) { - return { - owner_user: `/api/v1/crates/${crate.id}/owner_user`, - owner_team: `/api/v1/crates/${crate.id}/owner_team`, - reverse_dependencies: `/api/v1/crates/${crate.id}/reverse_dependencies`, - version_downloads: `/api/v1/crates/${crate.id}/downloads`, - versions: `/api/v1/crates/${crate.id}/versions`, - }; - }, + links(crate) { + return { + owner_user: `/api/v1/crates/${crate.id}/owner_user`, + owner_team: `/api/v1/crates/${crate.id}/owner_team`, + reverse_dependencies: `/api/v1/crates/${crate.id}/reverse_dependencies`, + version_downloads: `/api/v1/crates/${crate.id}/downloads`, + versions: `/api/v1/crates/${crate.id}/versions`, + }; + }, }); diff --git a/mirage/serializers/version.js b/mirage/serializers/version.js index a8cb81f6c8..06f2d158cc 100644 --- a/mirage/serializers/version.js +++ b/mirage/serializers/version.js @@ -1,26 +1,26 @@ import BaseSerializer from './application'; export default BaseSerializer.extend({ - attrs: [ - 'crate', - 'created_at', - 'dl_path', - 'downloads', - 'features', - 'id', - 'links', - 'num', - 'updated_at', - 'yanked', - 'license', - 'crate_size', - ], + attrs: [ + 'crate', + 'created_at', + 'dl_path', + 'downloads', + 'features', + 'id', + 'links', + 'num', + 'updated_at', + 'yanked', + 'license', + 'crate_size', + ], - links(version) { - return { - authors: `/api/v1/crates/${version.crate}/${version.num}/authors`, - dependencies: `/api/v1/crates/${version.crate}/${version.num}/dependencies`, - version_downloads: `/api/v1/crates/${version.crate}/${version.num}/downloads`, - }; - }, + links(version) { + return { + authors: `/api/v1/crates/${version.crate}/${version.num}/authors`, + dependencies: `/api/v1/crates/${version.crate}/${version.num}/dependencies`, + version_downloads: `/api/v1/crates/${version.crate}/${version.num}/downloads`, + }; + }, }); diff --git a/testem.js b/testem.js index 97d3c255dd..6f7073f7dd 100644 --- a/testem.js +++ b/testem.js @@ -1,15 +1,15 @@ 'use strict'; module.exports = { - test_page: 'tests/index.html?hidepassed', - disable_watching: true, - parallel: -1, - launch_in_ci: ['Chrome'], - launch_in_dev: ['Chrome'], - browser_args: { - Chrome: { - mode: 'ci', - args: ['--disable-gpu', '--headless', '--remote-debugging-port=9222', '--window-size=1440,900'], - }, + test_page: 'tests/index.html?hidepassed', + disable_watching: true, + parallel: -1, + launch_in_ci: ['Chrome'], + launch_in_dev: ['Chrome'], + browser_args: { + Chrome: { + mode: 'ci', + args: ['--disable-gpu', '--headless', '--remote-debugging-port=9222', '--window-size=1440,900'], }, + }, }; diff --git a/tests/acceptance/categories-test.js b/tests/acceptance/categories-test.js index b5c01dc38c..4c8b34446d 100644 --- a/tests/acceptance/categories-test.js +++ b/tests/acceptance/categories-test.js @@ -7,62 +7,62 @@ import setupMirage from '../helpers/setup-mirage'; import { percySnapshot } from 'ember-percy'; module('Acceptance | categories', function(hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); + setupApplicationTest(hooks); + setupMirage(hooks); - test('is accessible', async function(assert) { - assert.expect(0); + test('is accessible', async function(assert) { + assert.expect(0); - this.server.create('category', { category: 'API bindings', crates_cnt: 0 }); - this.server.create('category', { category: 'Algorithms', crates_cnt: 1 }); - this.server.create('category', { category: 'Asynchronous', crates_cnt: 3910 }); + this.server.create('category', { category: 'API bindings', crates_cnt: 0 }); + this.server.create('category', { category: 'Algorithms', crates_cnt: 1 }); + this.server.create('category', { category: 'Asynchronous', crates_cnt: 3910 }); - await visit('/categories'); - percySnapshot(assert); + await visit('/categories'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('category/:category_id is accessible', async function(assert) { - assert.expect(0); + test('category/:category_id is accessible', async function(assert) { + assert.expect(0); - this.server.create('category', { category: 'Algorithms', crates_cnt: 1 }); + this.server.create('category', { category: 'Algorithms', crates_cnt: 1 }); - await visit('/categories/algorithms'); - percySnapshot(assert); + await visit('/categories/algorithms'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('listing categories', async function(assert) { - this.server.create('category', { category: 'API bindings', crates_cnt: 0 }); - this.server.create('category', { category: 'Algorithms', crates_cnt: 1 }); - this.server.create('category', { category: 'Asynchronous', crates_cnt: 3910 }); + test('listing categories', async function(assert) { + this.server.create('category', { category: 'API bindings', crates_cnt: 0 }); + this.server.create('category', { category: 'Algorithms', crates_cnt: 1 }); + this.server.create('category', { category: 'Asynchronous', crates_cnt: 3910 }); - await visit('/categories'); + await visit('/categories'); - assert.dom('[data-test-category="api-bindings"] [data-test-crate-count]').hasText('0 crates'); - assert.dom('[data-test-category="algorithms"] [data-test-crate-count]').hasText('1 crate'); - assert.dom('[data-test-category="asynchronous"] [data-test-crate-count]').hasText('3,910 crates'); - }); + assert.dom('[data-test-category="api-bindings"] [data-test-crate-count]').hasText('0 crates'); + assert.dom('[data-test-category="algorithms"] [data-test-crate-count]').hasText('1 crate'); + assert.dom('[data-test-category="asynchronous"] [data-test-crate-count]').hasText('3,910 crates'); + }); - test('category/:category_id index default sort is recent-downloads', async function(assert) { - this.server.create('category', { category: 'Algorithms', crates_cnt: 1 }); + test('category/:category_id index default sort is recent-downloads', async function(assert) { + this.server.create('category', { category: 'Algorithms', crates_cnt: 1 }); - await visit('/categories/algorithms'); + await visit('/categories/algorithms'); - assert.dom('[data-test-category-sort] [data-test-current-order]').hasText('Recent Downloads'); - }); + assert.dom('[data-test-category-sort] [data-test-current-order]').hasText('Recent Downloads'); + }); - test('listing category slugs', async function(assert) { - this.server.create('category', { category: 'Algorithms', description: 'Crates for algorithms' }); - this.server.create('category', { category: 'Asynchronous', description: 'Async crates' }); + test('listing category slugs', async function(assert) { + this.server.create('category', { category: 'Algorithms', description: 'Crates for algorithms' }); + this.server.create('category', { category: 'Asynchronous', description: 'Async crates' }); - await visit('/category_slugs'); + await visit('/category_slugs'); - assert.dom('[data-test-category-slug="algorithms"]').hasText('algorithms'); - assert.dom('[data-test-category-description="algorithms"]').hasText('Crates for algorithms'); - assert.dom('[data-test-category-slug="asynchronous"]').hasText('asynchronous'); - assert.dom('[data-test-category-description="asynchronous"]').hasText('Async crates'); - }); + assert.dom('[data-test-category-slug="algorithms"]').hasText('algorithms'); + assert.dom('[data-test-category-description="algorithms"]').hasText('Crates for algorithms'); + assert.dom('[data-test-category-slug="asynchronous"]').hasText('asynchronous'); + assert.dom('[data-test-category-description="asynchronous"]').hasText('Async crates'); + }); }); diff --git a/tests/acceptance/crate-test.js b/tests/acceptance/crate-test.js index 943c20a96f..fc49eb0b5f 100644 --- a/tests/acceptance/crate-test.js +++ b/tests/acceptance/crate-test.js @@ -8,279 +8,279 @@ import setupMirage from '../helpers/setup-mirage'; import { percySnapshot } from 'ember-percy'; module('Acceptance | crate page', function(hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); + setupApplicationTest(hooks); + setupMirage(hooks); - test('is accessible', async function(assert) { - assert.expect(0); + test('is accessible', async function(assert) { + assert.expect(0); - this.server.create('crate', 'withVersion', { id: 'nanomsg' }); + this.server.create('crate', 'withVersion', { id: 'nanomsg' }); - await visit('/'); - percySnapshot(assert); + await visit('/'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('/crates/:crate is accessible', async function(assert) { - assert.expect(0); + test('/crates/:crate is accessible', async function(assert) { + assert.expect(0); - this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); + this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); - await visit('/crates/nanomsg'); - percySnapshot(assert); + await visit('/crates/nanomsg'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('/crates/:crate/:version is accessible', async function(assert) { - assert.expect(0); + test('/crates/:crate/:version is accessible', async function(assert) { + assert.expect(0); - this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); + this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); - await visit('/crates/nanomsg/0.6.0'); - percySnapshot(assert); + await visit('/crates/nanomsg/0.6.0'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('/crates/:crate/owners is accessible', async function(assert) { - assert.expect(0); + test('/crates/:crate/owners is accessible', async function(assert) { + assert.expect(0); - this.server.loadFixtures(); + this.server.loadFixtures(); - await visit('/crates/nanomsg/owners'); - percySnapshot(assert); + await visit('/crates/nanomsg/owners'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('visiting a crate page from the front page', async function(assert) { - this.server.create('crate', 'withVersion', { id: 'nanomsg' }); + test('visiting a crate page from the front page', async function(assert) { + this.server.create('crate', 'withVersion', { id: 'nanomsg' }); - await visit('/'); - await click('[data-test-just-updated] [data-test-crate-link="0"]'); + await visit('/'); + await click('[data-test-just-updated] [data-test-crate-link="0"]'); - assert.equal(currentURL(), '/crates/nanomsg'); - assert.equal(document.title, 'nanomsg - crates.io: Rust Package Registry'); - }); + assert.equal(currentURL(), '/crates/nanomsg'); + assert.equal(document.title, 'nanomsg - crates.io: Rust Package Registry'); + }); - test('visiting /crates/nanomsg', async function(assert) { - this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); + test('visiting /crates/nanomsg', async function(assert) { + this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); - await visit('/crates/nanomsg'); + await visit('/crates/nanomsg'); - assert.equal(currentURL(), '/crates/nanomsg'); - assert.equal(currentRouteName(), 'crate.index'); - assert.equal(document.title, 'nanomsg - crates.io: Rust Package Registry'); + assert.equal(currentURL(), '/crates/nanomsg'); + assert.equal(currentRouteName(), 'crate.index'); + assert.equal(document.title, 'nanomsg - crates.io: Rust Package Registry'); - assert.dom('[data-test-heading] [data-test-crate-name]').hasText('nanomsg'); - assert.dom('[data-test-heading] [data-test-crate-version]').hasText('0.6.1'); - }); + assert.dom('[data-test-heading] [data-test-crate-name]').hasText('nanomsg'); + assert.dom('[data-test-heading] [data-test-crate-version]').hasText('0.6.1'); + }); - test('visiting /crates/nanomsg/', async function(assert) { - this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); + test('visiting /crates/nanomsg/', async function(assert) { + this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); - await visit('/crates/nanomsg/'); + await visit('/crates/nanomsg/'); - assert.equal(currentURL(), '/crates/nanomsg/'); - assert.equal(currentRouteName(), 'crate.index'); - assert.equal(document.title, 'nanomsg - crates.io: Rust Package Registry'); + assert.equal(currentURL(), '/crates/nanomsg/'); + assert.equal(currentRouteName(), 'crate.index'); + assert.equal(document.title, 'nanomsg - crates.io: Rust Package Registry'); - assert.dom('[data-test-heading] [data-test-crate-name]').hasText('nanomsg'); - assert.dom('[data-test-heading] [data-test-crate-version]').hasText('0.6.1'); - }); + assert.dom('[data-test-heading] [data-test-crate-name]').hasText('nanomsg'); + assert.dom('[data-test-heading] [data-test-crate-version]').hasText('0.6.1'); + }); - test('visiting /crates/nanomsg/0.6.0', async function(assert) { - this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); - this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); + test('visiting /crates/nanomsg/0.6.0', async function(assert) { + this.server.create('crate', { id: 'nanomsg', max_version: '0.6.1' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.0' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); - await visit('/crates/nanomsg/0.6.0'); + await visit('/crates/nanomsg/0.6.0'); - assert.equal(currentURL(), '/crates/nanomsg/0.6.0'); - assert.equal(currentRouteName(), 'crate.version'); - assert.equal(document.title, 'nanomsg - crates.io: Rust Package Registry'); + assert.equal(currentURL(), '/crates/nanomsg/0.6.0'); + assert.equal(currentRouteName(), 'crate.version'); + assert.equal(document.title, 'nanomsg - crates.io: Rust Package Registry'); - assert.dom('[data-test-heading] [data-test-crate-name]').hasText('nanomsg'); - assert.dom('[data-test-heading] [data-test-crate-version]').hasText('0.6.0'); - }); + assert.dom('[data-test-heading] [data-test-crate-name]').hasText('nanomsg'); + assert.dom('[data-test-heading] [data-test-crate-version]').hasText('0.6.0'); + }); - test('navigating to the all versions page', async function(assert) { - this.server.loadFixtures(); + test('navigating to the all versions page', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg'); - await click('[data-test-all-versions-link]'); + await visit('/crates/nanomsg'); + await click('[data-test-all-versions-link]'); - assert.dom('.info').hasText(/All 13\s+versions of nanomsg since\s+December \d+, 2014/); - }); + assert.dom('.info').hasText(/All 13\s+versions of nanomsg since\s+December \d+, 2014/); + }); - test('navigating to the reverse dependencies page', async function(assert) { - this.server.loadFixtures(); + test('navigating to the reverse dependencies page', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg'); - await click('[data-test-reverse-deps-link]'); + await visit('/crates/nanomsg'); + await click('[data-test-reverse-deps-link]'); - assert.equal(currentURL(), '/crates/nanomsg/reverse_dependencies'); - assert.dom('a[href="/crates/unicorn-rpc"]').hasText('unicorn-rpc'); - }); + assert.equal(currentURL(), '/crates/nanomsg/reverse_dependencies'); + assert.dom('a[href="/crates/unicorn-rpc"]').hasText('unicorn-rpc'); + }); - test('navigating to a user page', async function(assert) { - this.server.loadFixtures(); + test('navigating to a user page', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg'); - await click('[data-test-owners] [data-test-user-link="blabaere"]'); + await visit('/crates/nanomsg'); + await click('[data-test-owners] [data-test-user-link="blabaere"]'); - assert.equal(currentURL(), '/users/blabaere'); - assert.dom('[data-test-heading] [data-test-username]').hasText('blabaere'); - }); + assert.equal(currentURL(), '/users/blabaere'); + assert.dom('[data-test-heading] [data-test-username]').hasText('blabaere'); + }); - test('navigating to a team page', async function(assert) { - this.server.loadFixtures(); + test('navigating to a team page', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg'); - await click('[data-test-owners] [data-test-team-link="github:org:thehydroimpulse"]'); + await visit('/crates/nanomsg'); + await click('[data-test-owners] [data-test-team-link="github:org:thehydroimpulse"]'); - assert.equal(currentURL(), '/teams/github:org:thehydroimpulse'); - assert.dom('[data-test-heading] [data-test-team-name]').hasText('thehydroimpulseteam'); - }); + assert.equal(currentURL(), '/teams/github:org:thehydroimpulse'); + assert.dom('[data-test-heading] [data-test-team-name]').hasText('thehydroimpulseteam'); + }); - test('crates having user-owners', async function(assert) { - this.server.loadFixtures(); + test('crates having user-owners', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg'); + await visit('/crates/nanomsg'); - assert - .dom('[data-test-owners] [data-test-team-link="github:org:thehydroimpulse"] img') - .hasAttribute('src', 'https://avatars.githubusercontent.com/u/565790?v=3&s=64'); + assert + .dom('[data-test-owners] [data-test-team-link="github:org:thehydroimpulse"] img') + .hasAttribute('src', 'https://avatars.githubusercontent.com/u/565790?v=3&s=64'); - assert.dom('[data-test-owners] li').exists({ count: 4 }); - }); + assert.dom('[data-test-owners] li').exists({ count: 4 }); + }); - test('crates having team-owners', async function(assert) { - this.server.loadFixtures(); + test('crates having team-owners', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg'); + await visit('/crates/nanomsg'); - assert.dom('[data-test-owners] [data-test-team-link="github:org:thehydroimpulse"]').exists(); - assert.dom('[data-test-owners] li').exists({ count: 4 }); - }); + assert.dom('[data-test-owners] [data-test-team-link="github:org:thehydroimpulse"]').exists(); + assert.dom('[data-test-owners] li').exists({ count: 4 }); + }); - test('crates license is supplied by version', async function(assert) { - this.server.loadFixtures(); + test('crates license is supplied by version', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg'); - assert.dom('[data-test-license]').hasText('Apache-2.0'); + await visit('/crates/nanomsg'); + assert.dom('[data-test-license]').hasText('Apache-2.0'); - await click('[data-test-version-link="0.5.0"]'); - assert.dom('[data-test-license]').hasText('MIT/Apache-2.0'); - }); + await click('[data-test-version-link="0.5.0"]'); + assert.dom('[data-test-license]').hasText('MIT/Apache-2.0'); + }); - test('navigating to the owners page when not logged in', async function(assert) { - this.server.loadFixtures(); + test('navigating to the owners page when not logged in', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg'); + await visit('/crates/nanomsg'); - assert.dom('#crate-owners p a').doesNotExist(); - }); + assert.dom('#crate-owners p a').doesNotExist(); + }); - test('navigating to the owners page when not an owner', async function(assert) { - this.server.loadFixtures(); + test('navigating to the owners page when not an owner', async function(assert) { + this.server.loadFixtures(); - this.owner.register( - 'service:session', - Service.extend({ - get currentUser() { - return { login: 'iain8' }; - }, - loadUser() {}, - }), - ); + this.owner.register( + 'service:session', + Service.extend({ + get currentUser() { + return { login: 'iain8' }; + }, + loadUser() {}, + }), + ); - await visit('/crates/nanomsg'); + await visit('/crates/nanomsg'); - assert.dom('#crate-owners p a').doesNotExist(); - }); + assert.dom('#crate-owners p a').doesNotExist(); + }); - test('navigating to the owners page', async function(assert) { - this.server.loadFixtures(); + test('navigating to the owners page', async function(assert) { + this.server.loadFixtures(); - this.owner.register( - 'service:session', - Service.extend({ - get currentUser() { - return { login: 'thehydroimpulse', id: '2' }; - }, - loadUser() {}, - }), - ); + this.owner.register( + 'service:session', + Service.extend({ + get currentUser() { + return { login: 'thehydroimpulse', id: '2' }; + }, + loadUser() {}, + }), + ); - await visit('/crates/nanomsg'); - await click('#crate-owners p a'); + await visit('/crates/nanomsg'); + await click('#crate-owners p a'); - assert.dom('#crates-heading h1').hasText('Manage Crate Owners'); - }); + assert.dom('#crates-heading h1').hasText('Manage Crate Owners'); + }); - test('listing crate owners', async function(assert) { - this.server.loadFixtures(); + test('listing crate owners', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg/owners'); + await visit('/crates/nanomsg/owners'); - assert.dom('.owners .row').exists({ count: 2 }); - assert.dom('a[href="/users/thehydroimpulse"]').exists(); - assert.dom('a[href="/users/blabaere"]').exists(); - }); + assert.dom('.owners .row').exists({ count: 2 }); + assert.dom('a[href="/users/thehydroimpulse"]').exists(); + assert.dom('a[href="/users/blabaere"]').exists(); + }); - test('attempting to add owner without username', async function(assert) { - this.server.loadFixtures(); + test('attempting to add owner without username', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg/owners'); - await click('#add-owner'); + await visit('/crates/nanomsg/owners'); + await click('#add-owner'); - assert.dom('.error').exists(); - assert.dom('.error').hasText('Please enter a username'); - assert.dom('.owners .row').exists({ count: 2 }); - }); + assert.dom('.error').exists(); + assert.dom('.error').hasText('Please enter a username'); + assert.dom('.owners .row').exists({ count: 2 }); + }); - test('attempting to add non-existent owner', async function(assert) { - this.server.loadFixtures(); + test('attempting to add non-existent owner', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg/owners'); - await fillIn('input[name="username"]', 'spookyghostboo'); - await click('#add-owner'); + await visit('/crates/nanomsg/owners'); + await fillIn('input[name="username"]', 'spookyghostboo'); + await click('#add-owner'); - assert.dom('.error').exists(); - assert.dom('.error').hasText('Error sending invite'); - assert.dom('.owners .row').exists({ count: 2 }); - }); + assert.dom('.error').exists(); + assert.dom('.error').hasText('Error sending invite'); + assert.dom('.owners .row').exists({ count: 2 }); + }); - test('add a new owner', async function(assert) { - this.server.loadFixtures(); + test('add a new owner', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg/owners'); - await fillIn('input[name="username"]', 'iain8'); - await click('#add-owner'); + await visit('/crates/nanomsg/owners'); + await fillIn('input[name="username"]', 'iain8'); + await click('#add-owner'); - assert.dom('.invited').exists(); - assert.dom('.invited').hasText('An invite has been sent to iain8'); - assert.dom('.owners .row').exists({ count: 2 }); - }); + assert.dom('.invited').exists(); + assert.dom('.invited').hasText('An invite has been sent to iain8'); + assert.dom('.owners .row').exists({ count: 2 }); + }); - test('remove a crate owner', async function(assert) { - this.server.loadFixtures(); + test('remove a crate owner', async function(assert) { + this.server.loadFixtures(); - await visit('/crates/nanomsg/owners'); - await click('.owners .row:first-child .remove-owner'); + await visit('/crates/nanomsg/owners'); + await click('.owners .row:first-child .remove-owner'); - assert.dom('.removed').exists(); - assert.dom('.owners .row').exists({ count: 1 }); - }); + assert.dom('.removed').exists(); + assert.dom('.owners .row').exists({ count: 1 }); + }); }); diff --git a/tests/acceptance/crates-test.js b/tests/acceptance/crates-test.js index 3b37a3ba28..5f6647b503 100644 --- a/tests/acceptance/crates-test.js +++ b/tests/acceptance/crates-test.js @@ -7,90 +7,90 @@ import setupMirage from '../helpers/setup-mirage'; import { percySnapshot } from 'ember-percy'; module('Acceptance | crates page', function(hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); + setupApplicationTest(hooks); + setupMirage(hooks); - test('is accessible', async function(assert) { - assert.expect(0); + test('is accessible', async function(assert) { + assert.expect(0); - this.server.loadFixtures(); + this.server.loadFixtures(); - await visit('/'); - percySnapshot(assert); + await visit('/'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('/crates is accessible', async function(assert) { - assert.expect(0); + test('/crates is accessible', async function(assert) { + assert.expect(0); - this.server.loadFixtures(); + this.server.loadFixtures(); - await visit('/crates'); - percySnapshot(assert); + await visit('/crates'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('visiting the crates page from the front page', async function(assert) { - this.server.loadFixtures(); + test('visiting the crates page from the front page', async function(assert) { + this.server.loadFixtures(); - await visit('/'); - await click('[data-test-all-crates-link]'); + await visit('/'); + await click('[data-test-all-crates-link]'); - assert.equal(currentURL(), '/crates'); - assert.equal(document.title, 'Crates - crates.io: Rust Package Registry'); - }); + assert.equal(currentURL(), '/crates'); + assert.equal(document.title, 'Crates - crates.io: Rust Package Registry'); + }); - test('visiting the crates page directly', async function(assert) { - this.server.loadFixtures(); + test('visiting the crates page directly', async function(assert) { + this.server.loadFixtures(); - await visit('/crates'); - await click('[data-test-all-crates-link]'); + await visit('/crates'); + await click('[data-test-all-crates-link]'); - assert.equal(currentURL(), '/crates'); - assert.equal(document.title, 'Crates - crates.io: Rust Package Registry'); - }); + assert.equal(currentURL(), '/crates'); + assert.equal(document.title, 'Crates - crates.io: Rust Package Registry'); + }); - test('listing crates', async function(assert) { - this.server.loadFixtures(); + test('listing crates', async function(assert) { + this.server.loadFixtures(); - await visit('/crates'); + await visit('/crates'); - assert.dom('[data-test-crates-nav] [data-test-current-rows]').hasText('1-10'); - assert.dom('[data-test-crates-nav] [data-test-total-rows]').hasText('19'); - }); + assert.dom('[data-test-crates-nav] [data-test-current-rows]').hasText('1-10'); + assert.dom('[data-test-crates-nav] [data-test-total-rows]').hasText('19'); + }); - test('navigating to next page of crates', async function(assert) { - this.server.loadFixtures(); + test('navigating to next page of crates', async function(assert) { + this.server.loadFixtures(); - await visit('/crates'); - await click('[data-test-pagination-next]'); + await visit('/crates'); + await click('[data-test-pagination-next]'); - assert.equal(currentURL(), '/crates?page=2'); - assert.dom('[data-test-crates-nav] [data-test-current-rows]').hasText('11-19'); - assert.dom('[data-test-crates-nav] [data-test-total-rows]').hasText('19'); - }); + assert.equal(currentURL(), '/crates?page=2'); + assert.dom('[data-test-crates-nav] [data-test-current-rows]').hasText('11-19'); + assert.dom('[data-test-crates-nav] [data-test-total-rows]').hasText('19'); + }); - test('crates default sort is alphabetical', async function(assert) { - this.server.loadFixtures(); + test('crates default sort is alphabetical', async function(assert) { + this.server.loadFixtures(); - await visit('/crates'); + await visit('/crates'); - assert.dom('[data-test-crates-sort] [data-test-current-order]').hasText('Alphabetical'); - }); + assert.dom('[data-test-crates-sort] [data-test-current-order]').hasText('Alphabetical'); + }); - test('downloads appears for each crate on crate list', async function(assert) { - this.server.loadFixtures(); + test('downloads appears for each crate on crate list', async function(assert) { + this.server.loadFixtures(); - await visit('/crates'); - assert.dom('[data-test-crate-row="0"] [data-test-downloads]').hasText('All-Time: 497'); - }); + await visit('/crates'); + assert.dom('[data-test-crate-row="0"] [data-test-downloads]').hasText('All-Time: 497'); + }); - test('recent downloads appears for each crate on crate list', async function(assert) { - this.server.loadFixtures(); + test('recent downloads appears for each crate on crate list', async function(assert) { + this.server.loadFixtures(); - await visit('/crates'); - assert.dom('[data-test-crate-row="0"] [data-test-recent-downloads]').hasText('Recent: 497'); - }); + await visit('/crates'); + assert.dom('[data-test-crate-row="0"] [data-test-recent-downloads]').hasText('Recent: 497'); + }); }); diff --git a/tests/acceptance/front-page-test.js b/tests/acceptance/front-page-test.js index cadcfd13d5..173a6d79e6 100644 --- a/tests/acceptance/front-page-test.js +++ b/tests/acceptance/front-page-test.js @@ -7,42 +7,42 @@ import setupMirage from '../helpers/setup-mirage'; import { percySnapshot } from 'ember-percy'; module('Acceptance | front page', function(hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); + setupApplicationTest(hooks); + setupMirage(hooks); - test('is accessible', async function(assert) { - assert.expect(0); + test('is accessible', async function(assert) { + assert.expect(0); - this.server.loadFixtures(); + this.server.loadFixtures(); - await visit('/'); - await a11yAudit(axeConfig); - }); + await visit('/'); + await a11yAudit(axeConfig); + }); - test('visiting /', async function(assert) { - this.server.loadFixtures(); + test('visiting /', async function(assert) { + this.server.loadFixtures(); - await visit('/'); + await visit('/'); - assert.equal(currentURL(), '/'); - assert.equal(document.title, 'crates.io: Rust Package Registry'); + assert.equal(currentURL(), '/'); + assert.equal(document.title, 'crates.io: Rust Package Registry'); - assert.dom('[data-test-install-cargo-link]').exists(); - assert.dom('[data-test-all-crates-link]').exists(); - assert.dom('[data-test-login-link]').exists(); + assert.dom('[data-test-install-cargo-link]').exists(); + assert.dom('[data-test-all-crates-link]').exists(); + assert.dom('[data-test-login-link]').exists(); - assert.dom('[data-test-total-downloads]').hasText('122,669'); - assert.dom('[data-test-total-crates]').hasText('19'); + assert.dom('[data-test-total-downloads]').hasText('122,669'); + assert.dom('[data-test-total-crates]').hasText('19'); - assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasText('Inflector (0.1.6)'); - assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasAttribute('href', '/crates/Inflector'); + assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasText('Inflector (0.1.6)'); + assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasAttribute('href', '/crates/Inflector'); - assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasText('serde (0.6.1)'); - assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasAttribute('href', '/crates/serde'); + assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasText('serde (0.6.1)'); + assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasAttribute('href', '/crates/serde'); - assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasText('nanomsg (0.7.0-alpha)'); - assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasAttribute('href', '/crates/nanomsg'); + assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasText('nanomsg (0.7.0-alpha)'); + assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasAttribute('href', '/crates/nanomsg'); - percySnapshot(assert); - }); + percySnapshot(assert); + }); }); diff --git a/tests/acceptance/keyword-test.js b/tests/acceptance/keyword-test.js index 0e44b5b246..05ea209fcd 100644 --- a/tests/acceptance/keyword-test.js +++ b/tests/acceptance/keyword-test.js @@ -7,25 +7,25 @@ import setupMirage from '../helpers/setup-mirage'; import { percySnapshot } from 'ember-percy'; module('Acceptance | keywords', function(hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); + setupApplicationTest(hooks); + setupMirage(hooks); - test('keyword/:keyword_id is accessible', async function(assert) { - assert.expect(0); + test('keyword/:keyword_id is accessible', async function(assert) { + assert.expect(0); - this.server.create('keyword', { id: 'network', keyword: 'network', crates_cnt: 38 }); + this.server.create('keyword', { id: 'network', keyword: 'network', crates_cnt: 38 }); - await visit('keywords/network'); - percySnapshot(assert); + await visit('keywords/network'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('keyword/:keyword_id index default sort is recent-downloads', async function(assert) { - this.server.create('keyword', { id: 'network', keyword: 'network', crates_cnt: 38 }); + test('keyword/:keyword_id index default sort is recent-downloads', async function(assert) { + this.server.create('keyword', { id: 'network', keyword: 'network', crates_cnt: 38 }); - await visit('/keywords/network'); + await visit('/keywords/network'); - assert.dom('[data-test-keyword-sort] [data-test-current-order]').hasText('Recent Downloads'); - }); + assert.dom('[data-test-keyword-sort] [data-test-current-order]').hasText('Recent Downloads'); + }); }); diff --git a/tests/acceptance/search-test.js b/tests/acceptance/search-test.js index d9a93ab9e2..dfe168ba0e 100644 --- a/tests/acceptance/search-test.js +++ b/tests/acceptance/search-test.js @@ -8,87 +8,87 @@ import setupMirage from '../helpers/setup-mirage'; import { percySnapshot } from 'ember-percy'; module('Acceptance | search', function(hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); + setupApplicationTest(hooks); + setupMirage(hooks); - test('/search?q=rust is accessible', async function(assert) { - assert.expect(0); + test('/search?q=rust is accessible', async function(assert) { + assert.expect(0); - this.server.loadFixtures(); + this.server.loadFixtures(); - await visit('/'); - percySnapshot(assert); + await visit('/'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('searching for "rust"', async function(assert) { - this.server.loadFixtures(); + test('searching for "rust"', async function(assert) { + this.server.loadFixtures(); - await visit('/'); - await fillIn('[data-test-search-input]', 'rust'); - await triggerEvent('[data-test-search-form]', 'submit'); + await visit('/'); + await fillIn('[data-test-search-input]', 'rust'); + await triggerEvent('[data-test-search-form]', 'submit'); - assert.equal(currentURL(), '/search?q=rust'); - assert.equal(document.title, "Search Results for 'rust' - crates.io: Rust Package Registry"); + assert.equal(currentURL(), '/search?q=rust'); + assert.equal(document.title, "Search Results for 'rust' - crates.io: Rust Package Registry"); - assert.dom('[data-test-heading]').hasText("Search Results for 'rust'"); - assert.dom('[data-test-search-nav]').hasText('Displaying 1-8 of 8 total results'); - assert - .dom('[data-test-search-sort]') - .hasText('Sort by Relevance Relevance All-Time Downloads Recent Downloads Recent Updates'); - assert.dom('[data-test-crate-row="0"] [data-test-crate-link]').hasText('kinetic-rust'); - assert.dom('[data-test-crate-row="0"] [data-test-version-badge]').hasAttribute('alt', '0.0.16'); + assert.dom('[data-test-heading]').hasText("Search Results for 'rust'"); + assert.dom('[data-test-search-nav]').hasText('Displaying 1-8 of 8 total results'); + assert + .dom('[data-test-search-sort]') + .hasText('Sort by Relevance Relevance All-Time Downloads Recent Downloads Recent Updates'); + assert.dom('[data-test-crate-row="0"] [data-test-crate-link]').hasText('kinetic-rust'); + assert.dom('[data-test-crate-row="0"] [data-test-version-badge]').hasAttribute('alt', '0.0.16'); - assert - .dom('[data-test-crate-row="0"] [data-test-description]') - .hasText('A Kinetic protocol library written in Rust'); - assert.dom('[data-test-crate-row="0"] [data-test-downloads]').hasText('All-Time: 225'); - assert.dom('[data-test-crate-row="0"] [data-test-badge="maintenance"]').exists(); - }); + assert + .dom('[data-test-crate-row="0"] [data-test-description]') + .hasText('A Kinetic protocol library written in Rust'); + assert.dom('[data-test-crate-row="0"] [data-test-downloads]').hasText('All-Time: 225'); + assert.dom('[data-test-crate-row="0"] [data-test-badge="maintenance"]').exists(); + }); - test('searching for "rust" from query', async function(assert) { - this.server.loadFixtures(); + test('searching for "rust" from query', async function(assert) { + this.server.loadFixtures(); - await visit('/search?q=rust'); + await visit('/search?q=rust'); - assert.equal(currentURL(), '/search?q=rust'); - assert.equal(document.title, "Search Results for 'rust' - crates.io: Rust Package Registry"); + assert.equal(currentURL(), '/search?q=rust'); + assert.equal(document.title, "Search Results for 'rust' - crates.io: Rust Package Registry"); - assert.dom('[data-test-search-input]').hasValue('rust'); - assert.dom('[data-test-heading]').hasText("Search Results for 'rust'"); - assert.dom('[data-test-search-nav]').hasText('Displaying 1-8 of 8 total results'); - }); + assert.dom('[data-test-search-input]').hasValue('rust'); + assert.dom('[data-test-heading]').hasText("Search Results for 'rust'"); + assert.dom('[data-test-search-nav]').hasText('Displaying 1-8 of 8 total results'); + }); - test('pressing S key to focus the search bar', async function(assert) { - this.server.loadFixtures(); + test('pressing S key to focus the search bar', async function(assert) { + this.server.loadFixtures(); - await visit('/'); + await visit('/'); - await blur('[data-test-search-input]'); - await triggerKeyPress('KeyA'); - assert.dom('[data-test-search-input]').isNotFocused(); + await blur('[data-test-search-input]'); + await triggerKeyPress('KeyA'); + assert.dom('[data-test-search-input]').isNotFocused(); - await blur('[data-test-search-input]'); - await triggerKeyPress('KeyS'); - assert.dom('[data-test-search-input]').isFocused(); + await blur('[data-test-search-input]'); + await triggerKeyPress('KeyS'); + assert.dom('[data-test-search-input]').isFocused(); - await blur('[data-test-search-input]'); - await triggerKeyDown('KeyS'); - assert.dom('[data-test-search-input]').isFocused(); + await blur('[data-test-search-input]'); + await triggerKeyDown('KeyS'); + assert.dom('[data-test-search-input]').isFocused(); - await blur('[data-test-search-input]'); - await triggerKeyDown('shift+KeyS'); - assert.dom('[data-test-search-input]').isFocused(); - }); + await blur('[data-test-search-input]'); + await triggerKeyDown('shift+KeyS'); + assert.dom('[data-test-search-input]').isFocused(); + }); - test('check search results are by default displayed by relevance', async function(assert) { - this.server.loadFixtures(); + test('check search results are by default displayed by relevance', async function(assert) { + this.server.loadFixtures(); - await visit('/'); - await fillIn('[data-test-search-input]', 'rust'); - await triggerEvent('[data-test-search-form]', 'submit'); + await visit('/'); + await fillIn('[data-test-search-input]', 'rust'); + await triggerEvent('[data-test-search-form]', 'submit'); - assert.dom('[data-test-search-sort] [data-test-current-order]').hasText('Relevance'); - }); + assert.dom('[data-test-search-sort] [data-test-current-order]').hasText('Relevance'); + }); }); diff --git a/tests/acceptance/team-page-test.js b/tests/acceptance/team-page-test.js index 9f2649242b..2c0c662553 100644 --- a/tests/acceptance/team-page-test.js +++ b/tests/acceptance/team-page-test.js @@ -7,52 +7,52 @@ import setupMirage from '../helpers/setup-mirage'; import { percySnapshot } from 'ember-percy'; module('Acceptance | team page', function(hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); + setupApplicationTest(hooks); + setupMirage(hooks); - test('is accessible', async function(assert) { - assert.expect(0); + test('is accessible', async function(assert) { + assert.expect(0); - this.server.loadFixtures(); + this.server.loadFixtures(); - await visit('/teams/github:org:thehydroimpulse'); - percySnapshot(assert); + await visit('/teams/github:org:thehydroimpulse'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('has team organization display', async function(assert) { - this.server.loadFixtures(); + test('has team organization display', async function(assert) { + this.server.loadFixtures(); - await visit('/teams/github:org:thehydroimpulse'); + await visit('/teams/github:org:thehydroimpulse'); - assert.dom('[data-test-heading] [data-test-org-name]').hasText('org'); - assert.dom('[data-test-heading] [data-test-team-name]').hasText('thehydroimpulseteam'); - }); + assert.dom('[data-test-heading] [data-test-org-name]').hasText('org'); + assert.dom('[data-test-heading] [data-test-team-name]').hasText('thehydroimpulseteam'); + }); - test('has link to github in team header', async function(assert) { - this.server.loadFixtures(); + test('has link to github in team header', async function(assert) { + this.server.loadFixtures(); - await visit('/teams/github:org:thehydroimpulse'); + await visit('/teams/github:org:thehydroimpulse'); - assert.dom('[data-test-heading] [data-test-github-link]').hasAttribute('href', 'https://github.com/org_test'); - }); + assert.dom('[data-test-heading] [data-test-github-link]').hasAttribute('href', 'https://github.com/org_test'); + }); - test('github link has image in team header', async function(assert) { - this.server.loadFixtures(); + test('github link has image in team header', async function(assert) { + this.server.loadFixtures(); - await visit('/teams/github:org:thehydroimpulse'); + await visit('/teams/github:org:thehydroimpulse'); - assert.dom('[data-test-heading] [data-test-github-link] img').hasAttribute('src', '/assets/GitHub-Mark.svg'); - }); + assert.dom('[data-test-heading] [data-test-github-link] img').hasAttribute('src', '/assets/GitHub-Mark.svg'); + }); - test('team organization details has github profile icon', async function(assert) { - this.server.loadFixtures(); + test('team organization details has github profile icon', async function(assert) { + this.server.loadFixtures(); - await visit('/teams/github:org:thehydroimpulse'); + await visit('/teams/github:org:thehydroimpulse'); - assert - .dom('[data-test-heading] [data-test-avatar]') - .hasAttribute('src', 'https://avatars.githubusercontent.com/u/565790?v=3&s=170'); - }); + assert + .dom('[data-test-heading] [data-test-avatar]') + .hasAttribute('src', 'https://avatars.githubusercontent.com/u/565790?v=3&s=170'); + }); }); diff --git a/tests/acceptance/user-page-test.js b/tests/acceptance/user-page-test.js index 8241f989cd..2a05c412ae 100644 --- a/tests/acceptance/user-page-test.js +++ b/tests/acceptance/user-page-test.js @@ -7,53 +7,51 @@ import setupMirage from '../helpers/setup-mirage'; import { percySnapshot } from 'ember-percy'; module('Acceptance | user page', function(hooks) { - setupApplicationTest(hooks); - setupMirage(hooks); + setupApplicationTest(hooks); + setupMirage(hooks); - test('is accessible', async function(assert) { - assert.expect(0); + test('is accessible', async function(assert) { + assert.expect(0); - this.server.loadFixtures(); + this.server.loadFixtures(); - await visit('/users/thehydroimpulse'); - percySnapshot(assert); + await visit('/users/thehydroimpulse'); + percySnapshot(assert); - await a11yAudit(axeConfig); - }); + await a11yAudit(axeConfig); + }); - test('has user display', async function(assert) { - this.server.loadFixtures(); + test('has user display', async function(assert) { + this.server.loadFixtures(); - await visit('/users/thehydroimpulse'); + await visit('/users/thehydroimpulse'); - assert.dom('[data-test-heading] [data-test-username]').hasText('thehydroimpulse'); - }); + assert.dom('[data-test-heading] [data-test-username]').hasText('thehydroimpulse'); + }); - test('has link to github in user header', async function(assert) { - this.server.loadFixtures(); + test('has link to github in user header', async function(assert) { + this.server.loadFixtures(); - await visit('/users/thehydroimpulse'); + await visit('/users/thehydroimpulse'); - assert - .dom('[data-test-heading] [data-test-user-link]') - .hasAttribute('href', 'https://github.com/thehydroimpulse'); - }); + assert.dom('[data-test-heading] [data-test-user-link]').hasAttribute('href', 'https://github.com/thehydroimpulse'); + }); - test('github link has image in user header', async function(assert) { - this.server.loadFixtures(); + test('github link has image in user header', async function(assert) { + this.server.loadFixtures(); - await visit('/users/thehydroimpulse'); + await visit('/users/thehydroimpulse'); - assert.dom('[data-test-heading] [data-test-user-link] img').hasAttribute('src', '/assets/GitHub-Mark.svg'); - }); + assert.dom('[data-test-heading] [data-test-user-link] img').hasAttribute('src', '/assets/GitHub-Mark.svg'); + }); - test('user details has github profile icon', async function(assert) { - this.server.loadFixtures(); + test('user details has github profile icon', async function(assert) { + this.server.loadFixtures(); - await visit('/users/thehydroimpulse'); + await visit('/users/thehydroimpulse'); - assert - .dom('[data-test-heading] [data-test-avatar]') - .hasAttribute('src', 'https://avatars.githubusercontent.com/u/565790?v=3&s=170'); - }); + assert + .dom('[data-test-heading] [data-test-avatar]') + .hasAttribute('src', 'https://avatars.githubusercontent.com/u/565790?v=3&s=170'); + }); }); diff --git a/tests/axe-config.js b/tests/axe-config.js index 19f27f1558..80e95df7ee 100644 --- a/tests/axe-config.js +++ b/tests/axe-config.js @@ -1,7 +1,7 @@ export default { - rules: { - 'color-contrast': { - enabled: false, - }, + rules: { + 'color-contrast': { + enabled: false, }, + }, }; diff --git a/tests/helpers/setup-mirage.js b/tests/helpers/setup-mirage.js index 4ec913e66f..ed2cae8c65 100644 --- a/tests/helpers/setup-mirage.js +++ b/tests/helpers/setup-mirage.js @@ -3,15 +3,15 @@ import { faker } from 'ember-cli-mirage'; import timekeeper from 'timekeeper'; export default function(hooks) { - setupMirage(hooks); + setupMirage(hooks); - // To have deterministic visual tests, the seed has to be constant - hooks.beforeEach(function() { - faker.seed(12345); - timekeeper.freeze(new Date('11/20/2017 12:00')); - }); + // To have deterministic visual tests, the seed has to be constant + hooks.beforeEach(function() { + faker.seed(12345); + timekeeper.freeze(new Date('11/20/2017 12:00')); + }); - hooks.afterEach(function() { - timekeeper.reset(); - }); + hooks.afterEach(function() { + timekeeper.reset(); + }); } diff --git a/tests/unit/controllers/crate/version-test.js b/tests/unit/controllers/crate/version-test.js index df75dcffa1..dae6d1b7f5 100644 --- a/tests/unit/controllers/crate/version-test.js +++ b/tests/unit/controllers/crate/version-test.js @@ -4,32 +4,32 @@ import { A } from '@ember/array'; import Service from '@ember/service'; module('Unit | Controller | crate/version', function(hooks) { - setupTest(hooks); - const userId = 1; - // stub the session service - // https://guides.emberjs.com/release/testing/testing-components/#toc_stubbing-services - const sessionStub = Service.extend(); + setupTest(hooks); + const userId = 1; + // stub the session service + // https://guides.emberjs.com/release/testing/testing-components/#toc_stubbing-services + const sessionStub = Service.extend(); - hooks.beforeEach(function() { - sessionStub.currentUser = { id: userId }; - this.owner.register('service:session', sessionStub); - }); + hooks.beforeEach(function() { + sessionStub.currentUser = { id: userId }; + this.owner.register('service:session', sessionStub); + }); - test('notYankedOrIsOwner is true when conditions fulfilled', function(assert) { - assert.expect(2); - let controller = this.owner.lookup('controller:crate/version'); - controller.model = { yanked: false }; - controller.crate = { owner_user: A([{ id: userId }]) }; - assert.ok(controller); - assert.ok(controller.notYankedOrIsOwner); - }); + test('notYankedOrIsOwner is true when conditions fulfilled', function(assert) { + assert.expect(2); + let controller = this.owner.lookup('controller:crate/version'); + controller.model = { yanked: false }; + controller.crate = { owner_user: A([{ id: userId }]) }; + assert.ok(controller); + assert.ok(controller.notYankedOrIsOwner); + }); - test('notYankedOrIsOwner is false when conditions fulfilled', function(assert) { - assert.expect(2); - let controller = this.owner.lookup('controller:crate/version'); - controller.model = { yanked: true }; - controller.crate = { owner_user: A([{ id: userId }]) }; - assert.ok(controller); - assert.notOk(controller.notYankedOrIsOwner); - }); + test('notYankedOrIsOwner is false when conditions fulfilled', function(assert) { + assert.expect(2); + let controller = this.owner.lookup('controller:crate/version'); + controller.model = { yanked: true }; + controller.crate = { owner_user: A([{ id: userId }]) }; + assert.ok(controller); + assert.notOk(controller.notYankedOrIsOwner); + }); }); diff --git a/tests/unit/helpers/format-crate-size-test.js b/tests/unit/helpers/format-crate-size-test.js index df310d4548..b244ed488a 100644 --- a/tests/unit/helpers/format-crate-size-test.js +++ b/tests/unit/helpers/format-crate-size-test.js @@ -2,19 +2,19 @@ import { formatCrateSize } from '../../../helpers/format-crate-size'; import { module, test } from 'qunit'; module('Unit | Helper | format-crate-size', function() { - test('Small crate size formats in kB', function(assert) { - assert.equal(formatCrateSize(531), '0.53 kB'); - }); + test('Small crate size formats in kB', function(assert) { + assert.equal(formatCrateSize(531), '0.53 kB'); + }); - test('Small crate size formats in kB without trailing 0', function(assert) { - assert.equal(formatCrateSize(90000), '90 kB'); - }); + test('Small crate size formats in kB without trailing 0', function(assert) { + assert.equal(formatCrateSize(90000), '90 kB'); + }); - test('Large crate size formats in MB', function(assert) { - assert.equal(formatCrateSize(912345), '0.91 MB'); - }); + test('Large crate size formats in MB', function(assert) { + assert.equal(formatCrateSize(912345), '0.91 MB'); + }); - test('Large crate size formats in MB without trailing 0', function(assert) { - assert.equal(formatCrateSize(9100000), '9.1 MB'); - }); + test('Large crate size formats in MB without trailing 0', function(assert) { + assert.equal(formatCrateSize(9100000), '9.1 MB'); + }); }); diff --git a/tests/unit/helpers/format-email-test.js b/tests/unit/helpers/format-email-test.js index 26f26afcea..20ab0b0eac 100644 --- a/tests/unit/helpers/format-email-test.js +++ b/tests/unit/helpers/format-email-test.js @@ -2,15 +2,15 @@ import { formatEmail } from '../../../helpers/format-email'; import { module, test } from 'qunit'; module('Unit | Helper | format-email', function() { - // Replace this with your real tests. - test('it works', function(assert) { - assert.equal(formatEmail('foo'), 'foo'); - assert.equal(formatEmail('foo ').toString(), `foo`); - assert.equal( - formatEmail(' ').toString(), - ``, - ); - assert.equal(formatEmail('').toString(), ''); - assert.equal(formatEmail('test ').toString(), `foo`); + assert.equal( + formatEmail(' ').toString(), + ``, + ); + assert.equal(formatEmail('').toString(), ''); + assert.equal(formatEmail('test Date: Fri, 30 Aug 2019 06:10:12 -0400 Subject: [PATCH 3/8] Add template lint NPM script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index ab06740047..880825f3c8 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "scripts": { "build": "ember build", + "lint:hbs": "ember-template-lint .", "lint:js": "eslint . --cache", "lint:deps": "ember dependency-lint", "prettier": "prettier --write '{app,tests,mirage}/**/*.js'", From c62fcb175852d4aa24ae648794fd706f38d90055 Mon Sep 17 00:00:00 2001 From: Josh Justice Date: Fri, 30 Aug 2019 06:26:22 -0400 Subject: [PATCH 4/8] Disable html-comments lint rule --- .template-lintrc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.template-lintrc.js b/.template-lintrc.js index de1deb105f..e09f15585b 100644 --- a/.template-lintrc.js +++ b/.template-lintrc.js @@ -9,5 +9,6 @@ module.exports = { 'block-indentation': false, 'img-alt-attributes': false, 'triple-curlies': false, + 'html-comments': false, }, }; From 8dffeefc4b6f130db722623bf29a6b5c5985d494 Mon Sep 17 00:00:00 2001 From: Josh Justice Date: Fri, 30 Aug 2019 06:28:12 -0400 Subject: [PATCH 5/8] Do not lint node_modules --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 880825f3c8..d9fce80145 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ }, "scripts": { "build": "ember build", - "lint:hbs": "ember-template-lint .", + "lint:hbs": "ember-template-lint app/templates", "lint:js": "eslint . --cache", "lint:deps": "ember dependency-lint", "prettier": "prettier --write '{app,tests,mirage}/**/*.js'", From 810f5765f54dd007908933a000c0389753b90289 Mon Sep 17 00:00:00 2001 From: Josh Justice Date: Fri, 30 Aug 2019 06:30:41 -0400 Subject: [PATCH 6/8] Enable indentation rule for templates --- .template-lintrc.js | 1 - 1 file changed, 1 deletion(-) diff --git a/.template-lintrc.js b/.template-lintrc.js index e09f15585b..1691cf83d5 100644 --- a/.template-lintrc.js +++ b/.template-lintrc.js @@ -6,7 +6,6 @@ module.exports = { extends: 'recommended', rules: { - 'block-indentation': false, 'img-alt-attributes': false, 'triple-curlies': false, 'html-comments': false, From ba9283cba3ef578c717eb9dec166b4518a0791b8 Mon Sep 17 00:00:00 2001 From: Josh Justice Date: Fri, 30 Aug 2019 06:50:02 -0400 Subject: [PATCH 7/8] Update templates for two-space indentation --- app/templates/application.hbs | 218 ++++---- app/templates/catch-all.hbs | 12 +- app/templates/categories.hbs | 112 ++-- app/templates/category-slugs.hbs | 24 +- app/templates/category/index.hbs | 154 +++--- app/templates/components/api-token-row.hbs | 122 ++-- app/templates/components/badge-appveyor.hbs | 12 +- .../components/badge-azure-devops.hbs | 2 +- app/templates/components/badge-circle-ci.hbs | 8 +- app/templates/components/badge-cirrus-ci.hbs | 8 +- app/templates/components/badge-codecov.hbs | 10 +- app/templates/components/badge-coveralls.hbs | 10 +- app/templates/components/badge-gitlab.hbs | 8 +- ...adge-is-it-maintained-issue-resolution.hbs | 8 +- .../badge-is-it-maintained-open-issues.hbs | 8 +- .../components/badge-maintenance.hbs | 8 +- app/templates/components/badge-travis-ci.hbs | 8 +- app/templates/components/category-list.hbs | 20 +- .../components/crate-downloads-list.hbs | 22 +- app/templates/components/crate-list.hbs | 20 +- app/templates/components/crate-row.hbs | 62 +-- app/templates/components/email-input.hbs | 111 ++-- app/templates/components/keyword-list.hbs | 20 +- app/templates/components/link-to-dep.hbs | 4 +- .../components/pending-owner-invite-row.hbs | 73 +-- app/templates/components/validated-input.hbs | 22 +- app/templates/crate/docs.hbs | 6 +- app/templates/crate/owners.hbs | 96 ++-- app/templates/crate/reverse-dependencies.hbs | 60 +- app/templates/crate/version.hbs | 522 +++++++++--------- app/templates/crate/versions.hbs | 40 +- app/templates/crates.hbs | 148 ++--- app/templates/dashboard.hbs | 134 ++--- app/templates/error.hbs | 2 +- app/templates/index.hbs | 102 ++-- app/templates/install.hbs | 6 +- app/templates/keyword/index.hbs | 108 ++-- app/templates/keywords.hbs | 100 ++-- app/templates/me/crates.hbs | 106 ++-- app/templates/me/following.hbs | 86 +-- app/templates/me/index.hbs | 74 +-- app/templates/me/pending-invites.hbs | 18 +- app/templates/policies.hbs | 144 ++--- app/templates/search.hbs | 162 +++--- app/templates/team.hbs | 148 ++--- app/templates/user.hbs | 132 ++--- 46 files changed, 1645 insertions(+), 1635 deletions(-) diff --git a/app/templates/application.hbs b/app/templates/application.hbs index 883a6ea4d3..3cffa08ef8 100644 --- a/app/templates/application.hbs +++ b/app/templates/application.hbs @@ -4,133 +4,133 @@ {{google-jsapi}}
- {{flash-message}} + {{flash-message}} - {{outlet}} + {{outlet}}
diff --git a/app/templates/catch-all.hbs b/app/templates/catch-all.hbs index e86dc64dd1..c4a01a5a5e 100644 --- a/app/templates/catch-all.hbs +++ b/app/templates/catch-all.hbs @@ -1,11 +1,11 @@

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 f59c02996b..b3ae63b6e5 100644 --- a/app/templates/categories.hbs +++ b/app/templates/categories.hbs @@ -1,72 +1,72 @@ {{ title 'Categories' }}
- {{svg-jar "crate"}} -

All Categories

+ {{svg-jar "crate"}} +

All Categories

- + -
- Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} +
+ Sort by + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="crates")}} - # Crates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="crates")}} + # Crates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    - {{#each model as |category|}} -
    -
    -
    - {{link-to category.category "category" category.slug}} - - {{ pluralize (format-num category.crates_cnt) "crate" }} - -
    -
    - - {{ category.description }} - -
    -
    + {{#each model as |category|}} +
    +
    +
    + {{link-to category.category "category" category.slug}} + + {{ pluralize (format-num category.crates_cnt) "crate" }} +
    - {{/each}} +
    + + {{ category.description }} + +
    +
    +
    + {{/each}}
    diff --git a/app/templates/category-slugs.hbs b/app/templates/category-slugs.hbs index 8644b50d13..5adf0881ba 100644 --- a/app/templates/category-slugs.hbs +++ b/app/templates/category-slugs.hbs @@ -1,17 +1,17 @@ {{ title 'Category Slugs' }}
    -
    - {{svg-jar "crate"}} -

    All Valid Category Slugs

    -
    +
    + {{svg-jar "crate"}} +

    All Valid Category Slugs

    +
    -
    -
    - {{#each model as |category|}} -
    {{category.slug}}
    -
    {{category.description}}
    - {{/each}} -
    -
    +
    +
    + {{#each model as |category|}} +
    {{category.slug}}
    +
    {{category.description}}
    + {{/each}} +
    +
    diff --git a/app/templates/category/index.hbs b/app/templates/category/index.hbs index a54d5ea9cd..537ce8c60d 100644 --- a/app/templates/category/index.hbs +++ b/app/templates/category/index.hbs @@ -1,101 +1,101 @@ {{ title category.category ' - Categories' }}
    - {{#link-to "categories" (html-attributes aria-label="Categories")}}{{svg-jar "crate"}}{{/link-to}} -

    - {{#each category.parent_categories as |parent|}}{{link-to parent.category "category" parent.slug}}::{{/each}} - {{~ category.category }} -

    + {{#link-to "categories" (html-attributes aria-label="Categories")}}{{svg-jar "crate"}}{{/link-to}} +

    + {{#each category.parent_categories as |parent|}}{{link-to parent.category "category" parent.slug}}::{{/each}} + {{~ category.category }} +

    -

    {{ category.description }}

    +

    {{ category.description }}

    {{#if category.subcategories }}
    -

    Subcategories

    -
    - {{#each category.subcategories as |subcategory| }} -
    -
    -
    - {{link-to subcategory.category "category" subcategory.slug}} - - {{ pluralize (format-num subcategory.crates_cnt) "crate" }} - -
    -
    - - {{ subcategory.description }} - -
    -
    -
    - {{/each}} -
    +

    Subcategories

    +
    + {{#each category.subcategories as |subcategory| }} +
    +
    +
    + {{link-to subcategory.category "category" subcategory.slug}} + + {{ pluralize (format-num subcategory.crates_cnt) "crate" }} + +
    +
    + + {{ subcategory.description }} + +
    +
    +
    + {{/each}} +
    {{/if}}

    Crates

    - + -
    - Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} +
    + Sort by + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="downloads")}} - All-Time Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-downloads")}} - Recent Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-updates")}} - Recent Updates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="downloads")}} + All-Time Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-downloads")}} + Recent Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-updates")}} + Recent Updates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    - {{#each model as |crate|}} - {{crate-row crate=crate}} - {{/each}} + {{#each model as |crate|}} + {{crate-row crate=crate}} + {{/each}}
    diff --git a/app/templates/components/api-token-row.hbs b/app/templates/components/api-token-row.hbs index 83d5f33146..8eeaf0a4df 100644 --- a/app/templates/components/api-token-row.hbs +++ b/app/templates/components/api-token-row.hbs @@ -1,74 +1,78 @@
    -
    - {{#if api_token.isNew}} - {{input - type="text" - placeholder="New token name" - disabled=api_token.isSaving - value=api_token.name - autofocus=true - enter="saveToken"}} - {{else}} - {{ api_token.name }} - {{/if}} -
    +
    + {{#if api_token.isNew}} + {{input + type="text" + placeholder="New token name" + disabled=api_token.isSaving + value=api_token.name + autofocus=true + enter="saveToken"}} + {{else}} + {{ api_token.name }} + {{/if}} +
    -
    +
    - {{#unless api_token.isNew}} -
    -
    - - Created {{moment-from-now api_token.created_at}} - -
    - {{#if api_token.last_used_at}} -
    - - Last used {{moment-from-now api_token.last_used_at}} - -
    - {{else}} -
    - Never used -
    - {{/if}} + {{#unless api_token.isNew}} +
    +
    + + Created {{moment-from-now api_token.created_at}} + +
    + {{#if api_token.last_used_at}} +
    + + Last used {{moment-from-now api_token.last_used_at}} +
    - {{/unless}} - -
    - {{#if api_token.isNew}} - - {{else}} - - {{/if}} - {{#if api_token.isSaving}} - - {{/if}} + {{else}} +
    + Never used +
    + {{/if}}
    + {{/unless}} + +
    + {{#if api_token.isNew}} + + {{else}} + + {{/if}} + {{#if api_token.isSaving}} + + {{/if}} +
    {{#if serverError}} -
    -
    - {{ serverError }} -
    +
    +
    + {{ serverError }}
    +
    {{/if}} {{#if api_token.token}} -
    -
    - Please record this token somewhere, you cannot retrieve - its value again. For use on the command line you can save it to ~/.cargo/credentials - with: +
    +
    + Please record this token somewhere, you cannot retrieve + its value again. For use on the command line you can save it to ~/.cargo/credentials + with: -
    cargo login {{ api_token.token }}
    -
    +
    cargo login {{ api_token.token }}
    +
    {{/if}} diff --git a/app/templates/components/badge-appveyor.hbs b/app/templates/components/badge-appveyor.hbs index 7f4fc26fa9..7c6cc34c8a 100644 --- a/app/templates/components/badge-appveyor.hbs +++ b/app/templates/components/badge-appveyor.hbs @@ -1,8 +1,8 @@
    - {{ text }} + {{ text }} diff --git a/app/templates/components/badge-azure-devops.hbs b/app/templates/components/badge-azure-devops.hbs index 8b39bac3cc..b58e9721f4 100644 --- a/app/templates/components/badge-azure-devops.hbs +++ b/app/templates/components/badge-azure-devops.hbs @@ -1,3 +1,3 @@ - {{ text }} + {{ text }} diff --git a/app/templates/components/badge-circle-ci.hbs b/app/templates/components/badge-circle-ci.hbs index 8dbc73a8e0..c26dc67f84 100644 --- a/app/templates/components/badge-circle-ci.hbs +++ b/app/templates/components/badge-circle-ci.hbs @@ -1,6 +1,6 @@ - {{ text }} + {{ text }} diff --git a/app/templates/components/badge-cirrus-ci.hbs b/app/templates/components/badge-cirrus-ci.hbs index 67a2324252..33afc52d76 100644 --- a/app/templates/components/badge-cirrus-ci.hbs +++ b/app/templates/components/badge-cirrus-ci.hbs @@ -1,6 +1,6 @@ - {{ text }} + {{ text }} diff --git a/app/templates/components/badge-codecov.hbs b/app/templates/components/badge-codecov.hbs index 87143b2934..b411913e4a 100644 --- a/app/templates/components/badge-codecov.hbs +++ b/app/templates/components/badge-codecov.hbs @@ -1,6 +1,6 @@ - {{ text }} - \ No newline at end of file + {{ text }} + diff --git a/app/templates/components/badge-coveralls.hbs b/app/templates/components/badge-coveralls.hbs index 220d105181..3beeeaeae8 100644 --- a/app/templates/components/badge-coveralls.hbs +++ b/app/templates/components/badge-coveralls.hbs @@ -1,6 +1,6 @@ - {{ text }} - \ No newline at end of file + {{ text }} + diff --git a/app/templates/components/badge-gitlab.hbs b/app/templates/components/badge-gitlab.hbs index 97abe5a7c3..2044609088 100644 --- a/app/templates/components/badge-gitlab.hbs +++ b/app/templates/components/badge-gitlab.hbs @@ -1,6 +1,6 @@ - {{ text }} + {{ text }} diff --git a/app/templates/components/badge-is-it-maintained-issue-resolution.hbs b/app/templates/components/badge-is-it-maintained-issue-resolution.hbs index c74a632f52..604b2d128d 100644 --- a/app/templates/components/badge-is-it-maintained-issue-resolution.hbs +++ b/app/templates/components/badge-is-it-maintained-issue-resolution.hbs @@ -1,6 +1,6 @@ - {{ text }} + {{ text }} diff --git a/app/templates/components/badge-is-it-maintained-open-issues.hbs b/app/templates/components/badge-is-it-maintained-open-issues.hbs index fb9c47c990..7034e257d9 100644 --- a/app/templates/components/badge-is-it-maintained-open-issues.hbs +++ b/app/templates/components/badge-is-it-maintained-open-issues.hbs @@ -1,6 +1,6 @@ - {{ text }} + {{ text }} diff --git a/app/templates/components/badge-maintenance.hbs b/app/templates/components/badge-maintenance.hbs index 5210f1189d..c1fe446056 100644 --- a/app/templates/components/badge-maintenance.hbs +++ b/app/templates/components/badge-maintenance.hbs @@ -1,6 +1,6 @@ {{#unless none}} - {{text}} + {{text}} {{/unless}} diff --git a/app/templates/components/badge-travis-ci.hbs b/app/templates/components/badge-travis-ci.hbs index c5dbc330b3..c61c2e6d64 100644 --- a/app/templates/components/badge-travis-ci.hbs +++ b/app/templates/components/badge-travis-ci.hbs @@ -1,6 +1,6 @@ - {{ text }} + {{ text }} diff --git a/app/templates/components/category-list.hbs b/app/templates/components/category-list.hbs index 172406d6ce..d1c092b2c6 100644 --- a/app/templates/components/category-list.hbs +++ b/app/templates/components/category-list.hbs @@ -1,12 +1,12 @@
      - {{#each categories as |category|}} -
    • - {{#link-to 'category' category.slug class='name'}} - {{ category.category }} ({{ format-num category.crates_cnt }}) -
      - {{svg-jar "right-arrow"}} -
      - {{/link-to}} -
    • - {{/each}} + {{#each categories as |category|}} +
    • + {{#link-to 'category' category.slug class='name'}} + {{ category.category }} ({{ format-num category.crates_cnt }}) +
      + {{svg-jar "right-arrow"}} +
      + {{/link-to}} +
    • + {{/each}}
    diff --git a/app/templates/components/crate-downloads-list.hbs b/app/templates/components/crate-downloads-list.hbs index 9fa90c936f..69f7341e95 100644 --- a/app/templates/components/crate-downloads-list.hbs +++ b/app/templates/components/crate-downloads-list.hbs @@ -1,13 +1,13 @@
      - {{#each crates as |crate|}} -
    • - {{#link-to 'crate' crate.id class='name'}} - {{ crate.name }} ({{ crate.max_version }}) -
      - {{svg-jar "download-clear-back"}} - {{ format-num crate.downloads }} -
      - {{/link-to}} -
    • - {{/each}} + {{#each crates as |crate|}} +
    • + {{#link-to 'crate' crate.id class='name'}} + {{ crate.name }} ({{ crate.max_version }}) +
      + {{svg-jar "download-clear-back"}} + {{ format-num crate.downloads }} +
      + {{/link-to}} +
    • + {{/each}}
    diff --git a/app/templates/components/crate-list.hbs b/app/templates/components/crate-list.hbs index f13d4061ff..50a474d721 100644 --- a/app/templates/components/crate-list.hbs +++ b/app/templates/components/crate-list.hbs @@ -1,12 +1,12 @@
      - {{#each crates as |crate index|}} -
    1. - {{#link-to 'crate' crate.id class='name' data-test-crate-link=index}} - {{ crate.name }} ({{ crate.max_version }}) -
      - {{svg-jar "right-arrow"}} -
      - {{/link-to}} -
    2. - {{/each}} + {{#each crates as |crate index|}} +
    3. + {{#link-to 'crate' crate.id class='name' data-test-crate-link=index}} + {{ crate.name }} ({{ crate.max_version }}) +
      + {{svg-jar "right-arrow"}} +
      + {{/link-to}} +
    4. + {{/each}}
    diff --git a/app/templates/components/crate-row.hbs b/app/templates/components/crate-row.hbs index 2111cbc0c8..f61dddfef4 100644 --- a/app/templates/components/crate-row.hbs +++ b/app/templates/components/crate-row.hbs @@ -1,37 +1,37 @@
    -
    - {{#link-to 'crate' crate.id data-test-crate-link}}{{ crate.name }}{{/link-to}} - {{crate-badge crate=crate}} - {{#each crate.annotated_badges as |badge|}} - {{component badge.component_name badge=badge data-test-badge=badge.badge_type}} - {{/each}} -
    -
    - - {{ truncate-text crate.description }} - -
    +
    + {{#link-to 'crate' crate.id data-test-crate-link}}{{ crate.name }}{{/link-to}} + {{crate-badge crate=crate}} + {{#each crate.annotated_badges as |badge|}} + {{component badge.component_name badge=badge data-test-badge=badge.badge_type}} + {{/each}} +
    +
    + + {{ truncate-text crate.description }} + +
    -
    - {{svg-jar "download"}} - All-Time: {{ format-num crate.downloads }} -
    -
    - {{svg-jar "download"}} - Recent: {{ format-num crate.recent_downloads }} -
    +
    + {{svg-jar "download"}} + All-Time: {{ format-num crate.downloads }} +
    +
    + {{svg-jar "download"}} + Recent: {{ format-num crate.recent_downloads }} +
    diff --git a/app/templates/components/email-input.hbs b/app/templates/components/email-input.hbs index 25b8952cdb..8944bd5239 100644 --- a/app/templates/components/email-input.hbs +++ b/app/templates/components/email-input.hbs @@ -1,64 +1,65 @@ {{#if emailIsNull }} -
    -

    Please add your email address. We will only use - it to contact you about your account. We promise we'll never share it! -

    -
    +
    +

    + Please add your email address. We will only use + it to contact you about your account. We promise we'll never share it! +

    +
    {{/if}} {{#if isEditing }} -
    -
    -
    Email
    -
    - +
    +
    +
    Email
    + +
    {{else}} +
    +
    +
    Email
    +
    + +
    + +
    +
    + {{#if emailNotVerified }}
    -
    -
    Email
    -
    - -
    - -
    +
    + {{#if user.email_verification_sent}} +

    We have sent a verification email to your address.

    + {{/if}} +

    Your email has not yet been verified.

    +
    +
    + +
    - {{#if emailNotVerified }} -
    -
    - {{#if user.email_verification_sent}} -

    We have sent a verification email to your address.

    - {{/if}} -

    Your email has not yet been verified.

    -
    -
    - -
    -
    - {{/if}} - {{#if isError}} -
    -
    -

    {{emailError}}

    -
    -
    - {{/if}} + {{/if}} + {{#if isError}} +
    +
    +

    {{emailError}}

    +
    +
    + {{/if}} {{/if}} diff --git a/app/templates/components/keyword-list.hbs b/app/templates/components/keyword-list.hbs index 171350fb16..aa9d91a5b5 100644 --- a/app/templates/components/keyword-list.hbs +++ b/app/templates/components/keyword-list.hbs @@ -1,12 +1,12 @@
      - {{#each keywords as |keyword|}} -
    • - {{#link-to 'keyword' keyword class='name'}} - {{ keyword.id }} ({{ format-num keyword.crates_cnt }}) -
      - {{svg-jar "right-arrow"}} -
      - {{/link-to}} -
    • - {{/each}} + {{#each keywords as |keyword|}} +
    • + {{#link-to 'keyword' keyword class='name'}} + {{ keyword.id }} ({{ format-num keyword.crates_cnt }}) +
      + {{svg-jar "right-arrow"}} +
      + {{/link-to}} +
    • + {{/each}}
    diff --git a/app/templates/components/link-to-dep.hbs b/app/templates/components/link-to-dep.hbs index e5768f42c2..641b6f4a44 100644 --- a/app/templates/components/link-to-dep.hbs +++ b/app/templates/components/link-to-dep.hbs @@ -1,6 +1,6 @@ {{#link-to 'crate' dep.crate_id}} - {{ dep.crate_id }} {{ format-req dep.req }} + {{ dep.crate_id }} {{ format-req dep.req }} {{/link-to}} {{#if dep.optional}} - optional + optional {{/if}} diff --git a/app/templates/components/pending-owner-invite-row.hbs b/app/templates/components/pending-owner-invite-row.hbs index ba4f86fc88..10ec86830e 100644 --- a/app/templates/components/pending-owner-invite-row.hbs +++ b/app/templates/components/pending-owner-invite-row.hbs @@ -1,40 +1,43 @@
    - {{#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}} + {{#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}}
    -
    -

    - {{#link-to 'crate' invite.crate_name}} - {{invite.crate_name}} - {{/link-to}} -

    -
    -
    -

    Invited by: - {{#link-to 'user' invite.invited_by_username}} - {{invite.invited_by_username}} - {{/link-to}} -

    -
    -
    - {{moment-from-now invite.created_at}} -
    -
    - - +
    +

    + {{#link-to 'crate' invite.crate_name}} + {{invite.crate_name}} + {{/link-to}} +

    +
    +
    +

    + Invited by: + {{#link-to 'user' invite.invited_by_username}} + {{invite.invited_by_username}} + {{/link-to}} +

    +
    +
    + {{moment-from-now invite.created_at}} +
    +
    + + +
    + {{#if isError}} +
    +

    {{inviteError}}

    - {{#if isError}} -
    -

    {{inviteError}}

    -
    - {{/if}} + {{/if}}
    - {{/if}} + {{/if}}
    diff --git a/app/templates/components/validated-input.hbs b/app/templates/components/validated-input.hbs index 08d90f7cdc..592e8f4887 100644 --- a/app/templates/components/validated-input.hbs +++ b/app/templates/components/validated-input.hbs @@ -1,14 +1,14 @@
    - {{input type=type value=value placeholder=placeholder class='form-control' name=valuePath}} - {{#if isValid}} - - {{/if}} + {{input type=type value=value placeholder=placeholder class='form-control' name=valuePath}} + {{#if isValid}} + + {{/if}} -
    - {{#if showErrorMessage}} -
    - {{v-get model valuePath 'message'}} -
    - {{/if}} -
    +
    + {{#if showErrorMessage}} +
    + {{v-get model valuePath 'message'}} +
    + {{/if}} +
    diff --git a/app/templates/crate/docs.hbs b/app/templates/crate/docs.hbs index da179b2fe6..82d4d5c661 100644 --- a/app/templates/crate/docs.hbs +++ b/app/templates/crate/docs.hbs @@ -1,8 +1,8 @@
    - {{svg-jar "circle-with-i"}} -

    Documentation for {{model.name}}

    + {{svg-jar "circle-with-i"}} +

    Documentation for {{model.name}}

    - Redirecting you to {{model.documentation}}… + Redirecting you to {{model.documentation}}

    diff --git a/app/templates/crate/owners.hbs b/app/templates/crate/owners.hbs index 0dd1218b44..bd30b32f25 100644 --- a/app/templates/crate/owners.hbs +++ b/app/templates/crate/owners.hbs @@ -1,67 +1,67 @@ {{ title 'Manage Crate Owners' }}
    - {{svg-jar "gear"}} -

    Manage Crate Owners

    -

    {{ crate.name }}

    + {{svg-jar "gear"}} +

    Manage Crate Owners

    +

    {{ crate.name }}

    -

    Add Owner

    +

    Add Owner

    -
    - +
    + +
    + +

    Owners

    {{#if removed}} -
    +

    {{removed}}

    -
    +
    {{/if}}
    - {{#each crate.owner_user as |user|}} -
    -
    - {{#link-to user.kind user.login}} - {{user-avatar user=user size='medium-small'}} - {{/link-to}} -
    -
    - {{#link-to user.kind user.login}} - {{ user.name }} - {{/link-to}} -
    -
    - {{{ if user.email user.email " " }}} -
    -
    - -
    -
    - {{/each}} -
    \ No newline at end of file + {{#each crate.owner_user as |user|}} +
    +
    + {{#link-to user.kind user.login}} + {{user-avatar user=user size='medium-small'}} + {{/link-to}} +
    +
    + {{#link-to user.kind user.login}} + {{ user.name }} + {{/link-to}} +
    +
    + {{{ if user.email user.email " " }}} +
    +
    + +
    +
    + {{/each}} +
    diff --git a/app/templates/crate/reverse-dependencies.hbs b/app/templates/crate/reverse-dependencies.hbs index 210216be19..157cbdfbf5 100644 --- a/app/templates/crate/reverse-dependencies.hbs +++ b/app/templates/crate/reverse-dependencies.hbs @@ -1,42 +1,42 @@
    - {{#link-to 'crate' crate.id}}⬅ Back to {{ crate.name }}{{/link-to}} + {{#link-to 'crate' crate.id}}⬅ Back to {{ crate.name }}{{/link-to}}
    - +
    - {{#each model as |dependency|}} -
    -
    - {{#link-to 'crate' dependency.version.crateName}}{{dependency.version.crateName}}{{/link-to}} requires {{dependency.req}} -
    -
    - {{svg-jar "download-clear-back"}} - {{ format-num dependency.downloads }} -
    -
    - {{/each}} + {{#each model as |dependency|}} +
    +
    + {{#link-to 'crate' dependency.version.crateName}}{{dependency.version.crateName}}{{/link-to}} requires {{dependency.req}} +
    +
    + {{svg-jar "download-clear-back"}} + {{ format-num dependency.downloads }} +
    +
    + {{/each}}
    diff --git a/app/templates/crate/version.hbs b/app/templates/crate/version.hbs index 468747ddc0..b9d00aa94b 100644 --- a/app/templates/crate/version.hbs +++ b/app/templates/crate/version.hbs @@ -1,296 +1,296 @@ {{title crate.name}}
    -
    -
    - {{svg-jar "crate" class='crate-icon'}} -

    {{ crate.name }}

    -

    {{ currentVersion.num }}

    -
    +
    +
    + {{svg-jar "crate" class='crate-icon'}} +

    {{ crate.name }}

    +

    {{ currentVersion.num }}

    +
    -
    - {{#if session.currentUser}} - +
    + {{#if session.currentUser}} +
    + {{/if}} + + {{/if}}
    +
    -
    -
    - {{#if currentVersion.yanked}} -

    - 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}} -
    -
    Cargo.toml
    - {{ 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}} -
    -
    - - {{#if showNotification}} - {{#if showSuccess}} - Copied! - {{else}} - An error occured. Please use CTRL+C. - {{/if}} - {{/if}} - -
    - {{#if crate.readme}} -
    - {{crate-readme rendered=crate.readme}} -
    +
    + {{#if currentVersion.yanked}} +

    + 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}} +
    +
    Cargo.toml
    + {{ 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}} +
    +
    + + {{#if showNotification}} + {{#if showSuccess}} + Copied! {{else}} - {{#if crate.description}} -
    -

    About This Package

    -

    {{ crate.description }}

    -
    - {{/if}} + An error occured. Please use CTRL+C. {{/if}} + {{/if}} +
    +
    + {{#if crate.readme}} +
    + {{crate-readme rendered=crate.readme}} +
    + {{else}} + {{#if crate.description}} +
    +

    About This Package

    +

    {{ crate.description }}

    +
    {{/if}} -
    - {{#if notYankedOrIsOwner}} -
    -
    -
    -
    Last Updated
    -
    {{moment-from-now crate.updated_at}}
    - {{#each crate.annotated_badges as |badge|}} -

    - {{component badge.component_name badge=badge}} -

    - {{/each}} -
    + {{/if}} + {{/if}} +
    + {{#if notYankedOrIsOwner}} +
    +
    +
    +
    Last Updated
    +
    {{moment-from-now crate.updated_at}}
    + {{#each crate.annotated_badges as |badge|}} +

    + {{component badge.component_name badge=badge}} +

    + {{/each}} +
    - {{#if currentVersion.crate_size}} -
    -
    Crate Size
    -
    {{format-crate-size currentVersion.crate_size}}
    -
    - {{/if}} + {{#if currentVersion.crate_size}} +
    +
    Crate Size
    +
    {{format-crate-size currentVersion.crate_size}}
    +
    + {{/if}} -
    -

    Authors

    -
      - {{#each displayedAuthors as |author|}} -
    • {{ format-email author.name }}
    • - {{/each}} -
    -
    -
    +
    +

    Authors

    +
      + {{#each displayedAuthors as |author|}} +
    • {{ format-email author.name }}
    • + {{/each}} +
    +
    +
    -
    - {{#if currentVersion.license}} -
    -

    License

    -

    {{ currentVersion.license }}

    -
    - {{/if}} +
    + {{#if currentVersion.license}} +
    +

    License

    +

    {{ currentVersion.license }}

    +
    + {{/if}} - {{#unless crate.keywords.isPending}} - {{#if anyKeywords}} -
    -

    Keywords

    -
      - {{#each keywords as |keyword|}} -
    • {{link-to keyword.id 'keyword' keyword}}
    • - {{/each}} -
    -
    - {{/if}} - {{/unless}} + {{#unless crate.keywords.isPending}} + {{#if anyKeywords}} +
    +

    Keywords

    +
      + {{#each keywords as |keyword|}} +
    • {{link-to keyword.id 'keyword' keyword}}
    • + {{/each}} +
    +
    + {{/if}} + {{/unless}} - {{#unless crate.categories.isPending}} - {{#if anyCategories}} -
    -

    Categories

    -
      - {{#each categories as |category|}} -
    • {{link-to category.category 'category' category.slug}}
    • - {{/each}} -
    -
    - {{/if}} - {{/unless}} + {{#unless crate.categories.isPending}} + {{#if anyCategories}} +
    +

    Categories

    +
      + {{#each categories as |category|}} +
    • {{link-to category.category 'category' category.slug}}
    • + {{/each}} +
    +
    + {{/if}} + {{/unless}} -
    -

    Owners

    +
    +

    Owners

    - {{#if isOwner}} -

    - {{#link-to 'crate.owners' crate}} - Manage owners - {{/link-to}} -

    - {{/if}} + {{#if isOwner}} +

    + {{#link-to 'crate.owners' crate}} + Manage owners + {{/link-to}} +

    + {{/if}} -
      - {{#each crate.owner_team as |team|}} -
    • - {{#link-to team.kind team.login data-test-team-link=team.login}} - {{user-avatar user=team size='medium-small'}} - {{/link-to}} -
    • - {{/each}} +
        + {{#each crate.owner_team as |team|}} +
      • + {{#link-to team.kind team.login data-test-team-link=team.login}} + {{user-avatar user=team size='medium-small'}} + {{/link-to}} +
      • + {{/each}} - {{#each crate.owner_user as |user|}} -
      • - {{#link-to user.kind user.login data-test-user-link=user.login}} - {{user-avatar user=user size='medium-small'}} - {{/link-to}} -
      • - {{/each}} -
      -
    + {{#each crate.owner_user as |user|}} +
  • + {{#link-to user.kind user.login data-test-user-link=user.login}} + {{user-avatar user=user size='medium-small'}} + {{/link-to}} +
  • + {{/each}} + +
    -
    -

    Versions

    -
      - {{#each smallSortedVersions as |version|}} -
    • - {{#link-to 'crate.version' version.num data-test-version-link=version.num}} - {{ version.num }} - {{/link-to}} - {{moment-format version.created_at 'll'}} - {{#if version.yanked}} - yanked - {{/if}} -
    • - {{/each}} -
    - - {{#if hasMoreVersions}} - {{#link-to 'crate.versions' crate data-test-all-versions-link=true}} - show all {{ crate.versions.length }} versions - {{/link-to}} - {{/if}} - -
    +
    +

    Versions

    +
      + {{#each smallSortedVersions as |version|}} +
    • + {{#link-to 'crate.version' version.num data-test-version-link=version.num}} + {{ version.num }} + {{/link-to}} + {{moment-format version.created_at 'll'}} + {{#if version.yanked}} + yanked + {{/if}} +
    • + {{/each}} +
    + + {{#if hasMoreVersions}} + {{#link-to 'crate.versions' crate data-test-all-versions-link=true}} + show all {{ crate.versions.length }} versions + {{/link-to}} + {{/if}} + +
    -
    -

    Dependencies

    -
      - {{#each currentDependencies as |dep|}} - {{link-to-dep tagName="li" dep=dep}} - {{else}} -
    • None
    • - {{/each}} -
    -
    +
    +

    Dependencies

    +
      + {{#each currentDependencies as |dep|}} + {{link-to-dep tagName="li" dep=dep}} + {{else}} +
    • None
    • + {{/each}} +
    +
    - {{#if currentDevDependencies}} -
    -

    Dev-Dependencies

    -
      - {{#each currentDevDependencies as |dep|}} - {{link-to-dep tagName="li" dep=dep}} - {{/each}} -
    -
    - {{/if}} -
    - - {{/if}} + {{#if currentDevDependencies}} +
    +

    Dev-Dependencies

    +
      + {{#each currentDevDependencies as |dep|}} + {{link-to-dep tagName="li" dep=dep}} + {{/each}} +
    +
    + {{/if}} +
    + + {{/if}}
    {{#unless currentVersion.yanked}} -
    -
    -

    Stats Overview

    -
    - - {{svg-jar "download"}} - {{ format-num downloadsContext.downloads }} - - Downloads all time -
    -
    - - {{svg-jar "crate"}} - {{ crate.versions.length }} - - Versions published -
    -
    +
    +
    +

    Stats Overview

    +
    + + {{svg-jar "download"}} + {{ format-num downloadsContext.downloads }} + + Downloads all time +
    +
    + + {{svg-jar "crate"}} + {{ crate.versions.length }} + + Versions published +
    +
    -
    - Showing stats for +
    + Showing stats for - {{#rl-dropdown-container class="button-holder"}} - {{#rl-dropdown-toggle class="tan-button dropdown"}} - {{#if requestedVersion}} - {{ requestedVersion }} - {{else}} - All Versions - {{/if}} - - {{/rl-dropdown-toggle}} + {{#rl-dropdown-container class="button-holder"}} + {{#rl-dropdown-toggle class="tan-button dropdown"}} + {{#if requestedVersion}} + {{ requestedVersion }} + {{else}} + All Versions + {{/if}} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown id="all-versions" tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to 'crate.version' 'all'}}All Versions{{/link-to}} -
  • - {{#each smallSortedVersions as |version|}} -
  • - {{#link-to 'crate.version' version.num}} - {{ version.num }} - {{/link-to}} -
  • - {{/each}} - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    -
    -

    Downloads over the last 90 days

    - {{download-graph data=downloadData}} -
    + {{#rl-dropdown id="all-versions" tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to 'crate.version' 'all'}}All Versions{{/link-to}} +
  • + {{#each smallSortedVersions as |version|}} +
  • + {{#link-to 'crate.version' version.num}} + {{ version.num }} + {{/link-to}} +
  • + {{/each}} + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    +
    +

    Downloads over the last 90 days

    + {{download-graph data=downloadData}}
    +
    {{/unless}} diff --git a/app/templates/crate/versions.hbs b/app/templates/crate/versions.hbs index 1873d57b65..fa35bc571d 100644 --- a/app/templates/crate/versions.hbs +++ b/app/templates/crate/versions.hbs @@ -1,29 +1,29 @@
    - {{#link-to 'crate' model}}⬅ Back to Main Page{{/link-to}} + {{#link-to 'crate' model}}⬅ Back to Main Page{{/link-to}}
    - - All {{ model.versions.length }} - versions of {{ model.name }} since - {{moment-format model.created_at 'LL'}} - + + All {{ model.versions.length }} + versions of {{ model.name }} since + {{moment-format model.created_at 'LL'}} +
    - {{#each model.versions as |version|}} -
    -
    - {{#link-to 'crate.version' version.num}}{{ version.num }}{{/link-to}} + {{#each model.versions as |version|}} +
    +
    + {{#link-to 'crate.version' version.num}}{{ version.num }}{{/link-to}} - {{moment-format version.created_at 'LL'}} - {{#if version.yanked}} - yanked - {{/if}} -
    - {{#link-to 'crate.version' version.num class='arrow'}} - {{svg-jar "right-arrow"}} - {{/link-to}} -
    - {{/each}} + {{moment-format version.created_at 'LL'}} + {{#if version.yanked}} + yanked + {{/if}} +
    + {{#link-to 'crate.version' version.num class='arrow'}} + {{svg-jar "right-arrow"}} + {{/link-to}} +
    + {{/each}}
    diff --git a/app/templates/crates.hbs b/app/templates/crates.hbs index 1b63ff233f..bca965170e 100644 --- a/app/templates/crates.hbs +++ b/app/templates/crates.hbs @@ -1,95 +1,95 @@ {{ title 'Crates' }}
    -
    - {{svg-jar "crate"}} -

    All Crates

    -
    - {{#if letter}} -

    starting with '{{ letter }}'

    - {{/if}} +
    + {{svg-jar "crate"}} +

    All Crates

    +
    + {{#if letter}} +

    starting with '{{ letter }}'

    + {{/if}}
    + {{#each alphabet as |letter|}} + {{#link-to (query-params letter=letter page=1)}} + {{ letter }} + {{/link-to}} + {{/each}} + + {{#x-select value=letter action=(action (mut letter)) as |xs|}} + {{#each alphabet as |letter|}} - {{#link-to (query-params letter=letter page=1)}} - {{ letter }} - {{/link-to}} + {{#xs.option value=letter}}{{ letter }}{{/xs.option}} {{/each}} - - {{#x-select value=letter action=(action (mut letter)) as |xs|}} - - {{#each alphabet as |letter|}} - {{#xs.option value=letter}}{{ letter }}{{/xs.option}} - {{/each}} - {{/x-select}} + {{/x-select}}
    - + -
    - Sort by +
    + Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params page=1 sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params page=1 sort="downloads")}} - All-Time Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params page=1 sort="recent-downloads")}} - Recent Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params page=1 sort="recent-updates")}} - Recent Updates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params page=1 sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params page=1 sort="downloads")}} + All-Time Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params page=1 sort="recent-downloads")}} + Recent Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params page=1 sort="recent-updates")}} + Recent Updates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    - {{#each model as |crate index|}} - {{crate-row crate=crate data-test-crate-row=index}} - {{/each}} + {{#each model as |crate index|}} + {{crate-row crate=crate data-test-crate-row=index}} + {{/each}}
    diff --git a/app/templates/dashboard.hbs b/app/templates/dashboard.hbs index 7a414332d7..5264b55cd8 100644 --- a/app/templates/dashboard.hbs +++ b/app/templates/dashboard.hbs @@ -1,84 +1,84 @@ {{ title 'Dashboard' }}
    - {{svg-jar "dashboard"}} -

    My Dashboard

    -
    -
    - - {{format-num visibleStats.total_downloads}} - Total Downloads -
    + {{svg-jar "dashboard"}} +

    My Dashboard

    +
    +
    + + {{format-num visibleStats.total_downloads}} + Total Downloads
    +
    -
    -
    -
    -

    - {{svg-jar "my-packages"}} - My Crates -

    - - {{#if hasMoreCrates}} - - {{link-to 'Show all' 'me.crates'}} - - {{/if}} -
    - {{crate-downloads-list crates=visibleCrates}} -
    -
    -
    -

    - {{svg-jar "following"}} - Following -

    +
    +
    +
    +

    + {{svg-jar "my-packages"}} + My Crates +

    - {{#if hasMoreFollowing}} - - {{link-to 'Show all' 'me.following'}} - - {{/if}} -
    - {{crate-downloads-list crates=visibleFollowing}} -
    + {{#if hasMoreCrates}} + + {{link-to 'Show all' 'me.crates'}} + + {{/if}} +
    + {{crate-downloads-list crates=visibleCrates}}
    - -
    +
    +

    - {{svg-jar "latest-updates"}} - Latest Updates + {{svg-jar "following"}} + Following

    -
    - {{#each myFeed as |version|}} -
    -
    - {{#link-to 'crate.version' version.crateName version.num}} - {{ version.crateName }} - {{ version.num }} - {{/link-to}} - - {{moment-from-now version.created_at}} - -
    -
    - {{/each}} + {{#if hasMoreFollowing}} + + {{link-to 'Show all' 'me.following'}} + + {{/if}} +
    + {{crate-downloads-list crates=visibleFollowing}} +
    +
    - {{#if loadingMore}} - - - - {{else}} - {{#if hasMore}} - - {{/if}} - {{/if}} +
    +

    + {{svg-jar "latest-updates"}} + Latest Updates +

    + +
    + {{#each myFeed as |version|}} +
    +
    + {{#link-to 'crate.version' version.crateName version.num}} + {{ version.crateName }} + {{ version.num }} + {{/link-to}} + + {{moment-from-now version.created_at}} + +
    + {{/each}} + + {{#if loadingMore}} + + + + {{else}} + {{#if hasMore}} + + {{/if}} + {{/if}}
    +
    diff --git a/app/templates/error.hbs b/app/templates/error.hbs index 32e95e8eef..95e6ededdb 100644 --- a/app/templates/error.hbs +++ b/app/templates/error.hbs @@ -1,5 +1,5 @@

    Something Went Wrong!

    {{model.message}}
    -    {{model.stack}}
    +  {{model.stack}}
     
    diff --git a/app/templates/index.hbs b/app/templates/index.hbs index 03c86a5ee8..c11be7b888 100644 --- a/app/templates/index.hbs +++ b/app/templates/index.hbs @@ -1,63 +1,63 @@
    -

    The Rust community’s crate registry

    +

    The Rust community’s crate registry

    -
    -
    - Instantly publish your crates and install them. Use the API to - interact and find out more information about available crates. Become - a contributor and enhance the site with your work. -
    +
    + Instantly publish your crates and install them. Use the API to + interact and find out more information about available crates. Become + a contributor and enhance the site with your work. +
    -
    -
    - {{svg-jar "download"}} - {{if hasData (format-num model.num_downloads) "---,---,---"}} - Downloads -
    -
    - {{svg-jar "crate"}} - {{if hasData (format-num model.num_crates) "---,---"}} - Crates in stock -
    +
    +
    + {{svg-jar "download"}} + {{if hasData (format-num model.num_downloads) "---,---,---"}} + Downloads +
    +
    + {{svg-jar "crate"}} + {{if hasData (format-num model.num_crates) "---,---"}} + Crates in stock
    +
    -
    -

    New Crates

    - {{crate-list crates=model.new_crates}} -
    -
    -

    Most Downloaded

    - {{crate-list crates=model.most_downloaded}} -
    -
    -

    Just Updated

    - {{crate-list crates=model.just_updated}} -
    -
    -

    Most Recent Downloads

    - {{crate-list crates=model.most_recently_downloaded}} -
    -
    -

    Popular Keywords {{#link-to 'keywords'}}(see all){{/link-to}}

    - {{keyword-list keywords=model.popular_keywords}} -
    -
    -

    Popular Categories {{#link-to 'categories'}}(see all){{/link-to}}

    - {{category-list categories=model.popular_categories}} -
    +
    +

    New Crates

    + {{crate-list crates=model.new_crates}} +
    +
    +

    Most Downloaded

    + {{crate-list crates=model.most_downloaded}} +
    +
    +

    Just Updated

    + {{crate-list crates=model.just_updated}} +
    +
    +

    Most Recent Downloads

    + {{crate-list crates=model.most_recently_downloaded}} +
    +
    +

    Popular Keywords {{#link-to 'keywords'}}(see all){{/link-to}}

    + {{keyword-list keywords=model.popular_keywords}} +
    +
    +

    Popular Categories {{#link-to 'categories'}}(see all){{/link-to}}

    + {{category-list categories=model.popular_categories}} +
    diff --git a/app/templates/install.hbs b/app/templates/install.hbs index 4f4ec760ec..3c8e849306 100644 --- a/app/templates/install.hbs +++ b/app/templates/install.hbs @@ -1,8 +1,8 @@
    - {{svg-jar "download"}} -

    Install Cargo

    + {{svg-jar "download"}} +

    Install Cargo

    - 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

    diff --git a/app/templates/keyword/index.hbs b/app/templates/keyword/index.hbs index d187261ea6..dccefc5fe2 100644 --- a/app/templates/keyword/index.hbs +++ b/app/templates/keyword/index.hbs @@ -1,69 +1,69 @@ {{ title keyword.keyword ' - Keywords' }}
    - {{svg-jar "crate"}} -

    All Crates

    -

    for keyword '{{ keyword.keyword }}'

    + {{svg-jar "crate"}} +

    All Crates

    +

    for keyword '{{ keyword.keyword }}'

    - + -
    - Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} +
    + Sort by + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="downloads")}} - All-Time Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-downloads")}} - Recent Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-updates")}} - Recent Updates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="downloads")}} + All-Time Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-downloads")}} + Recent Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-updates")}} + Recent Updates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    - {{#each model as |crate|}} - {{crate-row crate=crate}} - {{/each}} + {{#each model as |crate|}} + {{crate-row crate=crate}} + {{/each}}
    diff --git a/app/templates/keywords.hbs b/app/templates/keywords.hbs index 48c6b57f21..10751d8529 100644 --- a/app/templates/keywords.hbs +++ b/app/templates/keywords.hbs @@ -1,65 +1,65 @@ {{ title 'Keywords' }}
    - {{svg-jar "crate"}} -

    All Keywords

    + {{svg-jar "crate"}} +

    All Keywords

    - + -
    - Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} +
    + Sort by + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="crates")}} - # Crates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="crates")}} + # Crates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    - {{#each model as |keyword|}} -
    -
    - {{link-to keyword.id "keyword" keyword}} - - {{ pluralize (format-num keyword.crates_cnt) "crate" }} - -
    -
    - {{/each}} + {{#each model as |keyword|}} +
    +
    + {{link-to keyword.id "keyword" keyword}} + + {{ pluralize (format-num keyword.crates_cnt) "crate" }} + +
    +
    + {{/each}}
    diff --git a/app/templates/me/crates.hbs b/app/templates/me/crates.hbs index fc3303e168..c5dfd9e704 100644 --- a/app/templates/me/crates.hbs +++ b/app/templates/me/crates.hbs @@ -1,70 +1,70 @@ {{ title 'My Crates' }}
    - {{svg-jar "crate"}} -

    My Crates

    + {{svg-jar "crate"}} +

    My Crates

    {{! TODO: reduce duplication with templates/crates.hbs }}
    - + -
    - Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown"}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} +
    + Sort by + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown"}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="downloads")}} - All-Time Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-downloads")}} - Recent Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-updates")}} - Recent Updates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="downloads")}} + All-Time Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-downloads")}} + Recent Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-updates")}} + Recent Updates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    - {{#each model as |crate|}} - {{crate-row crate=crate}} - {{/each}} + {{#each model as |crate|}} + {{crate-row crate=crate}} + {{/each}}
    diff --git a/app/templates/me/following.hbs b/app/templates/me/following.hbs index 6c68deb3d6..de3047b1a8 100644 --- a/app/templates/me/following.hbs +++ b/app/templates/me/following.hbs @@ -1,58 +1,58 @@
    - {{svg-jar "crate"}} -

    My Crates

    + {{svg-jar "crate"}} +

    My Crates

    {{! TODO: reduce duplication with templates/me/crates.hbs }}
    - + -
    - Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown"}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} +
    + Sort by + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown"}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="downloads")}} - Downloads - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="downloads")}} + Downloads + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    - {{#each model as |crate|}} - {{crate-row crate=crate}} - {{/each}} + {{#each model as |crate|}} + {{crate-row crate=crate}} + {{/each}}
    diff --git a/app/templates/me/index.hbs b/app/templates/me/index.hbs index ffe434749d..04a720f8c1 100644 --- a/app/templates/me/index.hbs +++ b/app/templates/me/index.hbs @@ -1,51 +1,51 @@ {{ title 'Settings' }}
    - {{svg-jar "gear"}} -

    Account Settings

    + {{svg-jar "gear"}} +

    Account Settings

    -

    Profile Information

    - -
    - {{#user-link user=model.user }} {{user-avatar user=model.user size='medium'}} {{/user-link}} - -
    -
    Name
    -
    {{ model.user.name }}
    -
    GitHub Account
    -
    {{ model.user.login }}
    -
    -
    +

    Profile Information

    + +
    + {{#user-link user=model.user }} {{user-avatar user=model.user size='medium'}} {{/user-link}} + +
    +
    Name
    +
    {{ model.user.name }}
    +
    GitHub Account
    +
    {{ model.user.login }}
    +
    +
    -

    User Email

    - {{email-input type='email' value=model.user.email user=model.user}} +

    User Email

    + {{email-input type='email' value=model.user.email user=model.user}}
    -
    -

    API Access

    -
    - -
    -
    - -

    - 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. -

    - -
    - {{#each sortedTokens as |api_token|}} - {{api-token-row api_token=api_token}} - {{/each}} +
    +

    API Access

    +
    +
    +
    + +

    + 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. +

    + +
    + {{#each sortedTokens as |api_token|}} + {{api-token-row api_token=api_token}} + {{/each}} +
    diff --git a/app/templates/me/pending-invites.hbs b/app/templates/me/pending-invites.hbs index f20ef3d15a..dd30d42cb9 100644 --- a/app/templates/me/pending-invites.hbs +++ b/app/templates/me/pending-invites.hbs @@ -1,16 +1,16 @@ {{ title 'Pending Invites' }}
    - {{svg-jar "gear"}} -

    Pending Owner Invites

    + {{svg-jar "gear"}} +

    Pending Owner Invites

    -
    - {{#each model as |invite|}} - {{pending-owner-invite-row invite=invite}} - {{else}} -

    You don't seem to have any pending invitations.

    - {{/each}} -
    +
    + {{#each model as |invite|}} + {{pending-owner-invite-row invite=invite}} + {{else}} +

    You don't seem to have any pending invitations.

    + {{/each}} +
    diff --git a/app/templates/policies.hbs b/app/templates/policies.hbs index c6025d666a..3e99e6d441 100644 --- a/app/templates/policies.hbs +++ b/app/templates/policies.hbs @@ -1,152 +1,154 @@
    - {{svg-jar 'circle-with-i'}} -

    Crates.io Package Policies

    + {{svg-jar 'circle-with-i'}} +

    Crates.io Package Policies

    -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.

    Package Ownership

    -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.

    Removal

    -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.

    Squatting

    -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.

    The Law

    -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.

    Code of Conduct

    -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:

      -
    • Package Name
    • -
    • Package Metadata
    • -
    • Documentation
    • -
    • Code
    • +
    • Package Name
    • +
    • Package Metadata
    • +
    • Documentation
    • +
    • Code

    -There are two important, related aspects: + There are two important, related aspects:

      -
    • +
    • We will not be pro-actively monitoring the site for these kinds of violations, but relying on the community to draw them to our attention. -
    • + -
    • +
    • “Does this violate the Code of Conduct” is a contextual question that cannot be directly answered in the hypothetical sense. All of the details must be taken into consideration in these kinds of situations. -
    • +

    Security

    -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.

    Crawlers

    -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 f261201d7e..89282b7345 100644 --- a/app/templates/search.hbs +++ b/app/templates/search.hbs @@ -1,97 +1,97 @@ {{title (concat "Search Results for '" q "'")}} {{#if firstResultPending}} -
    -

    Loading search results...

    -
    +
    +

    Loading search results...

    +
    {{else if hasItems}} -
    - +
    + -
    - Sort by +
    + Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown" data-test-current-order=true}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params page=1 sort="relevance")}} - Relevance - {{/link-to}} -
  • -
  • - {{#link-to (query-params page=1 sort="downloads")}} - All-Time Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params page=1 sort="recent-downloads")}} - Recent Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params page=1 sort="recent-updates")}} - Recent Updates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params page=1 sort="relevance")}} + Relevance + {{/link-to}} +
  • +
  • + {{#link-to (query-params page=1 sort="downloads")}} + All-Time Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params page=1 sort="recent-downloads")}} + Recent Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params page=1 sort="recent-updates")}} + Recent Updates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}}
    +
    -
    - {{#each model as |crate index|}} - {{#if crate.exact_match}} -
    - {{#link-to "crate" crate}} -

    Exact Match

    - {{/link-to}} - {{crate-row crate=crate data-test-crate-row=index}} -
    - {{else}} -
    - {{crate-row crate=crate data-test-crate-row=index}} -
    - {{/if}} - {{/each}} -
    +
    + {{#each model as |crate index|}} + {{#if crate.exact_match}} +
    + {{#link-to "crate" crate}} +

    Exact Match

    + {{/link-to}} + {{crate-row crate=crate data-test-crate-row=index}} +
    + {{else}} +
    + {{crate-row crate=crate data-test-crate-row=index}} +
    + {{/if}} + {{/each}} +
    - + {{else}} -
    -

    0 crates found. Get started and create your own.

    -
    +
    +

    0 crates found. Get started and create your own.

    +
    {{/if}} diff --git a/app/templates/team.hbs b/app/templates/team.hbs index a0481e6e52..d0821752c0 100644 --- a/app/templates/team.hbs +++ b/app/templates/team.hbs @@ -1,86 +1,86 @@
    -
    -
    - {{user-avatar user=model.team size='medium' data-test-avatar=true}} -
    -

    - {{ model.team.org_name }} -

    -

    - {{ model.team.name }} -

    -
    - {{#user-link user=model.team data-test-github-link=true}} - GitHub profile - {{/user-link}} -
    +
    +
    + {{user-avatar user=model.team size='medium' data-test-avatar=true}} +
    +

    + {{ model.team.org_name }} +

    +

    + {{ model.team.name }} +

    +
    + {{#user-link user=model.team data-test-github-link=true}} + GitHub profile + {{/user-link}}
    +
    -
    - {{! TODO: reduce duplication with templates/crates.hbs }} +
    + {{! TODO: reduce duplication with templates/crates.hbs }} -
    - +
    + -
    - Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown"}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} +
    + Sort by + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown"}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="downloads")}} - All-Time Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-downloads")}} - Recent Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-updates")}} - Recent Updates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="downloads")}} + All-Time Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-downloads")}} + Recent Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-updates")}} + Recent Updates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    +
    -
    - {{#each model.crates as |crate|}} - {{crate-row crate=crate}} - {{/each}} -
    +
    + {{#each model.crates as |crate|}} + {{crate-row crate=crate}} + {{/each}} +
    - + +
    diff --git a/app/templates/user.hbs b/app/templates/user.hbs index 69ce4ce34d..be98992d82 100644 --- a/app/templates/user.hbs +++ b/app/templates/user.hbs @@ -1,77 +1,77 @@
    - {{user-avatar user=model.user size='medium' data-test-avatar=true}} -

    - {{ model.user.login }} -

    - {{#user-link user=model.user data-test-user-link=true}} - GitHub profile - {{/user-link}} + {{user-avatar user=model.user size='medium' data-test-avatar=true}} +

    + {{ model.user.login }} +

    + {{#user-link user=model.user data-test-user-link=true}} + GitHub profile + {{/user-link}}
    -
    - {{! TODO: reduce duplication with templates/crates.hbs }} +
    + {{! TODO: reduce duplication with templates/crates.hbs }} -
    - +
    + -
    - Sort by - {{#rl-dropdown-container class="dropdown-container"}} - {{#rl-dropdown-toggle tagName="a" class="dropdown"}} - {{svg-jar "sort"}} - {{ currentSortBy }} - - {{/rl-dropdown-toggle}} +
    + Sort by + {{#rl-dropdown-container class="dropdown-container"}} + {{#rl-dropdown-toggle tagName="a" class="dropdown"}} + {{svg-jar "sort"}} + {{ currentSortBy }} + + {{/rl-dropdown-toggle}} - {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} -
  • - {{#link-to (query-params sort="alpha")}} - Alphabetical - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="downloads")}} - All-Time Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-downloads")}} - Recent Downloads - {{/link-to}} -
  • -
  • - {{#link-to (query-params sort="recent-updates")}} - Recent Updates - {{/link-to}} -
  • - {{/rl-dropdown}} - {{/rl-dropdown-container}} -
    -
    + {{#rl-dropdown tagName="ul" class="dropdown" closeOnChildClick="a:link"}} +
  • + {{#link-to (query-params sort="alpha")}} + Alphabetical + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="downloads")}} + All-Time Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-downloads")}} + Recent Downloads + {{/link-to}} +
  • +
  • + {{#link-to (query-params sort="recent-updates")}} + Recent Updates + {{/link-to}} +
  • + {{/rl-dropdown}} + {{/rl-dropdown-container}} +
    +
    -
    - {{#each model.crates as |crate|}} - {{crate-row crate=crate}} - {{/each}} -
    +
    + {{#each model.crates as |crate|}} + {{crate-row crate=crate}} + {{/each}} +
    - + +
    From a5c5db83c32ebc5dea4ffb537ab2ad121481b2fc Mon Sep 17 00:00:00 2001 From: Josh Justice Date: Fri, 30 Aug 2019 07:31:46 -0400 Subject: [PATCH 8/8] Run template lint on CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4b41efa0ac..6c4a4797e3 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