mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-06 03:46:39 +08:00
Add elements and attachments to new result [SCI-8953]
This commit is contained in:
parent
ac37885885
commit
f6191dbb67
14 changed files with 531 additions and 23 deletions
56
app/controllers/result_elements/base_controller.rb
Normal file
56
app/controllers/result_elements/base_controller.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ResultElements
|
||||
class BaseController < ApplicationController
|
||||
before_action :load_result_and_my_module
|
||||
before_action :check_manage_permissions
|
||||
|
||||
private
|
||||
|
||||
def load_result_and_my_module
|
||||
@result = Result.find_by(id: params[:result_id])
|
||||
return render_404 unless @result
|
||||
|
||||
@my_module = @result.my_module
|
||||
end
|
||||
|
||||
def check_manage_permissions
|
||||
render_403 unless can_manage_my_module?(@my_module)
|
||||
end
|
||||
|
||||
def create_in_result!(result, new_orderable)
|
||||
ActiveRecord::Base.transaction do
|
||||
new_orderable.save!
|
||||
|
||||
result.result_orderable_elements.create!(
|
||||
position: result.result_orderable_elements.length,
|
||||
orderable: new_orderable
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def render_result_orderable_element(orderable)
|
||||
result_orderable_element = orderable.result_orderable_element
|
||||
render json: result_orderable_element, serializer: ResultOrderableElementSerializer, user: current_user
|
||||
end
|
||||
|
||||
def log_step_activity(element_type_of, message_items)
|
||||
# TODO
|
||||
#message_items[:my_module] = @protocol.my_module.id if @protocol.in_module?
|
||||
#Activities::CreateActivityService.call(
|
||||
# activity_type: "#{!@step.protocol.in_module? ? 'protocol_step_' : 'task_step_'}#{element_type_of}",
|
||||
# owner: current_user,
|
||||
# team: @protocol.team,
|
||||
# project: @protocol.in_module? ? @protocol.my_module.project : nil,
|
||||
# subject: @protocol,
|
||||
# message_items: {
|
||||
# step: @step.id,
|
||||
# step_position: {
|
||||
# id: @step.id,
|
||||
# value_for: 'position_plus_one'
|
||||
# },
|
||||
# }.merge(message_items)
|
||||
#)
|
||||
end
|
||||
end
|
||||
end
|
99
app/controllers/result_elements/tables_controller.rb
Normal file
99
app/controllers/result_elements/tables_controller.rb
Normal file
|
@ -0,0 +1,99 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ResultElements
|
||||
class TablesController < BaseController
|
||||
before_action :load_table, only: %i(update destroy duplicate)
|
||||
|
||||
def create
|
||||
predefined_table_dimensions = create_table_params[:tableDimensions].map(&:to_i)
|
||||
name = if predefined_table_dimensions[0] == predefined_table_dimensions[1]
|
||||
t('protocols.steps.table.default_name',
|
||||
position: @step.step_tables.length + 1)
|
||||
else
|
||||
t('protocols.steps.plate.default_name',
|
||||
position: @step.step_tables.length + 1)
|
||||
end
|
||||
result_table = @result.result_tables.new(table:
|
||||
Table.new(
|
||||
name: name,
|
||||
contents: { data: Array.new(predefined_table_dimensions[0],
|
||||
Array.new(predefined_table_dimensions[1], '')) }.to_json,
|
||||
metadata: { plateTemplate: create_table_params[:plateTemplate] == 'true' },
|
||||
created_by: current_user,
|
||||
team: @my_module.team
|
||||
))
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
create_in_step!(@step, step_table)
|
||||
# log_step_activity(:table_added, { table_name: step_table.table.name })
|
||||
end
|
||||
|
||||
render_result_orderable_element(step_table)
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
head :unprocessable_entity
|
||||
end
|
||||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
@table.assign_attributes(table_params.except(:metadata))
|
||||
begin
|
||||
if table_params[:metadata].present?
|
||||
|
||||
@table.metadata = if @table.metadata
|
||||
@table.metadata.merge(JSON.parse(table_params[:metadata]))
|
||||
else
|
||||
JSON.parse(table_params[:metadata])
|
||||
end
|
||||
end
|
||||
rescue JSON::ParserError
|
||||
@table.metadata = {}
|
||||
end
|
||||
@table.save!
|
||||
#log_step_activity(:table_edited, { table_name: @table.name })
|
||||
end
|
||||
|
||||
render json: @table, serializer: ResultTableSerializer, user: current_user
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
head :unprocessable_entity
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @table.destroy
|
||||
#log_step_activity(:table_deleted, { table_name: @table.name })
|
||||
head :ok
|
||||
else
|
||||
head :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def duplicate
|
||||
#ActiveRecord::Base.transaction do
|
||||
# position = @table.step_table.step_orderable_element.position
|
||||
# @step.step_orderable_elements.where('position > ?', position).order(position: :desc).each do |element|
|
||||
# element.update(position: element.position + 1)
|
||||
# end
|
||||
# @table.name += ' (1)'
|
||||
# new_table = @table.duplicate(@step, current_user, position + 1)
|
||||
# log_step_activity(:table_duplicated, { table_name: new_table.name })
|
||||
# render_step_orderable_element(new_table.step_table)
|
||||
#end
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
head :unprocessable_entity
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def table_params
|
||||
params.permit(:name, :contents, :metadata)
|
||||
end
|
||||
|
||||
def create_table_params
|
||||
params.permit(:plateTemplate, tableDimensions: [])
|
||||
end
|
||||
|
||||
def load_table
|
||||
@table = @result.tables.find_by(id: params[:id])
|
||||
return render_404 unless @table
|
||||
end
|
||||
end
|
||||
end
|
95
app/controllers/result_elements/texts_controller.rb
Normal file
95
app/controllers/result_elements/texts_controller.rb
Normal file
|
@ -0,0 +1,95 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ResultElements
|
||||
class TextsController < BaseController
|
||||
include ActionView::Helpers::UrlHelper
|
||||
include ApplicationHelper
|
||||
include InputSanitizeHelper
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
before_action :load_result_text, only: %i(update destroy duplicate)
|
||||
|
||||
def create
|
||||
result_text = @result.result_texts.build
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
create_in_step!(@result, result_text)
|
||||
#log_step_activity(:text_added, { text_name: step_text.name })
|
||||
end
|
||||
|
||||
render_result_orderable_element(result_text)
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
head :unprocessable_entity
|
||||
end
|
||||
|
||||
def update
|
||||
old_text = @result_text.text
|
||||
ActiveRecord::Base.transaction do
|
||||
@result_text.update!(result_text_params)
|
||||
TinyMceAsset.update_images(@result_text, params[:tiny_mce_images], current_user)
|
||||
#log_step_activity(:text_edited, { text_name: @step_text.name })
|
||||
result_annotation_notification(old_text)
|
||||
end
|
||||
|
||||
render json: @result_text, serializer: ResultTextSerializer, user: current_user
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render json: @result_text.errors, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @result_text.destroy
|
||||
log_step_activity(:text_deleted, { text_name: @result_text.name })
|
||||
head :ok
|
||||
else
|
||||
head :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def duplicate
|
||||
#ActiveRecord::Base.transaction do
|
||||
# position = @step_text.step_orderable_element.position
|
||||
# @step.step_orderable_elements.where('position > ?', position).order(position: :desc).each do |element|
|
||||
# element.update(position: element.position + 1)
|
||||
# end
|
||||
# new_step_text = @step_text.duplicate(@step, position + 1)
|
||||
# log_step_activity(:text_duplicated, { text_name: new_step_text.name })
|
||||
# render_step_orderable_element(new_step_text)
|
||||
#end
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
head :unprocessable_entity
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def result_text_params
|
||||
params.require(:text_component).permit(:text)
|
||||
end
|
||||
|
||||
def load_result_text
|
||||
@result_text = @result.result_texts.find_by(id: params[:id])
|
||||
return render_404 unless @result_text
|
||||
end
|
||||
|
||||
def result_annotation_notification(old_text = nil)
|
||||
smart_annotation_notification(
|
||||
old_text: (old_text if old_text),
|
||||
new_text: @result_text.text,
|
||||
title: t('notifications.result_annotation_title',
|
||||
result: @result.name,
|
||||
user: current_user.full_name),
|
||||
message: t('notifications.result_annotation_message_html',
|
||||
project: link_to(@result.my_module.experiment.project.name,
|
||||
project_url(@result.my_module
|
||||
.experiment
|
||||
.project)),
|
||||
experiment: link_to(@result.my_module.experiment.name,
|
||||
my_modules_experiment_url(@result.my_module
|
||||
.experiment)),
|
||||
my_module: link_to(@result.my_module.name,
|
||||
protocols_my_module_url(
|
||||
@result.my_module
|
||||
)))
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,6 +4,7 @@ import Results from '../../vue/results/results.vue';
|
|||
|
||||
Vue.use(TurbolinksAdapter);
|
||||
Vue.prototype.i18n = window.I18n;
|
||||
Vue.prototype.ActiveStoragePreviews = window.ActiveStoragePreviews;
|
||||
|
||||
new Vue({
|
||||
el: '#results',
|
||||
|
|
|
@ -222,7 +222,7 @@
|
|||
import ReorderableItemsModal from '../shared/reorderable_items_modal.vue'
|
||||
|
||||
import UtilsMixin from '../mixins/utils.js'
|
||||
import AttachmentsMixin from './mixins/attachments.js'
|
||||
import AttachmentsMixin from '../shared/content/mixins/attachments.js'
|
||||
import WopiFileModal from '../shared/content/attachments/mixins/wopi_file_modal.js'
|
||||
import StorageUsage from '../shared/content/attachments/storage_usage.vue'
|
||||
|
||||
|
|
|
@ -5,6 +5,68 @@
|
|||
<button @click="openReorderModal">
|
||||
Open Rearrange Modal
|
||||
</button>
|
||||
<div>
|
||||
<input type="file" class="hidden" ref="fileSelector" @change="loadFromComputer" multiple />
|
||||
<div ref="elementsDropdownButton" v-if="urls.update_url" class="dropdown">
|
||||
<button class="btn btn-light dropdown-toggle insert-button" type="button" :id="'stepInserMenu_' + step.id" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
{{ i18n.t('protocols.steps.insert.button') }}
|
||||
<span class="sn-icon sn-icon-down"></span>
|
||||
</button>
|
||||
<ul ref="elementsDropdown" class="dropdown-menu insert-element-dropdown dropdown-menu-right" :aria-labelledby="'stepInserMenu_' + step.id">
|
||||
<li class="title">
|
||||
{{ i18n.t('protocols.steps.insert.title') }}
|
||||
</li>
|
||||
<li class="action" @click="createElement('table')">
|
||||
<i class="sn-icon sn-icon-tables"></i>
|
||||
{{ i18n.t('protocols.steps.insert.table') }}
|
||||
</li>
|
||||
<li class="action dropdown-submenu-item">
|
||||
<i class="sn-icon sn-icon-tables"></i>
|
||||
{{ i18n.t('protocols.steps.insert.well_plate') }}
|
||||
<span class="caret"></span>
|
||||
|
||||
<ul class="dropdown-submenu">
|
||||
<li v-for="option in wellPlateOptions" :key="option.dimensions.toString()" class="action" @click="createElement('table', option.dimensions, true)">
|
||||
{{ i18n.t(option.label) }}
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="action" @click="createElement('checklist')">
|
||||
<i class="sn-icon sn-icon-activities"></i>
|
||||
{{ i18n.t('protocols.steps.insert.checklist') }}
|
||||
</li>
|
||||
<li class="action" @click="createElement('text')">
|
||||
<i class="sn-icon sn-icon-result-text"></i>
|
||||
{{ i18n.t('protocols.steps.insert.text') }}
|
||||
</li>
|
||||
<li class="action dropdown-submenu-item">
|
||||
<i class="sn-icon sn-icon-files"></i>
|
||||
{{ i18n.t('protocols.steps.insert.attachment') }}
|
||||
<span class="caret"></span>
|
||||
<ul class="dropdown-submenu">
|
||||
<li class="action" @click="openLoadFromComputer">
|
||||
{{ i18n.t('protocols.steps.insert.add_file') }}
|
||||
</li>
|
||||
<li class="action" v-if="step.attributes.wopi_enabled" @click="openWopiFileModal">
|
||||
{{ i18n.t('assets.create_wopi_file.button_text') }}
|
||||
</li>
|
||||
<li class="action" v-if="step.attributes.marvinjs_enabled" @click="openMarvinJsModal($refs.marvinJsButton)">
|
||||
<span
|
||||
class="new-marvinjs-upload-button text-sn-black text-decoration-none"
|
||||
:data-object-id="step.id"
|
||||
ref="marvinJsButton"
|
||||
:data-marvin-url="step.attributes.marvinjs_context.marvin_js_asset_url"
|
||||
:data-object-type="step.attributes.type"
|
||||
tabindex="0"
|
||||
>
|
||||
{{ i18n.t('marvinjs.new_button') }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<ReorderableItemsModal v-if="reordering"
|
||||
title="Placeholder title for this modal"
|
||||
|
@ -12,12 +74,46 @@
|
|||
@reorder="updateElementOrder"
|
||||
@close="closeReorderModal"
|
||||
/>
|
||||
<div>
|
||||
<template v-for="(element, index) in orderedElements">
|
||||
<component
|
||||
:is="elements[index].attributes.orderable_type"
|
||||
:key="index"
|
||||
:element.sync="elements[index]"
|
||||
:inRepository="false"
|
||||
:reorderElementUrl="elements.length > 1 ? urls.reorder_elements_url : ''"
|
||||
:assignableMyModuleId="result.attributes.my_module_id"
|
||||
:isNew="element.isNew"
|
||||
@component:delete="deleteElement"
|
||||
@update="updateElement"
|
||||
@reorder="openReorderModal"
|
||||
@component:insert="insertElement"
|
||||
/>
|
||||
</template>
|
||||
<Attachments v-if="attachments.length"
|
||||
:parent="result"
|
||||
:attachments="attachments"
|
||||
:attachmentsReady="attachmentsReady"
|
||||
@attachments:openFileModal="showFileModal = true"
|
||||
@attachment:deleted="attachmentDeleted"
|
||||
@attachment:uploaded="loadAttachments"
|
||||
@attachments:order="() => {}"
|
||||
@attachments:viewMode="() => {}"
|
||||
@attachment:viewMode="() => {}"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import ReorderableItemsModal from '../shared/reorderable_items_modal.vue'
|
||||
import ReorderableItemsModal from '../shared/reorderable_items_modal.vue';
|
||||
import ResultTable from '../shared/content/table.vue';
|
||||
import ResultText from '../shared/content/text.vue';
|
||||
import Attachments from '../shared/content/attachments.vue';
|
||||
|
||||
import AttachmentsMixin from '../shared/content/mixins/attachments.js'
|
||||
import WopiFileModal from '../shared/content/attachments/mixins/wopi_file_modal.js'
|
||||
import UtilsMixin from '../mixins/utils.js'
|
||||
|
||||
export default {
|
||||
name: 'Results',
|
||||
|
@ -27,11 +123,18 @@
|
|||
data() {
|
||||
return {
|
||||
reordering: false,
|
||||
elements: []
|
||||
elements: [],
|
||||
attachments: [],
|
||||
attachmentsReady: false,
|
||||
showFileModal: false
|
||||
}
|
||||
},
|
||||
mixins: [UtilsMixin, AttachmentsMixin, WopiFileModal],
|
||||
components: {
|
||||
ReorderableItemsModal
|
||||
ReorderableItemsModal,
|
||||
ResultTable,
|
||||
ResultText,
|
||||
Attachments
|
||||
},
|
||||
computed: {
|
||||
reorderableElements() {
|
||||
|
@ -44,6 +147,10 @@
|
|||
return this.result.attributes.urls || {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadAttachments();
|
||||
this.loadElements();
|
||||
},
|
||||
methods: {
|
||||
openReorderModal() {
|
||||
this.reordering = true;
|
||||
|
@ -76,6 +183,37 @@
|
|||
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||
});
|
||||
},
|
||||
deleteElement(element) {
|
||||
},
|
||||
updateElement(element) {
|
||||
},
|
||||
insertElement(element) {
|
||||
},
|
||||
loadElements() {
|
||||
$.get(this.urls.elements_url, (result) => {
|
||||
this.elements = result.data
|
||||
});
|
||||
},
|
||||
loadAttachments() {
|
||||
this.attachmentsReady = false
|
||||
|
||||
$.get(this.urls.attachments_url, (result) => {
|
||||
this.attachments = result.data
|
||||
|
||||
if (this.attachments.findIndex((e) => e.attributes.attached === false) >= 0) {
|
||||
setTimeout(() => {
|
||||
this.loadAttachments()
|
||||
}, 10000)
|
||||
} else {
|
||||
this.attachmentsReady = true
|
||||
}
|
||||
});
|
||||
this.showFileModal = false;
|
||||
},
|
||||
attachmentDeleted(id) {
|
||||
this.attachments = this.attachments.filter((a) => a.id !== id );
|
||||
this.$emit('resultUpdated');
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -10,6 +10,14 @@ export default {
|
|||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
attachmentsParent() {
|
||||
return this.step || this.result;
|
||||
},
|
||||
attachmentsParentName() {
|
||||
return this.step ? 'step' : 'result';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
dropFile(e) {
|
||||
if (!this.showFileModal && e.dataTransfer && e.dataTransfer.files.length) {
|
||||
|
@ -30,7 +38,7 @@ export default {
|
|||
button.click();
|
||||
},
|
||||
openWopiFileModal() {
|
||||
this.initWopiFileModal(this.step, (_e, data, status) => {
|
||||
this.initWopiFileModal(this.attachmentsParent, (_e, data, status) => {
|
||||
if (status === 'success') {
|
||||
this.addAttachment(data)
|
||||
} else {
|
||||
|
@ -43,17 +51,17 @@ export default {
|
|||
let filesUploadedCntr = 0;
|
||||
this.showFileModal = false;
|
||||
|
||||
if (!this.step.attributes.urls.upload_attachment_url) return false;
|
||||
if (!this.attachmentsParent.attributes.urls.upload_attachment_url) return false;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
$(files).each((_, file) => {
|
||||
const fileObject = {
|
||||
attributes: {
|
||||
progress: 0,
|
||||
view_mode: this.step.attributes.assets_view_mode,
|
||||
view_mode: this.attachmentsParent.attributes.assets_view_mode,
|
||||
file_name: file.name,
|
||||
uploading: true,
|
||||
asset_order: this.viewModeOrder[this.step.attributes.assets_view_mode]
|
||||
asset_order: this.viewModeOrder[this.attachmentsParent.attributes.assets_view_mode]
|
||||
},
|
||||
directUploadWillStoreFileWithXHR(request) {
|
||||
request.upload.addEventListener('progress', (e) => {
|
||||
|
@ -68,16 +76,16 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
const storageLimit = this.step.attributes.storage_limit &&
|
||||
this.step.attributes.storage_limit.total > 0 &&
|
||||
this.step.attributes.storage_limit.used >= this.step.attributes.storage_limit.total;
|
||||
const storageLimit = this.attachmentsParent.attributes.storage_limit &&
|
||||
this.attachmentsParent.attributes.storage_limit.total > 0 &&
|
||||
this.attachmentsParent.attributes.storage_limit.used >= this.attachmentsParent.attributes.storage_limit.total;
|
||||
if (storageLimit) {
|
||||
fileObject.error = I18n.t('protocols.steps.attachments.new.no_more_space');
|
||||
this.attachments.push(fileObject);
|
||||
return;
|
||||
}
|
||||
|
||||
const upload = new ActiveStorage.DirectUpload(file, this.step.attributes.urls.direct_upload_url, fileObject);
|
||||
const upload = new ActiveStorage.DirectUpload(file, this.attachmentsParent.attributes.urls.direct_upload_url, fileObject);
|
||||
|
||||
fileObject.isNewUpload = true;
|
||||
this.attachments.push(fileObject);
|
||||
|
@ -93,7 +101,7 @@ export default {
|
|||
reject(error);
|
||||
} else {
|
||||
const signedId = blob.signed_id;
|
||||
$.post(this.step.attributes.urls.upload_attachment_url, {
|
||||
$.post(this.attachmentsParent.attributes.urls.upload_attachment_url, {
|
||||
signed_blob_id: signedId
|
||||
}, (result) => {
|
||||
fileObject.id = result.data.id;
|
||||
|
@ -108,7 +116,7 @@ export default {
|
|||
filesUploadedCntr += 1;
|
||||
if (filesUploadedCntr === filesToUploadCntr) {
|
||||
setTimeout(() => {
|
||||
this.$emit('stepUpdated');
|
||||
this.$emit(`${this.attachmentsParentName}Updated`);
|
||||
}, 1000);
|
||||
resolve('done');
|
||||
}
|
||||
|
@ -118,18 +126,18 @@ export default {
|
|||
});
|
||||
},
|
||||
changeAttachmentsOrder(order) {
|
||||
this.step.attributes.assets_order = order;
|
||||
$.post(this.step.attributes.urls.update_view_state_step_url, {
|
||||
this.attachmentsParent.attributes.assets_order = order;
|
||||
$.post(this.attachmentsParent.attributes.urls.update_view_state_url, {
|
||||
assets: { order }
|
||||
});
|
||||
},
|
||||
changeAttachmentsViewMode(viewMode) {
|
||||
this.step.attributes.assets_view_mode = viewMode;
|
||||
this.attachmentsParent.attributes.assets_view_mode = viewMode;
|
||||
this.attachments.forEach((attachment) => {
|
||||
this.$set(attachment.attributes, 'view_mode', viewMode);
|
||||
this.$set(attachment.attributes, 'asset_order', this.viewModeOrder[viewMode]);
|
||||
});
|
||||
$.post(this.step.attributes.urls.update_asset_view_mode_url, {
|
||||
$.post(this.attachmentsParent.attributes.urls.update_asset_view_mode_url, {
|
||||
assets_view_mode: viewMode
|
||||
});
|
||||
},
|
14
app/serializers/result_orderable_element_serializer.rb
Normal file
14
app/serializers/result_orderable_element_serializer.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ResultOrderableElementSerializer < ActiveModel::Serializer
|
||||
attributes :position, :orderable, :orderable_type
|
||||
|
||||
def orderable
|
||||
case object.orderable_type
|
||||
when 'ResultTable'
|
||||
ResultTableSerializer.new(object.orderable.table, scope: { user: @instance_options[:user] }).as_json
|
||||
when 'ResultText'
|
||||
ResultTextSerializer.new(object.orderable, scope: { user: @instance_options[:user] }).as_json
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,7 +7,7 @@ class ResultSerializer < ActiveModel::Serializer
|
|||
include ActionView::Helpers::TextHelper
|
||||
include InputSanitizeHelper
|
||||
|
||||
attributes :name, :id, :urls, :updated_at, :created_at_formatted, :updated_at_formatted, :user
|
||||
attributes :name, :id, :urls, :updated_at, :created_at_formatted, :updated_at_formatted, :user, :my_module_id
|
||||
|
||||
def updated_at
|
||||
object.updated_at.to_i
|
||||
|
@ -30,7 +30,8 @@ class ResultSerializer < ActiveModel::Serializer
|
|||
|
||||
def urls
|
||||
{
|
||||
|
||||
elements_url: elements_my_module_result_path(object.my_module, object),
|
||||
attachments_url: assets_my_module_result_path(object.my_module, object)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
33
app/serializers/result_table_serializer.rb
Normal file
33
app/serializers/result_table_serializer.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ResultTableSerializer < ActiveModel::Serializer
|
||||
include Canaid::Helpers::PermissionsHelper
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
attributes :name, :contents, :urls, :icon, :metadata
|
||||
|
||||
def contents
|
||||
object.contents_utf_8
|
||||
end
|
||||
|
||||
def icon
|
||||
'fa-table'
|
||||
end
|
||||
|
||||
def urls
|
||||
return if object.destroyed?
|
||||
|
||||
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)
|
||||
|
||||
{
|
||||
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),
|
||||
update_url: my_module_result_table_path(object.result.my_module, object.result, object)
|
||||
}
|
||||
end
|
||||
end
|
46
app/serializers/result_text_serializer.rb
Normal file
46
app/serializers/result_text_serializer.rb
Normal file
|
@ -0,0 +1,46 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ResultTextSerializer < ActiveModel::Serializer
|
||||
include Canaid::Helpers::PermissionsHelper
|
||||
include Rails.application.routes.url_helpers
|
||||
include ApplicationHelper
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
attributes :id, :text, :urls, :text_view, :icon, :placeholder
|
||||
|
||||
def updated_at
|
||||
object.updated_at.to_i
|
||||
end
|
||||
|
||||
def placeholder
|
||||
I18n.t('protocols.steps.text.placeholder')
|
||||
end
|
||||
|
||||
def text_view
|
||||
@user = scope[:user]
|
||||
custom_auto_link(object.tinymce_render('text'),
|
||||
simple_format: false,
|
||||
tags: %w(img),
|
||||
team: object.result.my_module.team)
|
||||
end
|
||||
|
||||
def text
|
||||
sanitize_input(object.tinymce_render('text'))
|
||||
end
|
||||
|
||||
def icon
|
||||
'fa-font'
|
||||
end
|
||||
|
||||
def urls
|
||||
result = object.result
|
||||
|
||||
return {} if object.destroyed? || !can_manage_result?(scope[:user] || @instance_options[:user], result)
|
||||
|
||||
{
|
||||
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),
|
||||
update_url: my_module_result_text_path(result.my_module, result, object)
|
||||
}
|
||||
end
|
||||
end
|
|
@ -84,7 +84,7 @@ class StepSerializer < ActiveModel::Serializer
|
|||
create_text_url: step_texts_path(object),
|
||||
create_checklist_url: step_checklists_path(object),
|
||||
update_asset_view_mode_url: update_asset_view_mode_step_path(object),
|
||||
update_view_state_step_url: update_view_state_step_path(object),
|
||||
update_view_state_url: update_view_state_step_path(object),
|
||||
direct_upload_url: rails_direct_uploads_url,
|
||||
upload_attachment_url: upload_attachment_step_path(object),
|
||||
reorder_elements_url: reorder_step_step_orderable_elements_path(step_id: object.id)
|
||||
|
|
|
@ -18,4 +18,8 @@
|
|||
<results url="<%= my_module_results_url(@my_module) %>">
|
||||
</div>
|
||||
|
||||
<%= javascript_include_tag "handsontable.full" %>
|
||||
<%= render partial: "shared/formulas_libraries" %>
|
||||
<%= render 'shared/tiny_mce_packs' %>
|
||||
<%= javascript_include_tag 'vue_results' %>
|
||||
|
||||
|
|
|
@ -535,8 +535,21 @@ Rails.application.routes.draw do
|
|||
get 'users/edit', to: 'user_my_modules#index_edit'
|
||||
|
||||
resources :results, only: %i(index show create update destroy) do
|
||||
get :elements
|
||||
get :assets
|
||||
member do
|
||||
get :elements
|
||||
get :assets
|
||||
end
|
||||
|
||||
resources :tables, controller: 'result_elements/tables', only: %i(create destroy update) do
|
||||
member do
|
||||
post :duplicate
|
||||
end
|
||||
end
|
||||
resources :texts, controller: 'result_elements/texts', only: %i(create destroy update) do
|
||||
member do
|
||||
post :duplicate
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue