mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-11-11 17:00:41 +08:00
Merge pull request #4755 from aignatov-bio/ai-sci-7590-update-protocol-screen-draft
Update protocol view screen [SCI-7590][SCI-7617]
This commit is contained in:
commit
65bf9b2511
9 changed files with 299 additions and 136 deletions
|
|
@ -9,38 +9,96 @@
|
||||||
margin: 0 -16px;
|
margin: 0 -16px;
|
||||||
min-height: calc(100vh - var(--navbar-height));
|
min-height: calc(100vh - var(--navbar-height));
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 36px 10px 10px;
|
padding: 0 0 10px;
|
||||||
width: calc(100% + 31px);
|
width: calc(100% + 31px);
|
||||||
|
|
||||||
|
.content-header {
|
||||||
|
padding: 0 2em;
|
||||||
|
}
|
||||||
|
|
||||||
.protocol-position-container {
|
.protocol-position-container {
|
||||||
background-color: $color-white;
|
background-color: $color-white;
|
||||||
box-shadow: $flyout-shadow;
|
box-shadow: $flyout-shadow;
|
||||||
margin: 0 auto;
|
margin: 20px auto;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
padding: 10px 10px 10px 26px;
|
padding: 10px 10px 10px 26px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.protocol-section {
|
||||||
|
margin: 16px 0 16px -20px;
|
||||||
|
|
||||||
|
&.protocol-steps-section {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.protocol-section-caret {
|
||||||
|
color: $color-volcano;
|
||||||
|
display: inline-block;
|
||||||
|
padding: .5em;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
.fas {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.collapsed) .fas {
|
||||||
|
@include rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.protocol-section-title {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.protocol-code {
|
||||||
|
color: $color-volcano;
|
||||||
|
margin-left: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.protocol-section-header {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.actions-block {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.caret {
|
||||||
|
margin-left: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.protocol-details {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.protocol-metadata {
|
.protocol-metadata {
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
|
|
||||||
|
.data-block {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.authors-data {
|
.authors-data {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-top: -12px;
|
||||||
|
|
||||||
.authors-list {
|
.authors-list {
|
||||||
flex-basis: calc(100% - 90px);
|
flex-basis: calc(100% - 90px);
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin-left: .75em;
|
margin-left: .75em;
|
||||||
|
line-height: 32px;
|
||||||
&:hover:not(.editing) {
|
|
||||||
.sci-inline-edit__content {
|
|
||||||
border: $border-focus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sci-inline-edit__content {
|
|
||||||
padding-top: .35em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
@ -51,6 +109,7 @@
|
||||||
.keywords-data {
|
.keywords-data {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-top: -12px;
|
||||||
|
|
||||||
.keywords-list {
|
.keywords-list {
|
||||||
flex-basis: calc(100% - 90px);
|
flex-basis: calc(100% - 90px);
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ class ProtocolsController < ApplicationController
|
||||||
only: %i(protocolsio_import_create protocolsio_import_save)
|
only: %i(protocolsio_import_create protocolsio_import_save)
|
||||||
|
|
||||||
before_action :set_importer, only: %i(load_from_file import)
|
before_action :set_importer, only: %i(load_from_file import)
|
||||||
|
before_action :set_inline_name_editing, only: :show
|
||||||
|
|
||||||
layout 'fluid'
|
layout 'fluid'
|
||||||
|
|
||||||
|
|
@ -1103,6 +1104,18 @@ class ProtocolsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_inline_name_editing
|
||||||
|
return unless can_manage_protocol_in_repository?(@protocol)
|
||||||
|
|
||||||
|
@inline_editable_title_config = {
|
||||||
|
name: 'title',
|
||||||
|
params_group: 'protocol',
|
||||||
|
item_id: @protocol.id,
|
||||||
|
field_to_udpate: 'name',
|
||||||
|
path_to_update: name_protocol_path(@protocol)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def load_team_and_type
|
def load_team_and_type
|
||||||
@current_team = current_team
|
@current_team = current_team
|
||||||
# :public, :private or :archive
|
# :public, :private or :archive
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-if="protocol.id" id="protocol-content" class="protocol-content collapse in" aria-expanded="true">
|
<div v-if="protocol.id" id="protocol-content" class="protocol-content collapse in" aria-expanded="true">
|
||||||
<div class="protocol-description">
|
<div class="protocol-description">
|
||||||
<div class="protocol-name">
|
<div class="protocol-name" v-if="!inRepository">
|
||||||
<InlineEdit
|
<InlineEdit
|
||||||
v-if="urls.update_protocol_name_url"
|
v-if="urls.update_protocol_name_url"
|
||||||
:value="protocol.attributes.name"
|
:value="protocol.attributes.name"
|
||||||
|
|
@ -48,6 +48,20 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<ProtocolMetadata v-if="protocol.attributes && protocol.attributes.in_repository" :protocol="protocol" @update="updateProtocol"/>
|
<ProtocolMetadata v-if="protocol.attributes && protocol.attributes.in_repository" :protocol="protocol" @update="updateProtocol"/>
|
||||||
|
<div :class="inRepository ? 'protocol-section protocol-information' : ''">
|
||||||
|
<div v-if="inRepository" id="protocol-description" class="protocol-section-header">
|
||||||
|
<div class="protocol-description-container">
|
||||||
|
<a class="protocol-section-caret" role="button" data-toggle="collapse" href="#protocol-description-container" aria-expanded="false" aria-controls="protocol-description-container">
|
||||||
|
<i class="fas fa-caret-right"></i>
|
||||||
|
<span id="protocolDescriptionLabel" class="protocol-section-title">
|
||||||
|
<h2>
|
||||||
|
{{ i18n.t("protocols.header.protocol_description") }}
|
||||||
|
</h2>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="protocol-description-container" :class=" inRepository ? 'protocol-description collapse in' : ''" >
|
||||||
<div v-if="urls.update_protocol_description_url">
|
<div v-if="urls.update_protocol_description_url">
|
||||||
<Tinymce
|
<Tinymce
|
||||||
:value="protocol.attributes.description"
|
:value="protocol.attributes.description"
|
||||||
|
|
@ -67,10 +81,22 @@
|
||||||
{{ i18n.t("protocols.no_text_placeholder") }}
|
{{ i18n.t("protocols.no_text_placeholder") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a v-if="urls.add_step_url && protocol.attributes.in_repository" class="btn btn-primary repository-new-step" @click="addStep(steps.length)">
|
</div>
|
||||||
<span class="fas fa-plus" aria-hidden="true"></span>
|
</div>
|
||||||
<span>{{ i18n.t("protocols.steps.new_step") }}</span>
|
<div :class="inRepository ? 'protocol-section protocol-steps-section protocol-information' : ''">
|
||||||
|
<div v-if="inRepository" id="protocol-steps" class="protocol-section-header">
|
||||||
|
<div class="protocol-steps-container">
|
||||||
|
<a class="protocol-section-caret" role="button" data-toggle="collapse" href="#protocol-steps-container" aria-expanded="false" aria-controls="protocol-steps-container">
|
||||||
|
<i class="fas fa-caret-right"></i>
|
||||||
|
<span id="protocolStepsLabel" class="protocol-section-title">
|
||||||
|
<h2>
|
||||||
|
{{ i18n.t("protocols.header.protocol_steps") }}
|
||||||
|
</h2>
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="protocol-steps-container" :class=" inRepository ? 'protocol-steps collapse in' : ''">
|
||||||
<div v-if="steps.length > 0" class="protocol-step-actions">
|
<div v-if="steps.length > 0" class="protocol-step-actions">
|
||||||
<button class="btn btn-light" @click="collapseSteps" tabindex="0">
|
<button class="btn btn-light" @click="collapseSteps" tabindex="0">
|
||||||
<span class="fas fa-caret-up"></span>
|
<span class="fas fa-caret-up"></span>
|
||||||
|
|
@ -110,11 +136,13 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<button v-if="steps.length > 0 && urls.add_step_url" class="btn btn-primary" @click="addStep(steps.length)">
|
<button v-if="(steps.length > 0 || inRepository) && urls.add_step_url" :class="!inRepository ? 'btn btn-primary' : 'btn btn-secondary'" @click="addStep(steps.length)">
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
{{ i18n.t("protocols.steps.new_step") }}
|
{{ i18n.t("protocols.steps.new_step") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<ProtocolModals/>
|
<ProtocolModals/>
|
||||||
<ReorderableItemsModal v-if="reordering"
|
<ReorderableItemsModal v-if="reordering"
|
||||||
:title="i18n.t('protocols.reorder_steps.modal.title')"
|
:title="i18n.t('protocols.reorder_steps.modal.title')"
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,46 @@
|
||||||
<template>
|
<template>
|
||||||
|
<div class="protocol-section protocol-information">
|
||||||
|
<div id="protocol-details" class="protocol-section-header">
|
||||||
|
<div class="protocol-details-container">
|
||||||
|
<a class="protocol-section-caret" role="button" data-toggle="collapse" href="#details-container" aria-expanded="false" aria-controls="details-container">
|
||||||
|
<i class="fas fa-caret-right"></i>
|
||||||
|
<span id="protocolDetailsLabel" class="protocol-section-title">
|
||||||
|
<h2>
|
||||||
|
{{ i18n.t("protocols.header.details") }}
|
||||||
|
</h2>
|
||||||
|
<span class="protocol-code" >{{ protocol.attributes.code }}</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="actions-block">
|
||||||
|
<a class="btn btn-light icon-btn pull-right" data-toggle="modal" data-target="#print-protocol-modal" tabindex="0">
|
||||||
|
<span class="fas fa-print" aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
<button class="btn btn-light">{{ i18n.t("protocols.header.versions") }}</button>
|
||||||
|
<button v-if="!protocol.attributes.published" class="btn btn-primary">{{ i18n.t("protocols.header.publish") }}</button>
|
||||||
|
<button v-else class="btn btn-secondary">{{ i18n.t("protocols.header.save_as_draft") }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="details-container" class="protocol-details collapse in">
|
||||||
<div class="protocol-metadata">
|
<div class="protocol-metadata">
|
||||||
<p class="data-block">
|
<p class="data-block">
|
||||||
<span class="fas block-icon fa-calendar-alt fa-fw"></span>
|
{{ i18n.t("protocols.header.version") }}
|
||||||
|
<b>{{ protocol.attributes.version }}</b>
|
||||||
|
</p>
|
||||||
|
<p class="data-block">
|
||||||
|
{{ i18n.t("protocols.header.updated_at") }}
|
||||||
|
<b>{{ protocol.attributes.updated_at_formatted }}</b>
|
||||||
|
</p>
|
||||||
|
<p class="data-block">
|
||||||
{{ i18n.t("protocols.header.created_at") }}
|
{{ i18n.t("protocols.header.created_at") }}
|
||||||
<b>{{ protocol.attributes.created_at_formatted }}</b>
|
<b>{{ protocol.attributes.created_at_formatted }}</b>
|
||||||
</p>
|
</p>
|
||||||
<p class="data-block">
|
<p class="data-block">
|
||||||
<span class="fas block-icon fa-user fa-fw"></span>
|
|
||||||
{{ i18n.t("protocols.header.added_by") }}
|
{{ i18n.t("protocols.header.added_by") }}
|
||||||
<img :src="protocol.attributes.added_by.avatar"/>
|
<img :src="protocol.attributes.added_by.avatar"/>
|
||||||
{{ protocol.attributes.added_by.name }}
|
{{ protocol.attributes.added_by.name }}
|
||||||
</p>
|
</p>
|
||||||
<p class="data-block">
|
|
||||||
<span class="fas block-icon fa-edit fa-fw"></span>
|
|
||||||
{{ i18n.t("protocols.header.updated_at") }}
|
|
||||||
<b>{{ protocol.attributes.updated_at_formatted }}</b>
|
|
||||||
</p>
|
|
||||||
<p class="data-block authors-data">
|
<p class="data-block authors-data">
|
||||||
<span class="fas block-icon fa-graduation-cap fa-fw"></span>
|
|
||||||
<span>{{ i18n.t("protocols.header.authors") }}</span>
|
<span>{{ i18n.t("protocols.header.authors") }}</span>
|
||||||
<span class="authors-list" v-if="protocol.attributes.urls.update_protocol_authors_url">
|
<span class="authors-list" v-if="protocol.attributes.urls.update_protocol_authors_url">
|
||||||
<InlineEdit
|
<InlineEdit
|
||||||
|
|
@ -33,7 +56,6 @@
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="data-block keywords-data">
|
<p class="data-block keywords-data">
|
||||||
<span class="fas block-icon fa-font fa-fw"></span>
|
|
||||||
<span>{{ i18n.t("protocols.header.keywords") }}</span>
|
<span>{{ i18n.t("protocols.header.keywords") }}</span>
|
||||||
<span class="keywords-list">
|
<span class="keywords-list">
|
||||||
<DropdownSelector
|
<DropdownSelector
|
||||||
|
|
@ -51,6 +73,8 @@
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ Canaid::Permissions.register_for(Protocol) do
|
||||||
# protocol in repository: update, create/update/delete/reorder step,
|
# protocol in repository: update, create/update/delete/reorder step,
|
||||||
# toggle private/public visibility, archive
|
# toggle private/public visibility, archive
|
||||||
can :manage_protocol_in_repository do |user, protocol|
|
can :manage_protocol_in_repository do |user, protocol|
|
||||||
|
protocol.protocol_type.in_repository_draft? &&
|
||||||
protocol.permission_granted?(user, ProtocolPermissions::MANAGE)
|
protocol.permission_granted?(user, ProtocolPermissions::MANAGE)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,21 @@ class ProtocolSerializer < ActiveModel::Serializer
|
||||||
include ActionView::Helpers::TextHelper
|
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
|
:created_at_formatted, :updated_at_formatted, :added_by, :authors, :keywords, :version, :code,
|
||||||
|
:published
|
||||||
|
|
||||||
def updated_at
|
def updated_at
|
||||||
object.updated_at.to_i
|
object.updated_at.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def version
|
||||||
|
object.in_repository_draft? ? I18n.t('protocols.draft') : object.version_number
|
||||||
|
end
|
||||||
|
|
||||||
|
def published
|
||||||
|
object.in_repository_published?
|
||||||
|
end
|
||||||
|
|
||||||
def added_by
|
def added_by
|
||||||
{
|
{
|
||||||
avatar: object.added_by&.avatar_url(:icon_small),
|
avatar: object.added_by&.avatar_url(:icon_small),
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,34 @@
|
||||||
<%= content_for :sidebar do %>
|
<%= content_for :sidebar do %>
|
||||||
<%= render partial: "/shared/sidebar/templates_sidebar", locals: {active: :protocol} %>
|
<%= render partial: "/shared/sidebar/templates_sidebar", locals: {active: :protocol} %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% provide(:container_class, 'no-second-nav-container') %>
|
||||||
<div class="content-pane protocols-show" >
|
<div class="content-pane protocols-show" >
|
||||||
<div class="protocol-position-container">
|
<div class="content-header">
|
||||||
<div class="protocol-actions">
|
<div id="breadcrumbsWrapper">
|
||||||
<a class="btn btn-secondary pull-right" href="<%= print_protocol_path(@protocol) %>" target="_blank" tabindex="0">
|
<div class="breadcrumbs-container">
|
||||||
<span class="fas fa-print" aria-hidden="true"></span>
|
<a href="<%= protocols_path %>" class="breadcrumbs-link">
|
||||||
<span><%= t("protocols.print.button") %></span>
|
<%= t('sidebar.templates.protocol_templates') %>
|
||||||
</a>
|
</a>
|
||||||
|
<span class="delimiter">/</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="title-row">
|
||||||
|
<h1>
|
||||||
|
<% if @inline_editable_title_config.present? %>
|
||||||
|
<%= render partial: "shared/inline_editing",
|
||||||
|
locals: {
|
||||||
|
initial_value: @protocol.name,
|
||||||
|
config: @inline_editable_title_config
|
||||||
|
} %>
|
||||||
|
<% else %>
|
||||||
|
<div class="name-readonly-placeholder">
|
||||||
|
<%= @protocol.name %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="protocol-position-container">
|
||||||
<div
|
<div
|
||||||
id="protocolContainer"
|
id="protocolContainer"
|
||||||
data-protocol-url="<%= protocol_path(@protocol) %>"
|
data-protocol-url="<%= protocol_path(@protocol) %>"
|
||||||
|
|
|
||||||
|
|
@ -2427,6 +2427,7 @@ en:
|
||||||
unchangable_error_message: "Predefined roles can not be changed!"
|
unchangable_error_message: "Predefined roles can not be changed!"
|
||||||
|
|
||||||
protocols:
|
protocols:
|
||||||
|
draft: "Draft"
|
||||||
no_text_placeholder: 'No protocol description'
|
no_text_placeholder: 'No protocol description'
|
||||||
reorder_steps:
|
reorder_steps:
|
||||||
button: "Rearrange steps"
|
button: "Rearrange steps"
|
||||||
|
|
@ -2530,6 +2531,14 @@ en:
|
||||||
row_success: "Exported"
|
row_success: "Exported"
|
||||||
row_failed: "Failed"
|
row_failed: "Failed"
|
||||||
header:
|
header:
|
||||||
|
details: 'Details'
|
||||||
|
versions: 'Versions'
|
||||||
|
protocol_description: 'Protocol description'
|
||||||
|
protocol_steps: 'Protocol steps'
|
||||||
|
publish: 'Publish'
|
||||||
|
save_as_draft: 'Save as draft'
|
||||||
|
version: "Version:"
|
||||||
|
draft: 'Draft'
|
||||||
created_at: "Created at:"
|
created_at: "Created at:"
|
||||||
updated_at: "Last modified at:"
|
updated_at: "Last modified at:"
|
||||||
added_by: "Added by:"
|
added_by: "Added by:"
|
||||||
|
|
|
||||||
|
|
@ -556,7 +556,7 @@ Rails.application.routes.draw do
|
||||||
get 'versions_modal', to: 'protocols#versions_modal'
|
get 'versions_modal', to: 'protocols#versions_modal'
|
||||||
get 'preview', to: 'protocols#preview'
|
get 'preview', to: 'protocols#preview'
|
||||||
patch 'description', to: 'protocols#update_description'
|
patch 'description', to: 'protocols#update_description'
|
||||||
patch 'name', to: 'protocols#update_name'
|
put 'name', to: 'protocols#update_name'
|
||||||
patch 'authors', to: 'protocols#update_authors'
|
patch 'authors', to: 'protocols#update_authors'
|
||||||
patch 'keywords', to: 'protocols#update_keywords'
|
patch 'keywords', to: 'protocols#update_keywords'
|
||||||
post 'clone', to: 'protocols#clone'
|
post 'clone', to: 'protocols#clone'
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue