mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-06 03:46:39 +08:00
Merge pull request #6123 from ivanscinote/SCI-9016-inline-edit-component-ui-rework
Rework inline edit vue component UI [SCI-9016]
This commit is contained in:
commit
b5883178a4
12 changed files with 155 additions and 174 deletions
|
@ -123,17 +123,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.authors-data {
|
.authors-data {
|
||||||
align-items: center;
|
align-items: baseline;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: -12px;
|
margin-top: -12px;
|
||||||
min-height: 36px;
|
min-height: 36px;
|
||||||
|
|
||||||
.authors-list {
|
.authors-list {
|
||||||
flex-basis: calc(100% - 90px);
|
font-weight: bold;
|
||||||
flex-grow: 1;
|
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
font-weight: bold;
|
max-width: calc(100% - 90px);
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
@ -260,10 +260,12 @@
|
||||||
|
|
||||||
.protocol-content {
|
.protocol-content {
|
||||||
.protocol-name {
|
.protocol-name {
|
||||||
|
display: inline-block;
|
||||||
font-size: 1.7em;
|
font-size: 1.7em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
margin-top: 28px;
|
margin-top: 28px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.repository-new-step {
|
.repository-new-step {
|
||||||
|
|
|
@ -26,8 +26,10 @@
|
||||||
grid-template-columns: max-content auto;
|
grid-template-columns: max-content auto;
|
||||||
|
|
||||||
.step-checklist-text {
|
.step-checklist-text {
|
||||||
|
display: inline-block;
|
||||||
margin-top: -.1em;
|
margin-top: -.1em;
|
||||||
width: 100%;
|
position: relative;
|
||||||
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover.done .step-checklist-text {
|
&:hover.done .step-checklist-text {
|
||||||
|
@ -42,7 +44,7 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
margin-right: .5em;
|
margin-right: .5em;
|
||||||
margin-top: 1em;
|
margin-top: .4em;
|
||||||
width: 4px;
|
width: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,95 +1,11 @@
|
||||||
// scss-lint:disable SelectorDepth
|
// scss-lint:disable SelectorDepth
|
||||||
// scss-lint:disable NestingDepth
|
// scss-lint:disable NestingDepth
|
||||||
.sci-inline-edit {
|
|
||||||
align-items: flex-start;
|
|
||||||
display: flex;
|
|
||||||
transition: .4s $timing-function-sharp border;
|
|
||||||
|
|
||||||
&.editing .sci-inline-edit__content {
|
.sci-cursor-edit {
|
||||||
.sci-inline-edit__content {
|
cursor: url("/images/icon_small/edit.svg") 0 16, auto;
|
||||||
padding-top: 0;
|
}
|
||||||
}
|
|
||||||
}
|
.inline-edit-placeholder:empty::before {
|
||||||
|
content: attr(placeholder);
|
||||||
.sci-inline-edit__content {
|
display: block;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-left: -.25em;
|
|
||||||
margin-right: .5rem;
|
|
||||||
min-height: 30px;
|
|
||||||
padding-left: .25em;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
textarea,
|
|
||||||
.sci-inline-edit__view {
|
|
||||||
line-height: 26px;
|
|
||||||
min-height: 30px;
|
|
||||||
padding: .1em .2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sci-inline-edit__view {
|
|
||||||
border: 1px solid transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&.blank {
|
|
||||||
color: $color-silver-chalice;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hover-border:hover {
|
|
||||||
border: 1px solid $color-silver;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
background-color: $color-white;
|
|
||||||
border: 1px solid $brand-focus;
|
|
||||||
border-radius: 4px;
|
|
||||||
outline: none;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sci-inline-edit__error {
|
|
||||||
bottom: -16px;
|
|
||||||
color: $brand-danger;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: normal;
|
|
||||||
line-height: 12px;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.editing {
|
|
||||||
margin-top: 0;
|
|
||||||
|
|
||||||
.sci-inline-edit__content {
|
|
||||||
&.error {
|
|
||||||
border-color: $brand-danger;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
border-color: $brand-danger;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sci-inline-edit__control {
|
|
||||||
margin: 0 .25em;
|
|
||||||
max-height: 30px;
|
|
||||||
max-width: 30px;
|
|
||||||
|
|
||||||
&.btn-disabled {
|
|
||||||
background: $color-silver-chalice;
|
|
||||||
color: $color-concrete;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-basis: 80%;
|
flex-basis: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-top: .4em;
|
padding-top: .4em;
|
||||||
|
gap: .5em;
|
||||||
|
|
||||||
.step-name-edit-icon {
|
.step-name-edit-icon {
|
||||||
background: linear-gradient(90deg,
|
background: linear-gradient(90deg,
|
||||||
|
@ -65,7 +66,6 @@
|
||||||
|
|
||||||
.step-name-container {
|
.step-name-container {
|
||||||
align-self: baseline;
|
align-self: baseline;
|
||||||
flex-grow: 1;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
|
@ -221,7 +221,6 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&.editing-name {
|
&.editing-name {
|
||||||
|
@ -242,8 +241,8 @@
|
||||||
|
|
||||||
.step-element-name {
|
.step-element-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
width: 100%;
|
margin-bottom: 2em;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
.step-element-number {
|
.step-element-number {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
:characterMinLimit="2"
|
:characterMinLimit="2"
|
||||||
:allowBlank="false"
|
:allowBlank="false"
|
||||||
:attributeName="i18n.t('label_templates.show.name_error_prefix')"
|
:attributeName="i18n.t('label_templates.show.name_error_prefix')"
|
||||||
|
:placeholder="i18n.t('label_templates.show.name_placeholder')"
|
||||||
:autofocus="editingName"
|
:autofocus="editingName"
|
||||||
:editOnload="newLabel"
|
:editOnload="newLabel"
|
||||||
:customClasses="['hover-border']"
|
|
||||||
@editingEnabled="editingName = true"
|
@editingEnabled="editingName = true"
|
||||||
@editingDisabled="editingName = false"
|
@editingDisabled="editingName = false"
|
||||||
@update="updateName"
|
@update="updateName"
|
||||||
|
@ -35,7 +35,6 @@
|
||||||
:attributeName="i18n.t('label_templates.show.description_error_prefix')"
|
:attributeName="i18n.t('label_templates.show.description_error_prefix')"
|
||||||
:placeholder="i18n.t('label_templates.show.description_placeholder')"
|
:placeholder="i18n.t('label_templates.show.description_placeholder')"
|
||||||
:autofocus="editingDescription"
|
:autofocus="editingDescription"
|
||||||
:customClasses="['hover-border']"
|
|
||||||
@editingEnabled="editingDescription = true"
|
@editingEnabled="editingDescription = true"
|
||||||
@editingDisabled="editingDescription = false"
|
@editingDisabled="editingDescription = false"
|
||||||
@update="updateDescription"
|
@update="updateDescription"
|
||||||
|
|
|
@ -71,7 +71,6 @@
|
||||||
:placeholder="i18n.t('my_modules.protocols.protocol_status_bar.enter_name')"
|
:placeholder="i18n.t('my_modules.protocols.protocol_status_bar.enter_name')"
|
||||||
:allowBlank="!inRepository"
|
:allowBlank="!inRepository"
|
||||||
:attributeName="`${i18n.t('Protocol')} ${i18n.t('name')}`"
|
:attributeName="`${i18n.t('Protocol')} ${i18n.t('name')}`"
|
||||||
:customClasses="['hover-border']"
|
|
||||||
@update="updateName"
|
@update="updateName"
|
||||||
/>
|
/>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
|
|
|
@ -56,7 +56,8 @@
|
||||||
:value="protocol.attributes.authors"
|
:value="protocol.attributes.authors"
|
||||||
:placeholder="i18n.t('protocols.header.add_authors')"
|
:placeholder="i18n.t('protocols.header.add_authors')"
|
||||||
:allowBlank="true"
|
:allowBlank="true"
|
||||||
:attributeName="`${i18n.t('Protocol')} ${i18n.t('authors')}`"
|
:attributeName="`${i18n.t('Protocol')} ${i18n.t('protocols.header.authors_list')}`"
|
||||||
|
:characterLimit="10000"
|
||||||
@update="updateAuthors"
|
@update="updateAuthors"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
:allowBlank="false"
|
:allowBlank="false"
|
||||||
:attributeName="`${i18n.t('Step')} ${i18n.t('name')}`"
|
:attributeName="`${i18n.t('Step')} ${i18n.t('name')}`"
|
||||||
:autofocus="editingName"
|
:autofocus="editingName"
|
||||||
|
:timestamp="i18n.t('protocols.steps.timestamp', { date: step.attributes.created_at, user: step.attributes.created_by })"
|
||||||
:placeholder="i18n.t('protocols.steps.placeholder')"
|
:placeholder="i18n.t('protocols.steps.placeholder')"
|
||||||
:defaultValue="i18n.t('protocols.steps.default_name')"
|
:defaultValue="i18n.t('protocols.steps.default_name')"
|
||||||
@editingEnabled="editingName = true"
|
@editingEnabled="editingName = true"
|
||||||
|
@ -52,9 +53,6 @@
|
||||||
@update="updateName"
|
@update="updateName"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button v-if="urls.update_url && !editingName" class="step-name-edit-icon btn btn-xs icon-btn btn-light my-1.5" @click="editingName = true">
|
|
||||||
<i class="sn-icon sn-icon-edit"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="elements-actions-container">
|
<div class="elements-actions-container">
|
||||||
<input type="file" class="hidden" ref="fileSelector" @change="loadFromComputer" multiple />
|
<input type="file" class="hidden" ref="fileSelector" @change="loadFromComputer" multiple />
|
||||||
|
@ -158,7 +156,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse in" :id="'stepBody' + step.id">
|
<div class="collapse in" :id="'stepBody' + step.id">
|
||||||
<div class="step-elements">
|
<div class="step-elements">
|
||||||
<div class="step-timestamp">{{ i18n.t('protocols.steps.timestamp', {date: step.attributes.created_at, user: step.attributes.created_by}) }}</div>
|
|
||||||
<template v-for="(element, index) in orderedElements">
|
<template v-for="(element, index) in orderedElements">
|
||||||
<component
|
<component
|
||||||
:is="elements[index].attributes.orderable_type"
|
:is="elements[index].attributes.orderable_type"
|
||||||
|
@ -261,6 +258,7 @@
|
||||||
reordering: false,
|
reordering: false,
|
||||||
isCollapsed: false,
|
isCollapsed: false,
|
||||||
editingName: false,
|
editingName: false,
|
||||||
|
inlineEditError: null,
|
||||||
wellPlateOptions: [
|
wellPlateOptions: [
|
||||||
{ label: 'protocols.steps.insert.well_plate_options.32_x_48', dimensions: [32, 48] },
|
{ 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.16_x_24', dimensions: [16, 24] },
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
:value="element.attributes.orderable.name"
|
:value="element.attributes.orderable.name"
|
||||||
:sa_value="element.attributes.orderable.sa_name"
|
:sa_value="element.attributes.orderable.sa_name"
|
||||||
:characterLimit="10000"
|
:characterLimit="10000"
|
||||||
:placeholder="i18n.t('protocols.steps.checklist.checklist_name')"
|
:placeholder="i18n.t('protocols.steps.checklist.placeholder')"
|
||||||
:allowBlank="false"
|
:allowBlank="false"
|
||||||
:autofocus="editingName"
|
:autofocus="editingName"
|
||||||
:smartAnnotation="true"
|
:smartAnnotation="true"
|
||||||
|
@ -173,6 +173,7 @@
|
||||||
this.$emit('update', this.element, skipRequest);
|
this.$emit('update', this.element, skipRequest);
|
||||||
},
|
},
|
||||||
postItem(item, callback) {
|
postItem(item, callback) {
|
||||||
|
console.log(this.element.attributes.orderable.urls.create_item_url)
|
||||||
$.post(this.element.attributes.orderable.urls.create_item_url, item).done((result) => {
|
$.post(this.element.attributes.orderable.urls.create_item_url, item).done((result) => {
|
||||||
this.checklistItems.splice(
|
this.checklistItems.splice(
|
||||||
result.data.attributes.position,
|
result.data.attributes.position,
|
||||||
|
@ -181,8 +182,8 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
if(callback) callback();
|
if(callback) callback();
|
||||||
}).fail((xhr) => {
|
}).fail((e) => {
|
||||||
this.setFlashErrors(xhr.responseJSON.errors)
|
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
|
|
|
@ -1,32 +1,41 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="sci-inline-edit" :class="{ 'editing': editing }" tabindex="0" @keyup.enter="enableEdit($event)">
|
<div class="flex flex-col">
|
||||||
<div class="sci-inline-edit__content" :class="{ 'error': error }">
|
<span
|
||||||
<textarea
|
v-if="editing"
|
||||||
ref="input"
|
ref="input"
|
||||||
rows="1"
|
contenteditable="true"
|
||||||
v-if="editing"
|
class="outline-none p-0 pb-2 border-0 border-solid border-b w-fit"
|
||||||
:placeholder="placeholder"
|
:class="{ 'inline-edit-placeholder text-sn-grey caret-black': isBlank, 'border-sn-delete-red': error, 'border-sn-science-blue': !error }"
|
||||||
v-model="newValue"
|
:placeholder="placeholder"
|
||||||
@input="handleInput"
|
@input="handleInput"
|
||||||
@keydown="handleKeypress"
|
@keydown="handleKeypress"
|
||||||
@paste="handlePaste"
|
@paste="handlePaste"
|
||||||
@blur="handleBlur"
|
@blur="handleBlur"
|
||||||
@keyup.escape="cancelEdit"
|
@keyup.escape="cancelEdit"
|
||||||
></textarea>
|
@focus="setCaretAtEnd"
|
||||||
<div v-else-if="smartAnnotation" @click="enableEdit($event)" class="sci-inline-edit__view" v-html="sa_value || placeholder" :class="{ 'blank': isBlank }"></div>
|
></span>
|
||||||
<div v-else @click="enableEdit($event)" class="sci-inline-edit__view" :class="[isBlank ? 'blank' : '', ...customClasses]">{{newValue || placeholder}}</div>
|
<div
|
||||||
<div v-if="editing && error" class="sci-inline-edit__error">
|
v-else-if="smartAnnotation"
|
||||||
{{ error }}
|
class="sci-cursor-edit"
|
||||||
</div>
|
:class="{ 'blank': isBlank }"
|
||||||
|
v-html="sa_value || placeholder"
|
||||||
|
@click="enableEdit($event)"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="sci-cursor-edit outline-none"
|
||||||
|
:class="{ 'text-sn-grey': isBlank }"
|
||||||
|
@click="enableEdit($event)"
|
||||||
|
>
|
||||||
|
{{newValue || placeholder}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="mt-2 whitespace-nowrap text-xs font-normal"
|
||||||
|
:class="{'text-sn-delete-red': editing && error}"
|
||||||
|
>
|
||||||
|
{{ editing && error ? error : timestamp }}
|
||||||
</div>
|
</div>
|
||||||
<template v-if="editing">
|
|
||||||
<div :class="{ 'btn-primary': !error, 'btn-disabled': error }" class="sci-inline-edit__control btn btn-sm icon-btn" @click="update">
|
|
||||||
<i class="sn-icon sn-icon-check"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sci-inline-edit__control btn btn-light btn-sm icon-btn" @mousedown="cancelEdit">
|
|
||||||
<i class="sn-icon sn-icon-close"></i>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -42,6 +51,7 @@
|
||||||
attributeName: { type: String, required: true },
|
attributeName: { type: String, required: true },
|
||||||
characterLimit: { type: Number },
|
characterLimit: { type: Number },
|
||||||
characterMinLimit: { type: Number },
|
characterMinLimit: { type: Number },
|
||||||
|
timestamp: { type: String},
|
||||||
placeholder: { type: String },
|
placeholder: { type: String },
|
||||||
autofocus: { type: Boolean, default: false },
|
autofocus: { type: Boolean, default: false },
|
||||||
saveOnEnter: { type: Boolean, default: true },
|
saveOnEnter: { type: Boolean, default: true },
|
||||||
|
@ -49,8 +59,7 @@
|
||||||
multilinePaste: { type: Boolean, default: false },
|
multilinePaste: { type: Boolean, default: false },
|
||||||
smartAnnotation: { type: Boolean, default: false },
|
smartAnnotation: { type: Boolean, default: false },
|
||||||
editOnload: { type: Boolean, default: false },
|
editOnload: { type: Boolean, default: false },
|
||||||
defaultValue: { type: String, default: '' },
|
defaultValue: { type: String, default: '' }
|
||||||
customClasses: { type: Array, default: () => [] }
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -60,7 +69,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mixins: [UtilsMixin],
|
mixins: [UtilsMixin],
|
||||||
created( ){
|
created() {
|
||||||
this.newValue = this.value || '';
|
this.newValue = this.value || '';
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -70,16 +79,22 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
newValue() {
|
||||||
|
if (this.newValue.length === 0 && this.editing) {
|
||||||
|
this.focus();
|
||||||
|
this.setCaretPosition();
|
||||||
|
}
|
||||||
|
},
|
||||||
autofocus() {
|
autofocus() {
|
||||||
this.handleAutofocus();
|
this.handleAutofocus();
|
||||||
},
|
|
||||||
value() {
|
|
||||||
this.newValue = this.value;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isBlank() {
|
isBlank() {
|
||||||
return this.newValue.length === 0
|
return this.newValue.length === 0;
|
||||||
|
},
|
||||||
|
isContentDefault() {
|
||||||
|
return this.newValue === this.defaultValue;
|
||||||
},
|
},
|
||||||
error() {
|
error() {
|
||||||
if(!this.allowBlank && this.isBlank) {
|
if(!this.allowBlank && this.isBlank) {
|
||||||
|
@ -118,7 +133,6 @@
|
||||||
},
|
},
|
||||||
handleBlur() {
|
handleBlur() {
|
||||||
if ($('.atwho-view:visible').length) return;
|
if ($('.atwho-view:visible').length) return;
|
||||||
|
|
||||||
if (this.allowBlank || !this.isBlank) {
|
if (this.allowBlank || !this.isBlank) {
|
||||||
this.$nextTick(this.update);
|
this.$nextTick(this.update);
|
||||||
} else {
|
} else {
|
||||||
|
@ -128,21 +142,47 @@
|
||||||
focus() {
|
focus() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (!this.$refs.input) return;
|
if (!this.$refs.input) return;
|
||||||
|
|
||||||
this.$refs.input.focus();
|
this.$refs.input.focus();
|
||||||
this.resize();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// Fixing Firefox specific caret placement issue
|
||||||
|
setCaretPosition() {
|
||||||
|
const range = document.createRange();
|
||||||
|
const sel = window.getSelection();
|
||||||
|
range.setStart(this.$refs.input, 0);
|
||||||
|
range.collapse(true);
|
||||||
|
sel.removeAllRanges();
|
||||||
|
sel.addRange(range);
|
||||||
|
},
|
||||||
|
setCaretAtEnd() {
|
||||||
|
if (this.isBlank || this.isContentDefault) return;
|
||||||
|
|
||||||
|
const el = this.$refs.input;
|
||||||
|
let range = document.createRange();
|
||||||
|
range.selectNodeContents(el);
|
||||||
|
range.collapse(false);
|
||||||
|
|
||||||
|
let selection = window.getSelection();
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
},
|
||||||
enableEdit(e) {
|
enableEdit(e) {
|
||||||
if (e && $(e.target).hasClass('atwho-user-popover')) return;
|
if (e && $(e.target).hasClass('atwho-user-popover')) return;
|
||||||
if (e && $(e.target).hasClass('sa-link')) return;
|
if (e && $(e.target).hasClass('sa-link')) return;
|
||||||
if (e && $(e.target).parent().hasClass('atwho-inserted')) return;
|
if (e && $(e.target).parent().hasClass('atwho-inserted')) return;
|
||||||
|
|
||||||
this.editing = true;
|
this.editing = true;
|
||||||
this.focus();
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (this.$refs.input.value === this.defaultValue) {
|
this.focus();
|
||||||
this.$refs.input.select();
|
this.$refs.input.innerText = this.newValue;
|
||||||
|
|
||||||
|
// Select whole content if it is default
|
||||||
|
if (this.isContentDefault) {
|
||||||
|
let range = document.createRange();
|
||||||
|
range.selectNodeContents(this.$refs.input);
|
||||||
|
let selection = window.getSelection();
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
}
|
}
|
||||||
if (this.smartAnnotation) {
|
if (this.smartAnnotation) {
|
||||||
SmartAnnotation.init($(this.$refs.input), false);
|
SmartAnnotation.init($(this.$refs.input), false);
|
||||||
|
@ -156,40 +196,57 @@
|
||||||
this.$emit('editingDisabled');
|
this.$emit('editingDisabled');
|
||||||
},
|
},
|
||||||
handlePaste(e) {
|
handlePaste(e) {
|
||||||
|
e.preventDefault();
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
|
|
||||||
if (!this.multilinePaste) return;
|
const clipboardData = (e.clipboardData || window.clipboardData).getData("text");
|
||||||
let lines = (e.originalEvent || e).clipboardData.getData('text/plain').split(/[\n\r]/);
|
let lines = clipboardData.split(/[\n\r]/).filter((l) => l).map((l) => l.trim());
|
||||||
lines = lines.filter((l) => l).map((l) => l.trim());
|
|
||||||
|
const selection = window.getSelection();
|
||||||
|
if (!selection.rangeCount) return;
|
||||||
|
|
||||||
if (lines.length > 1) {
|
selection.deleteFromDocument();
|
||||||
this.newValue = lines[0];
|
|
||||||
this.$emit('multilinePaste', lines);
|
let textNode = document.createTextNode(lines[0]);
|
||||||
this.update();
|
selection.getRangeAt(0).insertNode(textNode);
|
||||||
}
|
|
||||||
|
let range = document.createRange();
|
||||||
|
range.setStart(textNode, textNode.length);
|
||||||
|
range.setEnd(textNode, textNode.length);
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.newValue = e.target.textContent;
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
|
||||||
|
// Handle multi-line paste
|
||||||
|
if (this.multilinePaste && lines.length > 1) {
|
||||||
|
this.$emit('multilinePaste', lines);
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
handleInput() {
|
handleInput(e) {
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
if (!this.allowNewLine) {
|
|
||||||
this.newValue = this.newValue.replace(/^[\n\r]+|[\n\r]+$/g, '');
|
const sel = document.getSelection();
|
||||||
}
|
const offset = sel.anchorOffset;
|
||||||
this.$nextTick(this.resize);
|
|
||||||
|
this.newValue = this.allowNewLine ? e.target.textContent : e.target.textContent.replace(/^[\n\r]+|[\n\r]+$/g, '');
|
||||||
|
|
||||||
|
sel.collapse(sel.anchorNode, offset);
|
||||||
},
|
},
|
||||||
handleKeypress(e) {
|
handleKeypress(e) {
|
||||||
if (e.key == 'Escape') {
|
if (e.key == 'Escape') {
|
||||||
this.cancelEdit();
|
this.cancelEdit();
|
||||||
} else if (e.key == 'Enter' && this.saveOnEnter) {
|
} else if (e.key == 'Enter' && this.saveOnEnter) {
|
||||||
|
e.preventDefault()
|
||||||
this.update();
|
this.update();
|
||||||
} else {
|
} else {
|
||||||
|
if (!this.error) this.$emit('error-cleared');
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resize() {
|
|
||||||
if (!this.$refs.input) return;
|
|
||||||
|
|
||||||
this.$refs.input.style.height = "auto";
|
|
||||||
this.$refs.input.style.height = (this.$refs.input.scrollHeight) + "px";
|
|
||||||
},
|
|
||||||
update() {
|
update() {
|
||||||
if (!this.dirty && !this.isBlank) {
|
if (!this.dirty && !this.isBlank) {
|
||||||
this.editing = false;
|
this.editing = false;
|
||||||
|
@ -198,8 +255,8 @@
|
||||||
|
|
||||||
if(this.error) return;
|
if(this.error) return;
|
||||||
if(!this.$refs.input) return;
|
if(!this.$refs.input) return;
|
||||||
this.newValue = this.$refs.input.value // Fix for smart annotation
|
|
||||||
this.newValue = this.newValue.trim();
|
this.newValue = this.$refs.input.innerText.trim() // Fix for smart annotation
|
||||||
this.editing = false;
|
this.editing = false;
|
||||||
this.$emit('editingDisabled');
|
this.$emit('editingDisabled');
|
||||||
this.$emit('update', this.newValue);
|
this.$emit('update', this.newValue);
|
||||||
|
|
|
@ -989,6 +989,7 @@ en:
|
||||||
show:
|
show:
|
||||||
breadcrumb_index: 'Label templates'
|
breadcrumb_index: 'Label templates'
|
||||||
name_error_prefix: 'Label template name'
|
name_error_prefix: 'Label template name'
|
||||||
|
name_placeholder: 'Enter label template name'
|
||||||
description_error_prefix: 'Label template description'
|
description_error_prefix: 'Label template description'
|
||||||
description_title: 'Template description'
|
description_title: 'Template description'
|
||||||
description_placeholder: 'Enter the template description (optional)'
|
description_placeholder: 'Enter the template description (optional)'
|
||||||
|
@ -2918,6 +2919,7 @@ en:
|
||||||
added_by: "Created by:"
|
added_by: "Created by:"
|
||||||
keywords: "Keywords:"
|
keywords: "Keywords:"
|
||||||
authors: "Authors:"
|
authors: "Authors:"
|
||||||
|
authors_list: "authors list"
|
||||||
no_authors: "No authors"
|
no_authors: "No authors"
|
||||||
add_authors: "+ Add authors"
|
add_authors: "+ Add authors"
|
||||||
add_keywords: "+ Add keywords"
|
add_keywords: "+ Add keywords"
|
||||||
|
@ -3118,6 +3120,7 @@ en:
|
||||||
error: "Table name can't be empty"
|
error: "Table name can't be empty"
|
||||||
table_name: "Table name"
|
table_name: "Table name"
|
||||||
checklist:
|
checklist:
|
||||||
|
placeholder: 'Enter checklist name'
|
||||||
default_name: 'Checklist %{position}'
|
default_name: 'Checklist %{position}'
|
||||||
checklist_name: "Checklist name"
|
checklist_name: "Checklist name"
|
||||||
empty_checklist: 'Doesn’t contain any checklist items'
|
empty_checklist: 'Doesn’t contain any checklist items'
|
||||||
|
|
4
public/images/icon_small/edit.svg
Normal file
4
public/images/icon_small/edit.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1.024 14.9594H2.1248L12.2624 4.65691L11.1616 3.53821L1.024 13.8407V14.9594ZM14.464 3.90244L11.904 1.32683L12.7232 0.494309C13.0304 0.16477 13.4144 0 13.8752 0C14.336 0 14.72 0.16477 15.0272 0.494309L15.6928 1.17073C15.8976 1.36152 16 1.60434 16 1.89919C16 2.19404 15.9061 2.43686 15.7184 2.62764L14.464 3.90244ZM13.7216 4.65691L2.56 16H0V13.3984L11.1616 2.05528L13.7216 4.65691Z" fill="#1D2939"/>
|
||||||
|
<path d="M1.024 14.9594H2.1248L12.2624 4.65691L11.1616 3.53821L1.024 13.8407V14.9594Z" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 612 B |
Loading…
Add table
Reference in a new issue