Add some basic result component layout [SCI-8959]

This commit is contained in:
Martin Artnik 2023-08-17 16:32:42 +02:00
parent c1cfb80de4
commit 23a8872e11
6 changed files with 146 additions and 86 deletions

View file

@ -1,10 +1,10 @@
# frozen_string_literal: true
class ResultsController < ApplicationController
skip_before_action :verify_authenticity_token, only: %i(create destroy)
skip_before_action :verify_authenticity_token, only: %i(create update destroy)
before_action :load_my_module
before_action :load_vars, only: %i(destroy elements assets upload_attachment update_view_state update_asset_view_mode )
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
def index
@ -32,6 +32,12 @@ class ResultsController < ApplicationController
render json: result
end
def update
@result.update!(result_params)
render json: @result
end
def elements
render json: @result.result_orderable_elements.order(:position),
each_serializer: ResultOrderableElementSerializer,
@ -107,6 +113,10 @@ class ResultsController < ApplicationController
private
def result_params
params.require(:result).permit(:name)
end
def apply_sort(results)
case params[:sort]
when 'updated_at_asc'

View file

@ -1,85 +1,123 @@
<template>
<div class="result-wrapper">
{{ result.id }}
{{ result.attributes.name }}
<button @click="openReorderModal">
Open Rearrange Modal
</button>
<div class="inline-block">
<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="'resultInsertMenu_' + result.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="'resultInsertMenu_' + result.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('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="result.attributes.wopi_enabled" @click="openWopiFileModal">
{{ i18n.t('assets.create_wopi_file.button_text') }}
</li>
<li class="action" v-if="result.attributes.marvinjs_enabled" @click="openMarvinJsModal($refs.marvinJsButton)">
<span
class="new-marvinjs-upload-button text-sn-black text-decoration-none"
:data-object-id="result.id"
ref="marvinJsButton"
:data-marvin-url="result.attributes.marvinjs_context.marvin_js_asset_url"
:data-object-type="result.attributes.type"
tabindex="0"
>
{{ i18n.t('marvinjs.new_button') }}
</span>
</li>
</ul>
</li>
</ul>
<div class="result-wrapper bg-white">
<div class="result-header flex justify-between p-3">
<div class="result-head-left">
<InlineEdit
:value="result.attributes.name"
:class="{ 'result-element--locked': !urls.update_url }"
:characterLimit="255"
:allowBlank="false"
:attributeName="`${i18n.t('Result')} ${i18n.t('name')}`"
:autofocus="editingName"
:placeholder="i18n.t('my_modules.results.placeholder')"
:defaultValue="i18n.t('my_modules.results.default_name')"
@editingEnabled="editingName = true"
@editingDisabled="editingName = false"
:editOnload="result.newResult == true"
@update="updateName"
/>
</div>
<div ref="actionsDropdownButton" class="dropdown">
<button class="btn btn-light icon-btn dropdown-toggle insert-button" type="button" :id="'resultOptionsMenu_' + result.id" data-toggle="dropdown" data-display="static" aria-haspopup="true" aria-expanded="true">
<i class="sn-icon sn-icon-more-hori"></i>
</button>
<ul ref="actionsDropdown" class="dropdown-menu dropdown-menu-right insert-element-dropdown" :aria-labelledby="'resultOptionsMenu_' + result.id">
<li class="action" @click="openReorderModal">
{{ i18n.t('my_modules.results.actions.rearrange') }}
</li>
<li class="action" @click="duplicateResult">
{{ i18n.t('my_modules.results.actions.duplicate') }}
</li>
<li class="action" @click="archiveResult">
{{ i18n.t('my_modules.results.actions.archive') }}
</li>
</ul>
<div class="result-head-right flex">
<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="'resultInsertMenu_' + result.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="'resultInsertMenu_' + result.id">
<li class="title">
<a>
{{ i18n.t('protocols.steps.insert.title') }}
</a>
</li>
<li class="action" @click="createElement('table')">
<a class="cursor-pointer">
<i class="sn-icon sn-icon-tables"></i>
{{ i18n.t('protocols.steps.insert.table') }}
</a>
</li>
<li class="action dropdown-submenu-item">
<a class="cursor-pointer">
<i class="sn-icon sn-icon-tables"></i>
{{ i18n.t('protocols.steps.insert.well_plate') }}
</a>
<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)">
<a class="cursor-pointer">
{{ i18n.t(option.label) }}
</a>
</li>
</ul>
</li>
<li class="action" @click="createElement('text')">
<a class="cursor-pointer">
<i class="sn-icon sn-icon-result-text"></i>
{{ i18n.t('protocols.steps.insert.text') }}
</a>
</li>
<li class="action dropdown-submenu-item">
<a class="cursor-pointer">
<i class="sn-icon sn-icon-files"></i>
{{ i18n.t('protocols.steps.insert.attachment') }}
</a>
<span class="caret"></span>
<ul class="dropdown-submenu">
<li class="action" @click="openLoadFromComputer">
<a class="cursor-pointer">
{{ i18n.t('protocols.steps.insert.add_file') }}
</a>
</li>
<li class="action" v-if="result.attributes.wopi_enabled" @click="openWopiFileModal">
<a class="cursor-pointer">
{{ i18n.t('assets.create_wopi_file.button_text') }}
</a>
</li>
<li class="action" v-if="result.attributes.marvinjs_enabled" @click="openMarvinJsModal($refs.marvinJsButton)">
<a class="cursor-point er">
<span
class="new-marvinjs-upload-button text-sn-black text-decoration-none"
:data-object-id="result.id"
ref="marvinJsButton"
:data-marvin-url="result.attributes.marvinjs_context.marvin_js_asset_url"
:data-object-type="result.attributes.type"
tabindex="0"
>
{{ i18n.t('marvinjs.new_button') }}
</span>
</a>
</li>
</ul>
</li>
</ul>
</div>
<a href="#"
ref="comments"
class="open-comments-sidebar btn icon-btn btn-light"
data-turbolinks="false"
data-object-type="Result"
:data-object-id="result.id">
<i class="sn-icon sn-icon-comments"></i>
</a>
<div ref="actionsDropdownButton" class="dropdown">
<button class="btn btn-light icon-btn dropdown-toggle insert-button" type="button" :id="'resultOptionsMenu_' + result.id" data-toggle="dropdown" data-display="static" aria-haspopup="true" aria-expanded="true">
<i class="sn-icon sn-icon-more-hori"></i>
</button>
<ul ref="actionsDropdown" class="dropdown-menu dropdown-menu-right insert-element-dropdown" :aria-labelledby="'resultOptionsMenu_' + result.id">
<li class="action" @click="openReorderModal">
<a class="cursor-pointer">{{ i18n.t('my_modules.results.actions.rearrange') }}</a>
</li>
<li class="action" @click="duplicateResult">
<a class="cursor-pointer">{{ i18n.t('my_modules.results.actions.duplicate') }}</a>
</li>
<li class="action" @click="archiveResult">
<a class="cursor-pointer">{{ i18n.t('my_modules.results.actions.archive') }}</a>
</li>
</ul>
</div>
</div>
</div>
<hr>
<ReorderableItemsModal v-if="reordering"
title="Placeholder title for this modal"
:items="reorderableElements"
@ -113,6 +151,7 @@
@attachments:viewMode="changeAttachmentsViewMode"
@attachment:viewMode="updateAttachmentViewMode"/>
</div>
<hr>
</div>
</template>
@ -122,6 +161,7 @@
import ResultTable from '../shared/content/table.vue';
import ResultText from '../shared/content/text.vue';
import Attachments from '../shared/content/attachments.vue';
import InlineEdit from '../shared/inline_edit.vue'
import AttachmentsMixin from '../shared/content/mixins/attachments.js'
import WopiFileModal from '../shared/content/attachments/mixins/wopi_file_modal.js'
@ -146,7 +186,8 @@
{ label: 'protocols.steps.insert.well_plate_options.6_x_8', dimensions: [6, 8] },
{ label: 'protocols.steps.insert.well_plate_options.6_x_4', dimensions: [6, 4] },
{ label: 'protocols.steps.insert.well_plate_options.2_x_3', dimensions: [2, 3] }
]
],
editingName: false
}
},
mixins: [UtilsMixin, AttachmentsMixin, WopiFileModal],
@ -154,7 +195,8 @@
ReorderableItemsModal,
ResultTable,
ResultText,
Attachments
Attachments,
InlineEdit
},
computed: {
reorderableElements() {
@ -278,7 +320,7 @@
$.post(this.urls[`create_${elementType}_url`], { tableDimensions: tableDimensions, plateTemplate: plateTemplate }, (result) => {
result.data.isNew = true;
this.elements.push(result.data)
this.$emit('stepUpdated')
this.$emit('resultUpdated')
}).fail(() => {
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
}).done(() => {
@ -298,6 +340,11 @@
},
duplicateResult() {
},
updateName(name) {
axios.patch(this.urls.update_url, { result: { name: name } }, (_) => {
this.$emit('resultUpdated')
});
}
}
}

View file

@ -1,6 +1,6 @@
<template>
<div class="results-wrapper">
<ResultsToolbar :sort="sort" @setSort="setSort" @newResult="createResult" @expandAll="expandAll" @collapseAll="collapseAll" lass="mb-3" />
<ResultsToolbar :sort="sort" @setSort="setSort" @newResult="createResult" @expandAll="expandAll" @collapseAll="collapseAll" class="mb-3" />
<div class="results-list">
<Result v-for="result in results" :key="result.id" :result="result" />
</div>

View file

@ -28,7 +28,6 @@ class ResultSerializer < ActiveModel::Serializer
end
end
def updated_at
object.updated_at.to_i
end
@ -74,7 +73,7 @@ class ResultSerializer < ActiveModel::Serializer
if can_manage_result?(object)
urls_list.merge!({
delete_url: result_path(object),
update_url: result_path(object),
update_url: my_module_result_path(object.my_module, object),
create_table_url: my_module_result_tables_path(object.my_module, object),
create_text_url: my_module_result_texts_path(object.my_module, object),
update_asset_view_mode_url: update_asset_view_mode_my_module_result_path(object.my_module, object),

View file

@ -14,6 +14,8 @@
<%= render partial: 'assets/wopi/create_wopi_file_modal' %>
<% provide(:container_class, 'no-second-nav-container') %>
<%= render partial: 'my_modules/header_actions' %>
<div id="results" data-behaviour="vue">
<results url="<%= my_module_results_url(@my_module) %>">
</div>

View file

@ -1240,6 +1240,8 @@ en:
load_from_file_protocol_general_error: "Failed to load the protocol from file. It is likely that certain fields (protocol and individual step titles and names) contain too many or too few characters.(max is %{max} and min is %{min})"
results:
head_title: "%{project} | %{module} | Results"
default_name: "New result"
placeholder: "Enter result name"
add_label: "New result"
new_text_result: "Text"
new_table_result: "Table"