Added data-e2e to protocol page [SCI-10761]

This commit is contained in:
Klemen Benedicic 2024-06-07 12:05:31 +02:00
parent 86c99feb39
commit 40c2f1a7de
18 changed files with 241 additions and 85 deletions

View file

@ -6,7 +6,7 @@
position="right" position="right"
@dtEvent="changeSort" @dtEvent="changeSort"
btnIcon="sn-icon sn-icon-sort-down" btnIcon="sn-icon sn-icon-sort-down"
:e2eButton="e2eSortButton" :dataE2e="e2eSortButton"
></MenuDropdown> ></MenuDropdown>
</template> </template>

View file

@ -85,9 +85,14 @@
<div :class="inRepository ? 'protocol-section protocol-information' : ''"> <div :class="inRepository ? 'protocol-section protocol-information' : ''">
<div v-if="inRepository" id="protocol-description" class="protocol-section-header"> <div v-if="inRepository" id="protocol-description" class="protocol-section-header">
<div class="protocol-description-container"> <div class="protocol-description-container">
<a class="protocol-section-caret" role="button" data-toggle="collapse" href="#protocol-description-container" aria-expanded="false" aria-controls="protocol-description-container"> <a class="protocol-section-caret"
role="button"
data-toggle="collapse"
href="#protocol-description-container"
aria-expanded="false"
aria-controls="protocol-description-container">
<i class="sn-icon sn-icon-right"></i> <i class="sn-icon sn-icon-right"></i>
<span id="protocolDescriptionLabel" class="protocol-section-title"> <span id="protocolDescriptionLabel" class="protocol-section-title" data-e2e="e2e-TX-protocolTemplates-protocolDescription-title">
<h2> <h2>
{{ i18n.t("protocols.header.protocol_description") }} {{ i18n.t("protocols.header.protocol_description") }}
</h2> </h2>
@ -95,7 +100,10 @@
</a> </a>
</div> </div>
</div> </div>
<div id="protocol-description-container" class="text-base" :class=" inRepository ? 'protocol-description collapse in' : ''" > <div id="protocol-description-container"
class="text-base"
:class=" inRepository ? 'protocol-description collapse in' : ''"
data-e2e="e2e-IF-protocolTemplates-protocolDescription-content">
<div v-if="urls.update_protocol_description_url"> <div v-if="urls.update_protocol_description_url">
<Tinymce <Tinymce
:value="protocol.attributes.description" :value="protocol.attributes.description"
@ -123,7 +131,7 @@
<div class="protocol-steps-container"> <div class="protocol-steps-container">
<a class="protocol-section-caret" role="button" data-toggle="collapse" href="#protocol-steps-container" aria-expanded="false" aria-controls="protocol-steps-container"> <a class="protocol-section-caret" role="button" data-toggle="collapse" href="#protocol-steps-container" aria-expanded="false" aria-controls="protocol-steps-container">
<i class="sn-icon sn-icon-right"></i> <i class="sn-icon sn-icon-right"></i>
<span id="protocolStepsLabel" class="protocol-section-title"> <span id="protocolStepsLabel" class="protocol-section-title" data-e2e="e2e-TX-protocol-templateSteps-title">
<h2> <h2>
{{ i18n.t("protocols.header.protocol_steps") }} {{ i18n.t("protocols.header.protocol_steps") }}
</h2> </h2>
@ -137,6 +145,7 @@
<a <a
class="btn btn-secondary" class="btn btn-secondary"
:title="i18n.t('protocols.steps.new_step_title')" :title="i18n.t('protocols.steps.new_step_title')"
data-e2e="e2e-BT-protocol-templateSteps-newStepTop"
@keyup.enter="addStep(steps.length)" @keyup.enter="addStep(steps.length)"
@click="addStep(steps.length)" @click="addStep(steps.length)"
tabindex="0"> tabindex="0">
@ -144,15 +153,16 @@
<span>{{ i18n.t("protocols.steps.new_step") }}</span> <span>{{ i18n.t("protocols.steps.new_step") }}</span>
</a> </a>
<div v-if="steps.length > 0" class="flex justify-between items-center gap-4"> <div v-if="steps.length > 0" class="flex justify-between items-center gap-4">
<button @click="collapseSteps" class="btn btn-secondary flex px-4" tabindex="0"> <button @click="collapseSteps" class="btn btn-secondary flex px-4" tabindex="0" data-e2e="e2e-BT-protocol-templateSteps-collapse">
{{ i18n.t("protocols.steps.collapse_label") }} {{ i18n.t("protocols.steps.collapse_label") }}
</button> </button>
<button @click="expandSteps" class="btn btn-secondary flex px-4" tabindex="0"> <button @click="expandSteps" class="btn btn-secondary flex px-4" tabindex="0" data-e2e="e2e-BT-protocol-templateSteps-expand">
{{ i18n.t("protocols.steps.expand_label") }} {{ i18n.t("protocols.steps.expand_label") }}
</button> </button>
<a v-if="steps.length > 0 && urls.reorder_steps_url" <a v-if="steps.length > 0 && urls.reorder_steps_url"
class="btn btn-light icon-btn" class="btn btn-light icon-btn"
data-toggle="modal" data-toggle="modal"
data-e2e="e2e-BT-protocol-templateSteps-reorder"
@click="startStepReorder" @click="startStepReorder"
@keyup.enter="startStepReorder" @keyup.enter="startStepReorder"
:class="{'disabled': steps.length == 1}" :class="{'disabled': steps.length == 1}"
@ -163,7 +173,7 @@
</div> </div>
<div class="protocol-steps pb-8"> <div class="protocol-steps pb-8">
<div v-for="(step, index) in steps" :key="step.id" class="step-block"> <div v-for="(step, index) in steps" :key="step.id" class="step-block">
<div v-if="index > 0 && urls.add_step_url" class="insert-step" @click="addStep(index)"> <div v-if="index > 0 && urls.add_step_url" class="insert-step" @click="addStep(index)" data-e2e="e2e-BT-protocol-templateSteps-insertStep">
<i class="sn-icon sn-icon-new-task"></i> <i class="sn-icon sn-icon-new-task"></i>
</div> </div>
<Step <Step
@ -185,7 +195,7 @@
:reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null" :reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null"
:assignableMyModuleId="protocol.attributes.assignable_my_module_id" :assignableMyModuleId="protocol.attributes.assignable_my_module_id"
/> />
<div v-if="(index === steps.length - 1) && urls.add_step_url" class="insert-step" @click="addStep(index + 1)"> <div v-if="(index === steps.length - 1) && urls.add_step_url" class="insert-step" @click="addStep(index + 1)" data-e2e="e2e-BT-protocol-templateSteps-insertStep">
<i class="sn-icon sn-icon-new-task"></i> <i class="sn-icon sn-icon-new-task"></i>
</div> </div>
</div> </div>
@ -193,6 +203,7 @@
<a <a
class="btn btn-secondary" class="btn btn-secondary"
:title="i18n.t('protocols.steps.new_step_title')" :title="i18n.t('protocols.steps.new_step_title')"
data-e2e="e2e-BT-protocol-templateSteps-newStepBottom"
@keyup.enter="addStep(steps.length)" @keyup.enter="addStep(steps.length)"
@click="addStep(steps.length)" @click="addStep(steps.length)"
tabindex="0"> tabindex="0">

View file

