mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-08 06:04:35 +08:00
Add favorite to project table [SCI-11800]
This commit is contained in:
parent
72f549f00b
commit
fe676f8996
7 changed files with 144 additions and 2 deletions
|
@ -27,6 +27,7 @@
|
|||
@access="access"
|
||||
@updateDueDate="updateDueDate"
|
||||
@updateStartDate="updateStartDate"
|
||||
@updateFavorite="updateFavorite"
|
||||
>
|
||||
<template #card="data">
|
||||
<ProjectCard :params="data.params" :dtComponent="data.dtComponent" ></ProjectCard>
|
||||
|
@ -93,6 +94,7 @@ import NewFolderModal from './modals/new_folder.vue';
|
|||
import MoveModal from './modals/move.vue';
|
||||
import AccessModal from '../shared/access_modal/modal.vue';
|
||||
import ExportLimitExceededModal from './modals/export_limit_exceeded_modal.vue';
|
||||
import FavoriteRenderer from '../shared/datatable/renderers/favorite.vue';
|
||||
|
||||
export default {
|
||||
name: 'ProjectsList',
|
||||
|
@ -112,7 +114,8 @@ export default {
|
|||
DescriptionRenderer,
|
||||
DescriptionModal,
|
||||
StatusRenderer,
|
||||
SuperviserRenderer
|
||||
SuperviserRenderer,
|
||||
FavoriteRenderer
|
||||
},
|
||||
props: {
|
||||
dataSource: { type: String, required: true },
|
||||
|
@ -158,6 +161,17 @@ export default {
|
|||
sortable: true,
|
||||
cellRenderer: 'NameRenderer'
|
||||
},
|
||||
{
|
||||
field: 'favorite',
|
||||
headerComponentParams: {
|
||||
html: '<div class="sn-icon sn-icon-star-filled"></div>'
|
||||
},
|
||||
headerName: this.i18n.t('projects.index.favorite'),
|
||||
sortable: true,
|
||||
cellRenderer: FavoriteRenderer,
|
||||
minWidth: 80,
|
||||
notSelectable: true
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
headerName: this.i18n.t('projects.index.card.id'),
|
||||
|
@ -365,6 +379,12 @@ export default {
|
|||
this.updateTable();
|
||||
});
|
||||
},
|
||||
updateFavorite(value, params) {
|
||||
const url = value ? params.data.urls.favorite : params.data.urls.unfavorite;
|
||||
axios.post(url).then(() => {
|
||||
this.updateTable();
|
||||
});
|
||||
},
|
||||
showDescription(_e, project) {
|
||||
[this.descriptionModalObject] = project;
|
||||
},
|
||||
|
|
43
app/javascript/vue/shared/datatable/renderers/favorite.vue
Normal file
43
app/javascript/vue/shared/datatable/renderers/favorite.vue
Normal file
|
@ -0,0 +1,43 @@
|
|||
<template>
|
||||
<div v-if="hasFavorite">
|
||||
<button @click="updateFavorite(!favorite)"
|
||||
class="flex justify-center items-center w-full h-9 bg-transparent border-none cursor-pointer">
|
||||
<div v-if="favorite" class="sn-icon sn-icon-star-filled text-sn-alert-brittlebush"></div>
|
||||
<div v-else @mouseover="hovered = true"
|
||||
@mouseleave="hovered = false">
|
||||
<div class="text-sn-grey-500 sn-icon" :class="{ 'sn-icon-star-filled': hovered, 'sn-icon-star': !hovered }"></div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'favoriteRenderer',
|
||||
props: {
|
||||
params: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
favorite: false,
|
||||
hovered: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.favorite = this.params.data.favorite;
|
||||
},
|
||||
computed: {
|
||||
hasFavorite() {
|
||||
return this.params.data.favorite !== null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateFavorite(value) {
|
||||
this.params.dtComponent.$emit('updateFavorite', value, this.params);
|
||||
this.favorite = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -77,6 +77,7 @@ module UserAssignments
|
|||
assigned_by: @assigned_by
|
||||
)
|
||||
else
|
||||
object.favorites.where(user: @user).destroy_all if object.respond_to?(:favorites)
|
||||
user_assignment.destroy!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Lists
|
|||
|
||||
attributes :name, :code, :created_at, :archived_on, :users, :urls, :folder, :hidden,
|
||||
:folder_info, :default_public_user_role_id, :team, :top_level_assignable, :supervised_by,
|
||||
:comments, :updated_at, :permissions, :due_date_cell, :start_on_cell, :description, :status,
|
||||
:comments, :updated_at, :permissions, :due_date_cell, :start_on_cell, :description, :status, :favorite,
|
||||
def team
|
||||
object.team.name
|
||||
end
|
||||
|
@ -17,6 +17,10 @@ module Lists
|
|||
!project?
|
||||
end
|
||||
|
||||
def favorite
|
||||
object.favorite if project?
|
||||
end
|
||||
|
||||
def top_level_assignable
|
||||
project?
|
||||
end
|
||||
|
|
|
@ -148,6 +148,10 @@ module Lists
|
|||
@records = @records.sort_by { |object| project_comments_count(object) }
|
||||
when 'comments_DESC'
|
||||
@records = @records.sort_by { |object| project_comments_count(object) }.reverse!
|
||||
when 'favorite_ASC'
|
||||
@records = @records.sort_by { |object| project_favorites(object) }
|
||||
when 'favorite_DESC'
|
||||
@records = @records.sort_by { |object| project_favorites(object) }.reverse!
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -163,6 +167,14 @@ module Lists
|
|||
project?(object) ? object.users.count : -1
|
||||
end
|
||||
|
||||
def project_favorites(object)
|
||||
if project?(object)
|
||||
object.favorite ? 1 : 0
|
||||
else
|
||||
-1
|
||||
end
|
||||
end
|
||||
|
||||
def project?(object)
|
||||
object.instance_of?(Project)
|
||||
end
|
||||
|
|
|
@ -655,6 +655,7 @@ en:
|
|||
add_start_date: "Add start date"
|
||||
no_start_date: "No start date"
|
||||
add_description: 'Add description'
|
||||
favorite: 'Favorites'
|
||||
status:
|
||||
not_started: "Not started"
|
||||
started: "In progress"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateFavorites < ActiveRecord::Migration[7.0]
|
||||
STATE_NAMES = %w(ProjectList_active_state ProjectList_archived_state ExperimentList_active_state
|
||||
ExperimentList_archived_state MyModuleList_active_state MyModuleList_archived_state).freeze
|
||||
def change
|
||||
create_table :favorites do |t|
|
||||
t.references :user, null: false, foreign_key: true
|
||||
|
@ -16,5 +18,64 @@ class CreateFavorites < ActiveRecord::Migration[7.0]
|
|||
unique: true,
|
||||
name: :index_favorites_on_user_and_item_and_team
|
||||
)
|
||||
|
||||
reversible do |dir|
|
||||
dir.up do
|
||||
User.find_each do |user|
|
||||
update = false
|
||||
STATE_NAMES.each do |state_name|
|
||||
state = user.settings.dig(state_name, 'columnsState')
|
||||
next if state.blank?
|
||||
|
||||
update = true
|
||||
|
||||
# get number of pinned columns
|
||||
pinned_items_count = state.count { |el| el['pinned'].present? }
|
||||
|
||||
# update position of columns if they are not pinned
|
||||
state.each do |el|
|
||||
el['position'] += 1 if el['pinned'].blank? && el['position'].present?
|
||||
end
|
||||
|
||||
# create new state of favorite column
|
||||
new_element = {
|
||||
colId: 'favorite',
|
||||
hide: false,
|
||||
pinned: nil
|
||||
}
|
||||
|
||||
# add only position if other columns have positions. Position only get columns for which user at least once change settings
|
||||
new_element[:position] = pinned_items_count if state.dig(0, 'position').present?
|
||||
state.insert(pinned_items_count, new_element)
|
||||
end
|
||||
user.save! if update
|
||||
end
|
||||
end
|
||||
|
||||
dir.down do
|
||||
User.find_each do |user|
|
||||
update = false
|
||||
STATE_NAMES.each do |state_name|
|
||||
state = user.settings.dig(state_name, 'columnsState')
|
||||
next if state.blank?
|
||||
|
||||
update = true
|
||||
|
||||
favorite = state.find { |el| el['colId'] == 'favorite' }
|
||||
|
||||
next unless favorite
|
||||
|
||||
state.reject! { |el| el['colId'] == 'favorite' }
|
||||
|
||||
next if favorite['position'].blank?
|
||||
|
||||
state.each do |el|
|
||||
el['position'] -= 1 if el['position'].present? && el['position'] > favorite['position']
|
||||
end
|
||||
end
|
||||
user.save! if update
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue