Merge pull request #4139 from aignatov-bio/ai-sci-6867-add-view-mode-for-protocol-and-step

Add view mode to protocol and step [SCI-6867]
This commit is contained in:
aignatov-bio 2022-06-03 15:27:15 +02:00 committed by GitHub
commit d7926654ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 231 additions and 133 deletions

View file

@ -32,6 +32,10 @@
border: 1px solid $brand-primary;
}
.sci-checkbox-container.disabled {
pointer-events: none;
}
.sci-inline-edit {
font-weight: normal;

View file

@ -22,9 +22,11 @@ module StepElements
)
end
render json: checklist_item, serializer: ChecklistItemSerializer
render json: checklist_item, serializer: ChecklistItemSerializer, user: current_user
rescue ActiveRecord::RecordInvalid
render json: checklist_item, serializer: ChecklistItemSerializer, status: :unprocessable_entity
render json: checklist_item, serializer: ChecklistItemSerializer,
user: current_user,
status: :unprocessable_entity
end
def update
@ -53,9 +55,11 @@ module StepElements
end
end
render json: @checklist_item, serializer: ChecklistItemSerializer
render json: @checklist_item, serializer: ChecklistItemSerializer, user: current_user
rescue ActiveRecord::RecordInvalid
render json: @checklist_item, serializer: ChecklistItemSerializer, status: :unprocessable_entity
render json: @checklist_item, serializer: ChecklistItemSerializer,
user: current_user,
status: :unprocessable_entity
end
def destroy
@ -65,9 +69,11 @@ module StepElements
checklist_item: @checklist_item.text,
checklist_name: @checklist.name
)
render json: @checklist_item, serializer: ChecklistItemSerializer
render json: @checklist_item, serializer: ChecklistItemSerializer, user: current_user
else
render json: @checklist_item, serializer: ChecklistItemSerializer, status: :unprocessable_entity
render json: @checklist_item, serializer: ChecklistItemSerializer,
user: current_user,
status: :unprocessable_entity
end
end

View file

@ -18,10 +18,7 @@ window.initProtocolComponent = () => {
},
data() {
return {
protocolUrl: $('#protocolContainer').data('protocol-url'),
stepsUrl: $('#protocolContainer').data('steps-url'),
addStepUrl: $('#protocolContainer').data('add-step-url'),
editable: $('#protocolContainer').data('editable')
protocolUrl: $('#protocolContainer').data('protocol-url')
};
}
});

View file

@ -25,16 +25,18 @@
{{ i18n.t(`general.sort_new.${orderOption}`) }}
</a>
</li>
<li role="separator" class="divider"></li>
<li class="divider-label">{{ i18n.t("protocols.steps.attachments.attachments_view_mode") }}</li>
<li v-for="(viewMode, index) in viewModeOptions" :key="`viewMode_${index}`">
<a
class="attachments-view-mode action-link"
:class="viewMode == step.attributes.assets_view_mode ? 'selected' : ''"
@click="changeAttachmentsViewMode(viewMode)"
v-html="i18n.t(`protocols.steps.attachments.view_mode.${viewMode}_html`)"
></a>
</li>
<template v-if="step.attributes.urls.update_asset_view_mode_url">
<li role="separator" class="divider"></li>
<li class="divider-label">{{ i18n.t("protocols.steps.attachments.attachments_view_mode") }}</li>
<li v-for="(viewMode, index) in viewModeOptions" :key="`viewMode_${index}`">
<a
class="attachments-view-mode action-link"
:class="viewMode == step.attributes.assets_view_mode ? 'selected' : ''"
@click="changeAttachmentsViewMode(viewMode)"
v-html="i18n.t(`protocols.steps.attachments.view_mode.${viewMode}_html`)"
></a>
</li>
</template>
</ul>
</div>
</div>

View file

