Add metadata block in protocol repository [SCI-6869]

This commit is contained in:
Anton 2022-06-06 13:56:22 +02:00
parent a8fe943658
commit e86a0610b2
7 changed files with 169 additions and 19 deletions

View file

@ -182,7 +182,7 @@ class ProtocolsController < ApplicationController
if @protocol.update_keywords(params[:keywords])
format.json do
log_activity(:edit_keywords_in_protocol_repository, nil, protocol: @protocol.id)
render json: { status: :ok }
render json: @protocol, serializer: ProtocolSerializer, user: current_user
end
else
format.json { render json: {}, status: :unprocessable_entity }
@ -193,7 +193,7 @@ class ProtocolsController < ApplicationController
def update_authors
if @protocol.update(authors: params.require(:protocol)[:authors])
log_activity(:edit_authors_in_protocol_repository, nil, protocol: @protocol.id)
render json: {}, status: :ok
render json: @protocol, serializer: ProtocolSerializer, user: current_user
else
render json: @protocol.errors, status: :unprocessable_entity
end

View file

@ -26,7 +26,7 @@
<div class="protocol-description">
<div class="protocol-name">
<InlineEdit
v-if="urls.update_protocol_url"
v-if="urls.update_protocol_name_url"
:value="protocol.attributes.name"
:characterLimit="255"
:placeholder="i18n.t('my_modules.protocols.protocol_status_bar.enter_name')"
@ -38,12 +38,13 @@
{{ protocol.attributes.name }}
</span>
</div>
<ProtocolMetadata v-if="protocol.attributes" :protocol="protocol" @update="updateProtocol"/>
<Tinymce
v-if="urls.update_protocol_url"
v-if="urls.update_protocol_description_url"
:value="protocol.attributes.description"
:value_html="protocol.attributes.description_view"
:placeholder="i18n.t('my_modules.protocols.protocol_status_bar.empty_description_edit_label')"
:updateUrl="urls.update_protocol"
:updateUrl="urls.update_protocol_description_url"
:objectType="'Protocol'"
:objectId="parseInt(protocol.id)"
:fieldName="'protocol[description]'"
@ -54,6 +55,10 @@
</div>
</div>
<div class="protocol-step-actions">
<a v-if="urls.add_step_url && protocol.attributes.in_repository" class="btn btn-primary" @click="addStep(steps.length)">
<span class="fas fa-plus" aria-hidden="true"></span>
<span>{{ i18n.t("protocols.steps.new_step") }}</span>
</a>
<a v-if="urls.reorder_steps_url" class="btn btn-default" data-toggle="modal" @click="startStepReorder">
<span class="fas fa-arrows-alt-v" aria-hidden="true"></span>
<span>{{ i18n.t("protocols.reorder_steps.button") }}</span>
@ -95,6 +100,7 @@
<script>
import InlineEdit from 'vue/shared/inline_edit.vue'
import Step from 'vue/protocol/step'
import ProtocolMetadata from 'vue/protocol/protocolMetadata'
import ProtocolOptions from 'vue/protocol/protocolOptions'
import ProtocolModals from 'vue/protocol/modals'
import Tinymce from 'vue/shared/tinymce.vue'
@ -110,7 +116,7 @@
required: true
}
},
components: { Step, InlineEdit, ProtocolModals, ProtocolOptions, Tinymce, ReorderableItemsModal },
components: { Step, InlineEdit, ProtocolModals, ProtocolOptions, Tinymce, ReorderableItemsModal, ProtocolMetadata },
mixins: [UtilsMixin],
computed: {
inRepository() {
@ -143,12 +149,15 @@
// legacy method from app/assets/javascripts/my_modules/protocols.js
refreshProtocolStatusBar();
},
updateProtocol(attributes) {
this.protocol.attributes = attributes
},
updateName(newName) {
this.protocol.attributes.name = newName;
this.refreshProtocolStatus();
$.ajax({
type: 'PATCH',
url: this.urls.update_protocol_url,
url: this.urls.update_protocol_name_url,
data: { protocol: { name: newName } }
});
},

View file

@ -0,0 +1,88 @@
<template>
<div class="protocol-metadata">
<div class="data-block">
<span class="fas block-icon fa-calendar-alt"></span>
{{ i18n.t("protocols.header.created_at") }}
{{ protocol.attributes.created_at_formatted }}
</div>
<div class="data-block">
<span class="fas block-icon fa-user"></span>
{{ i18n.t("protocols.header.added_by") }}
<img :src="protocol.attributes.added_by.avatar"/>
{{ protocol.attributes.added_by.name }}
</div>
<div class="data-block">
<span class="fas block-icon fa-edit"></span>
{{ i18n.t("protocols.header.updated_at") }}
{{ protocol.attributes.updated_at_formatted }}
</div>
<div class="data-block">
<span class="fas block-icon fa-graduation-cap"></span>
{{ i18n.t("protocols.header.authors") }}
<InlineEdit
v-if="protocol.attributes.urls.update_protocol_authors_url"
:value="protocol.attributes.authors"
:placeholder="i18n.t('protocols.header.no_authors')"
:allowBlank="true"
:attributeName="`${i18n.t('Protocol')} ${i18n.t('authors')}`"
@update="updateAuthors"
/>
<span v-else>
{{ protocol.attributes.authors }}
</span>
</div>
<div class="data-block">
<span class="fas block-icon fa-font"></span>
{{ i18n.t("protocols.header.keywords") }}
<DropdownSelector
:inputTagMode="true"
:options="this.protocol.attributes.keywords"
:selectorId="'keywordsSelector'"
:singleSelect="false"
:closeOnSelect="false"
:noEmptyOption="false"
:selectAppearance="'tag'"
:viewMode="protocol.attributes.urls.update_protocol_keywords_url == null"
@dropdown:changed="updateKeywords"
/>
</div>
</div>
</template>
<script>
import InlineEdit from 'vue/shared/inline_edit.vue'
import DropdownSelector from 'vue/shared/dropdown_selector.vue'
export default {
name: 'ProtocolMetadata',
components: { InlineEdit, DropdownSelector },
props: {
protocol: {
type: Object,
required: true
},
},
methods: {
updateAuthors(authors) {
$.ajax({
type: 'PATCH',
url: this.protocol.attributes.urls.update_protocol_authors_url,
data: { protocol: { authors: authors } },
success: (result) => {
this.$emit('update', result.data.attributes)
}
});
},
updateKeywords(keywords) {
$.ajax({
type: 'PATCH',
url: this.protocol.attributes.urls.update_protocol_keywords_url,
data: { keywords: keywords },
success: (result) => {
this.$emit('update', result.data.attributes)
}
});
}
}
}
</script>

View file

@ -6,6 +6,7 @@
:data-select-multiple-all-selected="dataSelectMultipleAllSelected"
:data-select-multiple-name="dataSelectMultipleName"
:data-placeholder="placeholder"
:data-view-mode="viewMode"
>
<template v-if="groupSelector">
<optgroup v-for="group in this.options" :label="group.label" :key="group.label">
@ -92,11 +93,20 @@
optionLabel: {
type: Function
},
inputTagMode: {
type: Boolean,
default: false
},
viewMode: {
type: Boolean,
default: false
},
onChange: Function
},
mounted: function() {
dropdownSelector.init(`#${this.selectorId}`, {
inputTagMode: this.inputTagMode,
optionClass: this.optionClass,
optionLabel: this.optionLabel,
noEmptyOption: this.noEmptyOption,

View file

@ -6,12 +6,32 @@ class ProtocolSerializer < ActiveModel::Serializer
include ApplicationHelper
include ActionView::Helpers::TextHelper
attributes :name, :id, :urls, :description, :description_view, :updated_at, :in_repository
attributes :name, :id, :urls, :description, :description_view, :updated_at, :in_repository,
:created_at_formatted, :updated_at_formatted, :added_by, :authors, :keywords
def updated_at
object.updated_at.to_i
end
def added_by
{
avatar: object.added_by.avatar_url(:icon_small),
name: object.added_by.full_name
}
end
def created_at_formatted
I18n.l(object.created_at, format: :full)
end
def updated_at_formatted
I18n.l(object.updated_at, format: :full)
end
def keywords
object.protocol_keywords.map{ |i| { label: i.name, value: i.name } }
end
def description_view
@user = @instance_options[:user]
custom_auto_link(object.tinymce_render('description'),
@ -33,7 +53,10 @@ class ProtocolSerializer < ActiveModel::Serializer
steps_url: steps_url,
reorder_steps_url: reorder_steps_url,
add_step_url: add_step_url,
update_protocol_url: update_protocol_url
update_protocol_name_url: update_protocol_name_url,
update_protocol_description_url: update_protocol_description_url,
update_protocol_authors_url: update_protocol_authors_url,
update_protocol_keywords_url: update_protocol_keywords_url
}
end
@ -85,11 +108,31 @@ class ProtocolSerializer < ActiveModel::Serializer
protocol_steps_path(protocol_id: object.id)
end
def update_protocol_url
def update_protocol_name_url
if in_repository && can_manage_protocol_in_repository?(object)
protocol_path(@protocol)
name_protocol_path(object)
elsif can_manage_protocol_in_module?(object)
protocol_my_module_path(object.my_module)
end
end
def update_protocol_description_url
if in_repository && can_manage_protocol_in_repository?(object)
description_protocol_path(object)
elsif can_manage_protocol_in_module?(object)
protocol_my_module_path(object.my_module)
end
end
def update_protocol_authors_url
if in_repository && can_manage_protocol_in_repository?(object)
authors_protocol_path(object)
end
end
def update_protocol_keywords_url
if in_repository && can_manage_protocol_in_repository?(object)
keywords_protocol_path(object)
end
end
end

View file

@ -2353,11 +2353,11 @@ en:
row_success: "Exported"
row_failed: "Failed"
header:
created_at: "Created at"
updated_at: "Last modified at"
added_by: "Added by"
keywords: "Keywords"
authors: "Authors"
created_at: "Created at:"
updated_at: "Last modified at:"
added_by: "Added by:"
keywords: "Keywords:"
authors: "Authors:"
no_authors: "No authors"
description: "Description"
no_description: "No description"

View file

@ -509,7 +509,7 @@ Rails.application.routes.draw do
get 'result_tables/:id/download' => 'result_tables#download',
as: :result_table_download
resources :protocols, only: %i(index show edit create) do
resources :protocols, only: %i(index show edit create update) do
resources :steps, only: [:new, :create] do
post :reorder, on: :collection
end
@ -520,8 +520,8 @@ Rails.application.routes.draw do
to: 'protocols#linked_children_datatable'
get 'preview', to: 'protocols#preview'
patch 'description', to: 'protocols#update_description'
put 'name', to: 'protocols#update_name'
put 'authors', to: 'protocols#update_authors'
patch 'name', to: 'protocols#update_name'
patch 'authors', to: 'protocols#update_authors'
patch 'keywords', to: 'protocols#update_keywords'
post 'clone', to: 'protocols#clone'
get 'unlink_modal', to: 'protocols#unlink_modal'