mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-07 12:27:11 +08:00
Merge pull request #6039 from aignatov-bio/ai-sci-9024-add-move-modal-for-elements
Add element movements between step and results [SCI-9024]
This commit is contained in:
commit
c111d287ef
30 changed files with 381 additions and 40 deletions
|
@ -5,6 +5,10 @@ module ResultElements
|
||||||
before_action :load_result_and_my_module
|
before_action :load_result_and_my_module
|
||||||
before_action :check_manage_permissions
|
before_action :check_manage_permissions
|
||||||
|
|
||||||
|
def move_targets
|
||||||
|
render json: { targets: @my_module.results.where.not(id: @result.id).map{ |i| [i.id, i.name] } }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_result_and_my_module
|
def load_result_and_my_module
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module ResultElements
|
module ResultElements
|
||||||
class TablesController < BaseController
|
class TablesController < BaseController
|
||||||
before_action :load_table, only: %i(update destroy duplicate)
|
before_action :load_table, only: %i(update destroy duplicate move)
|
||||||
|
|
||||||
def create
|
def create
|
||||||
predefined_table_dimensions = create_table_params[:tableDimensions].map(&:to_i)
|
predefined_table_dimensions = create_table_params[:tableDimensions].map(&:to_i)
|
||||||
|
@ -57,6 +57,19 @@ module ResultElements
|
||||||
head :unprocessable_entity
|
head :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def move
|
||||||
|
target = @my_module.results.find_by(id: params[:target_id])
|
||||||
|
result_table = @table.result_table
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
result_table.update!(result: target)
|
||||||
|
result_table.result_orderable_element.update!(result: target, position: target.result_orderable_elements.size)
|
||||||
|
@result.normalize_elements_position
|
||||||
|
render json: @table, serializer: ResultTableSerializer, user: current_user
|
||||||
|
rescue ActiveRecord::RecordInvalid
|
||||||
|
render json: result_table.errors, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @table.destroy
|
if @table.destroy
|
||||||
#log_step_activity(:table_deleted, { table_name: @table.name })
|
#log_step_activity(:table_deleted, { table_name: @table.name })
|
||||||
|
|
|
@ -7,7 +7,7 @@ module ResultElements
|
||||||
include InputSanitizeHelper
|
include InputSanitizeHelper
|
||||||
include Rails.application.routes.url_helpers
|
include Rails.application.routes.url_helpers
|
||||||
|
|
||||||
before_action :load_result_text, only: %i(update destroy duplicate)
|
before_action :load_result_text, only: %i(update destroy duplicate move)
|
||||||
|
|
||||||
def create
|
def create
|
||||||
result_text = @result.result_texts.build
|
result_text = @result.result_texts.build
|
||||||
|
@ -36,6 +36,18 @@ module ResultElements
|
||||||
render json: @result_text.errors, status: :unprocessable_entity
|
render json: @result_text.errors, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def move
|
||||||
|
target = @my_module.results.find_by(id: params[:target_id])
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
@result_text.update!(result: target)
|
||||||
|
@result_text.result_orderable_element.update!(result: target, position: target.result_orderable_elements.size)
|
||||||
|
@result.normalize_elements_position
|
||||||
|
render json: @result_text, serializer: ResultTextSerializer, user: current_user
|
||||||
|
rescue ActiveRecord::RecordInvalid
|
||||||
|
render json: @result_text.errors, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @result_text.destroy
|
if @result_text.destroy
|
||||||
log_step_activity(:text_deleted, { text_name: @result_text.name })
|
log_step_activity(:text_deleted, { text_name: @result_text.name })
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ResultsController < ApplicationController
|
class ResultsController < ApplicationController
|
||||||
skip_before_action :verify_authenticity_token, only: %i(create update destroy)
|
|
||||||
|
|
||||||
before_action :load_my_module
|
before_action :load_my_module
|
||||||
before_action :load_vars, only: %i(destroy elements assets upload_attachment update_view_state update_asset_view_mode update)
|
before_action :load_vars, only: %i(destroy elements assets upload_attachment update_view_state update_asset_view_mode update)
|
||||||
before_action :check_destroy_permissions, only: :destroy
|
before_action :check_destroy_permissions, only: :destroy
|
||||||
|
|
|
@ -5,6 +5,11 @@ module StepElements
|
||||||
before_action :load_step_and_protocol
|
before_action :load_step_and_protocol
|
||||||
before_action :check_manage_permissions
|
before_action :check_manage_permissions
|
||||||
|
|
||||||
|
|
||||||
|
def move_targets
|
||||||
|
render json: { targets: @protocol.steps.order(:position).where.not(id: @step.id).map{|i| [i.id, i.name] } }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_step_and_protocol
|
def load_step_and_protocol
|
||||||
|
|
|
@ -4,7 +4,7 @@ module StepElements
|
||||||
class ChecklistsController < BaseController
|
class ChecklistsController < BaseController
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include StepsActions
|
include StepsActions
|
||||||
before_action :load_checklist, only: %i(update destroy duplicate)
|
before_action :load_checklist, only: %i(update destroy duplicate move)
|
||||||
def create
|
def create
|
||||||
checklist = @step.checklists.build(
|
checklist = @step.checklists.build(
|
||||||
name: t('protocols.steps.checklist.default_name', position: @step.checklists.length + 1)
|
name: t('protocols.steps.checklist.default_name', position: @step.checklists.length + 1)
|
||||||
|
@ -32,6 +32,18 @@ module StepElements
|
||||||
head :unprocessable_entity
|
head :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def move
|
||||||
|
target = @protocol.steps.find_by(id: params[:target_id])
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
@checklist.update!(step: target)
|
||||||
|
@checklist.step_orderable_element.update!(step: target, position: target.step_orderable_elements.size)
|
||||||
|
@step.normalize_elements_position
|
||||||
|
render json: @checklist, serializer: ChecklistSerializer, user: current_user
|
||||||
|
rescue ActiveRecord::RecordInvalid
|
||||||
|
render json: @checklist.errors, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @checklist.destroy
|
if @checklist.destroy
|
||||||
log_step_activity(:checklist_deleted, { checklist_name: @checklist.name })
|
log_step_activity(:checklist_deleted, { checklist_name: @checklist.name })
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
module StepElements
|
module StepElements
|
||||||
class TablesController < BaseController
|
class TablesController < BaseController
|
||||||
before_action :load_table, only: %i(update destroy duplicate)
|
before_action :load_table, only: %i(update destroy duplicate move)
|
||||||
|
|
||||||
def create
|
def create
|
||||||
predefined_table_dimensions = create_table_params[:tableDimensions].map(&:to_i)
|
predefined_table_dimensions = create_table_params[:tableDimensions].map(&:to_i)
|
||||||
|
@ -57,6 +57,19 @@ module StepElements
|
||||||
head :unprocessable_entity
|
head :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def move
|
||||||
|
target = @protocol.steps.find_by(id: params[:target_id])
|
||||||
|
step_table = @table.step_table
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
step_table.update!(step: target)
|
||||||
|
step_table.step_orderable_element.update!(step: target, position: target.step_orderable_elements.size)
|
||||||
|
@step.normalize_elements_position
|
||||||
|
render json: @table, serializer: TableSerializer, user: current_user
|
||||||
|
rescue ActiveRecord::RecordInvalid
|
||||||
|
render json: step_table.errors, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @table.destroy
|
if @table.destroy
|
||||||
log_step_activity(:table_deleted, { table_name: @table.name })
|
log_step_activity(:table_deleted, { table_name: @table.name })
|
||||||
|
|
|
@ -5,7 +5,7 @@ module StepElements
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include StepsActions
|
include StepsActions
|
||||||
|
|
||||||
before_action :load_step_text, only: %i(update destroy duplicate)
|
before_action :load_step_text, only: %i(update destroy duplicate move)
|
||||||
|
|
||||||
def create
|
def create
|
||||||
step_text = @step.step_texts.build
|
step_text = @step.step_texts.build
|
||||||
|
@ -34,6 +34,18 @@ module StepElements
|
||||||
render json: @step_text.errors, status: :unprocessable_entity
|
render json: @step_text.errors, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def move
|
||||||
|
target = @protocol.steps.find_by(id: params[:target_id])
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
@step_text.update!(step: target)
|
||||||
|
@step_text.step_orderable_element.update!(step: target, position: target.step_orderable_elements.size)
|
||||||
|
@step.normalize_elements_position
|
||||||
|
render json: @step_text, serializer: StepTextSerializer, user: current_user
|
||||||
|
rescue ActiveRecord::RecordInvalid
|
||||||
|
render json: @step_text.errors, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @step_text.destroy
|
if @step_text.destroy
|
||||||
log_step_activity(:text_deleted, { text_name: @step_text.name })
|
log_step_activity(:text_deleted, { text_name: @step_text.name })
|
||||||
|
|
22
app/javascript/packs/custom_axios.js
Normal file
22
app/javascript/packs/custom_axios.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const instance = axios.create({
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
instance.interceptors.request.use(
|
||||||
|
function (config) {
|
||||||
|
const csrfToken = document.querySelector('[name=csrf-token]').content;
|
||||||
|
config.headers["X-CSRF-Token"] = csrfToken;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default instance;
|
|
@ -3,7 +3,9 @@
|
||||||
import TurbolinksAdapter from 'vue-turbolinks';
|
import TurbolinksAdapter from 'vue-turbolinks';
|
||||||
import Vue from 'vue/dist/vue.esm';
|
import Vue from 'vue/dist/vue.esm';
|
||||||
import ProtocolContainer from '../../vue/protocol/container.vue';
|
import ProtocolContainer from '../../vue/protocol/container.vue';
|
||||||
|
import PerfectScrollbar from 'vue2-perfect-scrollbar';
|
||||||
|
|
||||||
|
Vue.use(PerfectScrollbar);
|
||||||
Vue.use(TurbolinksAdapter);
|
Vue.use(TurbolinksAdapter);
|
||||||
Vue.prototype.i18n = window.I18n;
|
Vue.prototype.i18n = window.I18n;
|
||||||
Vue.prototype.inlineEditing = window.inlineEditing;
|
Vue.prototype.inlineEditing = window.inlineEditing;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import TurbolinksAdapter from 'vue-turbolinks';
|
import TurbolinksAdapter from 'vue-turbolinks';
|
||||||
import Vue from 'vue/dist/vue.esm';
|
import Vue from 'vue/dist/vue.esm';
|
||||||
import Results from '../../vue/results/results.vue';
|
import Results from '../../vue/results/results.vue';
|
||||||
|
import PerfectScrollbar from 'vue2-perfect-scrollbar';
|
||||||
|
|
||||||
|
Vue.use(PerfectScrollbar);
|
||||||
Vue.use(TurbolinksAdapter);
|
Vue.use(TurbolinksAdapter);
|
||||||
Vue.prototype.i18n = window.I18n;
|
Vue.prototype.i18n = window.I18n;
|
||||||
Vue.prototype.ActiveStoragePreviews = window.ActiveStoragePreviews;
|
Vue.prototype.ActiveStoragePreviews = window.ActiveStoragePreviews;
|
||||||
|
|
|
@ -129,10 +129,13 @@
|
||||||
:step.sync="steps[index]"
|
:step.sync="steps[index]"
|
||||||
@reorder="startStepReorder"
|
@reorder="startStepReorder"
|
||||||
:inRepository="inRepository"
|
:inRepository="inRepository"
|
||||||
|
:stepToReload="stepToReload"
|
||||||
@step:delete="updateStepsPosition"
|
@step:delete="updateStepsPosition"
|
||||||
@step:update="updateStep"
|
@step:update="updateStep"
|
||||||
@stepUpdated="refreshProtocolStatus"
|
@stepUpdated="refreshProtocolStatus"
|
||||||
@step:insert="updateStepsPosition"
|
@step:insert="updateStepsPosition"
|
||||||
|
@step:elements:loaded="stepToReload = null"
|
||||||
|
@step:move_element="reloadStep"
|
||||||
:reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null"
|
:reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null"
|
||||||
:assignableMyModuleId="protocol.attributes.assignable_my_module_id"
|
:assignableMyModuleId="protocol.attributes.assignable_my_module_id"
|
||||||
/>
|
/>
|
||||||
|
@ -200,7 +203,8 @@
|
||||||
},
|
},
|
||||||
steps: [],
|
steps: [],
|
||||||
reordering: false,
|
reordering: false,
|
||||||
publishing: false
|
publishing: false,
|
||||||
|
stepToReload: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -215,6 +219,9 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
reloadStep(step) {
|
||||||
|
this.stepToReload = step;
|
||||||
|
},
|
||||||
collapseSteps() {
|
collapseSteps() {
|
||||||
$('.step-container .collapse').collapse('hide')
|
$('.step-container .collapse').collapse('hide')
|
||||||
},
|
},
|
||||||
|
|
|
@ -175,6 +175,7 @@
|
||||||
@update="updateElement"
|
@update="updateElement"
|
||||||
@reorder="openReorderModal"
|
@reorder="openReorderModal"
|
||||||
@component:insert="insertElement"
|
@component:insert="insertElement"
|
||||||
|
@moved="moveElement"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<Attachments v-if="attachments.length"
|
<Attachments v-if="attachments.length"
|
||||||
|
@ -243,7 +244,11 @@
|
||||||
assignableMyModuleId: {
|
assignableMyModuleId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: false
|
required: false
|
||||||
}
|
},
|
||||||
|
stepToReload: {
|
||||||
|
type: Number,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -284,6 +289,13 @@
|
||||||
this.loadAttachments();
|
this.loadAttachments();
|
||||||
this.loadElements();
|
this.loadElements();
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
stepToReload() {
|
||||||
|
if (this.stepToReload == this.step.id) {
|
||||||
|
this.loadElements();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
$(this.$refs.comments).data('closeCallback', this.closeCommentsSidebar);
|
$(this.$refs.comments).data('closeCallback', this.closeCommentsSidebar);
|
||||||
$(this.$refs.comments).data('openCallback', this.closeCommentsSidebar);
|
$(this.$refs.comments).data('openCallback', this.closeCommentsSidebar);
|
||||||
|
@ -335,6 +347,7 @@
|
||||||
loadElements() {
|
loadElements() {
|
||||||
$.get(this.urls.elements_url, (result) => {
|
$.get(this.urls.elements_url, (result) => {
|
||||||
this.elements = result.data
|
this.elements = result.data
|
||||||
|
this.$emit('step:elements:loaded');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showStorageUsage() {
|
showStorageUsage() {
|
||||||
|
@ -522,6 +535,17 @@
|
||||||
})
|
})
|
||||||
this.elements.push(element);
|
this.elements.push(element);
|
||||||
},
|
},
|
||||||
|
moveElement(position, target_id) {
|
||||||
|
this.elements.splice(position, 1)
|
||||||
|
let unorderedElements = this.elements.map( e => {
|
||||||
|
if (e.attributes.position >= position) {
|
||||||
|
e.attributes.position -= 1;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
})
|
||||||
|
this.$emit('stepUpdated')
|
||||||
|
this.$emit('step:move_element', target_id)
|
||||||
|
},
|
||||||
duplicateStep() {
|
duplicateStep() {
|
||||||
$.post(this.urls.duplicate_step_url, (result) => {
|
$.post(this.urls.duplicate_step_url, (result) => {
|
||||||
this.$emit('step:insert', result.data);
|
this.$emit('step:insert', result.data);
|
||||||
|
|
|
@ -138,6 +138,7 @@
|
||||||
@update="updateElement"
|
@update="updateElement"
|
||||||
@reorder="openReorderModal"
|
@reorder="openReorderModal"
|
||||||
@component:insert="insertElement"
|
@component:insert="insertElement"
|
||||||
|
@moved="moveElement"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<Attachments v-if="attachments.length"
|
<Attachments v-if="attachments.length"
|
||||||
|
@ -156,7 +157,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
import axios from '../../packs/custom_axios.js';
|
||||||
import ReorderableItemsModal from '../shared/reorderable_items_modal.vue';
|
import ReorderableItemsModal from '../shared/reorderable_items_modal.vue';
|
||||||
import ResultTable from '../shared/content/table.vue';
|
import ResultTable from '../shared/content/table.vue';
|
||||||
import ResultText from '../shared/content/text.vue';
|
import ResultText from '../shared/content/text.vue';
|
||||||
|
@ -170,7 +171,8 @@
|
||||||
export default {
|
export default {
|
||||||
name: 'Results',
|
name: 'Results',
|
||||||
props: {
|
props: {
|
||||||
result: { type: Object, required: true }
|
result: { type: Object, required: true },
|
||||||
|
resultToReload: { type: Number, required: false }
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -198,6 +200,13 @@
|
||||||
Attachments,
|
Attachments,
|
||||||
InlineEdit
|
InlineEdit
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
resultToReload() {
|
||||||
|
if (this.resultToReload == this.result.id) {
|
||||||
|
this.loadElements();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
reorderableElements() {
|
reorderableElements() {
|
||||||
return this.orderedElements.map((e) => { return { id: e.id, attributes: e.attributes.orderable } })
|
return this.orderedElements.map((e) => { return { id: e.id, attributes: e.attributes.orderable } })
|
||||||
|
@ -294,6 +303,7 @@
|
||||||
loadElements() {
|
loadElements() {
|
||||||
$.get(this.urls.elements_url, (result) => {
|
$.get(this.urls.elements_url, (result) => {
|
||||||
this.elements = result.data
|
this.elements = result.data
|
||||||
|
this.$emit('result:elements:loaded');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
loadAttachments() {
|
loadAttachments() {
|
||||||
|
@ -340,6 +350,17 @@
|
||||||
},
|
},
|
||||||
duplicateResult() {
|
duplicateResult() {
|
||||||
|
|
||||||
|
},
|
||||||
|
moveElement(position, target_id) {
|
||||||
|
this.elements.splice(position, 1)
|
||||||
|
let unorderedElements = this.elements.map( e => {
|
||||||
|
if (e.attributes.position >= position) {
|
||||||
|
e.attributes.position -= 1;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
})
|
||||||
|
this.$emit('resultUpdated')
|
||||||
|
this.$emit('result:move_element', target_id)
|
||||||
},
|
},
|
||||||
updateName(name) {
|
updateName(name) {
|
||||||
axios.patch(this.urls.update_url, { result: { name: name } }, (_) => {
|
axios.patch(this.urls.update_url, { result: { name: name } }, (_) => {
|
||||||
|
|
|
@ -2,13 +2,18 @@
|
||||||
<div class="results-wrapper">
|
<div class="results-wrapper">
|
||||||
<ResultsToolbar :sort="sort" @setSort="setSort" @newResult="createResult" @expandAll="expandAll" @collapseAll="collapseAll" class="mb-3" />
|
<ResultsToolbar :sort="sort" @setSort="setSort" @newResult="createResult" @expandAll="expandAll" @collapseAll="collapseAll" class="mb-3" />
|
||||||
<div class="results-list">
|
<div class="results-list">
|
||||||
<Result v-for="result in results" :key="result.id" :result="result" />
|
<Result v-for="result in results" :key="result.id"
|
||||||
|
:result="result"
|
||||||
|
:resultToReload="resultToReload"
|
||||||
|
@result:elements:loaded="resultToReload = null"
|
||||||
|
@result:move_element="reloadResult"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
import axios from '../../packs/custom_axios.js';
|
||||||
import ResultsToolbar from './results_toolbar.vue';
|
import ResultsToolbar from './results_toolbar.vue';
|
||||||
import Result from './result.vue';
|
import Result from './result.vue';
|
||||||
|
|
||||||
|
@ -21,13 +26,17 @@
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
results: [],
|
results: [],
|
||||||
sort: 'created_at_desc'
|
sort: 'created_at_desc',
|
||||||
|
resultToReload: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.loadResults();
|
this.loadResults();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
reloadResult(result) {
|
||||||
|
this.resultToReload = result;
|
||||||
|
},
|
||||||
loadResults() {
|
loadResults() {
|
||||||
axios.get(
|
axios.get(
|
||||||
`${this.url}?sort=${this.sort}`,
|
`${this.url}?sort=${this.sort}`,
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
<button v-if="element.attributes.orderable.urls.duplicate_url" class="btn icon-btn btn-light btn-sm" tabindex="0" @click="duplicateElement">
|
<button v-if="element.attributes.orderable.urls.duplicate_url" class="btn icon-btn btn-light btn-sm" tabindex="0" @click="duplicateElement">
|
||||||
<i class="sn-icon sn-icon-duplicate"></i>
|
<i class="sn-icon sn-icon-duplicate"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button v-if="element.attributes.orderable.urls.move_targets_url" class="btn btn-light btn-sm" tabindex="0" @click="showMoveModal">
|
||||||
|
Move
|
||||||
|
</button>
|
||||||
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light btn-sm" @click="showDeleteModal" tabindex="0">
|
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light btn-sm" @click="showDeleteModal" tabindex="0">
|
||||||
<i class="sn-icon sn-icon-delete"></i>
|
<i class="sn-icon sn-icon-delete"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -76,21 +79,27 @@
|
||||||
{{ i18n.t("protocols.steps.checklist.empty_checklist") }}
|
{{ i18n.t("protocols.steps.checklist.empty_checklist") }}
|
||||||
</div>
|
</div>
|
||||||
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement" @cancel="closeDeleteModal"/>
|
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement" @cancel="closeDeleteModal"/>
|
||||||
|
<moveElementModal v-if="movingElement"
|
||||||
|
:parent_type="element.attributes.orderable.parent_type"
|
||||||
|
:targets_url="element.attributes.orderable.urls.move_targets_url"
|
||||||
|
@confirm="moveElement($event)" @cancel="closeMoveModal"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import DeleteMixin from './mixins/delete.js'
|
import DeleteMixin from './mixins/delete.js'
|
||||||
|
import MoveMixin from './mixins/move.js'
|
||||||
import DuplicateMixin from './mixins/duplicate.js'
|
import DuplicateMixin from './mixins/duplicate.js'
|
||||||
import deleteElementModal from './modal/delete.vue'
|
import deleteElementModal from './modal/delete.vue'
|
||||||
import InlineEdit from '../inline_edit.vue'
|
import InlineEdit from '../inline_edit.vue'
|
||||||
import ChecklistItem from './checklistItem.vue'
|
import ChecklistItem from './checklistItem.vue'
|
||||||
import Draggable from 'vuedraggable'
|
import Draggable from 'vuedraggable'
|
||||||
|
import moveElementModal from './modal/move.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Checklist',
|
name: 'Checklist',
|
||||||
components: { deleteElementModal, InlineEdit, ChecklistItem, Draggable },
|
components: { deleteElementModal, InlineEdit, ChecklistItem, Draggable, moveElementModal },
|
||||||
mixins: [DeleteMixin, DuplicateMixin],
|
mixins: [DeleteMixin, DuplicateMixin, MoveMixin],
|
||||||
props: {
|
props: {
|
||||||
element: {
|
element: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
25
app/javascript/vue/shared/content/mixins/move.js
Normal file
25
app/javascript/vue/shared/content/mixins/move.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import axios from '../../../../packs/custom_axios.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
movingElement: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showMoveModal(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.movingElement = true;
|
||||||
|
},
|
||||||
|
closeMoveModal() {
|
||||||
|
this.movingElement = false;
|
||||||
|
},
|
||||||
|
moveElement(target_id) {
|
||||||
|
axios.post(this.element.attributes.orderable.urls.move_url, { target_id: target_id }).
|
||||||
|
then(() => {
|
||||||
|
this.movingElement = false;
|
||||||
|
this.$emit('moved', this.element.attributes.position, target_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
83
app/javascript/vue/shared/content/modal/move.vue
Normal file
83
app/javascript/vue/shared/content/modal/move.vue
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<template>
|
||||||
|
<div ref="modal" @keydown.esc="cancel" class="modal" id="modalDestroyProtocolContent" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="sn-icon sn-icon-close"></i></button>
|
||||||
|
<h4 class="modal-title" id="modal-destroy-team-label">
|
||||||
|
{{ i18n.t(`protocols.steps.modals.move_element.${parent_type}.title`) }}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<label>
|
||||||
|
{{ i18n.t(`protocols.steps.modals.move_element.${parent_type}.targets_label`) }}
|
||||||
|
</label>
|
||||||
|
<div class="w-full">
|
||||||
|
<Select
|
||||||
|
:value="target"
|
||||||
|
:options="targets"
|
||||||
|
v-bind:disabled="false"
|
||||||
|
@change="setTarget"
|
||||||
|
></Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-secondary" @click="cancel">{{ i18n.t('general.cancel') }}</button>
|
||||||
|
<button class="btn btn-primary" @click="confirm">{{ i18n.t('general.save')}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import axios from '../../../../packs/custom_axios.js';
|
||||||
|
import Select from "../../select.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'moveElementModal',
|
||||||
|
props: {
|
||||||
|
parent_type: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
targets_url: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
target: null,
|
||||||
|
targets: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Select
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
$(this.$refs.modal).modal('show');
|
||||||
|
$(this.$refs.modal).on('hidden.bs.modal', () => {
|
||||||
|
this.$emit('cancel');
|
||||||
|
});
|
||||||
|
this.fetchTargets();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setTarget(target) {
|
||||||
|
this.target = target;
|
||||||
|
},
|
||||||
|
fetchTargets() {
|
||||||
|
axios.get(this.targets_url)
|
||||||
|
.then(response => {
|
||||||
|
this.targets = response.data.targets;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
confirm() {
|
||||||
|
$(this.$refs.modal).modal('hide');
|
||||||
|
this.$emit('confirm', this.target);
|
||||||
|
},
|
||||||
|
cancel() {
|
||||||
|
$(this.$refs.modal).modal('hide');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -28,6 +28,9 @@
|
||||||
<button v-if="element.attributes.orderable.urls.duplicate_url" class="btn icon-btn btn-light" tabindex="0" @click="duplicateElement">
|
<button v-if="element.attributes.orderable.urls.duplicate_url" class="btn icon-btn btn-light" tabindex="0" @click="duplicateElement">
|
||||||
<i class="sn-icon sn-icon-duplicate"></i>
|
<i class="sn-icon sn-icon-duplicate"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button v-if="element.attributes.orderable.urls.move_targets_url" class="btn btn-light btn-sm" tabindex="0" @click="showMoveModal">
|
||||||
|
Move
|
||||||
|
</button>
|
||||||
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light" @click="showDeleteModal" tabindex="0">
|
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light" @click="showDeleteModal" tabindex="0">
|
||||||
<i class="sn-icon sn-icon-delete"></i>
|
<i class="sn-icon sn-icon-delete"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -59,20 +62,26 @@
|
||||||
</div>
|
</div>
|
||||||
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement" @cancel="closeDeleteModal"/>
|
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement" @cancel="closeDeleteModal"/>
|
||||||
<tableNameModal v-if="nameModalOpen" :element="element" @update="updateEmptyName" @cancel="nameModalOpen = false" />
|
<tableNameModal v-if="nameModalOpen" :element="element" @update="updateEmptyName" @cancel="nameModalOpen = false" />
|
||||||
|
<moveElementModal v-if="movingElement"
|
||||||
|
:parent_type="element.attributes.orderable.parent_type"
|
||||||
|
:targets_url="element.attributes.orderable.urls.move_targets_url"
|
||||||
|
@confirm="moveElement($event)" @cancel="closeMoveModal"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import DeleteMixin from './mixins/delete.js'
|
import DeleteMixin from './mixins/delete.js'
|
||||||
|
import MoveMixin from './mixins/move.js'
|
||||||
import DuplicateMixin from './mixins/duplicate.js'
|
import DuplicateMixin from './mixins/duplicate.js'
|
||||||
import deleteElementModal from './modal/delete.vue'
|
import deleteElementModal from './modal/delete.vue'
|
||||||
import InlineEdit from '../inline_edit.vue'
|
import InlineEdit from '../inline_edit.vue'
|
||||||
import TableNameModal from './modal/table_name.vue'
|
import TableNameModal from './modal/table_name.vue'
|
||||||
|
import moveElementModal from './modal/move.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ContentTable',
|
name: 'ContentTable',
|
||||||
components: { deleteElementModal, InlineEdit, TableNameModal },
|
components: { deleteElementModal, InlineEdit, TableNameModal, moveElementModal },
|
||||||
mixins: [DeleteMixin, DuplicateMixin],
|
mixins: [DeleteMixin, DuplicateMixin, MoveMixin],
|
||||||
props: {
|
props: {
|
||||||
element: {
|
element: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
<button v-if="element.attributes.orderable.urls.duplicate_url" class="btn icon-btn btn-light btn-sm" tabindex="0" @click="duplicateElement">
|
<button v-if="element.attributes.orderable.urls.duplicate_url" class="btn icon-btn btn-light btn-sm" tabindex="0" @click="duplicateElement">
|
||||||
<i class="sn-icon sn-icon-duplicate"></i>
|
<i class="sn-icon sn-icon-duplicate"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button v-if="element.attributes.orderable.urls.move_targets_url" class="btn btn-light btn-sm" tabindex="0" @click="showMoveModal">
|
||||||
|
Move
|
||||||
|
</button>
|
||||||
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light btn-sm" @click="showDeleteModal" tabindex="0">
|
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light btn-sm" @click="showDeleteModal" tabindex="0">
|
||||||
<i class="sn-icon sn-icon-delete"></i>
|
<i class="sn-icon sn-icon-delete"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -41,19 +44,25 @@
|
||||||
{{ i18n.t("protocols.steps.text.empty_text") }}
|
{{ i18n.t("protocols.steps.text.empty_text") }}
|
||||||
</div>
|
</div>
|
||||||
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement($event)" @cancel="closeDeleteModal"/>
|
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement($event)" @cancel="closeDeleteModal"/>
|
||||||
|
<moveElementModal v-if="movingElement"
|
||||||
|
:parent_type="element.attributes.orderable.parent_type"
|
||||||
|
:targets_url="element.attributes.orderable.urls.move_targets_url"
|
||||||
|
@confirm="moveElement($event)" @cancel="closeMoveModal"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import DeleteMixin from './mixins/delete.js'
|
import DeleteMixin from './mixins/delete.js'
|
||||||
|
import MoveMixin from './mixins/move.js'
|
||||||
import DuplicateMixin from './mixins/duplicate.js'
|
import DuplicateMixin from './mixins/duplicate.js'
|
||||||
import deleteElementModal from './modal/delete.vue'
|
import deleteElementModal from './modal/delete.vue'
|
||||||
|
import moveElementModal from './modal/move.vue'
|
||||||
import Tinymce from '../tinymce.vue'
|
import Tinymce from '../tinymce.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TextContent',
|
name: 'TextContent',
|
||||||
components: { deleteElementModal, Tinymce },
|
components: { deleteElementModal, Tinymce, moveElementModal },
|
||||||
mixins: [DeleteMixin, DuplicateMixin],
|
mixins: [DeleteMixin, DuplicateMixin, MoveMixin],
|
||||||
props: {
|
props: {
|
||||||
element: {
|
element: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
|
@ -111,4 +111,10 @@ class Result < ApplicationRecord
|
||||||
def comments
|
def comments
|
||||||
result_comments
|
result_comments
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def normalize_elements_position
|
||||||
|
result_orderable_elements.order(:position).each_with_index do |element, index|
|
||||||
|
element.update!(position: index) unless element.position == index
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -180,6 +180,12 @@ class Step < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def normalize_elements_position
|
||||||
|
step_orderable_elements.order(:position).each_with_index do |element, index|
|
||||||
|
element.update!(position: index) unless element.position == index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def touch_protocol
|
def touch_protocol
|
||||||
|
|
|
@ -23,13 +23,7 @@ class StepOrderableElement < ApplicationRecord
|
||||||
def decrement_following_elements_positions
|
def decrement_following_elements_positions
|
||||||
step.with_lock do
|
step.with_lock do
|
||||||
yield
|
yield
|
||||||
step.step_orderable_elements
|
step.normalize_elements_position
|
||||||
.where('position > ?', position)
|
|
||||||
.order(position: :asc).each do |step_orderable_element|
|
|
||||||
# find_each ignore any ordering
|
|
||||||
step_orderable_element.position -= 1
|
|
||||||
step_orderable_element.save!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,16 @@ class ChecklistSerializer < ActiveModel::Serializer
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include ActionView::Helpers::TextHelper
|
include ActionView::Helpers::TextHelper
|
||||||
|
|
||||||
attributes :id, :name, :urls, :icon, :sa_name, :checklist_items
|
attributes :id, :name, :urls, :icon, :sa_name, :checklist_items, :parent_type
|
||||||
|
|
||||||
def icon
|
def icon
|
||||||
'fa-list-ul'
|
'fa-list-ul'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parent_type
|
||||||
|
:step
|
||||||
|
end
|
||||||
|
|
||||||
def checklist_items
|
def checklist_items
|
||||||
object.checklist_items.map do |item|
|
object.checklist_items.map do |item|
|
||||||
ChecklistItemSerializer.new(item, scope: { user: scope[:user] || @instance_options[:user] }).as_json
|
ChecklistItemSerializer.new(item, scope: { user: scope[:user] || @instance_options[:user] }).as_json
|
||||||
|
@ -34,7 +38,9 @@ class ChecklistSerializer < ActiveModel::Serializer
|
||||||
delete_url: step_checklist_path(object.step, object),
|
delete_url: step_checklist_path(object.step, object),
|
||||||
update_url: step_checklist_path(object.step, object),
|
update_url: step_checklist_path(object.step, object),
|
||||||
reorder_url: reorder_step_checklist_checklist_items_path(object.step, object),
|
reorder_url: reorder_step_checklist_checklist_items_path(object.step, object),
|
||||||
create_item_url: step_checklist_checklist_items_path(object.step, object)
|
create_item_url: step_checklist_checklist_items_path(object.step, object),
|
||||||
|
move_targets_url: move_targets_step_checklist_path(object.step, object),
|
||||||
|
move_url: move_step_checklist_path(object.step, object)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ class ResultTableSerializer < ActiveModel::Serializer
|
||||||
include Canaid::Helpers::PermissionsHelper
|
include Canaid::Helpers::PermissionsHelper
|
||||||
include Rails.application.routes.url_helpers
|
include Rails.application.routes.url_helpers
|
||||||
|
|
||||||
attributes :name, :contents, :urls, :icon, :metadata
|
attributes :name, :contents, :urls, :icon, :metadata, :parent_type
|
||||||
|
|
||||||
def contents
|
def contents
|
||||||
object.contents_utf_8
|
object.contents_utf_8
|
||||||
|
@ -14,20 +14,23 @@ class ResultTableSerializer < ActiveModel::Serializer
|
||||||
'fa-table'
|
'fa-table'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parent_type
|
||||||
|
:result
|
||||||
|
end
|
||||||
|
|
||||||
def urls
|
def urls
|
||||||
return if object.destroyed?
|
return if object.destroyed?
|
||||||
|
|
||||||
object.reload unless object.result
|
object.reload unless object.result
|
||||||
|
|
||||||
p object.result
|
|
||||||
p scope[:user] || @instance_options[:user]
|
|
||||||
p can_manage_result?(scope[:user] || @instance_options[:user], object.result)
|
|
||||||
return {} unless can_manage_result?(scope[:user] || @instance_options[:user], object.result)
|
return {} unless can_manage_result?(scope[:user] || @instance_options[:user], object.result)
|
||||||
|
|
||||||
{
|
{
|
||||||
duplicate_url: duplicate_my_module_result_table_path(object.result.my_module, object.result, object),
|
duplicate_url: duplicate_my_module_result_table_path(object.result.my_module, object.result, object),
|
||||||
delete_url: my_module_result_table_path(object.result.my_module, object.result, object),
|
delete_url: my_module_result_table_path(object.result.my_module, object.result, object),
|
||||||
update_url: my_module_result_table_path(object.result.my_module, object.result, object)
|
update_url: my_module_result_table_path(object.result.my_module, object.result, object),
|
||||||
|
move_targets_url: move_targets_my_module_result_table_path(object.result.my_module, object.result, object),
|
||||||
|
move_url: move_my_module_result_table_path(object.result.my_module, object.result, object)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ class ResultTextSerializer < ActiveModel::Serializer
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include ActionView::Helpers::TextHelper
|
include ActionView::Helpers::TextHelper
|
||||||
|
|
||||||
attributes :id, :text, :urls, :text_view, :icon, :placeholder, :name
|
attributes :id, :text, :urls, :text_view, :icon, :placeholder, :name, :parent_type
|
||||||
|
|
||||||
def updated_at
|
def updated_at
|
||||||
object.updated_at.to_i
|
object.updated_at.to_i
|
||||||
|
@ -16,6 +16,10 @@ class ResultTextSerializer < ActiveModel::Serializer
|
||||||
I18n.t('protocols.steps.text.placeholder')
|
I18n.t('protocols.steps.text.placeholder')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parent_type
|
||||||
|
:result
|
||||||
|
end
|
||||||
|
|
||||||
def text_view
|
def text_view
|
||||||
@user = scope[:user]
|
@user = scope[:user]
|
||||||
custom_auto_link(object.tinymce_render('text'),
|
custom_auto_link(object.tinymce_render('text'),
|
||||||
|
@ -40,7 +44,9 @@ class ResultTextSerializer < ActiveModel::Serializer
|
||||||
{
|
{
|
||||||
duplicate_url: duplicate_my_module_result_text_path(result.my_module, result, object),
|
duplicate_url: duplicate_my_module_result_text_path(result.my_module, result, object),
|
||||||
delete_url: my_module_result_text_path(result.my_module, result, object),
|
delete_url: my_module_result_text_path(result.my_module, result, object),
|
||||||
update_url: my_module_result_text_path(result.my_module, result, object)
|
update_url: my_module_result_text_path(result.my_module, result, object),
|
||||||
|
move_targets_url: move_targets_my_module_result_text_path(result.my_module, result, object),
|
||||||
|
move_url: move_my_module_result_text_path(result.my_module, result, object)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,16 @@ class StepTextSerializer < ActiveModel::Serializer
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include ActionView::Helpers::TextHelper
|
include ActionView::Helpers::TextHelper
|
||||||
|
|
||||||
attributes :id, :text, :urls, :text_view, :updated_at, :icon, :name, :placeholder
|
attributes :id, :text, :urls, :text_view, :updated_at, :icon, :name, :placeholder, :parent_type
|
||||||
|
|
||||||
def updated_at
|
def updated_at
|
||||||
object.updated_at.to_i
|
object.updated_at.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parent_type
|
||||||
|
:step
|
||||||
|
end
|
||||||
|
|
||||||
def placeholder
|
def placeholder
|
||||||
I18n.t('protocols.steps.text.placeholder')
|
I18n.t('protocols.steps.text.placeholder')
|
||||||
end
|
end
|
||||||
|
@ -38,7 +42,9 @@ class StepTextSerializer < ActiveModel::Serializer
|
||||||
{
|
{
|
||||||
duplicate_url: duplicate_step_text_path(object.step, object),
|
duplicate_url: duplicate_step_text_path(object.step, object),
|
||||||
delete_url: step_text_path(object.step, object),
|
delete_url: step_text_path(object.step, object),
|
||||||
update_url: step_text_path(object.step, object)
|
update_url: step_text_path(object.step, object),
|
||||||
|
move_url: move_step_text_path(object.step, object),
|
||||||
|
move_targets_url: move_targets_step_text_path(object.step, object)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ class TableSerializer < ActiveModel::Serializer
|
||||||
include Canaid::Helpers::PermissionsHelper
|
include Canaid::Helpers::PermissionsHelper
|
||||||
include Rails.application.routes.url_helpers
|
include Rails.application.routes.url_helpers
|
||||||
|
|
||||||
attributes :name, :contents, :urls, :icon, :metadata
|
attributes :name, :contents, :urls, :icon, :metadata, :parent_type
|
||||||
|
|
||||||
def contents
|
def contents
|
||||||
object.contents_utf_8
|
object.contents_utf_8
|
||||||
|
@ -14,6 +14,10 @@ class TableSerializer < ActiveModel::Serializer
|
||||||
'fa-table'
|
'fa-table'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parent_type
|
||||||
|
:step
|
||||||
|
end
|
||||||
|
|
||||||
def urls
|
def urls
|
||||||
return if object.destroyed?
|
return if object.destroyed?
|
||||||
|
|
||||||
|
@ -24,7 +28,9 @@ class TableSerializer < ActiveModel::Serializer
|
||||||
{
|
{
|
||||||
duplicate_url: duplicate_step_table_path(object.step, object),
|
duplicate_url: duplicate_step_table_path(object.step, object),
|
||||||
delete_url: step_table_path(object.step, object),
|
delete_url: step_table_path(object.step, object),
|
||||||
update_url: step_table_path(object.step, object)
|
update_url: step_table_path(object.step, object),
|
||||||
|
move_targets_url: move_targets_step_table_path(object.step, object),
|
||||||
|
move_url: move_step_table_path(object.step, object)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3099,6 +3099,13 @@ en:
|
||||||
description_1: 'You’re about to delete a content block from your protocol. It might contain data you don’t want to lose. You won’t be able to get it back.'
|
description_1: 'You’re about to delete a content block from your protocol. It might contain data you don’t want to lose. You won’t be able to get it back.'
|
||||||
description_2: 'Are you sure you want to delete it?'
|
description_2: 'Are you sure you want to delete it?'
|
||||||
confirm: 'Delete forever'
|
confirm: 'Delete forever'
|
||||||
|
move_element:
|
||||||
|
step:
|
||||||
|
title: Move to different step
|
||||||
|
targets_label: Select step
|
||||||
|
result:
|
||||||
|
title: Move to different result
|
||||||
|
targets_label: Select result
|
||||||
delete_step:
|
delete_step:
|
||||||
title: 'Delete step'
|
title: 'Delete step'
|
||||||
description_1: 'You’re about to delete a whole step from your protocol. It might contain data you don’t want to lose. You won’t be able to get it back.'
|
description_1: 'You’re about to delete a whole step from your protocol. It might contain data you don’t want to lose. You won’t be able to get it back.'
|
||||||
|
|
|
@ -542,11 +542,15 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resources :tables, controller: 'result_elements/tables', only: %i(create destroy update) do
|
resources :tables, controller: 'result_elements/tables', only: %i(create destroy update) do
|
||||||
member do
|
member do
|
||||||
|
get :move_targets
|
||||||
|
post :move
|
||||||
post :duplicate
|
post :duplicate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :texts, controller: 'result_elements/texts', only: %i(create destroy update) do
|
resources :texts, controller: 'result_elements/texts', only: %i(create destroy update) do
|
||||||
member do
|
member do
|
||||||
|
get :move_targets
|
||||||
|
post :move
|
||||||
post :duplicate
|
post :duplicate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -562,16 +566,22 @@ Rails.application.routes.draw do
|
||||||
only: %i(create index update destroy)
|
only: %i(create index update destroy)
|
||||||
resources :tables, controller: 'step_elements/tables', only: %i(create destroy update) do
|
resources :tables, controller: 'step_elements/tables', only: %i(create destroy update) do
|
||||||
member do
|
member do
|
||||||
|
get :move_targets
|
||||||
|
post :move
|
||||||
post :duplicate
|
post :duplicate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :texts, controller: 'step_elements/texts', only: %i(create destroy update) do
|
resources :texts, controller: 'step_elements/texts', only: %i(create destroy update) do
|
||||||
member do
|
member do
|
||||||
|
get :move_targets
|
||||||
|
post :move
|
||||||
post :duplicate
|
post :duplicate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :checklists, controller: 'step_elements/checklists', only: %i(create destroy update) do
|
resources :checklists, controller: 'step_elements/checklists', only: %i(create destroy update) do
|
||||||
member do
|
member do
|
||||||
|
get :move_targets
|
||||||
|
post :move
|
||||||
post :duplicate
|
post :duplicate
|
||||||
end
|
end
|
||||||
resources :checklist_items, controller: 'step_elements/checklist_items', only: %i(create update destroy) do
|
resources :checklist_items, controller: 'step_elements/checklist_items', only: %i(create update destroy) do
|
||||||
|
|
Loading…
Add table
Reference in a new issue