Skip to content

Commit

Permalink
Merge pull request #59 from rokumatsumoto/like-design
Browse files Browse the repository at this point in the history
Add like button to the design page
  • Loading branch information
rokumatsumoto authored Dec 24, 2019
2 parents e741b9f + 53e09e8 commit fe43e60
Show file tree
Hide file tree
Showing 45 changed files with 507 additions and 58 deletions.
5 changes: 5 additions & 0 deletions app/assets/stylesheets/framework/buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
}
}

.btn-grayish-navy {
color: $white;
background-color: #525f7f;
}

.no-outline {

&:focus,
Expand Down
8 changes: 6 additions & 2 deletions app/assets/stylesheets/framework/common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,15 @@
}

.inline-list > li {
display: inline-block;
display: inline-block;

&:empty {
display: none;
}
}

.inline-list li:last-child {
margin-right: 0;
margin-right: 0;
}
.inline-list li a {
display: block;
Expand Down
14 changes: 14 additions & 0 deletions app/assets/stylesheets/pages/design.scss
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,20 @@ a.thumb{
display: table-cell;
vertical-align: top;
}

.actionbar {
display: flex;
align-items: flex-end;
margin-bottom: .5rem;
}

.actionbar-left {
float: left;
flex: 1;
}
.actionbar-right{
float: right;
}
}

.design-infos{
Expand Down
9 changes: 7 additions & 2 deletions app/controllers/designs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class DesignsController < ApplicationController
include AhoyActions

before_action :authenticate_user!, except: %i[show latest popular]
before_action :design, only: %i[show edit update destroy download]
before_action :design, only: %i[show edit update destroy download like]

def new
@design = Design.new
Expand All @@ -22,7 +22,8 @@ def show
fields: { blueprint: file_preview_fields })
.serialize

@page_views_count = Ahoy::Event.where_event('Viewed design', design_id: design.id).count
@page_views_count = Ahoy::Event.where_event(Ahoy::Event::VIEWED_DESIGN,
design_id: design.id).count

Designs::PageViews::AfterPageViewService.new(design, current_user, controller: self).execute
end
Expand Down Expand Up @@ -72,6 +73,10 @@ def download
render json: { url: url }, status: :ok
end

def like
Designs::Likes::AfterLikeService.new(design, current_user, controller: self).execute
end

def latest
@pagy, @designs = pagy(DesignsFinder.new(design_list_params).execute)
end
Expand Down
6 changes: 6 additions & 0 deletions app/helpers/designs_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ def fetch_popular_designs

JSON.parse(design_list)
end

def liked_design?(design_id)
return false unless current_user

Ahoy::Event.cached_any_events_for?(Ahoy::Event::LIKED_DESIGN, current_user, design_id: design_id)
end
end
66 changes: 66 additions & 0 deletions app/javascript/like_button/components/like_button.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<script>
import { mapActions, mapState } from 'vuex';
export default {
name: 'LikeButton',
props: {
likeCssClass: {
type: String,
required: true,
},
unlikeCssClass: {
type: String,
required: true,
},
likeText: {
type: String,
required: true,
},
unlikeText: {
type: String,
required: true,
},
likedStatus: {
type: Boolean,
required: true,
},
endpoint: {
type: String,
required: true,
},
},
computed: {
...mapState(['liked']),
buttonText() {
return this.liked ? this.unlikeText : this.likeText;
},
buttonCssClass() {
return this.liked ? this.unlikeCssClass : this.likeCssClass;
},
},
created() {
this.setLiked(this.likedStatus);
},
methods: {
...mapActions(['createNewLike', 'deleteLike', 'setLiked']),
actionButtonClicked() {
if (this.liked) {
return this.deleteLike({ endpoint: this.endpoint });
}
return this.createNewLike({ endpoint: this.endpoint });
},
},
};
</script>

<template>
<div>
<button :class="buttonCssClass" @click="actionButtonClicked">
<span>
<i class="fas fa-lg fa-heart"></i>
</span>
<span class="btn-inner--text">{{ buttonText }}</span>
</button>
</div>
</template>
49 changes: 49 additions & 0 deletions app/javascript/like_button/store/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import axios from 'lib/utils/axios_utils';
import eventHub from 'page_counters/components/event_hub';
import * as types from './mutation_types';