@ -11,7 +11,7 @@
<!-- protocol status dropdown gets mounted here -->
</div>
<div class="sci-btn-group actions-block">
<a class="btn btn-primary" @click="addStep(steps.length)">
<a v-if="urls.add_step_url" class="btn btn-primary" @click="addStep(steps.length)">
<span class="fas fa-plus" aria-hidden="true"></span>
<span>{{ i18n.t("protocols.steps.new_step") }}</span>
</a>
@ -26,6 +26,7 @@
<div class="protocol-description">
<div class="protocol-name">
<InlineEdit
v-if="urls.update_protocol_url"
:value="protocol.attributes.name"
:characterLimit="255"
:placeholder="i18n.t('my_modules.protocols.protocol_status_bar.enter_name')"
@ -33,21 +34,27 @@
:attributeName="`${i18n.t('Protocol')} ${i18n.t('name')}`"
@update="updateName"
/>
<span v-else>
{{ protocol.attributes.name }}
</span>
</div>
<Tinymce
v-if="urls.update_protocol_url"
:value="protocol.attributes.description"
:value_html="protocol.attributes.description_view"
:placeholder="i18n.t('my_modules.protocols.protocol_status_bar.empty_description_edit_label')"
:updateUrl="protocolUrl"
:updateUrl="urls.update_protocol"
:objectType="'Protocol'"
:objectId="parseInt(protocol.id)"
:fieldName="'protocol[description]'"
:lastUpdated="protocol.attributes.updated_at"
@update="updateDescription"
/>
<div v-else v-html="protocol.attributes.description_view">
</div>
</div>
<div class="protocol-step-actions">
<a class="btn btn-default" data-toggle="modal" @click="startStepReorder">
<a v-if="urls.reorder_steps_url" class="btn btn-default" data-toggle="modal" @click="startStepReorder">
<span class="fas fa-arrows-alt-v" aria-hidden="true"></span>
<span>{{ i18n.t("protocols.reorder_steps.button") }}</span>
</a>
@ -55,7 +62,7 @@
<div class="protocol-steps">
<template v-for="(step, index) in steps">
<div class="step-block" :key="step.id">
<div v-if="index > 0" class="insert-step" @click="addStep(index)">
<div v-if="index > 0 && urls.add_step_url" class="insert-step" @click="addStep(index)">
<i class="fas fa-plus"></i>
</div>
<Step
@ -64,11 +71,12 @@
:inRepository="inRepository"
@step:delete="updateStepsPosition"
@step:update="updateStep"
:reorderStepUrl="urls.reorder_steps_url"
/>
</div>
</template>
</div>
<button class="btn btn-primary" @click="addStep(steps.length)">
<button v-if="urls.add_step_url" class="btn btn-primary" @click="addStep(steps.length)">
<i class="fas fa-plus"></i>
{{ i18n.t("protocols.steps.new_step") }}
</button>
@ -100,18 +108,6 @@
protocolUrl: {
type: String,
required: true
},
stepsUrl: {
type: String,
required: true
},
addStepUrl: {
type: String,
required: true
},
editable:{
Boolean,
required: true
}
},
components: { Step, InlineEdit, ProtocolModals, ProtocolOptions, Tinymce, ReorderableItemsModal },
@ -119,6 +115,9 @@
computed: {
inRepository() {
return this.protocol.attributes.in_repository
},
urls() {
return this.protocol.attributes.urls || {}
}
},
data() {
@ -133,10 +132,10 @@
created() {
$.get(this.protocolUrl, (result) => {
this.protocol = result.data;
$.get(this.urls.steps_url, (result) => {
this.steps = result.data
})
});
$.get(this.stepsUrl, (result) => {
this.steps = result.data
})
},
methods: {
refreshProtocolStatus() {
@ -149,7 +148,7 @@
this.refreshProtocolStatus();
$.ajax({
type: 'PATCH',
url: this.protocolUrl,
url: this.urls.update_protocol_url,
data: { protocol: { name: newName } }
});
},
@ -157,7 +156,7 @@
this.protocol.attributes = protocol.data.attributes
},
addStep(position) {
$.post(this.addStepUrl, {position: position}, (result) => {
$.post(this.urls.add_step_url, {position: position}, (result) => {
this.updateStepsPosition(result.data)
})
this.refreshProtocolStatus();

View file

@ -12,7 +12,7 @@
<StorageUsage v-if="step.attributes.storage_limit" :step="step"/>
</div>
<div class="step-header step-element-header">
<div class="step-element-grip" @click="$emit('reorder')">
<div v-if="reorderStepUrl" class="step-element-grip" @click="$emit('reorder')">
<i class="fas fa-grip-vertical"></i>
</div>
<a class="step-collapse-link"
@ -29,15 +29,19 @@
</div>
<div class="step-name-container">
<InlineEdit
v-if="urls.update_url"
:value="step.attributes.name"
:characterLimit="255"
:allowBlank="false"
:attributeName="`${i18n.t('Step')} ${i18n.t('name')}`"
@update="updateName"
/>
<span v-else>
{{ step.attributes.name }}
</span>
</div>
<div class="step-actions-container">
<div class="dropdown">
<div 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="caret"></span>
@ -79,7 +83,7 @@
{{ step.attributes.comments_count }}
</span>
</a>
<div class="step-actions-container">
<div v-if="urls.update_url" class="step-actions-container">
<div class="dropdown">
<button class="btn btn-light dropdown-toggle insert-button" type="button" :id="'stepInserMenu_' + step.id" data-toggle="dropdown" data-display="static" aria-haspopup="true" aria-expanded="true">
<i class="fas fa-ellipsis-v"></i>
@ -88,11 +92,11 @@
<li class="title">
{{ i18n.t('protocols.steps.options_dropdown.title') }}
</li>
<li class="action" @click="openReorderModal">
<li v-if="urls.reorder_elements_url" class="action" @click="openReorderModal">
<i class="fas fa-arrows-alt-v"></i>
{{ i18n.t('protocols.steps.options_dropdown.rearrange') }}
</li>
<li class="action" @click="showDeleteModal">
<li v-if="urls.delete_url" class="action" @click="showDeleteModal">
<i class="fas fa-trash"></i>
{{ i18n.t('protocols.steps.options_dropdown.delete') }}
</li>
@ -107,6 +111,7 @@
:is="elements[index].attributes.orderable_type"
:key="index"
:element.sync="elements[index]"
:reorderElementUrl="urls.reorder_elements_url"
@component:delete="deleteElement"
@update="updateElement"
@reorder="openReorderModal"
@ -166,6 +171,10 @@
type: Boolean,
required: true
},
reorderStepUrl: {
type: String,
required: true
}
},
data() {
return {
@ -200,16 +209,19 @@
computed: {
reorderableElements() {
return this.elements.map((e) => { return { id: e.id, attributes: e.attributes.orderable } })
},
urls() {
return this.step.attributes.urls || {}
}
},
methods: {
loadAttachments() {
$.get(this.step.attributes.urls.attachments_url, (result) => {
$.get(this.urls.attachments_url, (result) => {
this.attachments = result.data
});
},
loadElements() {
$.get(this.step.attributes.urls.elements_url, (result) => {
$.get(this.urls.elements_url, (result) => {
this.elements = result.data
});
},
@ -221,7 +233,7 @@
},
deleteStep() {
$.ajax({
url: this.step.attributes.urls.delete_url,
url: this.urls.delete_url,
type: 'DELETE',
success: (result) => {
this.$emit(
@ -233,9 +245,11 @@
});
},
changeState() {
if (!this.urls.state_url) return;
this.step.attributes.completed = !this.step.attributes.completed;
this.$emit('step:update', this.step.attributes)
$.post(this.step.attributes.urls.state_url, {completed: this.step.attributes.completed}).error(() => {
$.post(this.urls.state_url, {completed: this.step.attributes.completed}).error(() => {
this.step.attributes.completed = !this.step.attributes.completed;
this.$emit('step:update', this.step.attributes)
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
@ -288,7 +302,7 @@
$.ajax({
type: "POST",
url: this.step.attributes.urls.reorder_elements_url,
url: this.urls.reorder_elements_url,
data: JSON.stringify(elementPositions),
contentType: "application/json",
dataType: "json",
@ -299,7 +313,7 @@
},
updateName(newName) {
$.ajax({
url: this.step.attributes.urls.update_url,
url: this.urls.update_url,
type: 'PATCH',
data: {step: {name: newName}},
success: (result) => {
@ -308,7 +322,7 @@
});
},
createElement(elementType) {
$.post(this.step.attributes.urls[`create_${elementType}_url`], (result) => {
$.post(this.urls[`create_${elementType}_url`], (result) => {
this.elements.push(result.data)
}).error(() => {
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');

View file

@ -8,7 +8,7 @@
aria-labelledby="dropdownAssetContextMenu"
:data-asset-id="attachment.id"
>
<li v-if="attachment.attributes.wopi" >
<li v-if="attachment.attributes.wopi && attachment.attributes.urls.edit_asset" >
<a :href="attachment.attributes.urls.edit_asset"
id="wopi_file_edit_button"
class="btn btn-light"
@ -20,7 +20,7 @@
{{ attachment.attributes.wopi_context.button_text }}
</a>
</li>
<li v-if="attachment.attributes.asset_type == 'marvinjs'">
<li v-if="attachment.attributes.asset_type == 'marvinjs' && attachment.attributes.urls.marvin_js_start_edit">
<a class="btn btn-light marvinjs-edit-button"
:data-sketch-id="attachment.id"
:data-update-url="attachment.attributes.urls.marvin_js"
@ -32,7 +32,7 @@
{{ i18n.t('assets.file_preview.edit_in_marvinjs') }}
</a>
</li>
<li v-if="attachment.attributes.image_editable">
<li v-if="attachment.attributes.image_editable && attachment.attributes.urls.start_edit_image">
<a class="btn btn-light image-edit-button"
:data-image-id="attachment.id"
:data-image-name="attachment.attributes.file_name"
@ -51,25 +51,29 @@
{{ i18n.t('Download') }}
</a>
</li>
<li role="separator" class="divider"></li>
<li class="divider-label">
{{ i18n.t("assets.context_menu.set_view_size") }}
</li>
<li v-for="(viewMode, index) in viewModeOptions" :key="`viewMode_${index}`">
<a
class="change-preview-type"
:class="viewMode == attachment.attributes.view_mode ? 'selected' : ''"
@click.prevent.stop="changeViewMode(viewMode)"
v-html="i18n.t(`assets.context_menu.${viewMode}_html`)"
></a>
</li>
<li role="separator" class="divider"></li>
<li>
<a @click.prevent.stop="deleteModal = true">
<i class="fas fa-trash"></i>
{{ i18n.t("assets.context_menu.delete") }}
</a>
</li>
<template v-if="attachment.attributes.urls.toggle_view_mode">
<li role="separator" class="divider"></li>
<li class="divider-label">
{{ i18n.t("assets.context_menu.set_view_size") }}
</li>
<li v-for="(viewMode, index) in viewModeOptions" :key="`viewMode_${index}`">
<a
class="change-preview-type"
:class="viewMode == attachment.attributes.view_mode ? 'selected' : ''"
@click.prevent.stop="changeViewMode(viewMode)"
v-html="i18n.t(`assets.context_menu.${viewMode}_html`)"
></a>
</li>
</template>
<template v-if="attachment.attributes.urls.delete">
<li role="separator" class="divider"></li>
<li>
<a @click.prevent.stop="deleteModal = true">
<i class="fas fa-trash"></i>
{{ i18n.t("assets.context_menu.delete") }}
</a>
</li>
</template>
</ul>
<deleteAttachmentModal
v-if="deleteModal"

View file

@ -1,11 +1,12 @@
<template>
<div class="step-checklist-container">
<div class="step-element-header" :class="{ 'locked': locked, 'editing-name': editingName }">
<div class="step-element-grip" @click="$emit('reorder')">
<div v-if="reorderElementUrl" class="step-element-grip" @click="$emit('reorder')">
<i class="fas fa-grip-vertical"></i>
</div>
<div class="step-element-name">
<InlineEdit
v-if="element.attributes.orderable.urls.update_url"
:value="element.attributes.orderable.name"
:characterLimit="255"
:placeholder="''"
@ -16,12 +17,15 @@
@editingDisabled="editingName = false"
@update="updateName"
/>
<span v-else>
{{ element.attributes.orderable.name }}
</span>
</div>
<div class="step-element-controls">
<button class="btn icon-btn btn-light" @click="editingName = true">
<button v-if="element.attributes.orderable.urls.update_url" class="btn icon-btn btn-light" @click="editingName = true">
<i class="fas fa-pen"></i>
</button>
<button class="btn icon-btn btn-light" @click="showDeleteModal">
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light" @click="showDeleteModal">
<i class="fas fa-trash"></i>
</button>
</div>
@ -33,7 +37,7 @@
:dragClass="'step-checklist-item-drag'"
:chosenClass="'step-checklist-item-chosen'"
:handle="'.step-element-grip'"
:disabled="editingItem"
:disabled="editingItem && !element.attributes.orderable.urls.reorder_url"
@start="startReorder"
@end="endReorder"
>
@ -42,6 +46,7 @@
:key="checklistItem.attributes.id"
:checklistItem="checklistItem"
:locked="locked"
:reorderChecklistItemUrl="element.attributes.orderable.urls.reorder_url"
@editStart="editingItem = true"
@editEnd="editingItem = false"
@update="saveItem"
@ -50,7 +55,7 @@
@multilinePaste="handleMultilinePaste"
/>
</Draggable>
<div class="btn btn-light step-checklist-add-item" @click="addItem">
<div v-if="element.attributes.orderable.urls.create_item_url" class="btn btn-light step-checklist-add-item" @click="addItem">
<i class="fas fa-plus"></i>
{{ i18n.t('protocols.steps.insert.checklist_item') }}
</div>
@ -74,6 +79,9 @@
element: {
type: Object,
required: true
},
reorderElementUrl: {
type: String
}
},
data() {

View file

@ -1,17 +1,21 @@
<template>
<div class="step-checklist-item">
<div class="step-element-header" :class="{ 'locked': locked || editingText, 'editing-name': editingText }">
<div class="step-element-grip">
<div v-if="reorderChecklistItemUrl" class="step-element-grip">
<i class="fas fa-grip-vertical"></i>
</div>
<div class="step-element-name" :class="{ 'done': checklistItem.attributes.checked }">
<div class="sci-checkbox-container">
<input ref="checkbox" type="checkbox" class="sci-checkbox" :checked="checklistItem.attributes.checked" @change="toggleChecked" />
<span class="sci-checkbox-label">
<div class="sci-checkbox-container" :class="{ 'disabled': !checklistItem.attributes.urls.update_url}">
<input ref="checkbox"
type="checkbox"
class="sci-checkbox"
:checked="checklistItem.attributes.checked" @change="toggleChecked($event)" />
<span class="sci-checkbox-label" >
</span>
</div>
<div class="step-checklist-text">
<InlineEdit
v-if="checklistItem.attributes.urls.update_url"
:value="checklistItem.attributes.text"
:characterLimit="10000"
:placeholder="''"
@ -25,13 +29,16 @@
@delete="checklistItem.attributes.id ? deleteElement() : removeItem()"
@multilinePaste="(data) => { $emit('multilinePaste', data) && removeItem() }"
/>
<span v-else>
{{ checklistItem.attributes.text }}
</span>
</div>
</div>
<div class="step-element-controls">
<button class="btn icon-btn btn-light" @click="enableTextEdit">
<button v-if="checklistItem.attributes.urls.update_url" class="btn icon-btn btn-light" @click="enableTextEdit">
<i class="fas fa-pen"></i>
</button>
<button class="btn icon-btn btn-light" @click="showDeleteModal">
<button v-if="checklistItem.attributes.urls.delete_url" class="btn icon-btn btn-light" @click="showDeleteModal">
<i class="fas fa-trash"></i>
</button>
</div>
@ -57,6 +64,9 @@
locked: {
type: Boolean,
default: false
},
reorderChecklistItemUrl: {
type: String
}
},
data() {
@ -83,7 +93,8 @@
this.editingText = false;
this.$emit('editEnd');
},
toggleChecked() {
toggleChecked(e) {
if (!this.checklistItem.attributes.urls.update_url) return
this.checklistItem.attributes.checked = this.$refs.checkbox.checked;
this.update();
},

View file

@ -1,11 +1,12 @@
<template>
<div class="step-table-container">
<div class="step-element-header" :class="{ 'editing-name': editingName }">
<div class="step-element-grip" @click="$emit('reorder')">
<div v-if="reorderElementUrl" class="step-element-grip" @click="$emit('reorder')">
<i class="fas fa-grip-vertical"></i>
</div>
<div class="step-element-name">
<InlineEdit
v-if="element.attributes.orderable.urls.update_url"
:value="element.attributes.orderable.name"
:characterLimit="255"
:placeholder="''"
@ -16,18 +17,21 @@
@editingDisabled="disableNameEdit"
@update="updateName"
/>
<span v-else>
{{ element.attributes.orderable.name }}
</span>
</div>
<div class="step-element-controls">
<button class="btn icon-btn btn-light" @click="enableNameEdit">
<button v-if="element.attributes.orderable.urls.update_url" class="btn icon-btn btn-light" @click="enableNameEdit">
<i class="fas fa-pen"></i>
</button>
<button class="btn icon-btn btn-light" @click="showDeleteModal">
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light" @click="showDeleteModal">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<div :class="'step-table ' + (editingTable ? 'edit' : 'view')">
<div class="enable-edit-mode" v-if="!editingTable" @click="enableTableEdit">
<div class="enable-edit-mode" v-if="!editingTable && element.attributes.orderable.urls.update_url" @click="enableTableEdit">
<i class="fas fa-pen"></i>
</div>
<div ref="hotTable" class="hot-table-container">
@ -61,6 +65,9 @@
element: {
type: Object,
required: true
},
reorderElementUrl: {
type: String
}
},
data() {

View file

@ -1,19 +1,20 @@
<template>
<div class="step-text-container" :class="{ 'edit': inEditMode }">
<div class="action-container" @click="enableEditMode">
<div class="element-grip" @click="$emit('reorder')">
<div v-if="reorderElementUrl" class="element-grip" @click="$emit('reorder')">
<i class="fas fa-grip-vertical"></i>
</div>
<div class="buttons-container">
<button class="btn icon-btn btn-light">
<button v-if="element.attributes.orderable.urls.update_url" class="btn icon-btn btn-light">
<i class="fas fa-pen"></i>
</button>
<button class="btn icon-btn btn-light" @click="showDeleteModal">
<button v-if="element.attributes.orderable.urls.delete_url" class="btn icon-btn btn-light" @click="showDeleteModal">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<Tinymce
v-if="element.attributes.orderable.urls.update_url"
:inEditMode="inEditMode"
:value="element.attributes.orderable.text"
:value_html="element.attributes.orderable.text_view"
@ -26,6 +27,7 @@
@update="update"
@editingDisabled="disableEditMode"
/>
<div v-else v-html="element.attributes.orderable.text_view"></div>
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement($event)" @cancel="closeDeleteModal"/>
</div>
</template>
@ -43,6 +45,9 @@
element: {
type: Object,
required: true
},
reorderElementUrl: {
type: String
}
},
data() {
@ -52,6 +57,7 @@
},
methods: {
enableEditMode() {
if (!this.element.attributes.orderable.urls.update_url) return
this.inEditMode = true
},
disableEditMode() {

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class AssetSerializer < ActiveModel::Serializer
include Canaid::Helpers::PermissionsHelper
include Rails.application.routes.url_helpers
include FileIconsHelper
include ActionView::Helpers::NumberHelper
@ -97,15 +98,21 @@ class AssetSerializer < ActiveModel::Serializer
download: rails_blob_path(object.file, disposition: 'attachment'),
load_asset: load_asset_path(object),
asset_file: asset_file_url_path(object),
toggle_view_mode: toggle_view_mode_path(object),
edit_asset: edit_asset_path(object),
marvin_js: marvin_js_asset_path(object),
marvin_js_start_edit: start_editing_marvin_js_asset_path(object),
marvin_js_icon: image_path('icon_small/marvinjs.svg'),
start_edit_image: start_edit_image_path(object),
delete: asset_destroy_path(object)
marvin_js_icon: image_path('icon_small/marvinjs.svg')
}
urls[:wopi_action] = object.get_action_url(@instance_options[:user], 'embedview') if wopi
if can_manage_asset?(object)
urls.merge!(
toggle_view_mode: toggle_view_mode_path(object),
edit_asset: edit_asset_path(object),
marvin_js_start_edit: start_editing_marvin_js_asset_path(object),
start_edit_image: start_edit_image_path(object),
delete: asset_destroy_path(object)
)
end
if wopi && can_manage_asset?(@asset)
urls[:wopi_action] = object.get_action_url(@instance_options[:user], 'embedview')
end
urls[:blob] = rails_blob_path(object.file, disposition: 'attachment') if object.file.attached?
urls

View file

@ -1,12 +1,15 @@
# frozen_string_literal: true
class ChecklistItemSerializer < ActiveModel::Serializer
include Canaid::Helpers::PermissionsHelper
include Rails.application.routes.url_helpers
attributes :id, :text, :checked, :position, :urls
def urls
return {} if object.destroyed? || !object.persisted?
return {} if object.destroyed? ||
!object.persisted? ||
!can_manage_step?(scope[:user] || @instance_options[:user], object.checklist.step)
{
update_url: step_checklist_checklist_item_path(object.checklist.step, object.checklist, object),

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class ChecklistSerializer < ActiveModel::Serializer
include Canaid::Helpers::PermissionsHelper
include Rails.application.routes.url_helpers
attributes :id, :name, :urls, :icon
@ -11,7 +12,7 @@ class ChecklistSerializer < ActiveModel::Serializer
end
def urls
return {} if object.destroyed?
return {} if object.destroyed? || !can_manage_step?(scope[:user], object.step)
{
delete_url: step_checklist_path(object.step, object),

View file

@ -30,7 +30,10 @@ class ProtocolSerializer < ActiveModel::Serializer
save_to_repo_url: save_to_repo_url,
export_url: export_url,
import_url: import_url,
reorder_steps_url: reorder_protocol_steps_url(protocol_id: object.id)
steps_url: steps_url,
reorder_steps_url: reorder_steps_url,
add_step_url: add_step_url,
update_protocol_url: update_protocol_url
}
end
@ -63,4 +66,30 @@ class ProtocolSerializer < ActiveModel::Serializer
export_protocols_path(protocol_ids: object.id, my_module_id: object.my_module.id)
end
def steps_url
return unless can_read_protocol_in_module?(object) || can_read_protocol_in_repository?(object)
steps_path(protocol_id: object.id)
end
def reorder_steps_url
return unless can_manage_protocol_in_module?(object) || can_manage_protocol_in_repository?(object)
reorder_protocol_steps_url(protocol_id: object.id)
end
def add_step_url
return unless can_manage_protocol_in_module?(object) || can_manage_protocol_in_repository?(object)
protocol_steps_path(protocol_id: object.id)
end
def update_protocol_url
if in_repository && can_manage_protocol_in_repository?(object)
protocol_path(@protocol)
elsif can_manage_protocol_in_module?(object)
protocol_my_module_path(object.my_module)
end
end
end

View file

@ -6,9 +6,9 @@ class StepOrderableElementSerializer < ActiveModel::Serializer
def orderable
case object.orderable_type
when 'Checklist'
ChecklistSerializer.new(object.orderable).as_json
ChecklistSerializer.new(object.orderable, scope: { user: @instance_options[:user] }).as_json
when 'StepTable'
TableSerializer.new(object.orderable.table).as_json
TableSerializer.new(object.orderable.table, scope: { user: @instance_options[:user] }).as_json
when 'StepText'
StepTextSerializer.new(object.orderable, scope: { user: @instance_options[:user] }).as_json
end

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class StepSerializer < ActiveModel::Serializer
include Canaid::Helpers::PermissionsHelper
include Rails.application.routes.url_helpers
include ApplicationHelper
include CommentHelper
@ -52,20 +53,27 @@ class StepSerializer < ActiveModel::Serializer
end
def urls
{
delete_url: step_path(object),
state_url: toggle_step_state_step_path(object),
update_url: step_path(object),
urls_list = {
elements_url: elements_step_path(object),
attachments_url: attachments_step_path(object),
create_table_url: step_tables_path(object),
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),
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)
attachments_url: attachments_step_path(object)
}
if can_manage_step?(object)
urls_list.merge!({
delete_url: step_path(object),
state_url: toggle_step_state_step_path(object),
update_url: step_path(object),
create_table_url: step_tables_path(object),
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),
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)
})
end
urls_list
end
end

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class StepTextSerializer < ActiveModel::Serializer
include Canaid::Helpers::PermissionsHelper
include Rails.application.routes.url_helpers
include ApplicationHelper
include ActionView::Helpers::TextHelper
@ -28,7 +29,7 @@ class StepTextSerializer < ActiveModel::Serializer
end
def urls
return if object.destroyed?
return {} if object.destroyed? || !can_manage_step?(scope[:user], object.step)
{
delete_url: step_text_path(object.step, object),

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class TableSerializer < ActiveModel::Serializer
include Canaid::Helpers::PermissionsHelper
include Rails.application.routes.url_helpers
attributes :name, :contents, :urls, :icon
@ -18,6 +19,8 @@ class TableSerializer < ActiveModel::Serializer
object.reload unless object.step
return {} unless can_manage_step?(scope[:user], object.step)
{
delete_url: step_table_path(object.step, object),
update_url: step_table_path(object.step, object)

View file

@ -124,17 +124,11 @@
<div
id="protocolContainer"
data-protocol-url="<%= protocol_my_module_path(@my_module) %>"
data-add-step-url="<%= protocol_steps_path(protocol_id: @protocol.id) %>"
data-steps-url="<%= steps_path(protocol_id: @protocol) %>"
data-editable="<%= can_manage_protocol_in_module?(@protocol) %>"
data-date-format="<%= datetime_picker_format_date_only %>"
data-user-utc-offset="<%= ActiveSupport::TimeZone.find_tzinfo(current_user.time_zone).utc_offset %>"
>
<protocol-container
:protocol-url="protocolUrl"
:steps-url="stepsUrl"
:add-step-url="addStepUrl"
:editable="editable"
/>
</div>
</div>

View file

@ -3,17 +3,11 @@
<div
id="protocolContainer"
data-protocol-url="<%= protocol_path(@protocol) %>"
data-add-step-url="<%= protocol_steps_path(protocol_id: @protocol.id) %>"
data-steps-url="<%= steps_path(protocol_id: @protocol) %>"
data-editable="<%= can_manage_protocol_in_module?(@protocol) %>"
data-date-format="<%= datetime_picker_format_date_only %>"
data-user-utc-offset="<%= ActiveSupport::TimeZone.find_tzinfo(current_user.time_zone).utc_offset %>"
>
<protocol-container
:protocol-url="protocolUrl"
:steps-url="stepsUrl"
:add-step-url="addStepUrl"
:editable="editable"
/>
</div>
</div>