Skip to content

Favorite crate owner #1769

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
16 changes: 16 additions & 0 deletions app/adapters/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,20 @@ export default ApplicationAdapter.extend({
let url = this.urlForFindRecord(query.user_id, 'user');
return this.ajax(url, 'GET');
},

favorite(id) {
return this.ajax(this.urlForFavoriteAction(id), 'PUT');
},

unfavorite(id) {
return this.ajax(this.urlForFavoriteAction(id), 'DELETE');
},

urlForFavoriteAction(id) {
return `${this.buildURL('user', id)}/favorite`;
},

favoriteUsers(id) {
return this.ajax(`${this.buildURL('user', id)}/favorite_users`, 'GET');
},
});
18 changes: 18 additions & 0 deletions app/controllers/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default Controller.extend({
this.myFollowing = A();
this.myFeed = A();
this.myStats = 0;
this.favoriteUsers = [];
},

visibleCrates: computed('myCrates.[]', function() {
Expand All @@ -33,10 +34,18 @@ export default Controller.extend({
return this.get('myCrates.length') > TO_SHOW;
}),

visibleFavorites: computed('favoriteUsers', function() {
return this.get('favoriteUsers').slice(0, TO_SHOW);
}),

hasMoreFollowing: computed('myFollowing.[]', function() {
return this.get('myFollowing.length') > TO_SHOW;
}),

hasMoreFavorites: computed('favoriteUsers', function() {
return this.get('favoriteUsers.length') > TO_SHOW;
}),

actions: {
async loadMore() {
this.set('loadingMore', true);
Expand All @@ -52,5 +61,14 @@ export default Controller.extend({
this.set('loadingMore', false);
}
},

unfavoriteUser: function(user) {
this.store
.adapterFor('user')
.unfavorite(user.id)
.then(() => {
this.get('favoriteUsers').users.removeObject(user);
});
},
},
});
14 changes: 14 additions & 0 deletions app/controllers/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,18 @@ export default Controller.extend(PaginationMixin, {
return 'Alphabetical';
}
}),

fetchingFavorite: false,
favorited: false,

actions: {
toggleFavorite() {
this.set('fetchingFavorite', true);

let owner = this.get('user');
let op = this.toggleProperty('favorited') ? owner.favorite() : owner.unfavorite();

return op.finally(() => this.set('fetchingFavorite', false));
},
},
});
12 changes: 12 additions & 0 deletions app/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,16 @@ export default DS.Model.extend({
stats() {
return this.store.adapterFor('user').stats(this.id);
},

favorite() {
return this.store.adapterFor('user').favorite(this.get('id'));
},

unfavorite() {
return this.store.adapterFor('user').unfavorite(this.get('id'));
},

favoriteUsers() {
return this.store.adapterFor('user').favoriteUsers(this.get('id'));
},
});
13 changes: 12 additions & 1 deletion app/routes/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default Route.extend(AuthenticatedRoute, {
controller.set('myCrates', this.get('data.myCrates'));
controller.set('myFollowing', this.get('data.myFollowing'));
controller.set('myStats', this.get('data.myStats'));
controller.set('favoriteUsers', this.get('data.favoriteUsers'));

if (!controller.loadingMore) {
controller.set('myFeed', A());
Expand All @@ -33,6 +34,16 @@ export default Route.extend(AuthenticatedRoute, {

let myStats = user.stats();

this.set('data', await RSVP.hash({ myCrates, myFollowing, myStats }));
let favoriteUsers = user.favoriteUsers();

this.set(
'data',
await RSVP.hash({
myCrates,
myFollowing,
myStats,
favoriteUsers,
}),
);
},
});
16 changes: 16 additions & 0 deletions app/routes/user.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import RSVP from 'rsvp';
import ajax from 'ic-ajax';

export default Route.extend({
flashMessages: service(),
Expand Down Expand Up @@ -28,4 +29,19 @@ export default Route.extend({
},
);
},

setupController(controller, model) {
this._super(controller, model);

controller.set('fetchingFeed', true);
controller.set('crates', this.get('data.crates'));
controller.set('user', model.user);
controller.set('allowFavorting', this.session.get('currentUser') !== model.user);

if (controller.get('allowFavoriting')) {
ajax(`/api/v1/users/${model.user.id}/favorited`)
.then(d => controller.set('favorited', d.favorited))
.finally(() => controller.set('fetchingFavorite', false));
}
},
});
82 changes: 82 additions & 0 deletions app/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,88 @@ h1 {
}
}