export const setLiked = ({ commit }, liked) => commit(types.SET_LIKED, liked);

export const receiveDeleteLikeError = ({ dispatch }, payload) => {
// TODO: post error
};

export const receiveDeleteLike = ({ dispatch }) => {
dispatch('setLiked', false);

eventHub.$emit('unlike');
};

export const deleteLike = ({ dispatch }, payload) => {
axios
.delete(payload.endpoint)
.then(response => {
dispatch('receiveDeleteLike');
})
.catch(error => {
const errorPayload = Object.assign(payload, { error });
dispatch('receiveDeleteLikeError', errorPayload);
});
};

export const receiveCreateLikeError = ({ dispatch }, payload) => {
// TODO: post error
};

export const receiveCreateLike = ({ dispatch }) => {
dispatch('setLiked', true);

eventHub.$emit('like');
};

export const createNewLike = ({ dispatch }, payload) => {
axios
.post(payload.endpoint)
.then(response => {
dispatch('receiveCreateLike');
})
.catch(error => {
const errorPayload = Object.assign(payload, { error });
dispatch('receiveCreateLikeError', errorPayload);
});
};
16 changes: 16 additions & 0 deletions app/javascript/like_button/store/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Vue from 'vue/dist/vue.esm';
import Vuex from 'vuex';
import * as actions from './actions';
import mutations from './mutations';
import state from './state';

Vue.use(Vuex);

export default function createStore() {
return new Vuex.Store({
actions,
mutations,
state: state(),
strict: process.env.NODE_ENV !== 'production',
});
};
1 change: 1 addition & 0 deletions app/javascript/like_button/store/mutation_types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const SET_LIKED = 'SET_LIKED';
7 changes: 7 additions & 0 deletions app/javascript/like_button/store/mutations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as types from './mutation_types';

export default {
[types.SET_LIKED](state, liked) {
Object.assign(state, { liked });
},
};
3 changes: 3 additions & 0 deletions app/javascript/like_button/store/state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default () => ({
liked: false,
});
17 changes: 3 additions & 14 deletions app/javascript/page_counters/components/downloads_counter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,6 @@ import eventHub from './event_hub';
export default {
name: 'DownloadsCounter',
mixins: [counterMixin],
props: {
min: {
type: Number,
required: true,
},
},
computed: {
showCounter() {
return this.count >= this.min;
},
},
created() {
eventHub.$on('download', this.incrementCounter);
},
Expand All @@ -27,10 +16,10 @@ export default {
...mapActions(['setDownloadsCount']),
incrementCounter() {
let downloadsCount = this.count;
this.setDownloadsCount(downloadsCount += 1);
this.setDownloadsCount((downloadsCount += 1));
},
}
}
},
};
</script>
<template>
<span v-if="showCounter" data-toggle="tooltip" data-placement="bottom" :title="counterTooltip">
Expand Down
35 changes: 35 additions & 0 deletions app/javascript/page_counters/components/likes_counter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script>
import counterMixin from 'page_counters/mixins/counter_mixin';
import { mapActions } from 'vuex';
import eventHub from './event_hub';
export default {
name: 'LikesCounter',
mixins: [counterMixin],
created() {
eventHub.$on('like', this.incrementCounter);
eventHub.$on('unlike', this.decrementCounter);
},
beforeDestroy() {
eventHub.$off('like', this.incrementCounter);
eventHub.$off('unlike', this.decrementCounter);
},
methods: {
...mapActions(['setLikesCount']),
incrementCounter() {
let likesCount = this.count;
this.setLikesCount((likesCount += 1));
},
decrementCounter() {
let likesCount = this.count;
this.setLikesCount((likesCount -= 1));
},
},
};
</script>
<template>
<span v-if="showCounter" data-toggle="tooltip" data-placement="bottom" :title="counterTooltip">
<i class="fas fa-heart mr-1"></i>
{{ localeCount }}
</span>
</template>
Loading

0 comments on commit fe43e60

Please sign in to comment.