@ -1,32 +1,33 @@
<template> <template>
<div class="protocol-section protocol-information mb-4"> <div class="protocol-section protocol-information mb-4" data-e2e="e2e-CO-protocolTemplates-protocolDetails">
<div id="protocol-details" class="protocol-section-header"> <div id="protocol-details" class="protocol-section-header">
<div class="protocol-details-container"> <div class="protocol-details-container">
<a class="protocol-section-caret" role="button" data-toggle="collapse" <a class="protocol-section-caret" role="button" data-toggle="collapse"
href="#details-container" aria-expanded="false" aria-controls="details-container"> href="#details-container" aria-expanded="false" aria-controls="details-container">
<i class="sn-icon sn-icon-right"></i> <i class="sn-icon sn-icon-right"></i>
<span id="protocolDetailsLabel" class="protocol-section-title"> <span id="protocolDetailsLabel" class="protocol-section-title">
<h2> <h2 data-e2e="e2e-TX-protocolTemplates-protocolDetails-title">
{{ i18n.t("protocols.header.details") }} {{ i18n.t("protocols.header.details") }}
</h2> </h2>
<span class="protocol-code" >{{ protocol.attributes.code }}</span> <span class="protocol-code" data-e2e="e2e-TX-protocolTemplates-protocolDetails-protocolId">{{ protocol.attributes.code }}</span>
</span> </span>
</a> </a>
</div> </div>
<div class="actions-block"> <div class="actions-block">
<a class="btn btn-light icon-btn pull-right" <a class="btn btn-light icon-btn pull-right"
:href="protocol.attributes.urls.print_protocol_url" target="_blank"> :href="protocol.attributes.urls.print_protocol_url" target="_blank"
data-e2e="e2e-BT-protocolTemplates-protocolDetails-print">
<span class="sn-icon sn-icon-printer" aria-hidden="true"></span> <span class="sn-icon sn-icon-printer" aria-hidden="true"></span>
</a> </a>
<button class="btn btn-light" @click="openVersionsModal"> <button class="btn btn-light" @click="openVersionsModal" data-e2e="e2e-BT-protocolTemplates-protocolDetails-versions">
{{ i18n.t("protocols.header.versions") }} {{ i18n.t("protocols.header.versions") }}
</button> </button>
<button v-if="protocol.attributes.urls.publish_url" <button v-if="protocol.attributes.urls.publish_url"
@click="$emit('publish')" class="btn btn-primary"> @click="$emit('publish')" class="btn btn-primary" data-e2e="e2e-BT-protocolTemplates-protocolDetails-publish">
{{ i18n.t("protocols.header.publish") }}</button> {{ i18n.t("protocols.header.publish") }}</button>
<button v-if="protocol.attributes.urls.save_as_draft_url" <button v-if="protocol.attributes.urls.save_as_draft_url"
:disabled="protocol.attributes.has_draft || creatingDraft" :disabled="protocol.attributes.has_draft || creatingDraft"
@click="saveAsdraft" class="btn btn-secondary"> @click="saveAsdraft" class="btn btn-secondary" data-e2e="e2e-BT-protocolTemplates-protocolDetails-saveAsDraft">
{{ i18n.t("protocols.header.save_as_draft") }} {{ i18n.t("protocols.header.save_as_draft") }}
</button> </button>
</div> </div>
@ -34,33 +35,33 @@
<div id="details-container" class="protocol-details collapse in"> <div id="details-container" class="protocol-details collapse in">
<div class="protocol-metadata"> <div class="protocol-metadata">
<p class="data-block"> <p class="data-block">
<span>{{ i18n.t("protocols.header.version") }}</span> <span data-e2e="e2e-TX-protocolTemplates-protocolDetails-versionLabel">{{ i18n.t("protocols.header.version") }}</span>
<b>{{ titleVersion }}</b> <b data-e2e="e2e-TX-protocolTemplates-protocolDetails-version">{{ titleVersion }}</b>
</p> </p>
<p class="data-block" v-if="protocol.attributes.published"> <p class="data-block" v-if="protocol.attributes.published">
<span>{{ i18n.t("protocols.header.published_on") }}</span> <span data-e2e="e2e-TX-protocolTemplates-protocolDetails-publishedOnLabel">{{ i18n.t("protocols.header.published_on") }}</span>
<b>{{ protocol.attributes.published_on_formatted }}</b> <b data-e2e="e2e-TX-protocolTemplates-protocolDetails-publishedOn">{{ protocol.attributes.published_on_formatted }}</b>
</p> </p>
<p class="data-block" v-if="protocol.attributes.published"> <p class="data-block" v-if="protocol.attributes.published" data-e2e="e2e-TX-protocolTemplates-protocolDetails-publishedBy">
<span>{{ i18n.t("protocols.header.published_by") }}</span> <span>{{ i18n.t("protocols.header.published_by") }}</span>
<img :src="protocol.attributes.published_by.avatar" class="rounded-full"/> <img :src="protocol.attributes.published_by.avatar" class="rounded-full"/>
{{ protocol.attributes.published_by.name }} {{ protocol.attributes.published_by.name }}
</p> </p>
<p class="data-block"> <p class="data-block">
<span>{{ i18n.t("protocols.header.updated_at") }}</span> <span data-e2e="e2e-TX-protocolTemplates-protocolDetails-updatedAtLabel">{{ i18n.t("protocols.header.updated_at") }}</span>
<b>{{ protocol.attributes.updated_at_formatted }}</b> <b data-e2e="e2e-TX-protocolTemplates-protocolDetails-updatedAt">{{ protocol.attributes.updated_at_formatted }}</b>
</p> </p>
<p class="data-block"> <p class="data-block">
<span>{{ i18n.t("protocols.header.created_at") }}</span> <span data-e2e="e2e-TX-protocolTemplates-protocolDetails-createdAtLabel">{{ i18n.t("protocols.header.created_at") }}</span>
<b>{{ protocol.attributes.created_at_formatted }}</b> <b data-e2e="e2e-TX-protocolTemplates-protocolDetails-createdAt">{{ protocol.attributes.created_at_formatted }}</b>
</p> </p>
<p class="data-block"> <p class="data-block" data-e2e="e2e-TX-protocolTemplates-protocolDetails-createdBy">
<span>{{ i18n.t("protocols.header.added_by") }}</span> <span>{{ i18n.t("protocols.header.added_by") }}</span>
<img :src="protocol.attributes.added_by.avatar" class="rounded-full"/> <img :src="protocol.attributes.added_by.avatar" class="rounded-full"/>
{{ protocol.attributes.added_by.name }} {{ protocol.attributes.added_by.name }}
</p> </p>
<p class="data-block authors-data"> <p class="data-block authors-data">
<span>{{ i18n.t("protocols.header.authors") }}</span> <span data-e2e="e2e-TX-protocolTemplates-protocolDetails-authorsLabel">{{ i18n.t("protocols.header.authors") }}</span>
<span class="authors-list" v-if="protocol.attributes.urls.update_protocol_authors_url"> <span class="authors-list" v-if="protocol.attributes.urls.update_protocol_authors_url">
<InlineEdit <InlineEdit
:value="protocol.attributes.authors" :value="protocol.attributes.authors"
@ -68,15 +69,16 @@
:allowBlank="true" :allowBlank="true"
:attributeName="`${i18n.t('Protocol')} ${i18n.t('protocols.header.authors_list')}`" :attributeName="`${i18n.t('Protocol')} ${i18n.t('protocols.header.authors_list')}`"
:characterLimit="10000" :characterLimit="10000"
:dataE2e="'protocolTemplates-protocolDetails-authors'"
@update="updateAuthors" @update="updateAuthors"
/> />
</span> </span>
<span class="authors-list" v-else> <span class="authors-list" data-e2e="e2e-TX-protocolTemplates-protocolDetails-authorsPublished" v-else>
{{ protocol.attributes.authors }} {{ protocol.attributes.authors }}
</span> </span>
</p> </p>
<p class="data-block keywords-data"> <p class="data-block keywords-data">
<span>{{ i18n.t("protocols.header.keywords") }}</span> <span data-e2e="e2e-TX-protocolTemplates-protocolDetails-keywordsLabel">{{ i18n.t("protocols.header.keywords") }}</span>
<span <span
class="keywords-list" class="keywords-list"
v-if="protocol.attributes.urls.update_protocol_authors_url || protocol.attributes.keywords.length"> v-if="protocol.attributes.urls.update_protocol_authors_url || protocol.attributes.keywords.length">
@ -90,6 +92,7 @@
:noEmptyOption="false" :noEmptyOption="false"
:selectAppearance="'tag'" :selectAppearance="'tag'"
:viewMode="protocol.attributes.urls.update_protocol_keywords_url == null" :viewMode="protocol.attributes.urls.update_protocol_keywords_url == null"
:dataE2e="'protocolTemplates-protocolDetails-keywords'"
@dropdown:changed="updateKeywords" @dropdown:changed="updateKeywords"
/> />
</span> </span>
@ -117,7 +120,7 @@ export default {
protocol: { protocol: {
type: Object, type: Object,
required: true required: true
}, }
}, },
data() { data() {
return { return {

View file

@ -6,6 +6,7 @@
@dragover.prevent @dragover.prevent
:data-id="step.id" :data-id="step.id"
:class="{ 'draging-file': dragingFile, 'editing-name': editingName, 'locked': !urls.update_url, 'pointer-events-none': addingContent }" :class="{ 'draging-file': dragingFile, 'editing-name': editingName, 'locked': !urls.update_url, 'pointer-events-none': addingContent }"
:data-e2e="`e2e-CO-protocol-step${step.id}`"
> >
<div class="drop-message" @dragleave.prevent="!showFileModal ? dragingFile = false : null"> <div class="drop-message" @dragleave.prevent="!showFileModal ? dragingFile = false : null">
{{ i18n.t('protocols.steps.drop_message', { position: step.attributes.position + 1 }) }} {{ i18n.t('protocols.steps.drop_message', { position: step.attributes.position + 1 }) }}
@ -18,7 +19,8 @@
:href="'#stepBody' + step.id" :href="'#stepBody' + step.id"
data-toggle="collapse" data-toggle="collapse"
data-remote="true" data-remote="true"
@click="toggleCollapsed"> @click="toggleCollapsed"
:data-e2e="`e2e-BT-protocol-step${step.id}-toggleCollapsed`">
<span class="sn-icon sn-icon-right "></span> <span class="sn-icon sn-icon-right "></span>
</a> </a>
<div v-if="!inRepository" class="step-complete-container" :class="{ 'step-element--locked': !urls.state_url }"> <div v-if="!inRepository" class="step-complete-container" :class="{ 'step-element--locked': !urls.state_url }">
@ -27,9 +29,10 @@
@keyup.enter="changeState" @keyup.enter="changeState"
tabindex="0" tabindex="0"
:title="step.attributes.completed ? i18n.t('protocols.steps.status.uncomplete') : i18n.t('protocols.steps.status.complete')" :title="step.attributes.completed ? i18n.t('protocols.steps.status.uncomplete') : i18n.t('protocols.steps.status.complete')"
:data-e2e="`e2e-BT-protocol-step${step.id}-toggleCompleted`"
></div> ></div>
</div> </div>
<div class="step-position leading-5"> <div class="step-position leading-5" :data-e2e="`e2e-TX-protocol-step${step.id}-position`">
{{ step.attributes.position + 1 }}. {{ step.attributes.position + 1 }}.
</div> </div>
</div> </div>
@ -48,6 +51,7 @@
@editingEnabled="editingName = true" @editingEnabled="editingName = true"
@editingDisabled="editingName = false" @editingDisabled="editingName = false"
:editOnload="step.newStep == true" :editOnload="step.newStep == true"
:dataE2e="`protocol-step${step.id}-title`"
@update="updateName" @update="updateName"
/> />
</div> </div>
@ -60,6 +64,7 @@
:btnText="i18n.t('protocols.steps.insert.button')" :btnText="i18n.t('protocols.steps.insert.button')"
:position="'right'" :position="'right'"
:caret="true" :caret="true"
:dataE2e="`e2e-DD-protocol-step${step.id}-insertContent`"
@create:table="(...args) => this.createElement('table', ...args)" @create:table="(...args) => this.createElement('table', ...args)"
@create:checklist="createElement('checklist')" @create:checklist="createElement('checklist')"
@create:text="createElement('text')" @create:text="createElement('text')"
@ -98,6 +103,7 @@
:btnClasses="'btn btn-light icon-btn'" :btnClasses="'btn btn-light icon-btn'"
:position="'right'" :position="'right'"
:btnIcon="'sn-icon sn-icon-more-hori'" :btnIcon="'sn-icon sn-icon-more-hori'"
:dataE2e="`e2e-DD-protocol-step${step.id}-options`"
@reorder="openReorderModal" @reorder="openReorderModal"
@duplicate="duplicateStep" @duplicate="duplicateStep"
@delete="showDeleteModal" @delete="showDeleteModal"
@ -116,6 +122,7 @@
:reorderElementUrl="elements.length > 1 ? urls.reorder_elements_url : ''" :reorderElementUrl="elements.length > 1 ? urls.reorder_elements_url : ''"
:assignableMyModuleId="assignableMyModuleId" :assignableMyModuleId="assignableMyModuleId"
:isNew="element.isNew" :isNew="element.isNew"
:dataE2e="`protocol-step${step.id}`"
@component:adding-content="($event) => addingContent = $event" @component:adding-content="($event) => addingContent = $event"
@component:delete="deleteElement" @component:delete="deleteElement"
@update="updateElement" @update="updateElement"
@ -127,6 +134,7 @@
:parent="step" :parent="step"
:attachments="attachments" :attachments="attachments"
:attachmentsReady="attachmentsReady" :attachmentsReady="attachmentsReady"
:dataE2e="`protocol-step${step.id}`"
@attachments:openFileModal="showFileModal = true" @attachments:openFileModal="showFileModal = true"
@attachment:deleted="attachmentDeleted" @attachment:deleted="attachmentDeleted"
@attachment:update="updateAttachment" @attachment:update="updateAttachment"
@ -142,6 +150,7 @@
<ReorderableItemsModal v-if="reordering" <ReorderableItemsModal v-if="reordering"
:title="i18n.t('protocols.steps.modals.reorder_elements.title', { step_position: step.attributes.position + 1 })" :title="i18n.t('protocols.steps.modals.reorder_elements.title', { step_position: step.attributes.position + 1 })"
:items="reorderableElements" :items="reorderableElements"
:dataE2e="`e2e-BT-protocol-step${step.id}-reorder`"
@reorder="updateElementOrder" @reorder="updateElementOrder"
@close="closeReorderModal" @close="closeReorderModal"
/> />
@ -212,13 +221,34 @@
editingName: false, editingName: false,
inlineEditError: null, inlineEditError: null,
wellPlateOptions: [ wellPlateOptions: [
{ text: I18n.t('protocols.steps.insert.well_plate_options.32_x_48'), emit: 'create:table', params: [32, 48] }, { text: I18n.t('protocols.steps.insert.well_plate_options.32_x_48'),
{ text: I18n.t('protocols.steps.insert.well_plate_options.16_x_24'), emit: 'create:table', params: [16, 24] }, emit: 'create:table',
{ text: I18n.t('protocols.steps.insert.well_plate_options.8_x_12'), emit: 'create:table', params: [8, 12] }, params: [32, 48],
{ text: I18n.t('protocols.steps.insert.well_plate_options.6_x_8'), emit: 'create:table', params: [6, 8] }, data_e2e: `e2e-BT-protocol-step${this.step.id}-insertWellPlate-32` },
{ text: I18n.t('protocols.steps.insert.well_plate_options.4_x_6'), emit: 'create:table', params: [4, 6] }, { text: I18n.t('protocols.steps.insert.well_plate_options.16_x_24'),
{ text: I18n.t('protocols.steps.insert.well_plate_options.3_x_4'), emit: 'create:table', params: [3, 4]}, emit: 'create:table',
{ text: I18n.t('protocols.steps.insert.well_plate_options.2_x_3'), emit: 'create:table', params: [2, 3] } params: [16, 24],
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertWellPlate-16` },
{ text: I18n.t('protocols.steps.insert.well_plate_options.8_x_12'),
emit: 'create:table',
params: [8, 12],
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertWellPlate-8` },
{ text: I18n.t('protocols.steps.insert.well_plate_options.6_x_8'),
emit: 'create:table',
params: [6, 8],
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertWellPlate-6` },
{ text: I18n.t('protocols.steps.insert.well_plate_options.4_x_6'),
emit: 'create:table',
params: [4, 6],
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertWellPlate-4` },
{ text: I18n.t('protocols.steps.insert.well_plate_options.3_x_4'),
emit: 'create:table',
params: [3, 4],
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertWellPlate-3` },
{ text: I18n.t('protocols.steps.insert.well_plate_options.2_x_3'),
emit: 'create:table',
params: [2, 3],
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertWellPlate-2` }
] ]
} }
}, },
@ -276,25 +306,29 @@
if (this.urls.upload_attachment_url) { if (this.urls.upload_attachment_url) {
menu = menu.concat([{ menu = menu.concat([{
text: this.i18n.t('protocols.steps.insert.add_file'), text: this.i18n.t('protocols.steps.insert.add_file'),
emit: 'create:file' emit: 'create:file',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertAttachment-file`
}]); }]);
} }
if (this.step.attributes.wopi_enabled) { if (this.step.attributes.wopi_enabled) {
menu = menu.concat([{ menu = menu.concat([{
text: this.i18n.t('assets.create_wopi_file.button_text'), text: this.i18n.t('assets.create_wopi_file.button_text'),
emit: 'create:wopi_file' emit: 'create:wopi_file',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertAttachment-wopi`
}]); }]);
} }
if (this.step.attributes.open_vector_editor_context.new_sequence_asset_url) { if (this.step.attributes.open_vector_editor_context.new_sequence_asset_url) {
menu = menu.concat([{ menu = menu.concat([{
text: this.i18n.t('open_vector_editor.new_sequence_file'), text: this.i18n.t('open_vector_editor.new_sequence_file'),
emit: 'create:ove_file' emit: 'create:ove_file',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertAttachment-sequence`
}]); }]);
} }
if (this.step.attributes.marvinjs_enabled) { if (this.step.attributes.marvinjs_enabled) {
menu = menu.concat([{ menu = menu.concat([{
text: this.i18n.t('marvinjs.new_button'), text: this.i18n.t('marvinjs.new_button'),
emit: 'create:marvinjs_file' emit: 'create:marvinjs_file',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertAttachment-chemicalDrawing`
}]); }]);
} }
return menu; return menu;
@ -304,21 +338,26 @@
if (this.urls.update_url) { if (this.urls.update_url) {
menu = menu.concat([{ menu = menu.concat([{
text: this.i18n.t('protocols.steps.insert.text'), text: this.i18n.t('protocols.steps.insert.text'),
emit: 'create:text' emit: 'create:text',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertText`
},{ },{
text: this.i18n.t('protocols.steps.insert.attachment'), text: this.i18n.t('protocols.steps.insert.attachment'),
submenu: this.filesMenu, submenu: this.filesMenu,
position: 'left' position: 'left',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertAttachment`
},{ },{
text: this.i18n.t('protocols.steps.insert.table'), text: this.i18n.t('protocols.steps.insert.table'),
emit: 'create:table' emit: 'create:table',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertTable`
},{ },{
text: this.i18n.t('protocols.steps.insert.well_plate'), text: this.i18n.t('protocols.steps.insert.well_plate'),
submenu: this.wellPlateOptions, submenu: this.wellPlateOptions,
position: 'left' position: 'left',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertWellplate`
},{ },{
text: this.i18n.t('protocols.steps.insert.checklist'), text: this.i18n.t('protocols.steps.insert.checklist'),
emit: 'create:checklist' emit: 'create:checklist',
data_e2e: `e2e-BT-protocol-step${this.step.id}-insertChecklist`
}]); }]);
} }
@ -329,19 +368,22 @@
if (this.urls.reorder_elements_url) { if (this.urls.reorder_elements_url) {
menu = menu.concat([{ menu = menu.concat([{
text: this.i18n.t('protocols.steps.options_dropdown.rearrange'), text: this.i18n.t('protocols.steps.options_dropdown.rearrange'),
emit: 'reorder' emit: 'reorder',
data_e2e: `e2e-BT-protocol-step${this.step.id}-stepOptions-rearrange`
}]); }]);
} }
if (this.urls.duplicate_step_url) { if (this.urls.duplicate_step_url) {
menu = menu.concat([{ menu = menu.concat([{
text: this.i18n.t('protocols.steps.options_dropdown.duplicate'), text: this.i18n.t('protocols.steps.options_dropdown.duplicate'),
emit: 'duplicate' emit: 'duplicate',
data_e2e: `e2e-BT-protocol-step${this.step.id}-stepOptions-duplicate`
}]); }]);
} }
if (this.urls.delete_url) { if (this.urls.delete_url) {
menu = menu.concat([{ menu = menu.concat([{
text: this.i18n.t('protocols.steps.options_dropdown.delete'), text: this.i18n.t('protocols.steps.options_dropdown.delete'),
emit: 'delete' emit: 'delete',
data_e2e: `e2e-BT-protocol-step${this.step.id}-stepOptions-delete`
}]); }]);
} }
return menu; return menu;

