mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-13 00:24:42 +08:00
Fix inline edit vue component [SCI-9254]
This commit is contained in:
parent
67c6d66ff1
commit
982da48bbe
4 changed files with 21 additions and 88 deletions
|
@ -15,13 +15,11 @@
|
||||||
margin-bottom: 1.2em;
|
margin-bottom: 1.2em;
|
||||||
|
|
||||||
.step-element-header {
|
.step-element-header {
|
||||||
align-items: baseline;
|
align-items: flex-start;
|
||||||
border-radius: 4px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-top: .4em;
|
gap: 1rem;
|
||||||
gap: .5em;
|
|
||||||
|
|
||||||
.step-name-edit-icon {
|
.step-name-edit-icon {
|
||||||
background: linear-gradient(90deg,
|
background: linear-gradient(90deg,
|
||||||
|
@ -44,7 +42,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-collapse-link {
|
.step-collapse-link {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -212,62 +210,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-element-header {
|
|
||||||
align-items: baseline;
|
|
||||||
border-radius: 4px;
|
|
||||||
display: flex;
|
|
||||||
min-height: 40px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&.editing-name {
|
|
||||||
.step-element-controls {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-controls {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 35px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sci-inline-edit {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-element-name {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 2em;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.step-element-number {
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-element-controls {
|
|
||||||
background: linear-gradient(90deg,
|
|
||||||
transparent,
|
|
||||||
$color-concrete 15%,
|
|
||||||
$color-concrete 100%);
|
|
||||||
display: flex;
|
|
||||||
margin-left: auto;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
.fas {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-element-controls,
|
|
||||||
.step-element-grip {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-element-grip {
|
.step-element-grip {
|
||||||
color: $color-silver-chalice;
|
color: $color-silver-chalice;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="step-header">
|
<div class="step-header">
|
||||||
<div class="step-element-header" :class="{ 'no-hover': !urls.update_url }">
|
<div class="step-element-header" :class="{ 'no-hover': !urls.update_url }">
|
||||||
<div class="step-controls gap-4 mr-4">
|
<div class="flex items-center gap-4 py-1 border-0 border-y border-transparent border-solid">
|
||||||
<a class="step-collapse-link hover:no-underline focus:no-underline"
|
<a class="step-collapse-link hover:no-underline focus:no-underline"
|
||||||
:href="'#stepBody' + step.id"
|
:href="'#stepBody' + step.id"
|
||||||
data-toggle="collapse"
|
data-toggle="collapse"
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
{{ step.attributes.position + 1 }}.
|
{{ step.attributes.position + 1 }}.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="step-name-container flex-grow" :class="{'step-element--locked': !urls.update_url}">
|
<div class="step-name-container basis-[calc(100%_-_100px)]" :class="{'step-element--locked': !urls.update_url}">
|
||||||
<InlineEdit
|
<InlineEdit
|
||||||
:value="step.attributes.name"
|
:value="step.attributes.name"
|
||||||
:class="{ 'step-element--locked': !urls.update_url }"
|
:class="{ 'step-element--locked': !urls.update_url }"
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<i class="sn-icon sn-icon-drag"></i>
|
<i class="sn-icon sn-icon-drag"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-start gap-2 grow" :class="{ 'done': checklistItem.attributes.checked }">
|
<div class="flex items-start gap-2 grow" :class="{ 'done': checklistItem.attributes.checked }">
|
||||||
<div v-if="!inRepository" class="sci-checkbox-container my-2.5 w-6" :class="{ 'disabled': !toggleUrl }">
|
<div v-if="!inRepository" class="sci-checkbox-container my-1.5 border-y border-transparent border-solid w-6" :class="{ 'disabled': !toggleUrl }">
|
||||||
<input ref="checkbox"
|
<input ref="checkbox"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="sci-checkbox"
|
class="sci-checkbox"
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
:characterLimit="10000"
|
:characterLimit="10000"
|
||||||
:placeholder="'Add a checklist item...'"
|
:placeholder="'Add a checklist item...'"
|
||||||
:allowBlank="true"
|
:allowBlank="true"
|
||||||
|
:singleLine="false"
|
||||||
:autofocus="editingText"
|
:autofocus="editingText"
|
||||||
:attributeName="`${i18n.t('ChecklistItem')} ${i18n.t('name')}`"
|
:attributeName="`${i18n.t('ChecklistItem')} ${i18n.t('name')}`"
|
||||||
:multilinePaste="true"
|
:multilinePaste="true"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full">
|
<div class="w-full relative">
|
||||||
<template v-if="editing">
|
<template v-if="editing">
|
||||||
<input type="text"
|
<input type="text"
|
||||||
v-if="singleLine"
|
v-if="singleLine"
|
||||||
|
@ -11,6 +11,7 @@
|
||||||
'border-b-sn-science-blue': !error,
|
'border-b-sn-science-blue': !error,
|
||||||
}"
|
}"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
|
v-model="newValue"
|
||||||
@keydown="handleKeypress"
|
@keydown="handleKeypress"
|
||||||
@paste="handlePaste"
|
@paste="handlePaste"
|
||||||
@blur="handleBlur"
|
@blur="handleBlur"
|
||||||
|
@ -18,13 +19,14 @@
|
||||||
@focus="setCaretAtEnd"/>
|
@focus="setCaretAtEnd"/>
|
||||||
<textarea v-else
|
<textarea v-else
|
||||||
ref="input"
|
ref="input"
|
||||||
class="overflow-hidden inline-block box-size outline-none p-0 py-1 border-0 border-solid border-b w-full border-t-transparent"
|
class="overflow-hidden inline-block outline-none px-0 py-1 border-0 border-solid border-b w-full border-t-transparent"
|
||||||
:class="{
|
:class="{
|
||||||
'inline-edit-placeholder text-sn-grey caret-black': isBlank,
|
'inline-edit-placeholder text-sn-grey caret-black': isBlank,
|
||||||
'border-sn-delete-red': error,
|
'border-sn-delete-red': error,
|
||||||
'border-sn-science-blue': !error,
|
'border-sn-science-blue': !error,
|
||||||
}"
|
}"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
|
v-model="newValue"
|
||||||
@keydown="handleKeypress"
|
@keydown="handleKeypress"
|
||||||
@paste="handlePaste"
|
@paste="handlePaste"
|
||||||
@blur="handleBlur"
|
@blur="handleBlur"
|
||||||
|
@ -33,8 +35,9 @@
|
||||||
</template>
|
</template>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
|
ref="view"
|
||||||
class="sci-cursor-edit border-0 py-1 outline-none inline-block border-solid border-y border-transparent"
|
class="sci-cursor-edit border-0 py-1 outline-none inline-block border-solid border-y border-transparent"
|
||||||
:class="{ 'text-sn-grey': isBlank }"
|
:class="{ 'text-sn-grey': isBlank, 'pb-1.5': !singleLine }"
|
||||||
@click="enableEdit($event)"
|
@click="enableEdit($event)"
|
||||||
>
|
>
|
||||||
<span v-if="smartAnnotation" v-html="sa_value || placeholder" ></span>
|
<span v-if="smartAnnotation" v-html="sa_value || placeholder" ></span>
|
||||||
|
@ -42,7 +45,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="mt-2 whitespace-nowrap text-xs font-normal"
|
class="mt-2 whitespace-nowrap text-xs font-normal absolute bottom-[-.75rem]"
|
||||||
:class="{'text-sn-delete-red': editing && error}"
|
:class="{'text-sn-delete-red': editing && error}"
|
||||||
>
|
>
|
||||||
{{ editing && error ? error : timestamp }}
|
{{ editing && error ? error : timestamp }}
|
||||||
|
@ -97,8 +100,8 @@
|
||||||
newValue() {
|
newValue() {
|
||||||
if (this.newValue.length === 0 && this.editing) {
|
if (this.newValue.length === 0 && this.editing) {
|
||||||
this.focus();
|
this.focus();
|
||||||
this.setCaretPosition();
|
|
||||||
}
|
}
|
||||||
|
this.refreshTexareaHeight();
|
||||||
},
|
},
|
||||||
autofocus() {
|
autofocus() {
|
||||||
this.handleAutofocus();
|
this.handleAutofocus();
|
||||||
|
@ -160,26 +163,11 @@
|
||||||
this.$refs.input.focus();
|
this.$refs.input.focus();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 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() {
|
setCaretAtEnd() {
|
||||||
if (this.isBlank || this.isContentDefault) return;
|
if (this.isBlank || this.isContentDefault) return;
|
||||||
|
|
||||||
const el = this.$refs.input;
|
const el = this.$refs.input;
|
||||||
let range = document.createRange();
|
el.focus();
|
||||||
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;
|
||||||
|
@ -250,7 +238,6 @@
|
||||||
this.newValue = this.allowNewLine ? e.target.textContent : e.target.textContent.replace(/^[\n\r]+|[\n\r]+$/g, '');
|
this.newValue = this.allowNewLine ? e.target.textContent : e.target.textContent.replace(/^[\n\r]+|[\n\r]+$/g, '');
|
||||||
|
|
||||||
sel.collapse(sel.anchorNode, offset);
|
sel.collapse(sel.anchorNode, offset);
|
||||||
this.refreshTexareaHeight()
|
|
||||||
},
|
},
|
||||||
handleKeypress(e) {
|
handleKeypress(e) {
|
||||||
if (e.key == 'Escape') {
|
if (e.key == 'Escape') {
|
||||||
|
@ -264,6 +251,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update() {
|
update() {
|
||||||
|
this.refreshTexareaHeight();
|
||||||
|
|
||||||
if (!this.dirty && !this.isBlank) {
|
if (!this.dirty && !this.isBlank) {
|
||||||
this.editing = false;
|
this.editing = false;
|
||||||
return;
|
return;
|
||||||
|
@ -271,8 +260,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.trim() // Fix for smart annotation
|
this.newValue = this.$refs.input.value.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);
|
||||||
|
@ -280,7 +269,8 @@
|
||||||
refreshTexareaHeight() {
|
refreshTexareaHeight() {
|
||||||
if (this.editing && !this.singleLine) {
|
if (this.editing && !this.singleLine) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.input.style.height = this.$refs.input.scrollHeight + 'px';
|
this.$refs.input.style.height = '0px';
|
||||||
|
this.$refs.input.style.height = this.$refs.input.scrollHeight - 3 + 'px';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue