@saooti/octopus-sdk 36.0.23 → 36.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +1 -0
- package/package.json +5 -1
- package/src/components/form/ClassicInputText.vue +203 -0
- package/src/components/form/Wysiwyg.vue +302 -0
- package/src/components/mixins/displayMethods.ts +1 -1
- package/src/locale/de.ts +1 -0
- package/src/locale/en.ts +1 -0
- package/src/locale/es.ts +1 -0
- package/src/locale/fr.ts +1 -0
- package/src/locale/it.ts +1 -0
- package/src/locale/sl.ts +1 -0
package/index.ts
CHANGED
|
@@ -65,6 +65,7 @@ export const getClassicDatePicker = () => import("./src/components/form/ClassicD
|
|
|
65
65
|
export const getPaginate = () => import("./src/components/display/list/Paginate.vue");
|
|
66
66
|
export const getListPaginate = () => import("./src/components/display/list/ListPaginate.vue");
|
|
67
67
|
export const getClassicMultiselect = () => import("./src/components/form/ClassicMultiselect.vue");
|
|
68
|
+
export const getClassicInputText = () => import("./src/components/form/ClassicInputText.vue");
|
|
68
69
|
|
|
69
70
|
//mixins
|
|
70
71
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saooti/octopus-sdk",
|
|
3
|
-
"version": "36.0.
|
|
3
|
+
"version": "36.0.25",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Javascript SDK for using octopus",
|
|
6
6
|
"author": "Saooti",
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@popperjs/core": "^2.11.7",
|
|
20
20
|
"@saooti/octopus-api": "^0.34.3",
|
|
21
|
+
"@tiptap/extension-link": "^2.0.3",
|
|
22
|
+
"@tiptap/extension-underline": "^2.0.3",
|
|
23
|
+
"@tiptap/starter-kit": "^2.0.3",
|
|
24
|
+
"@tiptap/vue-3": "^2.0.3",
|
|
21
25
|
"@vue/cli": "^5.0.8",
|
|
22
26
|
"@vue/compat": "^3.3.2",
|
|
23
27
|
"autoprefixer": "^10.4.14",
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="d-flex flex-column classic-input-text">
|
|
3
|
+
<div class="d-flex">
|
|
4
|
+
<label
|
|
5
|
+
class="form-label"
|
|
6
|
+
:for="inputId"
|
|
7
|
+
:class="displayLabel?'':'d-none'"
|
|
8
|
+
>{{ label }}</label>
|
|
9
|
+
<template v-if="popover">
|
|
10
|
+
<span
|
|
11
|
+
:id="'popover'+inputId"
|
|
12
|
+
role="button"
|
|
13
|
+
class="saooti-help m-0"
|
|
14
|
+
tabindex="0"
|
|
15
|
+
:title="$t('Help')"
|
|
16
|
+
/>
|
|
17
|
+
<Popover
|
|
18
|
+
:target="'popover'+inputId"
|
|
19
|
+
>
|
|
20
|
+
<!-- eslint-disable vue/no-v-html -->
|
|
21
|
+
<div
|
|
22
|
+
v-html="popover"
|
|
23
|
+
/>
|
|
24
|
+
<!-- eslint-enable -->
|
|
25
|
+
</Popover>
|
|
26
|
+
</template>
|
|
27
|
+
</div>
|
|
28
|
+
<input
|
|
29
|
+
v-if="!isWysiwyg && !isTextarea"
|
|
30
|
+
:id="inputId"
|
|
31
|
+
v-model="textValue"
|
|
32
|
+
type="text"
|
|
33
|
+
class="form-input"
|
|
34
|
+
:placeholder="placeholder"
|
|
35
|
+
:data-selenium="dataSelenium"
|
|
36
|
+
:data-value="textValue"
|
|
37
|
+
:maxlength="inputMaxLengthField"
|
|
38
|
+
:readonly="readonly?'readonly':undefined"
|
|
39
|
+
:class="{
|
|
40
|
+
'border border-danger':forceError || (isError && (undefined!==textValue ||canBeNull)),
|
|
41
|
+
}"
|
|
42
|
+
:disabled="isDisable"
|
|
43
|
+
>
|
|
44
|
+
<textarea
|
|
45
|
+
v-else-if="isTextarea"
|
|
46
|
+
:id="inputId"
|
|
47
|
+
v-model="textValue"
|
|
48
|
+
:data-selenium="dataSelenium"
|
|
49
|
+
:placeholder="placeholder"
|
|
50
|
+
:readonly="readonly?'readonly':undefined"
|
|
51
|
+
class="form-input"
|
|
52
|
+
:class="{
|
|
53
|
+
'border border-danger':forceError ||(isError && (undefined!==textValue ||canBeNull))
|
|
54
|
+
}"
|
|
55
|
+
:disabled="isDisable"
|
|
56
|
+
/>
|
|
57
|
+
<Wysiwyg
|
|
58
|
+
v-else
|
|
59
|
+
v-model:content="textValue"
|
|
60
|
+
:error-description="forceError || (isError && (undefined!==textValue ||canBeNull))"
|
|
61
|
+
:is-disabled="isDisable"
|
|
62
|
+
/>
|
|
63
|
+
<div class="d-flex justify-content-between">
|
|
64
|
+
<div
|
|
65
|
+
v-if="isWysiwyg"
|
|
66
|
+
class="h6"
|
|
67
|
+
>
|
|
68
|
+
{{ $t('Characters number calculated over HTML code') }}
|
|
69
|
+
</div>
|
|
70
|
+
<div
|
|
71
|
+
v-else-if="''!==indicText"
|
|
72
|
+
class="text-indic"
|
|
73
|
+
>
|
|
74
|
+
{{ indicText }}
|
|
75
|
+
</div>
|
|
76
|
+
<div
|
|
77
|
+
v-else-if="forceError|| (isError && (undefined!==textValue ||canBeNull))"
|
|
78
|
+
class="text-danger"
|
|
79
|
+
>
|
|
80
|
+
{{ errorText }}
|
|
81
|
+
</div>
|
|
82
|
+
<p
|
|
83
|
+
v-if="0!==maxLength"
|
|
84
|
+
class="counter-align-right"
|
|
85
|
+
:class="{ 'text-danger': !valueLengthValid }"
|
|
86
|
+
>
|
|
87
|
+
{{ countValue + ' / ' + maxLength }}
|
|
88
|
+
</p>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</template>
|
|
92
|
+
<script lang="ts">
|
|
93
|
+
import { defineAsyncComponent, defineComponent } from 'vue';
|
|
94
|
+
const Popover = defineAsyncComponent(
|
|
95
|
+
() => import('../misc/Popover.vue')
|
|
96
|
+
);
|
|
97
|
+
const Wysiwyg = defineAsyncComponent(
|
|
98
|
+
() => import('./Wysiwyg.vue')
|
|
99
|
+
);
|
|
100
|
+
export default defineComponent({
|
|
101
|
+
components: {
|
|
102
|
+
Wysiwyg,
|
|
103
|
+
Popover
|
|
104
|
+
},
|
|
105
|
+
props: {
|
|
106
|
+
inputId: { default: "", type: String },
|
|
107
|
+
label: { default: "", type: String },
|
|
108
|
+
textInit: { default: undefined, type: String },
|
|
109
|
+
maxLength: { default: 0, type: Number },
|
|
110
|
+
errorText: { default: "", type: String },
|
|
111
|
+
isTextarea: {default: false, type: Boolean},
|
|
112
|
+
isWysiwyg: {default: false, type: Boolean},
|
|
113
|
+
regex: {default : undefined, type: RegExp},
|
|
114
|
+
canBeNull : {default: false, type: Boolean},
|
|
115
|
+
inputMaxLengthField : {default: undefined, type: Number},
|
|
116
|
+
errorVariable: {default: true, type:Boolean},
|
|
117
|
+
isDisable: {default: false, type: Boolean},
|
|
118
|
+
indicText:{ default: "", type: String },
|
|
119
|
+
dataSelenium:{ default: "", type: String },
|
|
120
|
+
placeholder:{ default: "", type: String },
|
|
121
|
+
popover: {default: undefined, type:String},
|
|
122
|
+
readonly: {default: false, type: Boolean},
|
|
123
|
+
forceError: {default: false, type: Boolean},
|
|
124
|
+
displayLabel:{default: true, type: Boolean},
|
|
125
|
+
},
|
|
126
|
+
emits: ['update:textInit', 'update:errorVariable'],
|
|
127
|
+
data() {
|
|
128
|
+
return {
|
|
129
|
+
textValue: undefined as string|undefined,
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
computed: {
|
|
133
|
+
isError(): boolean{
|
|
134
|
+
return !this.valueTrimValid || !this.valueLengthValid || !this.valueRegexValid;
|
|
135
|
+
},
|
|
136
|
+
countValue(): number {
|
|
137
|
+
if(this.textValue){
|
|
138
|
+
return this.textValue.length;
|
|
139
|
+
}
|
|
140
|
+
return 0;
|
|
141
|
+
},
|
|
142
|
+
valueTrimValid(): boolean {
|
|
143
|
+
if(!this.canBeNull){
|
|
144
|
+
if(!this.textValue){
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
return 0 !== this.textValue.trim().length;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
},
|
|
151
|
+
valueLengthValid(): boolean {
|
|
152
|
+
if(0===this.maxLength){return true}
|
|
153
|
+
return this.maxLength >= this.countValue;
|
|
154
|
+
},
|
|
155
|
+
valueRegexValid(): boolean {
|
|
156
|
+
if (this.regex !== undefined) {
|
|
157
|
+
if(!this.textValue || ""===this.textValue){
|
|
158
|
+
if(this.canBeNull){
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
return this.textValue.match(this.regex) !== null;
|
|
164
|
+
}
|
|
165
|
+
return true;
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
watch: {
|
|
169
|
+
isError(){
|
|
170
|
+
this.$emit('update:errorVariable', this.isError);
|
|
171
|
+
},
|
|
172
|
+
textValue(){
|
|
173
|
+
if(this.textInit !== this.textValue){
|
|
174
|
+
this.$emit('update:textInit', this.textValue)
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
textInit(){
|
|
178
|
+
if(this.textInit !== this.textValue){
|
|
179
|
+
this.textValue =this.textInit;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
mounted(){
|
|
184
|
+
this.textValue = this.textInit;
|
|
185
|
+
if(this.errorVariable !== this.isError){
|
|
186
|
+
this.$emit('update:errorVariable', this.isError);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
</script>
|
|
191
|
+
<style lang="scss">
|
|
192
|
+
.octopus-app .classic-input-text{
|
|
193
|
+
.text-indic{
|
|
194
|
+
font-style: italic;
|
|
195
|
+
font-size: 0.7rem;
|
|
196
|
+
color: #666;
|
|
197
|
+
}
|
|
198
|
+
textarea{
|
|
199
|
+
height: auto;
|
|
200
|
+
min-height: 120px;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
</style>
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="wysiwyg-editor">
|
|
3
|
+
<div
|
|
4
|
+
v-if="editor"
|
|
5
|
+
class="editor-menubar"
|
|
6
|
+
>
|
|
7
|
+
<button
|
|
8
|
+
title="Bold"
|
|
9
|
+
data-selenium="Bold"
|
|
10
|
+
:class="{ 'is-active': editor.isActive('bold') }"
|
|
11
|
+
@click="editor.chain().focus().toggleBold().run()"
|
|
12
|
+
>
|
|
13
|
+
<svg>
|
|
14
|
+
<path
|
|
15
|
+
transform="translate(8, 8)"
|
|
16
|
+
d="M17.194 10.962A6.271 6.271 0 0012.844.248H4.3a1.25 1.25 0 000 2.5h1.013a.25.25 0 01.25.25V21a.25.25 0 01-.25.25H4.3a1.25 1.25 0 100 2.5h9.963a6.742 6.742 0 002.93-12.786zm-4.35-8.214a3.762 3.762 0 010 7.523H8.313a.25.25 0 01-.25-.25V3a.25.25 0 01.25-.25zm1.42 18.5H8.313a.25.25 0 01-.25-.25v-7.977a.25.25 0 01.25-.25h5.951a4.239 4.239 0 010 8.477z"
|
|
17
|
+
/>
|
|
18
|
+
</svg>
|
|
19
|
+
</button>
|
|
20
|
+
<button
|
|
21
|
+
title="Italic"
|
|
22
|
+
data-selenium="Italic"
|
|
23
|
+
:class="{ 'is-active': editor.isActive('italic') }"
|
|
24
|
+
@click="editor.chain().focus().toggleItalic().run()"
|
|
25
|
+
>
|
|
26
|
+
<svg>
|
|
27
|
+
<path
|
|
28
|
+
transform="translate(8, 8)"
|
|
29
|
+
d="M22.5.248h-7.637a1.25 1.25 0 000 2.5h1.086a.25.25 0 01.211.384L4.78 21.017a.5.5 0 01-.422.231H1.5a1.25 1.25 0 000 2.5h7.637a1.25 1.25 0 000-2.5H8.051a.25.25 0 01-.211-.384L19.22 2.98a.5.5 0 01.422-.232H22.5a1.25 1.25 0 000-2.5z"
|
|
30
|
+
/>
|
|
31
|
+
</svg>
|
|
32
|
+
</button>
|
|
33
|
+
<button
|
|
34
|
+
title="Underline"
|
|
35
|
+
data-selenium="Underline"
|
|
36
|
+
:class="{ 'is-active': editor.isActive('underline') }"
|
|
37
|
+
@click="editor.chain().focus().toggleUnderline().run()"
|
|
38
|
+
>
|
|
39
|
+
<svg>
|
|
40
|
+
<path
|
|
41
|
+
transform="translate(8, 8)"
|
|
42
|
+
d="M22.5 21.248h-21a1.25 1.25 0 000 2.5h21a1.25 1.25 0 000-2.5zM1.978 2.748h1.363a.25.25 0 01.25.25v8.523a8.409 8.409 0 0016.818 0V3a.25.25 0 01.25-.25h1.363a1.25 1.25 0 000-2.5H16.3a1.25 1.25 0 000 2.5h1.363a.25.25 0 01.25.25v8.523a5.909 5.909 0 01-11.818 0V3a.25.25 0 01.25-.25H7.7a1.25 1.25 0 100-2.5H1.978a1.25 1.25 0 000 2.5z"
|
|
43
|
+
/>
|
|
44
|
+
</svg>
|
|
45
|
+
</button>
|
|
46
|
+
<button
|
|
47
|
+
title="Link"
|
|
48
|
+
data-selenium="Link"
|
|
49
|
+
:class="{ 'is-active': editor.isActive('link') }"
|
|
50
|
+
@click="setLink"
|
|
51
|
+
>
|
|
52
|
+
<svg viewBox="0 0 24 24" fill="none">
|
|
53
|
+
<path transform="translate(2, 2)scale(0.8)" d="M7.7574 10.5858L4.92897 13.4142C3.7574 14.5858 3.7574 16.4853 4.92897 17.6569L6.34319 19.0711C7.51476 20.2427 9.41425 20.2427 10.5858 19.0711L13.4143 16.2427M9.87873 14.1214L14.1214 9.87873M10.5858 7.7574L13.4142 4.92897C14.5858 3.7574 16.4853 3.7574 17.6569 4.92897L19.0711 6.34319C20.2427 7.51476 20.2427 9.41425 19.0711 10.5858L16.2427 13.4143" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
54
|
+
</svg>
|
|
55
|
+
</button>
|
|
56
|
+
<button @click="editor.chain().focus().unsetLink().run()" :disabled="!editor.isActive('link')">
|
|
57
|
+
<svg viewBox="0 0 24 24" fill="none">
|
|
58
|
+
<path transform="translate(2, 2)scale(0.8)" d="M7.05029 11.2929L4.92897 13.4142C3.7574 14.5858 3.7574 16.4853 4.92897 17.6568L6.34319 19.0711C7.51476 20.2426 9.41425 20.2426 10.5858 19.0711L12.7071 16.9497M5.00004 5L19 19" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
59
|
+
<path transform="translate(2, 2)scale(0.8)" fill-rule="evenodd" clip-rule="evenodd" d="M11.8358 10.75L9.17156 13.4142C8.78103 13.8048 8.78103 14.4379 9.17156 14.8284C9.56208 15.219 10.1952 15.219 10.5858 14.8284L13.25 12.1642L11.8358 10.75ZM17.4926 13.5785L16.0784 12.1643L16.2426 12L17.6568 10.5858L18.3639 9.87872C19.145 9.09767 19.145 7.83134 18.3639 7.05029L16.9497 5.63608C16.1687 4.85503 14.9024 4.85503 14.1213 5.63608L13.4142 6.34319L12 7.7574L11.8358 7.92161L10.4216 6.5074L10.5858 6.34319L12 4.92897L12.7071 4.22187C14.2692 2.65977 16.8019 2.65977 18.3639 4.22187L19.7782 5.63608C21.3403 7.19818 21.3403 9.73084 19.7782 11.2929L19.0711 12L17.6568 13.4143L17.4926 13.5785ZM13.25 9.33581L13.4142 9.1716C13.8047 8.78107 14.4379 8.78107 14.8284 9.1716C15.2189 9.56212 15.2189 10.1953 14.8284 10.5858L14.6642 10.75L13.25 9.33581Z" fill="#000000"/>
|
|
60
|
+
</svg>
|
|
61
|
+
</button>
|
|
62
|
+
<button
|
|
63
|
+
title="Heading3"
|
|
64
|
+
data-selenium="Heading3"
|
|
65
|
+
:class="{ 'is-active': editor.isActive('heading', { level: 3 }) }"
|
|
66
|
+
@click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
|
|
67
|
+
>
|
|
68
|
+
H3
|
|
69
|
+
</button>
|
|
70
|
+
<button
|
|
71
|
+
title="Heading4"
|
|
72
|
+
data-selenium="Heading4"
|
|
73
|
+
:class="{ 'is-active': editor.isActive('heading', { level: 4 }) }"
|
|
74
|
+
@click="editor.chain().focus().toggleHeading({ level: 4 }).run()"
|
|
75
|
+
>
|
|
76
|
+
H4
|
|
77
|
+
</button>
|
|
78
|
+
<button
|
|
79
|
+
title="UnorderedList"
|
|
80
|
+
data-selenium="UnorderedList"
|
|
81
|
+
class="saooti-ul"
|
|
82
|
+
:class="{ 'is-active': editor.isActive('bulletList') }"
|
|
83
|
+
@click="editor.chain().focus().toggleBulletList().run()"
|
|
84
|
+
>
|
|
85
|
+
<svg>
|
|
86
|
+
<circle
|
|
87
|
+
transform="translate(8, 8)"
|
|
88
|
+
cx="2.5"
|
|
89
|
+
cy="3.998"
|
|
90
|
+
r="2.5"
|
|
91
|
+
/>
|
|
92
|
+
<path
|
|
93
|
+
transform="translate(8, 8)"
|
|
94
|
+
d="M8.5 5H23a1 1 0 000-2H8.5a1 1 0 000 2z"
|
|
95
|
+
/>
|
|
96
|
+
<circle
|
|
97
|
+
transform="translate(8, 8)"
|
|
98
|
+
cx="2.5"
|
|
99
|
+
cy="11.998"
|
|
100
|
+
r="2.5"
|
|
101
|
+
/>
|
|
102
|
+
<path
|
|
103
|
+
transform="translate(8, 8)"
|
|
104
|
+
d="M23 11H8.5a1 1 0 000 2H23a1 1 0 000-2z"
|
|
105
|
+
/>
|
|
106
|
+
<circle
|
|
107
|
+
transform="translate(8, 8)"
|
|
108
|
+
cx="2.5"
|
|
109
|
+
cy="19.998"
|
|
110
|
+
r="2.5"
|
|
111
|
+
/>
|
|
112
|
+
<path
|
|
113
|
+
transform="translate(8, 8)"
|
|
114
|
+
d="M23 19H8.5a1 1 0 000 2H23a1 1 0 000-2z"
|
|
115
|
+
/>
|
|
116
|
+
</svg>
|
|
117
|
+
</button>
|
|
118
|
+
<button
|
|
119
|
+
title="List"
|
|
120
|
+
data-selenium="List"
|
|
121
|
+
:class="{ 'is-active': editor.isActive('orderedList') }"
|
|
122
|
+
@click="editor.chain().focus().toggleOrderedList().run()"
|
|
123
|
+
>
|
|
124
|
+
<svg>
|
|
125
|
+
<path
|
|
126
|
+
transform="translate(8, 8)"
|
|
127
|
+
d="M7.75 4.5h15a1 1 0 000-2h-15a1 1 0 000 2zm15 6.5h-15a1 1 0 100 2h15a1 1 0 000-2zm0 8.5h-15a1 1 0 000 2h15a1 1 0 000-2zM2.212 17.248a2 2 0 00-1.933 1.484.75.75 0 101.45.386.5.5 0 11.483.63.75.75 0 100 1.5.5.5 0 11-.482.635.75.75 0 10-1.445.4 2 2 0 103.589-1.648.251.251 0 010-.278 2 2 0 00-1.662-3.111zm2.038-6.5a2 2 0 00-4 0 .75.75 0 001.5 0 .5.5 0 011 0 1.031 1.031 0 01-.227.645L.414 14.029A.75.75 0 001 15.248h2.5a.75.75 0 000-1.5h-.419a.249.249 0 01-.195-.406L3.7 12.33a2.544 2.544 0 00.55-1.582zM4 5.248h-.25A.25.25 0 013.5 5V1.623A1.377 1.377 0 002.125.248H1.5a.75.75 0 000 1.5h.25A.25.25 0 012 2v3a.25.25 0 01-.25.25H1.5a.75.75 0 000 1.5H4a.75.75 0 000-1.5z"
|
|
128
|
+
/>
|
|
129
|
+
</svg>
|
|
130
|
+
</button>
|
|
131
|
+
<button
|
|
132
|
+
title="Display HTML"
|
|
133
|
+
data-selenium="Display-HTML"
|
|
134
|
+
class="html-button"
|
|
135
|
+
:class="{ 'is-active': isHtmlDisplay }"
|
|
136
|
+
@click="isHtmlDisplay = !isHtmlDisplay"
|
|
137
|
+
>
|
|
138
|
+
HTML
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
<editor-content
|
|
142
|
+
v-if="!isHtmlDisplay"
|
|
143
|
+
class="form-input html-wysiwyg-content"
|
|
144
|
+
:class="{ 'border border-danger': errorDescription, 'disabled':isDisabled }"
|
|
145
|
+
:editor="editor"
|
|
146
|
+
/>
|
|
147
|
+
<pre
|
|
148
|
+
v-else
|
|
149
|
+
class="form-input"
|
|
150
|
+
:class="{ 'border border-danger': errorDescription, 'disabled':isDisabled }"
|
|
151
|
+
><code>{{ html }}</code></pre>
|
|
152
|
+
</div>
|
|
153
|
+
</template>
|
|
154
|
+
|
|
155
|
+
<script lang="ts">
|
|
156
|
+
import { EditorContent, Editor } from '@tiptap/vue-3';
|
|
157
|
+
import StarterKit from '@tiptap/starter-kit';
|
|
158
|
+
import Underline from '@tiptap/extension-underline';
|
|
159
|
+
import Link from '@tiptap/extension-link';
|
|
160
|
+
import { defineComponent } from 'vue';
|
|
161
|
+
export default defineComponent({
|
|
162
|
+
components: {
|
|
163
|
+
EditorContent,
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
props: {
|
|
167
|
+
content: { default: undefined, type: String },
|
|
168
|
+
errorDescription: { default: false, type: Boolean },
|
|
169
|
+
isDisabled: { default: false, type: Boolean },
|
|
170
|
+
},
|
|
171
|
+
emits: ['update:content'],
|
|
172
|
+
data() {
|
|
173
|
+
return {
|
|
174
|
+
isHtmlDisplay: false as boolean,
|
|
175
|
+
html: this.content as string,
|
|
176
|
+
editor: null as Editor|null,
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
watch: {
|
|
180
|
+
content(): void {
|
|
181
|
+
if(this.content===this.html){return;}
|
|
182
|
+
this.initContent();
|
|
183
|
+
},
|
|
184
|
+
isDisabled(): void {
|
|
185
|
+
if(this.editor){
|
|
186
|
+
this.editor.setOptions({
|
|
187
|
+
editable: true !== this.isDisabled,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
mounted(){
|
|
194
|
+
this.editor = new Editor({
|
|
195
|
+
extensions: [StarterKit, Underline,
|
|
196
|
+
Link.configure({
|
|
197
|
+
openOnClick: false,
|
|
198
|
+
})],
|
|
199
|
+
content: '',
|
|
200
|
+
editable: true !== this.isDisabled,
|
|
201
|
+
onUpdate: this.updateHtml,
|
|
202
|
+
});
|
|
203
|
+
this.initContent();
|
|
204
|
+
},
|
|
205
|
+
beforeUnmount() {
|
|
206
|
+
if(this.editor){
|
|
207
|
+
this.editor.destroy();
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
methods: {
|
|
212
|
+
initContent(): void {
|
|
213
|
+
if (undefined !== this.content && this.editor && !this.editor.isFocused) {
|
|
214
|
+
this.editor.commands.setContent(this.content);
|
|
215
|
+
this.html = this.editor.getHTML();
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
updateHtml(): void {
|
|
219
|
+
if(this.editor){
|
|
220
|
+
this.html = this.editor.getHTML();
|
|
221
|
+
this.$emit('update:content', this.html);
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
setLink() {
|
|
225
|
+
if(!this.editor){return;}
|
|
226
|
+
const previousUrl = this.editor.getAttributes('link').href;
|
|
227
|
+
const url = window.prompt('URL', previousUrl)
|
|
228
|
+
if(!url) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if(""===url) {
|
|
232
|
+
this.editor
|
|
233
|
+
.chain()
|
|
234
|
+
.focus()
|
|
235
|
+
.extendMarkRange('link')
|
|
236
|
+
.unsetLink()
|
|
237
|
+
.run()
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
this.editor
|
|
241
|
+
.chain()
|
|
242
|
+
.focus()
|
|
243
|
+
.extendMarkRange('link')
|
|
244
|
+
.setLink({ href: url })
|
|
245
|
+
.run();
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
</script>
|
|
250
|
+
<style lang="scss">
|
|
251
|
+
@import '@scss/_variables.scss';
|
|
252
|
+
.octopus-app{
|
|
253
|
+
.wysiwyg-editor {
|
|
254
|
+
.form-input {
|
|
255
|
+
height: 200px;
|
|
256
|
+
display: flex;
|
|
257
|
+
}
|
|
258
|
+
pre {
|
|
259
|
+
background: #ddd;
|
|
260
|
+
margin: 0;
|
|
261
|
+
}
|
|
262
|
+
code {
|
|
263
|
+
display: block;
|
|
264
|
+
white-space: pre-wrap;
|
|
265
|
+
width: 0;
|
|
266
|
+
flex-grow: 1;
|
|
267
|
+
}
|
|
268
|
+
.editor-menubar {
|
|
269
|
+
display: flex;
|
|
270
|
+
padding: 0.2rem;
|
|
271
|
+
flex-wrap: wrap;
|
|
272
|
+
button {
|
|
273
|
+
width: 40px;
|
|
274
|
+
height: 40px;
|
|
275
|
+
background: $octopus-secondary-color;
|
|
276
|
+
border-width: 0;
|
|
277
|
+
border-radius: $octopus-borderradius;
|
|
278
|
+
margin: 0.2rem;
|
|
279
|
+
padding: 0;
|
|
280
|
+
font-size: 1.1rem;
|
|
281
|
+
font-weight: 600;
|
|
282
|
+
&:hover,
|
|
283
|
+
&.is-active {
|
|
284
|
+
background: $primaryColorTransparent;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
.html-button {
|
|
288
|
+
font-size: 12px;
|
|
289
|
+
}
|
|
290
|
+
svg {
|
|
291
|
+
width: 40px;
|
|
292
|
+
height: 40px;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
.ProseMirror {
|
|
296
|
+
width: 0;
|
|
297
|
+
flex-grow: 1;
|
|
298
|
+
overflow: auto;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
</style>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export default{
|
|
3
3
|
methods: {
|
|
4
4
|
urlify(text: string): string {
|
|
5
|
-
const urlRegex = /(https?:\/\/[^\s<]+)/g;
|
|
5
|
+
const urlRegex = /[^"](https?:\/\/[^\s<]+)/g;
|
|
6
6
|
if (!text) return '';
|
|
7
7
|
return text.replace(urlRegex, (url: string) => {
|
|
8
8
|
return '<a href="' + url + '" target="_blank" rel="noopener">' + url + '</a>';
|
package/src/locale/de.ts
CHANGED
|
@@ -326,4 +326,5 @@ export default{
|
|
|
326
326
|
"No programming":"Nicht programmieren",
|
|
327
327
|
'Canal name image': 'Kanalbild {name}',
|
|
328
328
|
"Show animated wave":"Animierte Welle anzeigen",
|
|
329
|
+
'Characters number calculated over HTML code':"Die Zeichenzahl wird mit dem HTML-Code ermittelt, der mit diesem Editor erstellt wurde. Über den HTML-Button können Sie diesen Code einsehen.",
|
|
329
330
|
}
|
package/src/locale/en.ts
CHANGED
|
@@ -333,4 +333,5 @@ export default{
|
|
|
333
333
|
"No programming":"No programming",
|
|
334
334
|
'Canal name image': 'Channel image {name}',
|
|
335
335
|
"Show animated wave":"Show animated wave",
|
|
336
|
+
'Characters number calculated over HTML code':'The number of characters is calculated from the HTML code generated by this editor. You can see this code using the "html" button.',
|
|
336
337
|
};
|
package/src/locale/es.ts
CHANGED
|
@@ -326,4 +326,5 @@ export default{
|
|
|
326
326
|
"No programming":"No programa",
|
|
327
327
|
'Canal name image': 'Imagen del canal {name}',
|
|
328
328
|
"Show animated wave":"Mostrar onda animada",
|
|
329
|
+
'Characters number calculated over HTML code':'El número de caracteres se calcula a partir del código HTML generado por este editor. Puedes visualizar este código pulsando en «html».',
|
|
329
330
|
}
|
package/src/locale/fr.ts
CHANGED
|
@@ -333,4 +333,5 @@ export default{
|
|
|
333
333
|
"No programming":"Aucune programmation",
|
|
334
334
|
'Canal name image': 'Image du canal {name}',
|
|
335
335
|
"Show animated wave":"Afficher la vague animée",
|
|
336
|
+
'Characters number calculated over HTML code':'Le nombre de caractères est calculé à partir du code HTML généré par cet éditeur. Vous pouvez voir ce code grâce au bouton "html".',
|
|
336
337
|
};
|
package/src/locale/it.ts
CHANGED
|
@@ -323,4 +323,5 @@ export default{
|
|
|
323
323
|
"No programming":"Non programmazione",
|
|
324
324
|
'Canal name image': 'Immagine del canale {name}',
|
|
325
325
|
"Show animated wave":"Mostra onda animata",
|
|
326
|
+
'Characters number calculated over HTML code':'Il numero di caratteri è calcolato dal codice HTML generato da questo editor. È possibile visualizzare il codice cliccando su "html".',
|
|
326
327
|
};
|
package/src/locale/sl.ts
CHANGED
|
@@ -326,4 +326,5 @@ export default{
|
|
|
326
326
|
"No programming":"Ne programiranje",
|
|
327
327
|
'Canal name image': 'Slika kanala {name}',
|
|
328
328
|
"Show animated wave":"Prikaži animirani val",
|
|
329
|
+
'Characters number calculated over HTML code':'Število znakov se izračuna iz kode HTML, ki jo ustvari ta urejevalnik. Ogledate si jo lahko s klikom na gumb „html“.',
|
|
329
330
|
}
|