View file

@ -1,5 +1,7 @@
<template> <template>
<div class="content__attachments pr-8" :id='"content__attachments-" + parent.id'> <div class="content__attachments pr-8"
:id='"content__attachments-" + parent.id'
:data-e2e="`e2e-CO-${dataE2e}-attachments`">
<div class="sci-divider my-6"></div> <div class="sci-divider my-6"></div>
<div class="content__attachments-actions"> <div class="content__attachments-actions">
<div class="title"> <div class="title">
@ -11,6 +13,7 @@
:btnText="i18n.t('attachments.preview_menu')" :btnText="i18n.t('attachments.preview_menu')"
:position="'right'" :position="'right'"
:caret="true" :caret="true"
:data_e2e="`e2e-DD-${dataE2e}-attachments-viewOptions`"
@attachment:viewMode = "changeAttachmentsViewMode" @attachment:viewMode = "changeAttachmentsViewMode"
></MenuDropdown> ></MenuDropdown>
<MenuDropdown <MenuDropdown
@ -18,6 +21,7 @@
:btnIcon="'sn-icon sn-icon-sort-down'" :btnIcon="'sn-icon sn-icon-sort-down'"
:btnClasses="'btn btn-light icon-btn'" :btnClasses="'btn btn-light icon-btn'"
:position="'right'" :position="'right'"
:data_e2e="`e2e-DD-${dataE2e}-attachments-orderOptions`"
@attachment:order = "changeAttachmentsOrder" @attachment:order = "changeAttachmentsOrder"
></MenuDropdown> ></MenuDropdown>
</div> </div>
@ -29,6 +33,7 @@
:is="attachment_view_mode(attachmentsOrdered[index])" :is="attachment_view_mode(attachmentsOrdered[index])"
:attachment="attachment" :attachment="attachment"
:parentId="parseInt(parent.id)" :parentId="parseInt(parent.id)"
:dataE2e="`${dataE2e}`"
@attachment:viewMode="updateAttachmentViewMode" @attachment:viewMode="updateAttachmentViewMode"
@attachment:delete="deleteAttachment(attachment.id)" @attachment:delete="deleteAttachment(attachment.id)"
@attachment:moved="attachmentMoved" @attachment:moved="attachmentMoved"
@ -64,6 +69,10 @@ export default {
attachmentsReady: { attachmentsReady: {
type: Boolean, type: Boolean,
required: true required: true
},
dataE2e: {
type: String,
default: ''
} }
}, },
data() { data() {
@ -119,7 +128,8 @@ export default {
active: this.parent.attributes.assets_view_mode == viewMode, active: this.parent.attributes.assets_view_mode == viewMode,
text: this.i18n.t(`attachments.view_mode.${viewMode}_html`), text: this.i18n.t(`attachments.view_mode.${viewMode}_html`),
emit: 'attachment:viewMode', emit: 'attachment:viewMode',
params: viewMode params: viewMode,
data_e2e: `e2e-BT-${this.dataE2e}-viewOptions-${viewMode}`
}); });
}); });
return menu; return menu;
@ -131,7 +141,8 @@ export default {
text: this.i18n.t(`general.sort_new.${orderOption}`), text: this.i18n.t(`general.sort_new.${orderOption}`),
emit: 'attachment:order', emit: 'attachment:order',
params: orderOption, params: orderOption,
active: this.parent.attributes.assets_order === orderOption active: this.parent.attributes.assets_order === orderOption,
data_e2e: `e2e-BT-${this.dataE2e}-orderOptions-${orderOption}`
}); });
}); });
return menu; return menu;

