diff --git a/.editorconfig b/.editorconfig
index 5d5dea4ccc8..3ef6636eed9 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,23 +11,24 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
-indent_size = 2
+indent_size = 4
[*.js]
indent_style = space
-indent_size = 2
+indent_size = 4
[*.hbs]
+insert_final_newline = false
indent_style = space
-indent_size = 2
+indent_size = 4
[*.css]
indent_style = space
-indent_size = 2
+indent_size = 4
[*.html]
indent_style = space
-indent_size = 2
+indent_size = 4
-[*.md]
+[*.{diff,md}]
trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
index 5125d2549d2..3a9963e3d61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,7 @@
# dependencies
/node_modules
-/bower_components/*
+/bower_components
# misc
/.sass-cache
diff --git a/.jshintrc b/.jshintrc
index 07ba69595b8..08096effaab 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -1,13 +1,11 @@
{
- "predef": {
- "document": true,
- "window": true,
- "-Promise": true,
- "moment": true,
- "google": true
- },
- "browser" : true,
- "boss" : true,
+ "predef": [
+ "document",
+ "window",
+ "-Promise"
+ ],
+ "browser": true,
+ "boss": true,
"curly": true,
"debug": false,
"devel": true,
diff --git a/.travis.yml b/.travis.yml
index 8fdf94ef19f..083b8546b02 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,16 +2,29 @@ language: rust
rust: nightly
sudo: false
-before_script:
+cache:
+ directories:
+ - node_modules
+
+before_install:
+ - nvm install 0.12
+ - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
+ - "npm config set spin false"
+ - "npm install -g npm@^2"
+
+install:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
- - psql -c 'create database cargo_registry_test;' -U postgres
- - npm install -g phantomjs ember-cli
+ - npm install -g bower
- npm install
+ - bower install
+
+before_script:
+ - psql -c 'create database cargo_registry_test;' -U postgres
script:
- cargo build
- cargo test
- - ember test
+ - npm test
after_success:
- travis-cargo coveralls --no-sudo
diff --git a/.watchmanconfig b/.watchmanconfig
new file mode 100644
index 00000000000..5e9462c2005
--- /dev/null
+++ b/.watchmanconfig
@@ -0,0 +1,3 @@
+{
+ "ignore_dirs": ["tmp"]
+}
diff --git a/Brocfile.js b/Brocfile.js
deleted file mode 100644
index d927ec0cf05..00000000000
--- a/Brocfile.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* global require, module */
-
-var EmberApp = require('ember-cli/lib/broccoli/ember-app');
-
-var app = new EmberApp();
-
-// 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('bower_components/moment/moment.js');
-app.import('bower_components/normalize-css/normalize.css');
-
-module.exports = app.toTree();
diff --git a/README.md b/README.md
index 4abc1d408ed..8f088357dfa 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ which enables tweaking the UI of the site without actually having the server
running locally. To get up and running with just the UI, run:
```
-npm run startui
+npm run start:ui
```
This will give you a local server to browse while using the staging backend
diff --git a/app/adapters/dependency.js b/app/adapters/dependency.js
index 0104c2899e5..7829d9c818d 100644
--- a/app/adapters/dependency.js
+++ b/app/adapters/dependency.js
@@ -1,9 +1,9 @@
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
- findQuery: function(store, type, query) {
+ query(store, type, query) {
if (!query.reverse) {
- return this._super(store, type, query);
+ return this._super(...arguments);
}
delete query.reverse;
var crate = query.crate;
diff --git a/app/app.js b/app/app.js
index 78679ead567..d1c7c209956 100644
--- a/app/app.js
+++ b/app/app.js
@@ -3,15 +3,19 @@ import Resolver from 'ember/resolver';
import loadInitializers from 'ember/load-initializers';
import config from './config/environment';
+var App;
+
Ember.MODEL_FACTORY_INJECTIONS = true;
-var App = Ember.Application.extend({
+App = Ember.Application.extend({
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix,
Resolver: Resolver
});
loadInitializers(App, config.modulePrefix);
-Ember.$.ajaxSetup({cache: false});
+Ember.$.ajaxSetup({
+ cache: false
+});
export default App;
diff --git a/app/components/crate-row.js b/app/components/crate-row.js
new file mode 100644
index 00000000000..33ee68e5cc6
--- /dev/null
+++ b/app/components/crate-row.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['crate', 'row']
+});
diff --git a/app/components/user-avatar.js b/app/components/user-avatar.js
index 704c4c973e7..39efdc25093 100644
--- a/app/components/user-avatar.js
+++ b/app/components/user-avatar.js
@@ -1,12 +1,14 @@
import Ember from 'ember';
+const { computed } = Ember;
+
export default Ember.Component.extend({
size: 'small',
user: null,
attributeBindings: ['src', 'width', 'height'],
tagName: 'img',
- width: function() {
+ width: computed('size', function() {
if (this.get('size') === 'small') {
return 22;
} else if (this.get('size') === 'medium-small') {
@@ -14,13 +16,11 @@ export default Ember.Component.extend({
} else {
return 85; // medium
}
- }.property('size'),
+ }),
- height: function() {
- return this.get('width');
- }.property('width'),
+ height: computed.readOnly('width'),
- src: function() {
+ src: computed('size', 'user', function() {
return this.get('user.avatar') + '&s=' + this.get('width');
- }.property('size', 'user'),
+ })
});
diff --git a/app/components/user-link.js b/app/components/user-link.js
index dbef9d4b70d..5cff012f3d4 100644
--- a/app/components/user-link.js
+++ b/app/components/user-link.js
@@ -1,17 +1,16 @@
import Ember from 'ember';
+const { computed } = Ember;
+
export default Ember.Component.extend({
user: null,
attributeBindings: ['title', 'href'],
tagName: 'a',
- title: function() {
- return this.get('user.login');
- }.property('user'),
-
- 'href': function() {
+ title: computed.readOnly('user.login'),
+ href: computed('user', function() {
// TODO replace this with a link to a native crates.io profile
// page when they exist.
return this.get('user.url');
- }.property('user'),
+ })
});
diff --git a/app/controllers/application.js b/app/controllers/application.js
index 31d2780b858..8e407728dec 100644
--- a/app/controllers/application.js
+++ b/app/controllers/application.js
@@ -1,30 +1,33 @@
import Ember from 'ember';
+const { observer } = Ember;
+
export default Ember.Controller.extend({
- needs: ['search'],
+ searchController: Ember.inject.controller('search'),
flashError: null,
nextFlashError: null,
showUserOptions: false,
- search: Ember.computed.oneWay('controllers.search.q'),
+ search: Ember.computed.oneWay('searchController.q'),
- stepFlash: function() {
+ stepFlash() {
this.set('flashError', this.get('nextFlashError'));
this.set('nextFlashError', null);
},
- aboutToTransition: function() {
+ aboutToTransition() {
Ember.$(document).trigger('mousedown');
},
- resetDropdownOption: function(controller, option) {
+ // don't use this from other controllers..
+ resetDropdownOption(controller, option) {
controller.set(option, !controller.get(option));
if (controller.get(option)) {
- Ember.$(document).on('mousedown.useroptions', function(e) {
+ Ember.$(document).on('mousedown.useroptions', (e) => {
if (Ember.$(e.target).prop('tagName') === 'INPUT') {
return;
}
- Ember.run.later(function() {
+ Ember.run.later(() => {
controller.set(option, false);
}, 150);
Ember.$(document).off('mousedown.useroptions');
@@ -32,18 +35,26 @@ export default Ember.Controller.extend({
}
},
- currentPathChanged: function () {
+ _scrollToTop() {
window.scrollTo(0, 0);
- }.observes('currentPath'),
+ },
+
+ // TODO: remove observer & DOM mutation in controller..
+ currentPathChanged: observer('currentPath', function () {
+ Ember.run.scheduleOnce('afterRender', this, this._scrollToTop);
+ }),
actions: {
- search: function(query) {
+ search(q) {
this.transitionToRoute('search', {
- queryParams: {q: query, page: 1}
+ queryParams: {
+ q,
+ page: 1
+ }
});
},
- toggleUserOptions: function() {
+ toggleUserOptions() {
this.resetDropdownOption(this, 'showUserOptions');
},
},
diff --git a/app/controllers/catch-all.js b/app/controllers/catch-all.js
index efe33d26a3a..1a37236b627 100644
--- a/app/controllers/catch-all.js
+++ b/app/controllers/catch-all.js
@@ -2,7 +2,7 @@ import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
- search: function(query) {
+ search(query) {
return this.transitionToRoute('search', {queryParams: {q: query}});
},
},
diff --git a/app/controllers/crate/index.js b/app/controllers/crate/index.js
index 0b58d77f09e..2963c2cfee4 100644
--- a/app/controllers/crate/index.js
+++ b/app/controllers/crate/index.js
@@ -1,11 +1,13 @@
import Ember from 'ember';
import DS from 'ember-data';
import ajax from 'ic-ajax';
+import moment from 'moment';
-var NUM_VERSIONS = 5;
+const NUM_VERSIONS = 5;
+const { computed } = Ember;
-export default Ember.ObjectController.extend({
- needs: ['application'],
+export default Ember.Controller.extend({
+ applicationController: Ember.inject.controller('application'),
isDownloading: false,
fetchingDownloads: true,
@@ -16,111 +18,97 @@ export default Ember.ObjectController.extend({
requestedVersion: null,
keywords: [],
- sortedVersions: function() {
+ sortedVersions: computed('model.versions.[]', function() {
return this.get("model.versions");
- }.property('model.versions.[]'),
+ }),
- smallSortedVersions: function() {
+ smallSortedVersions: computed('sortedVersions', function() {
return this.get('sortedVersions').slice(0, NUM_VERSIONS);
- }.property('sortedVersions'),
-
- hasMoreVersions: function() {
- return this.get("sortedVersions.length") > NUM_VERSIONS;
- }.property('sortedVersions'),
-
- anyLinks: function() {
- return this.get('homepage') ||
- this.get('wiki') ||
- this.get('mailing_list') ||
- this.get('documentation') ||
- this.get('repository');
- }.property('homepage', 'wiki', 'mailing_list', 'documentation', 'repository'),
-
- versionsCount: function() {
- return this.get('versions.length');
- }.property('versions.@each'),
-
- displayedAuthors: function() {
- var self = this;
+ }),
+
+ hasMoreVersions: computed.gt('sortedVersions.length', NUM_VERSIONS),
+
+ anyLinks: computed.or('model.homepage',
+ 'model.wiki',
+ 'model.mailing_list',
+ 'model.documentation',
+ 'model.repository'),
+
+ displayedAuthors: computed('currentVersion.authors.[]', function() {
if (!this.get('currentVersion')) {
return [];
}
+
return DS.PromiseArray.create({
- promise: this.get('currentVersion.authors').then(function(authors) {
- var ret = [];
- authors.forEach(function(author) {
- ret.push(author);
- });
- var others = self.store.metadataFor('user');
+ promise: this.get('currentVersion.authors').then((authors) => {
+ var ret = authors.slice();
+ var others = this.store.metadataFor('user');
for (var i = 0; i < others.names.length; i++) {
ret.push({name: others.names[i]});
}
return ret;
- }),
+ })
});
- }.property('currentVersion.authors.@each'),
+ }),
- anyKeywords: function() {
- return this.get('keywords.length') > 0;
- }.property('keywords'),
+ anyKeywords: computed.gt('keywords.length', 0),
- currentDependencies: function() {
+ currentDependencies: computed('currentVersion.dependencies', function() {
var deps = this.get('currentVersion.dependencies');
+
if (deps === null) { return []; }
+
return DS.PromiseArray.create({
- promise: deps.then(function(deps) {
- var non_dev = deps.filter(function(dep) {
- return dep.get('kind') !== 'dev';
- });
+ promise: deps.then((deps) => {
+ var non_dev = deps.filter((dep) => dep.get('kind') !== 'dev' );
var map = {};
var ret = [];
- non_dev.forEach(function(dep) {
+
+ non_dev.forEach((dep) => {
if (!(dep.get('crate_id') in map)) {
map[dep.get('crate_id')] = 1;
ret.push(dep);
}
});
+
return ret;
- }),
+ })
});
- }.property('currentVersion.dependencies'),
+ }),
- currentDevDependencies: function() {
+ currentDevDependencies: computed('currentVersion.dependencies', function() {
var deps = this.get('currentVersion.dependencies');
if (deps === null) { return []; }
return DS.PromiseArray.create({
- promise: deps.then(function(deps) {
- return deps.filter(function(dep) {
- return dep.get('kind') === 'dev';
- });
+ promise: deps.then((deps) => {
+ return deps.filterBy('kind', 'dev');
}),
});
- }.property('currentVersion.dependencies'),
+ }),
actions: {
- download: function(version) {
+ download(version) {
this.set('isDownloading', true);
- var self = this;
+
var crate_downloads = this.get('model').get('downloads');
var ver_downloads = version.get('downloads');
+
return ajax({
url: version.get('dl_path'),
dataType: 'json',
- }).then(function(data) {
- self.get('model').set('downloads', crate_downloads + 1);
+ }).then((data) => {
+ this.get('model').set('downloads', crate_downloads + 1);
version.set('downloads', ver_downloads + 1);
Ember.$('#download-frame').attr('src', data.url);
- }).finally(function() {
- self.set('isDownloading', false);
- });
+ }).finally(() => this.set('isDownloading', false) );
},
- toggleVersions: function() {
- this.get('controllers.application')
+ toggleVersions() {
+ this.get('applicationController')
.resetDropdownOption(this, 'showAllVersions');
},
- toggleFollow: function() {
+ toggleFollow() {
this.set('fetchingFollowing', true);
this.set('following', !this.get('following'));
var url = '/api/v1/crates/' + this.get('model.name') + '/follow';
@@ -130,20 +118,22 @@ export default Ember.ObjectController.extend({
} else {
method = 'delete';
}
- var self = this;
- ajax({ method: method, url: url }).finally(function() {
- self.set('fetchingFollowing', false);
- });
+
+ ajax({
+ method,
+ url
+ }).finally(() => this.set('fetchingFollowing', false));
},
- renderChart: function(downloads, extra) {
+ renderChart(downloads, extra) {
var dates = {};
var versions = [];
for (var i = 0; i < 90; i++) {
var now = moment().subtract(i, 'days');
dates[now.format('MMM D')] = {date: now, cnt: {}};
}
- downloads.forEach(function(d) {
+
+ downloads.forEach((d) => {
var version_id = d.get('version.id');
var key = moment(d.get('date')).utc().format('MMM D');
if (dates[key]) {
@@ -151,7 +141,8 @@ export default Ember.ObjectController.extend({
dates[key].cnt[version_id] = prev + d.get('downloads');
}
});
- extra.forEach(function(d) {
+
+ extra.forEach((d) => {
var key = moment(d.date).utc().format('MMM D');
if (dates[key]) {
var prev = dates[key].cnt[null] || 0;
@@ -166,15 +157,21 @@ export default Ember.ObjectController.extend({
} else {
var tmp = this.get('smallSortedVersions');
for (i = 0; i < tmp.length; i++) {
- versions.push({id: tmp[i].get('id'), num: tmp[i].get('num')});
+ versions.push({
+ id: tmp[i].get('id'),
+ num: tmp[i].get('num')
+ });
}
}
if (extra.length > 0) {
- versions.push({ id: null, num: 'Other' });
+ versions.push({
+ id: null,
+ num: 'Other'
+ });
}
var headers = ['Date'];
- versions.sort(function(b) { return b.num; }).reverse();
+ versions.sort((b) => b.num).reverse();
for (i = 0; i < versions.length; i++) {
headers.push(versions[i].num);
}
@@ -187,16 +184,17 @@ export default Ember.ObjectController.extend({
data.push(row);
}
- var drawChart = function() {
+ // TODO: move this to a component
+ function drawChart() {
if (!window.google || !window.googleChartsLoaded) {
Ember.$('.graph').hide();
return;
} else {
Ember.$('.graph').show();
}
- var myData = google.visualization.arrayToDataTable(data);
+ var myData = window.google.visualization.arrayToDataTable(data);
- var fmt = new google.visualization.DateFormat({
+ var fmt = new window.google.visualization.DateFormat({
pattern: 'LLL d, yyyy',
});
fmt.format(myData, 0);
@@ -204,7 +202,7 @@ export default Ember.ObjectController.extend({
if (!el) {
return;
}
- var chart = new google.visualization.AreaChart(el);
+ var chart = new window.google.visualization.AreaChart(el);
chart.draw(myData, {
chartArea: {'left': 85, 'width': '77%', 'height': '80%'},
hAxis: {
@@ -217,7 +215,7 @@ export default Ember.ObjectController.extend({
isStacked: true,
focusTarget: 'category',
});
- };
+ }
Ember.run.scheduleOnce('afterRender', this, drawChart);
Ember.$(window).off('resize.chart');
@@ -227,4 +225,3 @@ export default Ember.ObjectController.extend({
},
},
});
-
diff --git a/app/controllers/crate/reverse-dependencies.js b/app/controllers/crate/reverse-dependencies.js
index f7305544938..514294acf25 100644
--- a/app/controllers/crate/reverse-dependencies.js
+++ b/app/controllers/crate/reverse-dependencies.js
@@ -1,13 +1,14 @@
import Ember from 'ember';
import PaginationMixin from 'cargo/mixins/pagination';
-export default Ember.ArrayController.extend(PaginationMixin, {
+const { computed } = Ember;
+
+export default Ember.Controller.extend(PaginationMixin, {
queryParams: ['page', 'per_page'],
page: '1',
per_page: 10,
- totalItems: function() {
+ totalItems: computed('model', function() {
return this.store.metadataFor('dependency').total;
- }.property('model'),
+ })
});
-
diff --git a/app/controllers/crate/versions.js b/app/controllers/crate/versions.js
index bd8bd406cd3..55ff9aa587a 100644
--- a/app/controllers/crate/versions.js
+++ b/app/controllers/crate/versions.js
@@ -1,4 +1,4 @@
import Ember from 'ember';
-export default Ember.ObjectController.extend({
+export default Ember.Controller.extend({
});
diff --git a/app/controllers/crates.js b/app/controllers/crates.js
index 5e8cc409387..835ef875af9 100644
--- a/app/controllers/crates.js
+++ b/app/controllers/crates.js
@@ -1,8 +1,10 @@
import Ember from 'ember';
import PaginationMixin from 'cargo/mixins/pagination';
-export default Ember.ArrayController.extend(PaginationMixin, {
- needs: ['application'],
+const { computed } = Ember;
+
+export default Ember.Controller.extend(PaginationMixin, {
+ applicationController: Ember.inject.controller('application'),
queryParams: ['letter', 'page', 'per_page', 'sort'],
letter: null,
page: '1',
@@ -11,24 +13,22 @@ export default Ember.ArrayController.extend(PaginationMixin, {
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(""),
showSortBy: false,
- totalItems: function() {
+ totalItems: computed('model', function() {
return this.store.metadataFor('crate').total;
- }.property('model'),
+ }),
- currentSortBy: function() {
+ currentSortBy: computed('sort', function() {
if (this.get('sort') === 'downloads') {
return 'Downloads';
} else {
return 'Alphabetical';
}
- }.property('sort'),
+ }),
actions: {
- toggleShowSortBy: function() {
+ toggleShowSortBy() {
var opt = 'showSortBy';
- this.get('controllers.application').resetDropdownOption(this, opt);
-
+ this.get('applicationController').resetDropdownOption(this, opt);
},
},
});
-
diff --git a/app/controllers/dashboard.js b/app/controllers/dashboard.js
index cd34ebb5ea8..ee0d0445b57 100644
--- a/app/controllers/dashboard.js
+++ b/app/controllers/dashboard.js
@@ -1,45 +1,54 @@
import Ember from 'ember';
import ajax from 'ic-ajax';
-var TO_SHOW = 5;
+const TO_SHOW = 5;
+const { computed } = Ember;
-export default Ember.ObjectController.extend({
- fetchingFeed: true,
- loadingMore: false,
- hasMore: false,
- myCrates: [],
- myFollowing: [],
- myFeed: [],
+export default Ember.Controller.extend({
+ init() {
+ this._super(...arguments);
- visibleCrates: function() {
+ this.fetchingFeed = true;
+ this.loadingMore = false;
+ this.hasMore = false;
+ this.myCrates = [];
+ this.myFollowing = [];
+ this.myFeed = [];
+ },
+
+ visibleCrates: computed('myCreates', function() {
return this.get('myCrates').slice(0, TO_SHOW);
- }.property('myCrates'),
+ }),
- visibleFollowing: function() {
+ visibleFollowing: computed('myFollowing', function() {
return this.get('myFollowing').slice(0, TO_SHOW);
- }.property('myFollowing'),
+ }),
- hasMoreCrates: function() {
+ hasMoreCrates: computed('myCreates', function() {
return this.get('myCrates.length') > TO_SHOW;
- }.property('myCrates'),
+ }),
- hasMoreFollowing: function() {
+ hasMoreFollowing: computed('myFollowing', function() {
return this.get('myFollowing.length') > TO_SHOW;
- }.property('myFollowing'),
+ }),
actions: {
- loadMore: function() {
- var self = this;
+ loadMore() {
this.set('loadingMore', true);
var page = (this.get('myFeed').length / 10) + 1;
- ajax('/me/updates?page=' + page).then(function(data) {
- self.store.pushMany('crate', data.crates);
- var versions = self.store.pushMany('version', data.versions);
- self.get('myFeed').pushObjects(versions);
- self.set('hasMore', data.meta.more);
- }).finally(function() {
- self.set('loadingMore', false);
+
+ ajax('/me/updates?page=' + page).then((data) => {
+ data.crates.forEach(crate =>
+ this.store.push(this.store.normalize('crate', crate)));
+
+ var versions = data.versions.map(version =>
+ this.store.push(this.store.normalize('version', version)));
+
+ this.get('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 a451f961d79..562af000e20 100644
--- a/app/controllers/index.js
+++ b/app/controllers/index.js
@@ -1,7 +1,8 @@
import Ember from 'ember';
+const { computed } = Ember;
-export default Ember.ObjectController.extend({
- currentPlatform: function() {
+export default Ember.Controller.extend({
+ currentPlatform: computed(function() {
var os = null;
if (navigator.platform === "Linux x86_64") {
@@ -22,12 +23,11 @@ export default Ember.ObjectController.extend({
}
return os;
- }.property(),
+ }),
- downloadUrl: function() {
+ downloadUrl: computed('currentPlatform', function() {
var plat = this.get('currentPlatform');
if (plat == null) { return null; }
- return "https://static.rust-lang.org/cargo-dist/cargo-nightly-" +
- plat + ".tar.gz";
- }.property('currentPlatform'),
+ return `https://static.rust-lang.org/cargo-dist/cargo-nightly-${plat}.tar.gz`;
+ })
});
diff --git a/app/controllers/install.js b/app/controllers/install.js
index f8687ac9a21..169d342b735 100644
--- a/app/controllers/install.js
+++ b/app/controllers/install.js
@@ -1,28 +1,14 @@
import Ember from 'ember';
-export default Ember.Controller.extend({
-
- linux64: function() {
- return this.link('x86_64-unknown-linux-gnu');
- }.property(),
- linux32: function() {
- return this.link('i686-unknown-linux-gnu');
- }.property(),
- mac64: function() {
- return this.link('x86_64-apple-darwin');
- }.property(),
- mac32: function() {
- return this.link('i686-apple-darwin');
- }.property(),
- win64: function() {
- return this.link('x86_64-pc-windows-gnu');
- }.property(),
- win32: function() {
- return this.link('i686-pc-windows-gnu');
- }.property(),
+function link(target) {
+ return `https://static.rust-lang.org/cargo-dist/cargo-nightly-${target}.tar.gz`;
+}
- link: function(target) {
- return 'https://static.rust-lang.org/cargo-dist/cargo-nightly-' +
- target + '.tar.gz';
- },
+export default Ember.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'),
});
diff --git a/app/controllers/keyword/index.js b/app/controllers/keyword/index.js
index 2a0a45701e4..f7e74772027 100644
--- a/app/controllers/keyword/index.js
+++ b/app/controllers/keyword/index.js
@@ -1,31 +1,32 @@
import Ember from 'ember';
import PaginationMixin from 'cargo/mixins/pagination';
-export default Ember.ArrayController.extend(PaginationMixin, {
- needs: ['application'],
+const { computed } = Ember;
+
+export default Ember.Controller.extend(PaginationMixin, {
+ applicationController: Ember.inject.controller('application'),
queryParams: ['page', 'per_page', 'sort'],
page: '1',
per_page: 10,
sort: 'alpha',
showSortBy: false,
- totalItems: function() {
+ totalItems: computed('model', function() {
return this.store.metadataFor('crate').total;
- }.property('model'),
+ }),
- currentSortBy: function() {
+ currentSortBy: computed('sort', function() {
if (this.get('sort') === 'downloads') {
return 'Downloads';
} else {
return 'Alphabetical';
}
- }.property('sort'),
+ }),
actions: {
- toggleShowSortBy: function() {
+ toggleShowSortBy() {
var opt = 'showSortBy';
- this.get('controllers.application').resetDropdownOption(this, opt);
+ this.get('applicationController').resetDropdownOption(this, opt);
},
},
});
-
diff --git a/app/controllers/keywords.js b/app/controllers/keywords.js
index ce37043a2b0..d8133f50db8 100644
--- a/app/controllers/keywords.js
+++ b/app/controllers/keywords.js
@@ -1,31 +1,32 @@
import Ember from 'ember';
import PaginationMixin from 'cargo/mixins/pagination';
-export default Ember.ArrayController.extend(PaginationMixin, {
- needs: ['application'],
+const { computed } = Ember;
+
+export default Ember.Controller.extend(PaginationMixin, {
+ applicationController: Ember.inject.controller('application'),
queryParams: ['page', 'per_page', 'sort'],
page: '1',
per_page: 10,
sort: 'crates',
showSortBy: false,
- totalItems: function() {
+ totalItems: computed('model', function() {
return this.store.metadataFor('keyword').total;
- }.property('model'),
+ }),
- currentSortBy: function() {
+ currentSortBy: computed('sort', function() {
if (this.get('sort') === 'crates') {
return '# Crates';
} else {
return 'Alphabetical';
}
- }.property('sort'),
+ }),
actions: {
- toggleShowSortBy: function() {
+ toggleShowSortBy() {
var opt = 'showSortBy';
- this.get('controllers.application').resetDropdownOption(this, opt);
-
+ this.get('applicationController').resetDropdownOption(this, opt);
},
},
});
diff --git a/app/controllers/me/crates.js b/app/controllers/me/crates.js
index e9ac9c78e52..e5fb19b8ebd 100644
--- a/app/controllers/me/crates.js
+++ b/app/controllers/me/crates.js
@@ -1,35 +1,34 @@
import Ember from 'ember';
import PaginationMixin from 'cargo/mixins/pagination';
+const { computed } = Ember;
// TODO: reduce duplicatoin with controllers/crates
-export default Ember.ArrayController.extend(PaginationMixin, {
- needs: ['application'],
+export default Ember.Controller.extend(PaginationMixin, {
+ applicationController: Ember.inject.controller('application'),
queryParams: ['page', 'per_page', 'sort'],
page: '1',
per_page: 10,
sort: 'alpha',
showSortBy: false,
- totalItems: function() {
+ totalItems: computed('model', function() {
return this.store.metadataFor('crate').total;
- }.property('model'),
+ }),
- currentSortBy: function() {
+ currentSortBy: computed('sort', function() {
if (this.get('sort') === 'downloads') {
return 'Downloads';
} else {
return 'Alphabetical';
}
- }.property('sort'),
+ }),
actions: {
- toggleShowSortBy: function() {
+ toggleShowSortBy() {
var opt = 'showSortBy';
- this.get('controllers.application').resetDropdownOption(this, opt);
+ this.get('applicationController').resetDropdownOption(this, opt);
},
},
});
-
-
diff --git a/app/controllers/me/following.js b/app/controllers/me/following.js
index ffec92152b8..347d25305eb 100644
--- a/app/controllers/me/following.js
+++ b/app/controllers/me/following.js
@@ -1,35 +1,34 @@
import Ember from 'ember';
import PaginationMixin from 'cargo/mixins/pagination';
+const { computed } = Ember;
// TODO: reduce duplicatoin with controllers/me/crates
-export default Ember.ArrayController.extend(PaginationMixin, {
- needs: ['application'],
+export default Ember.Controller.extend(PaginationMixin, {
+ applicationController: Ember.inject.controller('application'),
queryParams: ['page', 'per_page', 'sort'],
page: '1',
per_page: 10,
sort: 'alpha',
showSortBy: false,
- totalItems: function() {
+ totalItems: computed('model', function() {
return this.store.metadataFor('crate').total;
- }.property('model'),
+ }),
- currentSortBy: function() {
+ currentSortBy: computed('sort', function() {
if (this.get('sort') === 'downloads') {
return 'Downloads';
} else {
return 'Alphabetical';
}
- }.property('sort'),
+ }),
actions: {
- toggleShowSortBy: function() {
+ toggleShowSortBy() {
var opt = 'showSortBy';
- this.get('controllers.application').resetDropdownOption(this, opt);
+ this.get('applicationController').resetDropdownOption(this, opt);
},
},
});
-
-
diff --git a/app/controllers/me/index.js b/app/controllers/me/index.js
index 110edc8a221..30d14b8d6e2 100644
--- a/app/controllers/me/index.js
+++ b/app/controllers/me/index.js
@@ -1,30 +1,32 @@
import Ember from 'ember';
import ajax from 'ic-ajax';
-export default Ember.ObjectController.extend({
+export default Ember.Controller.extend({
isResetting: false,
actions: {
- resetToken: function() {
+ resetToken() {
this.set('isResetting', true);
- var self = this;
+
ajax({
dataType: "json",
url: '/me/reset_token',
method: 'put',
- }).then(function(d) {
- self.get('model').set('api_token', d.api_token);
- }).catch(function(reason) {
+ }).then((d) => {
+ this.get('model').set('api_token', d.api_token);
+ }).catch((reason) => {
var msg;
if (reason.status === 403) {
msg = "A login is required to perform this action";
} else {
msg = "An unknown error occurred";
}
- self.controllerFor('application').set('nextFlashError', msg);
- self.transitionToRoute('index');
- }).finally(function() {
- self.set('isResetting', false);
+ this.controllerFor('application').set('nextFlashError', msg);
+ // TODO: this should be an action, the route state machine
+ // should recieve signals not external transitions
+ this.transitionToRoute('index');
+ }).finally(() => {
+ this.set('isResetting', false);
});
}
}
diff --git a/app/controllers/search.js b/app/controllers/search.js
index 059813ab4c0..2e9770c59cc 100644
--- a/app/controllers/search.js
+++ b/app/controllers/search.js
@@ -1,17 +1,19 @@
import Ember from 'ember';
import PaginationMixin from 'cargo/mixins/pagination';
-export default Ember.ArrayController.extend(PaginationMixin, {
+const { computed } = Ember;
+
+export default Ember.Controller.extend(PaginationMixin, {
queryParams: ['q', 'page', 'per_page'],
q: null,
page: '1',
per_page: 10,
- name: function() {
+ name: computed('model', function() {
return this.get("q") + " - Cargo search";
- }.property('model'),
+ }),
- totalItems: function() {
+ totalItems: computed('model', function() {
return this.store.metadataFor('crate').total;
- }.property('model'),
+ })
});
diff --git a/app/helpers/date-long.js b/app/helpers/date-long.js
index 4206102fdb2..b0e957cd0b2 100644
--- a/app/helpers/date-long.js
+++ b/app/helpers/date-long.js
@@ -1,11 +1,8 @@
import Ember from 'ember';
+import moment from 'moment';
-function dateLong(value) {
+export function dateLong(value) {
return moment(value).format('LL');
}
-export {
- dateLong
-};
-
-export default Ember.Handlebars.makeBoundHelper(dateLong);
+export default Ember.Helper.helper(params => dateLong(params[0]));
diff --git a/app/helpers/date-small.js b/app/helpers/date-small.js
index 7f2c28fc011..7fe11bbdeb7 100644
--- a/app/helpers/date-small.js
+++ b/app/helpers/date-small.js
@@ -1,11 +1,8 @@
import Ember from 'ember';
+import moment from 'moment';
-function dateSmall(value) {
+export function dateSmall(value) {
return moment(value).format('ll');
}
-export {
- dateSmall
-};
-
-export default Ember.Handlebars.makeBoundHelper(dateSmall);
+export default Ember.Helper.helper(params => dateSmall(params[0]));
diff --git a/app/helpers/format-email.js b/app/helpers/format-email.js
index 41754ef7397..a958b10f187 100644
--- a/app/helpers/format-email.js
+++ b/app/helpers/format-email.js
@@ -2,7 +2,7 @@ import Ember from "ember";
var escape = Ember.Handlebars.Utils.escapeExpression;
-function formatEmail(email) {
+export function formatEmail(email) {
var formatted = email.match(/^(.*?)\s*(?:<(.*)>)?$/);
var ret = "";
@@ -15,9 +15,4 @@ function formatEmail(email) {
return ret.htmlSafe();
}
-
-export {
- formatEmail
-};
-
-export default Ember.Handlebars.makeBoundHelper(formatEmail);
+export default Ember.Helper.helper(params => formatEmail(params[0]));
diff --git a/app/helpers/format-num.js b/app/helpers/format-num.js
index 1c1c6301350..8ef3825d455 100644
--- a/app/helpers/format-num.js
+++ b/app/helpers/format-num.js
@@ -1,6 +1,6 @@
import Ember from 'ember';
-function formatNum(value) {
+export function formatNum(value) {
if (value === 0) { return "0"; }
var ret = "";
@@ -17,8 +17,4 @@ function formatNum(value) {
return ret;
}
-export {
- formatNum
-};
-
-export default Ember.Handlebars.makeBoundHelper(formatNum);
+export default Ember.Helper.helper(params => formatNum(params[0]));
diff --git a/app/helpers/format-req.js b/app/helpers/format-req.js
index a15e6a3c21c..187589c43f2 100644
--- a/app/helpers/format-req.js
+++ b/app/helpers/format-req.js
@@ -1,7 +1,6 @@
import Ember from "ember";
-function formatReq(req) {
+export default Ember.Helper.helper(function(params) {
+ let req = params[0];
return req === "*" ? "" : req;
-}
-
-export default Ember.Handlebars.makeBoundHelper(formatReq);
+});
diff --git a/app/helpers/from-now.js b/app/helpers/from-now.js
index 5363042ae93..cc9c52d507c 100644
--- a/app/helpers/from-now.js
+++ b/app/helpers/from-now.js
@@ -1,11 +1,7 @@
import Ember from 'ember';
+import moment from 'moment';
-function fromNow(value) {
+export default Ember.Helper.helper(function(params) {
+ let value = params[0];
return moment(value).fromNow();
-}
-
-export {
- fromNow
-};
-
-export default Ember.Handlebars.makeBoundHelper(fromNow);
+});
diff --git a/app/helpers/truncate-text.js b/app/helpers/truncate-text.js
index 98fa6de8907..a57efaf3cdd 100644
--- a/app/helpers/truncate-text.js
+++ b/app/helpers/truncate-text.js
@@ -1,15 +1,10 @@
import Ember from 'ember';
-function truncateText(value) {
+export default Ember.Helper.helper(function(params) {
+ let value = params[0];
if (!value) { return value; }
if (value.length > 200) {
return value.slice(0, 200) + ' ...';
}
return value;
-}
-
-export {
- truncateText
-};
-
-export default Ember.Handlebars.makeBoundHelper(truncateText);
+});
diff --git a/app/index.html b/app/index.html
index bbd93a99862..129f19b6003 100644
--- a/app/index.html
+++ b/app/index.html
@@ -7,7 +7,7 @@
- {{BASE_TAG}}
+ {{content-for 'head'}}
+
-
+
+ {{content-for 'body-footer'}}