mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-24 08:43:13 +08:00
Add step layout [SCI-6755]
This commit is contained in:
parent
8aaab73856
commit
6dde945d61
10 changed files with 195 additions and 38 deletions
|
@ -39,6 +39,7 @@
|
|||
@import "reports/*";
|
||||
@import "settings/*";
|
||||
@import "shared/*";
|
||||
@import "steps/*";
|
||||
@import "themes/*";
|
||||
|
||||
@import "*"
|
||||
|
|
30
app/assets/stylesheets/my_modules/protocol.scss
Normal file
30
app/assets/stylesheets/my_modules/protocol.scss
Normal file
|
@ -0,0 +1,30 @@
|
|||
.task-protocol {
|
||||
.insert-step {
|
||||
align-items: center;
|
||||
color: $color-concrete;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
background-color: $color-concrete;
|
||||
content: '';
|
||||
display: inline-block;
|
||||
flex-grow: 1;
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
.fa-plus {
|
||||
margin: 0 .5em;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $brand-primary;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
background-color: $brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,6 @@
|
|||
}
|
||||
|
||||
.task-section {
|
||||
border-left: 3px solid $color-concrete;
|
||||
margin: 16px 0;
|
||||
padding-left: 16px;
|
||||
|
||||
|
|
55
app/assets/stylesheets/steps/step.scss
Normal file
55
app/assets/stylesheets/steps/step.scss
Normal file
|
@ -0,0 +1,55 @@
|
|||
.step-container {
|
||||
padding: 8px 24px;
|
||||
margin: 20px 0;
|
||||
|
||||
.step-header {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
||||
.step-collapse-link {
|
||||
display: inline-block;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
width: 24px;
|
||||
|
||||
&:not(.collapsed) {
|
||||
@include rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.step-state {
|
||||
border: 2px solid $color-alto;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
width: 24px;
|
||||
|
||||
&.completed {
|
||||
background: $brand-success;
|
||||
border: 2px solid $brand-success;
|
||||
|
||||
&::after {
|
||||
@include font-awesome;
|
||||
color: $color-white;
|
||||
content: $font-fas-check;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-position {
|
||||
@include font-main;
|
||||
line-height: 24px;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.step-name-container {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.step-actions-container {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,13 +32,21 @@ class StepsController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
new_step = Step.new(
|
||||
@step = Step.new(
|
||||
name: t('protocols.steps.default_name'),
|
||||
completed: false,
|
||||
user: current_user,
|
||||
last_modified_by: current_user
|
||||
)
|
||||
render json: @protocol.insert_step(new_step, params[:position]), serializer: StepSerializer
|
||||
|
||||
@step = @protocol.insert_step(@step, params[:position])
|
||||
# Generate activity
|
||||
if @protocol.in_module?
|
||||
log_activity(:create_step, @my_module.experiment.project, my_module: @my_module.id)
|
||||
else
|
||||
log_activity(:add_step_to_protocol_repository, nil, protocol: @protocol.id)
|
||||
end
|
||||
render json: @step, serializer: StepSerializer
|
||||
end
|
||||
|
||||
def create_old
|
||||
|
@ -143,6 +151,20 @@ class StepsController < ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
if @step.update(step_params)
|
||||
# Generate activity
|
||||
if @protocol.in_module?
|
||||
log_activity(:edit_step, @my_module.experiment.project, my_module: @my_module.id)
|
||||
else
|
||||
log_activity(:edit_step_in_protocol_repository, nil, protocol: @protocol.id)
|
||||
end
|
||||
render json: @step, serializer: StepSerializer
|
||||
else
|
||||
render json: {}, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def update_old
|
||||
respond_to do |format|
|
||||
old_description = @step.description
|
||||
old_checklists = fetch_old_checklists_data(@step)
|
||||
|
@ -327,34 +349,30 @@ class StepsController < ApplicationController
|
|||
|
||||
# Complete/uncomplete step
|
||||
def toggle_step_state
|
||||
respond_to do |format|
|
||||
completed = params[:completed] == 'true'
|
||||
changed = @step.completed != completed
|
||||
@step.completed = completed
|
||||
@step.last_modified_by = current_user
|
||||
@step.completed = params[:completed] == 'true'
|
||||
@step.last_modified_by = current_user
|
||||
|
||||
if @step.save
|
||||
# Create activity
|
||||
if changed
|
||||
completed_steps = @protocol.steps.where(completed: true).count
|
||||
all_steps = @protocol.steps.count
|
||||
if @step.save
|
||||
# Create activity
|
||||
if @step.saved_change_to_completed
|
||||
completed_steps = @protocol.steps.where(completed: true).count
|
||||
all_steps = @protocol.steps.count
|
||||
|
||||
type_of = completed ? :complete_step : :uncomplete_step
|
||||
# Toggling step state can only occur in
|
||||
# module protocols, so my_module is always
|
||||
# not nil; nonetheless, check if my_module is present
|
||||
if @protocol.in_module?
|
||||
log_activity(type_of,
|
||||
@protocol.my_module.experiment.project,
|
||||
my_module: @my_module.id,
|
||||
num_completed: completed_steps.to_s,
|
||||
num_all: all_steps.to_s)
|
||||
end
|
||||
type_of = @step.completed ? :complete_step : :uncomplete_step
|
||||
# Toggling step state can only occur in
|
||||
# module protocols, so my_module is always
|
||||
# not nil; nonetheless, check if my_module is present
|
||||
if @protocol.in_module?
|
||||
log_activity(type_of,
|
||||
@protocol.my_module.experiment.project,
|
||||
my_module: @my_module.id,
|
||||
num_completed: completed_steps.to_s,
|
||||
num_all: all_steps.to_s)
|
||||
end
|
||||
format.json { render json: {}, status: :ok }
|
||||
else
|
||||
format.json { render json: {}, status: :unprocessable_entity }
|
||||
end
|
||||
render json: @step, serializer: StepSerializer
|
||||
else
|
||||
render json: {}, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -514,6 +532,10 @@ class StepsController < ApplicationController
|
|||
end
|
||||
|
||||
def step_params
|
||||
params.require(:step).permit(:name)
|
||||
end
|
||||
|
||||
def step_params_old
|
||||
params.require(:step).permit(
|
||||
:name,
|
||||
:description,
|
||||
|
|
|
@ -73,13 +73,13 @@
|
|||
<div class="protocol-steps">
|
||||
<template v-for="(step, index) in steps">
|
||||
<div class="step-block" :key="step.id">
|
||||
<button v-if="index > 0" class="btn btn-primary" @click="addStep(index)">
|
||||
<div v-if="index > 0" class="insert-step" @click="addStep(index)">
|
||||
<i class="fas fa-plus"></i>
|
||||
{{ i18n.t("protocols.steps.new_step") }}
|
||||
</button>
|
||||
</div>
|
||||
<Step
|
||||
:step.sync="steps[index]"
|
||||
@step:delete="updateStepsPosition"
|
||||
@step:update="updateStep"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -166,6 +166,9 @@
|
|||
this.reorderSteps(unordered_steps)
|
||||
|
||||
},
|
||||
updateStep(step) {
|
||||
this.$set(this.steps, step.attributes.position, step)
|
||||
},
|
||||
reorderSteps(steps) {
|
||||
this.steps = steps.sort((a, b) => a.attributes.position - b.attributes.position);
|
||||
}
|
||||
|
|
|
@ -1,15 +1,42 @@
|
|||
<template>
|
||||
<div class="step-container">
|
||||
{{ step.attributes.position + 1 }}
|
||||
{{ step.attributes.name }}
|
||||
<button class="btn btn-danger" @click="deleteStep">
|
||||
<i class="fas fa-trash"></i>
|
||||
{{ i18n.t("protocols.steps.options.delete_title") }}
|
||||
</button>
|
||||
<div class="step-header">
|
||||
<a class="step-collapse-link"
|
||||
:href="'#stepBody' + step.id"
|
||||
data-toggle="collapse"
|
||||
data-remote="true">
|
||||
<span class="fas fa-caret-right"></span>
|
||||
</a>
|
||||
<div class="step-complete-container">
|
||||
<div :class="`step-state ${step.attributes.completed ? 'completed' : ''}`" @click="changeState"></div>
|
||||
</div>
|
||||
<div class="step-position">
|
||||
{{ step.attributes.position + 1 }}.
|
||||
</div>
|
||||
<div class="step-name-container">
|
||||
<InlineEdit
|
||||
:value="step.attributes.name"
|
||||
:characterLimit="255"
|
||||
:allowBlank="false"
|
||||
:attributeName="`${i18n.t('Step')} ${i18n.t('name')}`"
|
||||
@update="updateName"
|
||||
/>
|
||||
</div>
|
||||
<div class="step-actions-container">
|
||||
<button class="btn icon-btn btn-light" @click="deleteStep">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse in" :id="'stepBody' + step.id">
|
||||
Components here
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import InlineEdit from 'vue/shared/inline_edit.vue'
|
||||
|
||||
export default {
|
||||
name: 'StepContainer',
|
||||
props: {
|
||||
|
@ -18,6 +45,7 @@
|
|||
required: true
|
||||
}
|
||||
},
|
||||
components: { InlineEdit },
|
||||
methods: {
|
||||
deleteStep() {
|
||||
$.ajax({
|
||||
|
@ -31,6 +59,21 @@
|
|||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
changeState() {
|
||||
$.post(this.step.attributes.urls.state_url, {completed: !this.step.attributes.completed}, (result) => {
|
||||
this.$emit('step:update', result.data)
|
||||
})
|
||||
},
|
||||
updateName(newName) {
|
||||
$.ajax({
|
||||
url: this.step.attributes.urls.update_url,
|
||||
type: 'PATCH',
|
||||
data: {step: {name: newName}},
|
||||
success: (result) => {
|
||||
this.$emit('step:update', result.data)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
}
|
||||
},
|
||||
created( ){
|
||||
this.newValue = this.value;
|
||||
this.newValue = this.value || '';
|
||||
},
|
||||
mounted() {
|
||||
if (this.autofocus) {
|
||||
|
|
|
@ -5,7 +5,9 @@ class StepSerializer < ActiveModel::Serializer
|
|||
|
||||
def urls
|
||||
{
|
||||
delete_url: step_path(object)
|
||||
delete_url: step_path(object),
|
||||
state_url: toggle_step_state_step_path(object),
|
||||
update_url: step_path(object)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,6 +50,8 @@ CREATE FUNCTION public.trim_html_tags(input text, OUT output text) RETURNS text
|
|||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- Name: active_storage_attachments; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
|
Loading…
Reference in a new issue