img {
&.right-pag, &.left-pag {
width: 29px;
height: 29px;
}

&.right-arrow, &.right-arrow-all-versions {
width: 20px;
height: 20px;
}

&.package, &.crate {
width: 32px;
height: 33px;
}

&.my-packages {
width:15px;
height: 17px;
}

&.sort {
width: 11px;
height: 12px;
}

&.flag {
width: 13px;
height: 15px;
}

&.dashboard {
width: 33px;
height: 33px;
}

&.lock {
width: 10px;
height: 13px;
}

&.download-clear-back {
width: 14px;
height: 17px;
}

&.button-download {
width: 14px;
height: 17px;
}

&.download {
width: 32px;
height: 33px;
}

&.following {
width: 15px;
height: 15px;
}

&.favorite {
width: 20px;
height: 20px;
}

&.gear {
width: 32px;
height: 32px;
}

&.circle-with-i {
width: 32px;
height: 32px;
}

&.latest-updates {
width: 14px;
height: 14px;
}
}

.arrow-in-list svg {
background: #fff;
}
Expand Down
25 changes: 24 additions & 1 deletion app/styles/me.scss
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
@include order(1);
margin-right: 0;
}
#my-crates, #my-following { margin: 0; }
#my-crates, #my-following, #my-favorite-users { margin: 0; }
}
}

Expand Down Expand Up @@ -283,3 +283,26 @@
padding: 0px 10px 10px 20px;
}
}

#my-favorite-users {
.users {
.user-item {
padding: 13px 10px;
.user-name {
margin-left: 5px;
}
.user-options {
padding-left: 5px;
opacity: 0;
.unfavorite-user {
width: 10px;
height: 10px;
}
}

&:hover .user-options{
opacity: 1;
}
}
}
}
16 changes: 16 additions & 0 deletions app/templates/components/favorite-users.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<ul class="users">
{{#each users as |user|}}
<li>
{{#link-to 'user' user.login class="user-item"}}
<span>
{{user-avatar user=user size='medium-small'}}
<span class="user-name">{{user.name}}</span>
</span>

<div class='right user-options'>
<img class="unfavorite-user" src="/assets/delete.png" {{ action (action unfavoriteUser user) on="click" bubbles=false}}/>
</div>
{{/link-to}}
</li>
{{/each}}
</ul>
9 changes: 9 additions & 0 deletions app/templates/dashboard.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@
</div>
{{crate-downloads-list crates=visibleFollowing}}
</div>
<div id='my-favorite-users'>
<div class='header'>
<h2>
<img class="favorite" src="/assets/favorite.png"/>
Favorite Users
</h2>
</div>
{{favorite-users users=favoriteUsers.users unfavoriteUser=(action "unfavoriteUser")}}
</div>
</div>

<div id='my-feed'>
Expand Down
35 changes: 27 additions & 8 deletions app/templates/user.hbs
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
<div id='crates-heading' data-test-heading>
{{user-avatar user=model.user size='medium' data-test-avatar=true}}
<h1 data-test-username>
{{ model.user.login }}
</h1>
{{#user-link user=model.user data-test-user-link=true}}
<img alt="GitHub profile" title="GitHub profile" src="/assets/GitHub-Mark.svg">
{{/user-link}}
<div id='crates-heading'>
<div class="wide">
<div class='info'>
{{user-avatar user=model.user size='medium' data-test-avatar=true}}
<h1>
{{ model.user.login }}
</h1>
{{#user-link user=model.user}}
<img alt="GitHub profile" title="GitHub profile" src="/assets/GitHub-Mark.svg">
{{/user-link}}
</div>
<div class='right'>
{{#if allowFavorting}}
<button class='tan-button' {{action 'toggleFavorite' this}}>
{{#if fetchingFavorite}}
<img src="/assets/ajax-loader.gif"/>
{{else}}
{{#if favorited}}
Unfavorite
{{else}}
Favorite
{{/if}}
{{/if}}
</button>
{{/if}}
</div>
</div>
</div>

<div id='user-profile'>
Expand Down
1 change: 1 addition & 0 deletions migrations/20170613160003_create_favorite_users/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE favorite_users;
9 changes: 9 additions & 0 deletions migrations/20170613160003_create_favorite_users/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE favorite_users (
user_id INTEGER NOT NULL,
target_id INTEGER NOT NULL,
CONSTRAINT favorites_pkey PRIMARY KEY (user_id, target_id),
CONSTRAINT fk_favorites_user_id FOREIGN KEY (user_id)
REFERENCES users (id),
CONSTRAINT fk_favorites_target_id FOREIGN KEY (target_id)
REFERENCES users (id)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP INDEX index_favorites_user_id;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE INDEX index_favorites_user_id ON favorite_users (user_id);
Loading