View file

@ -1,5 +1,7 @@
<template> <template>
<div class="attachment-container asset" :data-asset-id="attachment.id"> <div class="attachment-container asset"
:data-asset-id="attachment.id"
:data-e2e="`e2e-CO-${dataE2e}-attachment${attachment.id}-empty`">
<div <div
class="file-name" class="file-name"
:id="`modal_link${attachment.id}`" :id="`modal_link${attachment.id}`"
@ -23,6 +25,10 @@ export default {
parentId: { parentId: {
type: Number, type: Number,
required: true required: true
},
dataE2e: {
type: String,
default: ''
} }
} }
}; };

View file

@ -1,6 +1,7 @@
<template> <template>
<div class="inline-attachment-container asset" <div class="inline-attachment-container asset"
:data-asset-id="attachment.id" :data-asset-id="attachment.id"
:data-e2e="`e2e-CO-${dataE2e}-attachment${attachment.id}-inline`"
> >
<div class="header"> <div class="header">
<div class="file-info"> <div class="file-info">
@ -86,6 +87,10 @@ export default {
parentId: { parentId: {
type: Number, type: Number,
required: true required: true
},
dataE2e: {
type: String,
default: ''
} }
}, },
data() { data() {

View file

@ -1,6 +1,7 @@
<template> <template>
<div class="list-attachment-container asset" <div class="list-attachment-container asset"
:data-asset-id="attachment.id" :data-asset-id="attachment.id"
:data-e2e="`e2e-CO-${dataE2e}-attachment${attachment.id}-list`"
> >
<i class="text-sn-grey asset-icon sn-icon" :class="attachment.attributes.icon"></i> <i class="text-sn-grey asset-icon sn-icon" :class="attachment.attributes.icon"></i>
<a :href="attachment.attributes.urls.blob" <a :href="attachment.attributes.urls.blob"
@ -57,6 +58,10 @@ export default {
parentId: { parentId: {
type: Number, type: Number,
required: true required: true
},
dataE2e: {
type: String,
default: ''
} }
}, },
data() { data() {

View file

@ -4,6 +4,7 @@
@mouseenter="handleMouseEnter" @mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave" @mouseleave="handleMouseLeave"
v-click-outside="handleClickOutsideThumbnail" v-click-outside="handleClickOutsideThumbnail"
:data-e2e="`e2e-CO-${dataE2e}-attachment${attachment.id}-thumbnail`"
> >
<a :class="{ hidden: showOptions }" <a :class="{ hidden: showOptions }"
:href="attachment.attributes.urls.blob" :href="attachment.attributes.urls.blob"
@ -101,7 +102,10 @@
> >
<i class="sn-icon sn-icon-open"></i> <i class="sn-icon sn-icon-open"></i>
</a> </a>
<a v-if="attachment.attributes.urls.move" @click.prevent.stop="showMoveModal" class="btn btn-light icon-btn thumbnail-action-btn" :title="i18n.t('attachments.thumbnail.buttons.move')"> <a v-if="attachment.attributes.urls.move"
@click.prevent.stop="showMoveModal"
class="btn btn-light icon-btn thumbnail-action-btn"
:title="i18n.t('attachments.thumbnail.buttons.move')">
<i class="sn-icon sn-icon-move"></i> <i class="sn-icon sn-icon-move"></i>
</a> </a>
<a class="btn btn-light icon-btn thumbnail-action-btn" <a class="btn btn-light icon-btn thumbnail-action-btn"
@ -202,6 +206,10 @@ export default {
parentId: { parentId: {
type: Number, type: Number,
required: true required: true
},
dataE2e: {
type: String,
default: ''
} }
}, },
data() { data() {
@ -244,7 +252,7 @@ export default {
}); });
} }
return options; return options;
}, }
}, },
mounted() { mounted() {
$(this.$nextTick(() => { $(this.$nextTick(() => {

View file

@ -1,7 +1,8 @@
<template> <template>
<div class="content__checklist-container pr-8" > <div class="content__checklist-container pr-8" :data-e2e="`e2e-CO-${dataE2e}-checklist${element.id}`">
<div class="sci-divider my-6" v-if="!inRepository"></div> <div class="sci-divider my-6" v-if="!inRepository"></div>
<div class="checklist-header flex rounded mb-1 items-center relative w-full group/checklist-header" :class="{ 'editing-name': editingName, 'locked': !element.attributes.orderable.urls.update_url }"> <div class="checklist-header flex rounded mb-1 items-center relative w-full group/checklist-header"
:class="{ 'editing-name': editingName, 'locked': !element.attributes.orderable.urls.update_url }">
<div class="grow-1 text-ellipsis whitespace-nowrap grow my-1 font-bold"> <div class="grow-1 text-ellipsis whitespace-nowrap grow my-1 font-bold">
<InlineEdit <InlineEdit
:class="{ 'pointer-events-none': !element.attributes.orderable.urls.update_url }" :class="{ 'pointer-events-none': !element.attributes.orderable.urls.update_url }"
@ -13,6 +14,7 @@
:autofocus="editingName" :autofocus="editingName"
:smartAnnotation="true" :smartAnnotation="true"
:attributeName="`${i18n.t('Checklist')} ${i18n.t('name')}`" :attributeName="`${i18n.t('Checklist')} ${i18n.t('name')}`"
:dataE2e="`${dataE2e}-checklist${element.id}`"
@editingEnabled="editingName = true" @editingEnabled="editingName = true"
@editingDisabled="editingName = false" @editingDisabled="editingName = false"
@update="updateName" @update="updateName"
@ -24,6 +26,7 @@
:btnClasses="'btn btn-light icon-btn btn-sm'" :btnClasses="'btn btn-light icon-btn btn-sm'"
:position="'right'" :position="'right'"
:btnIcon="'sn-icon sn-icon-more-hori'" :btnIcon="'sn-icon sn-icon-more-hori'"
:dataE2e="`e2e-DD-${dataE2e}-checklist${element.id}-options`"
@edit="editingName = true" @edit="editingName = true"
@duplicate="duplicateElement" @duplicate="duplicateElement"
@move="showMoveModal" @move="showMoveModal"
@ -51,6 +54,7 @@
:reorderChecklistItemUrl="this.element.attributes.orderable.urls.reorder_url" :reorderChecklistItemUrl="this.element.attributes.orderable.urls.reorder_url"
:inRepository="inRepository" :inRepository="inRepository"
:draggable="checklistItems.length > 1" :draggable="checklistItems.length > 1"
:data-e2e="`${dataE2e}-checklistItem${element.id}`"
@editStart="editingItem = true" @editStart="editingItem = true"
@editEnd="editingItem = false" @editEnd="editingItem = false"
@update="saveItem" @update="saveItem"
@ -63,6 +67,7 @@
<div v-if="element.attributes.orderable.urls.create_item_url && !addingNewItem" <div v-if="element.attributes.orderable.urls.create_item_url && !addingNewItem"
class="flex items-center gap-1 text-sn-blue cursor-pointer mb-2 mt-1 " class="flex items-center gap-1 text-sn-blue cursor-pointer mb-2 mt-1 "
tabindex="0" tabindex="0"
:data-e2e="`e2e-BT-${dataE2e}-checklist${element.id}-addNew`"
@keyup.enter="addItem(checklistItems[checklistItems.length - 1]?.id)" @keyup.enter="addItem(checklistItems[checklistItems.length - 1]?.id)"
@click="addItem(checklistItems[checklistItems.length - 1]?.id)"> @click="addItem(checklistItems[checklistItems.length - 1]?.id)">
<i class="sn-icon sn-icon-new-task w-6 text-center inline-block"></i> <i class="sn-icon sn-icon-new-task w-6 text-center inline-block"></i>
@ -120,6 +125,10 @@ export default {
assignableMyModuleId: { assignableMyModuleId: {
type: Number, type: Number,
required: false required: false
},
dataE2e: {
type: String,
default: ''
} }
}, },
data() { data() {
@ -154,25 +163,29 @@ export default {
if (this.element.attributes.orderable.urls.update_url) { if (this.element.attributes.orderable.urls.update_url) {
menu.push({ menu.push({
text: I18n.t('general.edit'), text: I18n.t('general.edit'),
emit: 'edit' emit: 'edit',
data_e2e: `e2e-BT-${this.dataE2e}-checklist${this.element.id}-options-edit`
}); });
} }
if (this.element.attributes.orderable.urls.duplicate_url) { if (this.element.attributes.orderable.urls.duplicate_url) {
menu.push({ menu.push({
text: I18n.t('general.duplicate'), text: I18n.t('general.duplicate'),
emit: 'duplicate' emit: 'duplicate',
data_e2e: `e2e-BT-${this.dataE2e}-checklist${this.element.id}-options-duplicate`
}); });
} }
if (this.element.attributes.orderable.urls.move_targets_url) { if (this.element.attributes.orderable.urls.move_targets_url) {
menu.push({ menu.push({
text: I18n.t('general.move'), text: I18n.t('general.move'),
emit: 'move' emit: 'move',
data_e2e: `e2e-BT-${this.dataE2e}-checklist${this.element.id}-options-move`
}); });
} }
if (this.element.attributes.orderable.urls.delete_url) { if (this.element.attributes.orderable.urls.delete_url) {
menu.push({ menu.push({
text: I18n.t('general.delete'), text: I18n.t('general.delete'),
emit: 'delete' emit: 'delete',
data_e2e: `e2e-BT-${this.dataE2e}-checklist${this.element.id}-options-delete`
}); });
} }
return menu; return menu;

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="content__checklist-item pl-10 ml-[-2.325rem] group/checklist-item-header"> <div class="content__checklist-item pl-10 ml-[-2.325rem] group/checklist-item-header" :data-e2e="`e2e-CO-${dataE2e}`">
<div class="checklist-item-header flex rounded items-center relative w-full" :class="{ 'locked': locked || editingText, 'editing-name': editingText }"> <div class="checklist-item-header flex rounded items-center relative w-full" :class="{ 'locked': locked || editingText, 'editing-name': editingText }">
<div v-if="reorderChecklistItemUrl" <div v-if="reorderChecklistItemUrl"
class="absolute h-6 cursor-grab justify-center left-[-2.325rem] top-0.5 px-2 tw-hidden text-sn-grey element-grip step-element-grip--draggable" class="absolute h-6 cursor-grab justify-center left-[-2.325rem] top-0.5 px-2 tw-hidden text-sn-grey element-grip step-element-grip--draggable"
@ -14,7 +14,9 @@
type="checkbox" type="checkbox"
class="sci-checkbox" class="sci-checkbox"
:disabled="checklistItem.attributes.isNew" :disabled="checklistItem.attributes.isNew"
:checked="checklistItem.attributes.checked" @change="toggleChecked($event)" /> :checked="checklistItem.attributes.checked"
:data-e2e="`e2e-CB-${dataE2e}-toggleChecked`"
@change="toggleChecked($event)" />
<span class="sci-checkbox-label" > <span class="sci-checkbox-label" >
</span> </span>
</div> </div>
@ -37,6 +39,7 @@
:editOnload="checklistItem.attributes.isNew" :editOnload="checklistItem.attributes.isNew"
:smartAnnotation="true" :smartAnnotation="true"
:allowNewLine="true" :allowNewLine="true"
:dataE2e="dataE2e"
@editingEnabled="enableTextEdit" @editingEnabled="enableTextEdit"
@editingDisabled="disableTextEdit" @editingDisabled="disableTextEdit"
@update="updateText" @update="updateText"
@ -46,6 +49,7 @@
/> />
<span v-if="!editingText && (!checklistItem.attributes.urls || deleteUrl)" <span v-if="!editingText && (!checklistItem.attributes.urls || deleteUrl)"
class="absolute right-0 top-0.5 leading-6 tw-hidden group-hover/checklist-item-header:inline-block !text-sn-blue cursor-pointer" class="absolute right-0 top-0.5 leading-6 tw-hidden group-hover/checklist-item-header:inline-block !text-sn-blue cursor-pointer"
:data-e2e="`e2e-BT-${dataE2e}-delete`"
@click="showDeleteModal" tabindex="0"> @click="showDeleteModal" tabindex="0">
<i class="sn-icon sn-icon-delete"></i> <i class="sn-icon sn-icon-delete"></i>
</span> </span>
@ -88,6 +92,10 @@ export default {
reordering: { reordering: {
type: Boolean, type: Boolean,
required: true required: true
},
dataE2e: {
type: String,
default: ''
} }
}, },
data() { data() {

View file

@ -1,5 +1,6 @@
<template> <template>
<div class="content__table-container pr-8"> <div class="content__table-container pr-8"
:data-e2e="`e2e-CO-${dataE2e}-${element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${element.id}`">
<div class="sci-divider my-6" v-if="!inRepository"></div> <div class="sci-divider my-6" v-if="!inRepository"></div>
<div class="table-header h-9 flex rounded mb-3 items-center relative w-full group/table-header" :class="{ 'editing-name': editingName, 'locked': locked }"> <div class="table-header h-9 flex rounded mb-3 items-center relative w-full group/table-header" :class="{ 'editing-name': editingName, 'locked': locked }">
<div v-if="!locked || element.attributes.orderable.name" :key="reloadHeader" <div v-if="!locked || element.attributes.orderable.name" :key="reloadHeader"
@ -12,6 +13,7 @@
:allowBlank="false" :allowBlank="false"
:autofocus="editingName" :autofocus="editingName"
:attributeName="`${i18n.t('Table')} ${i18n.t('name')}`" :attributeName="`${i18n.t('Table')} ${i18n.t('name')}`"
:dataE2e="`${dataE2e}-${element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${element.id}`"
@editingEnabled="enableNameEdit" @editingEnabled="enableNameEdit"
@editingDisabled="disableNameEdit" @editingDisabled="disableNameEdit"
@update="updateName" @update="updateName"
@ -23,6 +25,7 @@
:btnClasses="'btn btn-light icon-btn btn-sm'" :btnClasses="'btn btn-light icon-btn btn-sm'"
:position="'right'" :position="'right'"
:btnIcon="'sn-icon sn-icon-more-hori'" :btnIcon="'sn-icon sn-icon-more-hori'"
:dataE2e="`e2e-DD-${dataE2e}-${element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${element.id}-options`"
@edit="enableNameEdit" @edit="enableNameEdit"
@duplicate="duplicateElement" @duplicate="duplicateElement"
@move="showMoveModal" @move="showMoveModal"
@ -32,11 +35,14 @@
<div class="table-body group/table-body relative border-solid border-transparent" <div class="table-body group/table-body relative border-solid border-transparent"
:class="{'edit border-sn-light-grey': editingTable, 'view': !editingTable, 'locked': !element.attributes.orderable.urls.update_url}" :class="{'edit border-sn-light-grey': editingTable, 'view': !editingTable, 'locked': !element.attributes.orderable.urls.update_url}"
tabindex="0" tabindex="0"
:data_e2e="`e2e-TB-${dataE2e}-${element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${element.id}`"
@keyup.enter="!editingTable && enableTableEdit()"> @keyup.enter="!editingTable && enableTableEdit()">
<div ref="hotTable" class="hot-table-container" @click="!editingTable && enableTableEdit()"> <div ref="hotTable" class="hot-table-container" @click="!editingTable && enableTableEdit()">
</div> </div>
<div class="text-xs pt-3 pb-2 text-sn-grey h-1"> <div class="text-xs pt-3 pb-2 text-sn-grey h-1">
<span v-if="editingTable">{{ i18n.t('protocols.steps.table.edit_message') }}</span> <span v-if="editingTable" :dataE2e="`e2e-TX-${dataE2e}-${element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${element.id}-editMessage`">
{{ i18n.t('protocols.steps.table.edit_message') }}
</span>
</div> </div>
</div> </div>
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement" @cancel="closeDeleteModal"/> <deleteElementModal v-if="confirmingDelete" @confirm="deleteElement" @cancel="closeDeleteModal"/>
@ -82,6 +88,10 @@ export default {
assignableMyModuleId: { assignableMyModuleId: {
type: Number, type: Number,
required: false required: false
},
dataE2e: {
type: String,
default: ''
} }
}, },
data() { data() {
@ -104,25 +114,29 @@ export default {
if (this.element.attributes.orderable.urls.update_url) { if (this.element.attributes.orderable.urls.update_url) {
menu.push({ menu.push({
text: I18n.t('general.edit'), text: I18n.t('general.edit'),
emit: 'edit' emit: 'edit',
data_e2e: `e2e-BT-${this.dataE2e}-${this.element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${this.element.id}-options-edit`
}); });
} }
if (this.element.attributes.orderable.urls.duplicate_url) { if (this.element.attributes.orderable.urls.duplicate_url) {
menu.push({ menu.push({
text: I18n.t('general.duplicate'), text: I18n.t('general.duplicate'),
emit: 'duplicate' emit: 'duplicate',
data_e2e: `e2e-BT-${this.dataE2e}-${this.element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${this.element.id}-options-duplicate`
}); });
} }
if (this.element.attributes.orderable.urls.move_targets_url) { if (this.element.attributes.orderable.urls.move_targets_url) {
menu.push({ menu.push({
text: I18n.t('general.move'), text: I18n.t('general.move'),
emit: 'move' emit: 'move',
data_e2e: `e2e-BT-${this.dataE2e}-${this.element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${this.element.id}-options-move`
}); });
} }
if (this.element.attributes.orderable.urls.delete_url) { if (this.element.attributes.orderable.urls.delete_url) {
menu.push({ menu.push({
text: I18n.t('general.delete'), text: I18n.t('general.delete'),
emit: 'delete' emit: 'delete',
data_e2e: `e2e-BT-${this.dataE2e}-${this.element.attributes.orderable.metadata.plateTemplate ? 'wellPlate' : 'table'}${this.element.id}-options-delete`
}); });
} }
return menu; return menu;

View file

@ -1,7 +1,9 @@
<template> <template>
<div class="content__text-container pr-8"> <div class="content__text-container pr-8" :data-e2e="`e2e-CO-${dataE2e}-stepText${element.id}`">
<div class="sci-divider my-6" v-if="!inRepository"></div> <div class="sci-divider my-6" v-if="!inRepository"></div>
<div class="text-header h-9 flex rounded mb-1 items-center relative w-full group/text-header" :class="{ 'editing-name': editingName, 'locked': !element.attributes.orderable.urls.update_url }"> <div class="text-header h-9 flex rounded mb-1 items-center relative w-full group/text-header"
:class="{ 'editing-name': editingName,
'locked': !element.attributes.orderable.urls.update_url }">
<div v-if="element.attributes.orderable.urls.update_url || element.attributes.orderable.name" <div v-if="element.attributes.orderable.urls.update_url || element.attributes.orderable.name"
class="grow-1 text-ellipsis whitespace-nowrap grow my-1 font-bold" class="grow-1 text-ellipsis whitespace-nowrap grow my-1 font-bold"
:class="{'pointer-events-none': !element.attributes.orderable.urls.update_url}" :class="{'pointer-events-none': !element.attributes.orderable.urls.update_url}"
@ -13,6 +15,7 @@
:allowBlank="true" :allowBlank="true"
:autofocus="editingName" :autofocus="editingName"
:attributeName="`${i18n.t('Text')} ${i18n.t('name')}`" :attributeName="`${i18n.t('Text')} ${i18n.t('name')}`"
:dataE2e="`${dataE2e}-stepText${element.id}`"
@editingEnabled="enableNameEdit" @editingEnabled="enableNameEdit"
@editingDisabled="disableNameEdit" @editingDisabled="disableNameEdit"
@update="updateName" @update="updateName"
@ -24,13 +27,18 @@
:btnClasses="'btn btn-light icon-btn btn-sm'" :btnClasses="'btn btn-light icon-btn btn-sm'"
:position="'right'" :position="'right'"
:btnIcon="'sn-icon sn-icon-more-hori'" :btnIcon="'sn-icon sn-icon-more-hori'"
:dataE2e="`e2e-DD-${dataE2e}-stepText${element.id}-options`"
@edit="enableNameEdit" @edit="enableNameEdit"
@duplicate="duplicateElement" @duplicate="duplicateElement"
@move="showMoveModal" @move="showMoveModal"
@delete="showDeleteModal" @delete="showDeleteModal"
></MenuDropdown> ></MenuDropdown>
</div> </div>
<div class="flex rounded min-h-[2.25rem] mb-4 relative group/text_container content__text-body" :class="{ 'edit': inEditMode, 'component__element--locked': !element.attributes.orderable.urls.update_url }" @keyup.enter="enableEditMode($event)" tabindex="0"> <div class="flex rounded min-h-[2.25rem] mb-4 relative group/text_container content__text-body"
:class="{ 'edit': inEditMode, 'component__element--locked': !element.attributes.orderable.urls.update_url }"
:data-e2e="`e2e-IF-${dataE2e}-stepText${element.id}`"
@keyup.enter="enableEditMode($event)"
tabindex="0">
<Tinymce <Tinymce
v-if="element.attributes.orderable.urls.update_url" v-if="element.attributes.orderable.urls.update_url"
:value="element.attributes.orderable.text" :value="element.attributes.orderable.text"
@ -48,8 +56,8 @@
@editingDisabled="disableEditMode" @editingDisabled="disableEditMode"
@editingEnabled="enableEditMode" @editingEnabled="enableEditMode"
/> />
<div class="view-text-element" v-else-if="element.attributes.orderable.text_view" v-html="wrappedTables"></div> <div class="view-text-element" v-else-if="element.attributes.orderable.text_view" v-html="wrappedTables" :data-e2e="`e2e-TX-${dataE2e}-stepText${element.id}`"></div>
<div v-else class="text-sn-grey"> <div v-else class="text-sn-grey" :data-e2e="`e2e-TX-${dataE2e}-stepText${element.id}-empty`">
{{ i18n.t("protocols.steps.text.empty_text") }} {{ i18n.t("protocols.steps.text.empty_text") }}
</div> </div>
</div> </div>
@ -96,6 +104,10 @@ export default {
assignableMyModuleId: { assignableMyModuleId: {
type: Number, type: Number,
required: false required: false
},
dataE2e: {
type: String,
default: ''
} }
}, },
data() { data() {
@ -126,25 +138,29 @@ export default {
if (this.element.attributes.orderable.urls.update_url) { if (this.element.attributes.orderable.urls.update_url) {
menu.push({ menu.push({
text: I18n.t('general.edit'), text: I18n.t('general.edit'),
emit: 'edit' emit: 'edit',
data_e2e: `e2e-BT-${this.dataE2e}-stepText${this.element.id}-options-edit`
}); });
} }
if (this.element.attributes.orderable.urls.duplicate_url) { if (this.element.attributes.orderable.urls.duplicate_url) {
menu.push({ menu.push({
text: I18n.t('general.duplicate'), text: I18n.t('general.duplicate'),
emit: 'duplicate' emit: 'duplicate',
data_e2e: `e2e-BT-${this.dataE2e}-stepText${this.element.id}-options-duplicate`
}); });
} }
if (this.element.attributes.orderable.urls.move_targets_url) { if (this.element.attributes.orderable.urls.move_targets_url) {
menu.push({ menu.push({
text: I18n.t('general.move'), text: I18n.t('general.move'),
emit: 'move' emit: 'move',
data_e2e: `e2e-BT-${this.dataE2e}-stepText${this.element.id}-options-move`
}); });
} }
if (this.element.attributes.orderable.urls.delete_url) { if (this.element.attributes.orderable.urls.delete_url) {
menu.push({ menu.push({
text: I18n.t('general.delete'), text: I18n.t('general.delete'),
emit: 'delete' emit: 'delete',
data_e2e: `e2e-BT-${this.dataE2e}-stepText${this.element.id}-options-delete`
}); });
} }
return menu; return menu;

View file

@ -12,6 +12,7 @@
'border-b-sn-science-blue': !error, 'border-b-sn-science-blue': !error,
}" }"
v-model="newValue" v-model="newValue"
:data-e2e="`e2e-IF-${dataE2e}`"
@keydown="handleKeypress" @keydown="handleKeypress"
@blur="handleBlur" @blur="handleBlur"
@keyup.escape="cancelEdit && this.atWhoOpened" @keyup.escape="cancelEdit && this.atWhoOpened"
@ -27,6 +28,7 @@
}" }"
:placeholder="placeholder" :placeholder="placeholder"
v-model="newValue" v-model="newValue"
:data-e2e="`e2e-IF-${dataE2e}`"
@keydown="handleKeypress" @keydown="handleKeypress"
@blur="handleBlur" @blur="handleBlur"
@keyup.escape="cancelEdit && this.atWhoOpened" @keyup.escape="cancelEdit && this.atWhoOpened"
@ -38,6 +40,7 @@
ref="view" ref="view"
class="grid sci-cursor-edit leading-5 border-0 outline-none border-solid border-y border-transparent" class="grid sci-cursor-edit leading-5 border-0 outline-none border-solid border-y border-transparent"
:class="{ 'text-sn-grey font-normal': isBlank, 'whitespace-pre-line py-1': !singleLine }" :class="{ 'text-sn-grey font-normal': isBlank, 'whitespace-pre-line py-1': !singleLine }"
:data-e2e="`e2e-TX-${dataE2e}`"
@click="enableEdit($event)" @click="enableEdit($event)"
> >
<span :class="{'truncate': singleLine }" :title="sa_value || placeholder" v-if="smartAnnotation" v-html="sa_value || placeholder" ></span> <span :class="{'truncate': singleLine }" :title="sa_value || placeholder" v-if="smartAnnotation" v-html="sa_value || placeholder" ></span>
@ -48,6 +51,7 @@
class="mt-2 whitespace-nowrap truncate text-xs font-normal absolute bottom-[-1rem] w-full" class="mt-2 whitespace-nowrap truncate text-xs font-normal absolute bottom-[-1rem] w-full"
:title="editing && error ? error : timestamp" :title="editing && error ? error : timestamp"
:class="{'text-sn-delete-red': editing && error}" :class="{'text-sn-delete-red': editing && error}"
:data-e2e="`e2e-TX-${dataE2e}-timestampError`"
> >
{{ editing && error ? error : timestamp }} {{ editing && error ? error : timestamp }}
</div> </div>
@ -76,7 +80,8 @@ export default {
editOnload: { type: Boolean, default: false }, editOnload: { type: Boolean, default: false },
defaultValue: { type: String, default: '' }, defaultValue: { type: String, default: '' },
singleLine: { type: Boolean, default: true }, singleLine: { type: Boolean, default: true },
preventLeavingUntilFilled: { type: Boolean, default: false } preventLeavingUntilFilled: { type: Boolean, default: false },
dataE2e: { type: String, default: '' }
}, },
data() { data() {
return { return {

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="dropdown-selector"> <div class="dropdown-selector" :data-e2e="`e2e-IF-${dataE2e}`">
<select :id="this.selectorId" <select :id="this.selectorId"
:data-select-by-group="groupSelector" :data-select-by-group="groupSelector"
:data-combine-tags="dataCombineTags" :data-combine-tags="dataCombineTags"
@ -111,6 +111,10 @@ export default {
type: Boolean, type: Boolean,
default: false default: false
}, },
dataE2e: {
type: String,
default: ''
},
onChange: Function onChange: Function
}, },
@ -127,6 +131,7 @@ export default {
tagLabel: this.tagLabel, tagLabel: this.tagLabel,
labelHTML: this.labelHTML, labelHTML: this.labelHTML,
onOpen: this.onOpen, onOpen: this.onOpen,
dataE2e: this.dataE2e,
onChange: () => { onChange: () => {
if (this.onChange) this.onChange(); if (this.onChange) this.onChange();
this.selectChanged(dropdownSelector.getValues(`#${this.selectorId}`)); this.selectChanged(dropdownSelector.getValues(`#${this.selectorId}`));

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="relative" v-if="listItems.length > 0 || alwaysShow" v-click-outside="closeMenu" > <div class="relative" v-if="listItems.length > 0 || alwaysShow" v-click-outside="closeMenu" >
<button ref="field" :class="btnClasses" :title="title" @click="isOpen = !isOpen" :data-e2e="e2eButton"> <button ref="field" :class="btnClasses" :title="title" @click="isOpen = !isOpen" :data-e2e="dataE2e">
<i v-if="btnIcon" :class="btnIcon"></i> <i v-if="btnIcon" :class="btnIcon"></i>
{{ btnText }} {{ btnText }}
<i v-if="caret && isOpen" class="sn-icon sn-icon-up"></i> <i v-if="caret && isOpen" class="sn-icon sn-icon-up"></i>
@ -35,6 +35,7 @@
:class="{ 'bg-sn-super-light-blue': item.active }" :class="{ 'bg-sn-super-light-blue': item.active }"
class="flex group items-center rounded relative text-sn-blue whitespace-nowrap px-3 py-2.5 hover:no-underline cursor-pointer class="flex group items-center rounded relative text-sn-blue whitespace-nowrap px-3 py-2.5 hover:no-underline cursor-pointer
group-hover:bg-sn-super-light-blue hover:!bg-sn-super-light-grey" group-hover:bg-sn-super-light-blue hover:!bg-sn-super-light-grey"
:data-e2e="item.data_e2e"
> >
{{ item.text }} {{ item.text }}
<i class="sn-icon sn-icon-right ml-auto"></i> <i class="sn-icon sn-icon-right ml-auto"></i>
@ -50,6 +51,7 @@
:href="sub_item.url" :href="sub_item.url"
:traget="sub_item.url_target || '_self'" :traget="sub_item.url_target || '_self'"
:class="{ 'bg-sn-super-light-blue': item.active }" :class="{ 'bg-sn-super-light-blue': item.active }"
:data-e2e="`${sub_item.data_e2e}`"
class="block whitespace-nowrap rounded px-3 py-2.5 hover:!text-sn-blue hover:no-underline cursor-pointer hover:bg-sn-super-light-grey leading-5" class="block whitespace-nowrap rounded px-3 py-2.5 hover:!text-sn-blue hover:no-underline cursor-pointer hover:bg-sn-super-light-grey leading-5"
@click="handleClick($event, sub_item)" @click="handleClick($event, sub_item)"
> >
@ -80,7 +82,7 @@ export default {
caret: { type: Boolean, default: false }, caret: { type: Boolean, default: false },
alwaysShow: { type: Boolean, default: false }, alwaysShow: { type: Boolean, default: false },
title: { type: String, default: '' }, title: { type: String, default: '' },
e2eButton: { type: String, default: '' } dataE2e: { type: String, default: '' }
}, },
data() { data() {
return { return {

View file

@ -117,6 +117,7 @@
data-protocol-url="<%= protocol_my_module_path(@my_module) %>" data-protocol-url="<%= protocol_my_module_path(@my_module) %>"
data-date-format="<%= datetime_picker_format_date_only %>" data-date-format="<%= datetime_picker_format_date_only %>"
data-user-utc-offset="<%= ActiveSupport::TimeZone.find_tzinfo(current_user.time_zone).utc_offset %>" data-user-utc-offset="<%= ActiveSupport::TimeZone.find_tzinfo(current_user.time_zone).utc_offset %>"
data-e2e="e2e-CO-task-protocol"
> >
<protocol-container <protocol-container
:protocol-url="protocolUrl" :protocol-url="protocolUrl"

View file

@ -6,7 +6,7 @@
<div class="content-pane protocols-show flexible with-grey-background pb-4" > <div class="content-pane protocols-show flexible with-grey-background pb-4" >
<div class="content-header sticky-header"> <div class="content-header sticky-header">
<div class="title-row"> <div class="title-row">
<h1> <h1 data-e2e="e2e-TX-protocolTemplates-protocol-title">
<% if @inline_editable_title_config.present? %> <% if @inline_editable_title_config.present? %>
<%= render partial: "shared/inline_editing", <%= render partial: "shared/inline_editing",
locals: { locals: {
@ -33,6 +33,7 @@
data-protocol-url="<%= protocol_path(@protocol) %>" data-protocol-url="<%= protocol_path(@protocol) %>"
data-date-format="<%= datetime_picker_format_date_only %>" data-date-format="<%= datetime_picker_format_date_only %>"
data-user-utc-offset="<%= ActiveSupport::TimeZone.find_tzinfo(current_user.time_zone).utc_offset %>" data-user-utc-offset="<%= ActiveSupport::TimeZone.find_tzinfo(current_user.time_zone).utc_offset %>"
data-e2e="e2e-CO-protocolTemplates-protocol"
> >
<protocol-container <protocol-container
:protocol-url="protocolUrl" :protocol-url="protocolUrl"