mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-20 14:45:56 +08:00
Add create actions [SCI-8953]
This commit is contained in:
parent
f6191dbb67
commit
6e5fa5ccd7
|
@ -55,7 +55,7 @@ $(document).on('click', '.asset .delete-asset', function(e) {
|
|||
|
||||
$(document).on('turbolinks:before-visit', (e) => {
|
||||
if ($('.uploading-attachment-container:not(.error)').length) {
|
||||
if (confirm(I18n.t('protocols.steps.attachments.new.leaving_warning'))) {
|
||||
if (confirm(I18n.t('attachments.new.leaving_warning'))) {
|
||||
return true;
|
||||
}
|
||||
e.preventDefault();
|
||||
|
|
|
@ -8,10 +8,10 @@ module ResultElements
|
|||
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)
|
||||
position: @result.result_tables.length + 1)
|
||||
else
|
||||
t('protocols.steps.plate.default_name',
|
||||
position: @step.step_tables.length + 1)
|
||||
position: @result.result_tables.length + 1)
|
||||
end
|
||||
result_table = @result.result_tables.new(table:
|
||||
Table.new(
|
||||
|
@ -24,11 +24,11 @@ module ResultElements
|
|||
))
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
create_in_step!(@step, step_table)
|
||||
create_in_result!(@result, result_table)
|
||||
# log_step_activity(:table_added, { table_name: step_table.table.name })
|
||||
end
|
||||
|
||||
render_result_orderable_element(step_table)
|
||||
render_result_orderable_element(result_table)
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
head :unprocessable_entity
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ module ResultElements
|
|||
result_text = @result.result_texts.build
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
create_in_step!(@result, result_text)
|
||||
create_in_result!(@result, result_text)
|
||||
#log_step_activity(:text_added, { text_name: step_text.name })
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ class ResultsController < ApplicationController
|
|||
skip_before_action :verify_authenticity_token, only: %i(create destroy)
|
||||
|
||||
before_action :load_my_module
|
||||
before_action :load_vars, only: %i(destroy elements assets)
|
||||
before_action :load_vars, only: %i(destroy elements assets upload_attachment update_view_state update_asset_view_mode )
|
||||
before_action :check_destroy_permissions, only: :destroy
|
||||
|
||||
def index
|
||||
|
@ -44,6 +44,44 @@ class ResultsController < ApplicationController
|
|||
user: current_user
|
||||
end
|
||||
|
||||
def upload_attachment
|
||||
@result.transaction do
|
||||
@asset = @result.assets.create!(
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
team: @my_module.team,
|
||||
view_mode: @result.assets_view_mode
|
||||
)
|
||||
@asset.file.attach(params[:signed_blob_id])
|
||||
@asset.post_process_file(@my_module.team)
|
||||
end
|
||||
|
||||
render json: @asset,
|
||||
serializer: AssetSerializer,
|
||||
user: current_user
|
||||
end
|
||||
|
||||
def update_view_state
|
||||
view_state = @result.current_view_state(current_user)
|
||||
view_state.state['result_assets']['sort'] = params.require(:assets).require(:order)
|
||||
view_state.save! if view_state.changed?
|
||||
|
||||
render json: {}, status: :ok
|
||||
end
|
||||
|
||||
def update_asset_view_mode
|
||||
html = ''
|
||||
ActiveRecord::Base.transaction do
|
||||
@result.assets_view_mode = params[:assets_view_mode]
|
||||
@result.save!(touch: false)
|
||||
@result.assets.update_all(view_mode: @result.assets_view_mode)
|
||||
end
|
||||
render json: { view_mode: @result.assets_view_mode }, status: :ok
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
Rails.logger.error(e.message)
|
||||
render json: { errors: e.message }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def destroy
|
||||
result_type = if @result.is_text
|
||||
t('activities.result_type.text')
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
<button @click="openReorderModal">
|
||||
Open Rearrange Modal
|
||||
</button>
|
||||
<div>
|
||||
<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="'stepInserMenu_' + step.id" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<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="'stepInserMenu_' + step.id">
|
||||
<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>
|
||||
|
@ -31,10 +31,6 @@
|
|||
</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') }}
|
||||
|
@ -47,16 +43,16 @@
|
|||
<li class="action" @click="openLoadFromComputer">
|
||||
{{ i18n.t('protocols.steps.insert.add_file') }}
|
||||
</li>
|
||||
<li class="action" v-if="step.attributes.wopi_enabled" @click="openWopiFileModal">
|
||||
<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="step.attributes.marvinjs_enabled" @click="openMarvinJsModal($refs.marvinJsButton)">
|
||||
<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="step.id"
|
||||
:data-object-id="result.id"
|
||||
ref="marvinJsButton"
|
||||
:data-marvin-url="step.attributes.marvinjs_context.marvin_js_asset_url"
|
||||
:data-object-type="step.attributes.type"
|
||||
:data-marvin-url="result.attributes.marvinjs_context.marvin_js_asset_url"
|
||||
:data-object-type="result.attributes.type"
|
||||
tabindex="0"
|
||||
>
|
||||
{{ i18n.t('marvinjs.new_button') }}
|
||||
|
@ -97,9 +93,9 @@
|
|||
@attachments:openFileModal="showFileModal = true"
|
||||
@attachment:deleted="attachmentDeleted"
|
||||
@attachment:uploaded="loadAttachments"
|
||||
@attachments:order="() => {}"
|
||||
@attachments:viewMode="() => {}"
|
||||
@attachment:viewMode="() => {}"/>
|
||||
@attachments:order="changeAttachmentsOrder"
|
||||
@attachments:viewMode="changeAttachmentsViewMode"
|
||||
@attachment:viewMode="updateAttachmentViewMode"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -126,7 +122,15 @@
|
|||
elements: [],
|
||||
attachments: [],
|
||||
attachmentsReady: false,
|
||||
showFileModal: false
|
||||
showFileModal: false,
|
||||
wellPlateOptions: [
|
||||
{ label: 'protocols.steps.insert.well_plate_options.32_x_48', dimensions: [32, 48] },
|
||||
{ label: 'protocols.steps.insert.well_plate_options.16_x_24', dimensions: [16, 24] },
|
||||
{ label: 'protocols.steps.insert.well_plate_options.8_x_12', dimensions: [8, 12] },
|
||||
{ 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] }
|
||||
]
|
||||
}
|
||||
},
|
||||
mixins: [UtilsMixin, AttachmentsMixin, WopiFileModal],
|
||||
|
@ -177,17 +181,57 @@
|
|||
}
|
||||
})
|
||||
.then(() => {
|
||||
this.$emit('stepUpdated');
|
||||
this.$emit('resultUpdated');
|
||||
})
|
||||
.catch(() => {
|
||||
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||
});
|
||||
},
|
||||
deleteElement(element) {
|
||||
deleteElement(position) {
|
||||
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')
|
||||
},
|
||||
updateElement(element) {
|
||||
updateElement(element, skipRequest=false, callback) {
|
||||
let index = this.elements.findIndex((e) => e.id === element.id);
|
||||
this.elements[index].isNew = false;
|
||||
|
||||
if (skipRequest) {
|
||||
this.elements[index].attributes.orderable = element.attributes.orderable;
|
||||
this.$emit('resultUpdated');
|
||||
} else {
|
||||
$.ajax({
|
||||
url: element.attributes.orderable.urls.update_url,
|
||||
method: 'PUT',
|
||||
data: element.attributes.orderable,
|
||||
success: (result) => {
|
||||
this.elements[index].attributes.orderable = result.data.attributes;
|
||||
this.$emit('resultUpdated');
|
||||
|
||||
// optional callback after successful update
|
||||
if(typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}).fail(() => {
|
||||
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||
})
|
||||
}
|
||||
},
|
||||
insertElement(element) {
|
||||
let position = element.attributes.position;
|
||||
this.elements = this.elements.map( s => {
|
||||
if (s.attributes.position >= position) {
|
||||
s.attributes.position += 1;
|
||||
}
|
||||
return s;
|
||||
})
|
||||
this.elements.push(element);
|
||||
},
|
||||
loadElements() {
|
||||
$.get(this.urls.elements_url, (result) => {
|
||||
|
@ -214,6 +258,25 @@
|
|||
this.attachments = this.attachments.filter((a) => a.id !== id );
|
||||
this.$emit('resultUpdated');
|
||||
},
|
||||
createElement(elementType, tableDimensions = [5,5], plateTemplate = false) {
|
||||
$.post(this.urls[`create_${elementType}_url`], { tableDimensions: tableDimensions, plateTemplate: plateTemplate }, (result) => {
|
||||
result.data.isNew = true;
|
||||
this.elements.push(result.data)
|
||||
this.$emit('stepUpdated')
|
||||
}).fail(() => {
|
||||
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||
}).done(() => {
|
||||
this.$parent.$nextTick(() => {
|
||||
const children = this.$children
|
||||
const lastChild = children[children.length - 1]
|
||||
lastChild.$el.scrollIntoView(false)
|
||||
window.scrollBy({
|
||||
top: 200,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
})
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div class="flex items-center gap-2" v-if="parent.attributes.attachments_manageble && attachmentsReady">
|
||||
<div ref="actionsDropdownButton" class="dropdown sci-dropdown">
|
||||
<button class="btn btn-light dropdown-toggle" type="button" id="dropdownAttachmentsOptions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<span>{{ i18n.t("protocols.steps.attachments.preview_menu") }}</span>
|
||||
<span>{{ i18n.t("attachments.preview_menu") }}</span>
|
||||
<span class="sn-icon sn-icon-down"></span>
|
||||
</button>
|
||||
<ul ref="actionsDropdown" class="dropdown-menu dropdown-menu-right dropdown-attachment-options"
|
||||
|
@ -20,7 +20,7 @@
|
|||
class="attachments-view-mode action-link"
|
||||
:class="viewMode == parent.attributes.assets_view_mode ? 'selected' : ''"
|
||||
@click="changeAttachmentsViewMode(viewMode)"
|
||||
v-html="i18n.t(`protocols.steps.attachments.view_mode.${viewMode}_html`)"
|
||||
v-html="i18n.t(`attachments.view_mode.${viewMode}_html`)"
|
||||
></a>
|
||||
</li>
|
||||
</template>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</span>
|
||||
</a>
|
||||
<span v-if="attachment.isNewUpload" class="attachment-label-new">
|
||||
{{ i18n.t('protocols.steps.attachments.new.description') }}
|
||||
{{ i18n.t('attachments.new.description') }}
|
||||
</span>
|
||||
<div class="file-metadata">
|
||||
<span>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</span>
|
||||
</a>
|
||||
<span v-if="attachment.isNewUpload" class="attachment-label-new">
|
||||
{{ i18n.t('protocols.steps.attachments.new.description') }}
|
||||
{{ i18n.t('attachments.new.description') }}
|
||||
</span>
|
||||
<div class="file-metadata">
|
||||
<span>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
:title="`${ attachment.attributes.file_name }`">
|
||||
{{ attachment.attributes.file_name }}
|
||||
<span v-if="attachment.isNewUpload" class="attachment-label-new">
|
||||
{{ i18n.t('protocols.steps.attachments.new.description') }}
|
||||
{{ i18n.t('attachments.new.description') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="attachment-metadata">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<i v-if="attachment.error" class="fas fa-exclamation-triangle"></i>
|
||||
</div>
|
||||
<div class="file-name" :class="{'one-line': attachmentViewMode == 'list-attachment-container' }">
|
||||
<div v-if="!attachment.error">{{ i18n.t("protocols.steps.attachments.new.uploading") }}</div>
|
||||
<div v-if="!attachment.error">{{ i18n.t("attachments.new.uploading") }}</div>
|
||||
<div class="file-name-text">{{ attachment.attributes.file_name }}</div>
|
||||
</div>
|
||||
<div v-if="!attachment.error" class="progress-container">
|
||||
|
|
|
@ -71,7 +71,7 @@ export default {
|
|||
}
|
||||
};
|
||||
if (file.size > GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB * 1024 * 1024) {
|
||||
fileObject.error = I18n.t('protocols.steps.attachments.new.file_too_big');
|
||||
fileObject.error = I18n.t('attachments.new.file_too_big');
|
||||
this.attachments.push(fileObject);
|
||||
return;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ export default {
|
|||
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');
|
||||
fileObject.error = I18n.t('attachments.new.no_more_space');
|
||||
this.attachments.push(fileObject);
|
||||
return;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ export default {
|
|||
|
||||
upload.create((error, blob) => {
|
||||
if (error) {
|
||||
fileObject.error = I18n.t('protocols.steps.attachments.new.general_error');
|
||||
fileObject.error = I18n.t('attachments.new.general_error');
|
||||
this.attachments.splice(filePosition, 1);
|
||||
setTimeout(() => {
|
||||
this.attachments.push(fileObject);
|
||||
|
@ -107,7 +107,7 @@ export default {
|
|||
fileObject.id = result.data.id;
|
||||
fileObject.attributes = result.data.attributes;
|
||||
}).fail(() => {
|
||||
fileObject.error = I18n.t('protocols.steps.attachments.new.general_error');
|
||||
fileObject.error = I18n.t('attachments.new.general_error');
|
||||
this.attachments.splice(filePosition, 1);
|
||||
setTimeout(() => {
|
||||
this.attachments.push(fileObject);
|
||||
|
|
|
@ -4,10 +4,13 @@ class Result < ApplicationRecord
|
|||
include ArchivableModel
|
||||
include SearchableModel
|
||||
include SearchableByNameModel
|
||||
include ViewableModel
|
||||
|
||||
auto_strip_attributes :name, nullify: false
|
||||
validates :name, length: { maximum: Constants::NAME_MAX_LENGTH }
|
||||
|
||||
enum assets_view_mode: { thumbnail: 0, list: 1, inline: 2 }
|
||||
|
||||
belongs_to :user, inverse_of: :results
|
||||
belongs_to :last_modified_by, class_name: 'User', optional: true
|
||||
belongs_to :archived_by, class_name: 'User', optional: true
|
||||
|
@ -51,6 +54,16 @@ class Result < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def default_view_state
|
||||
{ 'assets' => { 'sort' => 'new' } }
|
||||
end
|
||||
|
||||
def validate_view_state(view_state)
|
||||
unless %w(new old atoz ztoa).include?(view_state.state.dig('assets', 'sort'))
|
||||
view_state.errors.add(:state, :wrong_state)
|
||||
end
|
||||
end
|
||||
|
||||
def self.viewable_by_user(user, teams)
|
||||
where(my_module: MyModule.viewable_by_user(user, teams))
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ResultOrderableElement < ApplicationRecord
|
||||
validates :position, uniqueness: { scope: :step }
|
||||
validates :position, uniqueness: { scope: :result }
|
||||
validate :check_result_relations
|
||||
|
||||
around_destroy :decrement_following_elements_positions
|
||||
|
@ -11,8 +11,8 @@ class ResultOrderableElement < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
def check_step_relations
|
||||
if step != orderable.step
|
||||
def check_result_relations
|
||||
if result != orderable.result
|
||||
errors.add(
|
||||
:step_orderable_element,
|
||||
I18n.t('activerecord.errors.models.result_orderable_element.attributes.result.wrong_result')
|
||||
|
|
|
@ -2,10 +2,17 @@
|
|||
|
||||
class ResultText < ApplicationRecord
|
||||
include TinyMceImages
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
auto_strip_attributes :text, nullify: false
|
||||
validates :text, length: { maximum: Constants::RICH_TEXT_MAX_LENGTH }
|
||||
|
||||
belongs_to :result, inverse_of: :result_texts, touch: true
|
||||
has_one :result_orderable_element, as: :orderable, dependent: :destroy
|
||||
|
||||
def name
|
||||
return if text.blank?
|
||||
|
||||
strip_tags(text.truncate(64))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ class Table < ApplicationRecord
|
|||
has_one :step_table, inverse_of: :table, dependent: :destroy
|
||||
has_one :step, through: :step_table
|
||||
|
||||
has_one :result_table, inverse_of: :table
|
||||
has_one :result_table, inverse_of: :table, dependent: :destroy
|
||||
has_one :result, through: :result_table
|
||||
has_many :report_elements, inverse_of: :table, dependent: :destroy
|
||||
|
||||
|
|
|
@ -7,7 +7,27 @@ class ResultSerializer < ActiveModel::Serializer
|
|||
include ActionView::Helpers::TextHelper
|
||||
include InputSanitizeHelper
|
||||
|
||||
attributes :name, :id, :urls, :updated_at, :created_at_formatted, :updated_at_formatted, :user, :my_module_id
|
||||
attributes :name, :id, :urls, :updated_at, :created_at_formatted, :updated_at_formatted, :user,
|
||||
:my_module_id, :attachments_manageble, :marvinjs_enabled, :marvinjs_context,
|
||||
:wopi_enabled, :wopi_context
|
||||
|
||||
def marvinjs_enabled
|
||||
MarvinJsService.enabled?
|
||||
end
|
||||
|
||||
def type
|
||||
'Result'
|
||||
end
|
||||
|
||||
def marvinjs_context
|
||||
if marvinjs_enabled
|
||||
{
|
||||
marvin_js_asset_url: marvin_js_assets_path,
|
||||
icon: image_path('icon_small/marvinjs.svg')
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def updated_at
|
||||
object.updated_at.to_i
|
||||
|
@ -20,6 +40,23 @@ class ResultSerializer < ActiveModel::Serializer
|
|||
}
|
||||
end
|
||||
|
||||
def attachments_manageble
|
||||
can_manage_result?(object)
|
||||
end
|
||||
|
||||
def wopi_enabled
|
||||
wopi_enabled?
|
||||
end
|
||||
|
||||
def wopi_context
|
||||
if wopi_enabled
|
||||
{
|
||||
create_wopi: create_wopi_file_path,
|
||||
icon: image_path('office/office.svg')
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def created_at_formatted
|
||||
I18n.l(object.created_at, format: :full)
|
||||
end
|
||||
|
@ -29,9 +66,24 @@ class ResultSerializer < ActiveModel::Serializer
|
|||
end
|
||||
|
||||
def urls
|
||||
{
|
||||
urls_list = {
|
||||
elements_url: elements_my_module_result_path(object.my_module, object),
|
||||
attachments_url: assets_my_module_result_path(object.my_module, object)
|
||||
}
|
||||
|
||||
if can_manage_result?(object)
|
||||
urls_list.merge!({
|
||||
delete_url: result_path(object),
|
||||
update_url: result_path(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),
|
||||
update_view_state_url: update_view_state_my_module_result_path(object.my_module, object),
|
||||
direct_upload_url: rails_direct_uploads_url,
|
||||
upload_attachment_url: upload_attachment_my_module_result_path(object.my_module, object)
|
||||
})
|
||||
end
|
||||
|
||||
urls_list
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@ class ResultTextSerializer < ActiveModel::Serializer
|
|||
include ApplicationHelper
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
attributes :id, :text, :urls, :text_view, :icon, :placeholder
|
||||
attributes :id, :text, :urls, :text_view, :icon, :placeholder, :name
|
||||
|
||||
def updated_at
|
||||
object.updated_at.to_i
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<div class="actions">
|
||||
<div class="dropdown sci-dropdown">
|
||||
<button class="btn btn-light dropdown-toggle" type="button" id="dropdownAttachmentsOptions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<span><%= t("protocols.steps.attachments.manage") %></span>
|
||||
<span><%= t("attachments.manage") %></span>
|
||||
<span class="caret pull-right"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right dropdown-attachment-options"
|
||||
|
@ -23,7 +23,7 @@
|
|||
data-view-mode-url="<%= update_asset_view_mode_step_path(step) %>"
|
||||
data-step-id="<%= step.id %>"
|
||||
data-state-save-url="<%= update_view_state_step_path(step.id) %>">
|
||||
<li class="divider-label"><%= t("protocols.steps.attachments.add") %></li>
|
||||
<li class="divider-label"><%= t("attachments.add") %></li>
|
||||
<%= render partial: '/assets/marvinjs/create_marvin_sketch_li',
|
||||
locals: { element_id: step.id, element_type: 'Step', sketch_container: ".attachments[data-step-id=#{step.id}]" },
|
||||
formats: :html %>
|
||||
|
@ -33,7 +33,7 @@
|
|||
locals: { element_id: step.id, element_type: 'Step' } %>
|
||||
</li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li class="divider-label"><%= t("protocols.steps.attachments.sort_by") %></li>
|
||||
<li class="divider-label"><%= t("attachments.sort_by") %></li>
|
||||
<% ['new', 'old', 'atoz', 'ztoa'].each do |sort| %>
|
||||
<li>
|
||||
<a data-order="<%= sort %>" class="action-link change-order <%= 'selected' if current_order == sort %>">
|
||||
|
@ -42,11 +42,11 @@
|
|||
</li>
|
||||
<% end %>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li class="divider-label"><%= t("protocols.steps.attachments.attachments_view_mode") %></li>
|
||||
<li class="divider-label"><%= t("attachments.attachments_view_mode") %></li>
|
||||
<% ['inline', 'thumbnail', 'list'].each do |view_mode| %>
|
||||
<li>
|
||||
<a class="attachments-view-mode action-link <%= 'selected' if view_mode == step.assets_view_mode %>" data-assets-view-mode="<%= view_mode %>">
|
||||
<%= t("protocols.steps.attachments.view_mode.#{view_mode}_html") %>
|
||||
<%= t("attachments.view_mode.#{view_mode}_html") %>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
|
|
|
@ -377,6 +377,34 @@ en:
|
|||
activities: "Activity"
|
||||
archive: "Archived results"
|
||||
|
||||
attachments:
|
||||
menu:
|
||||
office_file: "New Office file"
|
||||
chemical_drawing: "New chemical drawing"
|
||||
file_from_pc: "File from your PC"
|
||||
modified_label: "Modified:"
|
||||
preview_menu: "Preview size"
|
||||
add: "ADD"
|
||||
sort_by: "SORT BY"
|
||||
attachments_view_mode: "ALL ATTACHMENTS VIEW SIZE"
|
||||
new:
|
||||
description: 'New'
|
||||
uploading: 'Uploading'
|
||||
file_too_big: 'Failed to upload: File size is too big'
|
||||
no_more_space: 'Failed to upload: You ran out of space'
|
||||
general_error: 'Failed to upload: Something went wrong, please try again'
|
||||
leaving_warning: 'Your changes will be lost if you navigate away'
|
||||
|
||||
sort:
|
||||
new_html: "Newest first ↓"
|
||||
old_html: "Oldest first ↑"
|
||||
atoz_html: "Name ↓"
|
||||
ztoa_html: "Name ↑"
|
||||
view_mode:
|
||||
inline_html: "Large"
|
||||
thumbnail_html: "Medium"
|
||||
list_html: "List"
|
||||
|
||||
search:
|
||||
whole_word: "Match any whole word"
|
||||
whole_phrase: "Match whole phrase"
|
||||
|
@ -3095,33 +3123,6 @@ en:
|
|||
duplicate_title: "Duplicate step"
|
||||
complete_title: "Complete step"
|
||||
uncomplete_title: "Restart step"
|
||||
attachments:
|
||||
menu:
|
||||
office_file: "New Office file"
|
||||
chemical_drawing: "New chemical drawing"
|
||||
file_from_pc: "File from your PC"
|
||||
modified_label: "Modified:"
|
||||
preview_menu: "Preview size"
|
||||
add: "ADD"
|
||||
sort_by: "SORT BY"
|
||||
attachments_view_mode: "ALL ATTACHMENTS VIEW SIZE"
|
||||
new:
|
||||
description: 'New'
|
||||
uploading: 'Uploading'
|
||||
file_too_big: 'Failed to upload: File size is too big'
|
||||
no_more_space: 'Failed to upload: You ran out of space'
|
||||
general_error: 'Failed to upload: Something went wrong, please try again'
|
||||
leaving_warning: 'Your changes will be lost if you navigate away'
|
||||
|
||||
sort:
|
||||
new_html: "Newest first ↓"
|
||||
old_html: "Oldest first ↑"
|
||||
atoz_html: "Name ↓"
|
||||
ztoa_html: "Name ↑"
|
||||
view_mode:
|
||||
inline_html: "Large"
|
||||
thumbnail_html: "Medium"
|
||||
list_html: "List"
|
||||
new:
|
||||
add_step_title: "Add new step"
|
||||
tab_checklists: "Checklists"
|
||||
|
|
|
@ -503,9 +503,6 @@ Rails.application.routes.draw do
|
|||
|
||||
post :select_default_snapshot, to: 'my_module_repository_snapshots#select'
|
||||
|
||||
resources :result_texts, only: [:new, :create]
|
||||
resources :result_assets, only: [:new, :create]
|
||||
resources :result_tables, only: [:new, :create]
|
||||
member do
|
||||
# AJAX popup accessed from full-zoom canvas for single module,
|
||||
# as well as full activities view (HTML) for single module
|
||||
|
@ -538,6 +535,9 @@ Rails.application.routes.draw do
|
|||
member do
|
||||
get :elements
|
||||
get :assets
|
||||
post :upload_attachment
|
||||
post :update_view_state
|
||||
post :update_asset_view_mode
|
||||
end
|
||||
|
||||
resources :tables, controller: 'result_elements/tables', only: %i(create destroy update) do
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
class AddAssetsViewModeToResult < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :results, :assets_view_mode, :integer, default: 0
|
||||
change_column_null :result_texts, :text, true
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_07_25_120831) do
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_08_11_115859) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "btree_gist"
|
||||
enable_extension "pg_trgm"
|
||||
|
@ -921,7 +921,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_25_120831) do
|
|||
end
|
||||
|
||||
create_table "result_texts", force: :cascade do |t|
|
||||
t.string "text", null: false
|
||||
t.string "text"
|
||||
t.bigint "result_id", null: false
|
||||
t.index "trim_html_tags((text)::text) gin_trgm_ops", name: "index_result_texts_on_text", using: :gin
|
||||
t.index ["result_id"], name: "index_result_texts_on_result_id"
|
||||
|
@ -939,6 +939,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_25_120831) do
|
|||
t.bigint "archived_by_id"
|
||||
t.bigint "restored_by_id"
|
||||
t.datetime "restored_on", precision: nil
|
||||
t.integer "assets_view_mode", default: 0
|
||||
t.index "trim_html_tags((name)::text) gin_trgm_ops", name: "index_results_on_name", using: :gin
|
||||
t.index ["archived"], name: "index_results_on_archived"
|
||||
t.index ["archived_by_id"], name: "index_results_on_archived_by_id"
|
||||
|
|
Loading…
Reference in a new issue