frappe-ui 0.0.42 → 0.0.45
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/package.json +1 -1
- package/src/components/Dialog.vue +6 -2
- package/src/components/TextEditor/Menu.vue +56 -0
- package/src/components/TextEditor/TextEditor.vue +5 -5
- package/src/components/TextEditor/commands.js +6 -0
- package/src/components/TextEditor/icons/image-add-line.vue +14 -0
- package/src/utils/plugin.js +2 -2
- package/src/utils/resources.js +22 -6
- package/src/utils/socketio.js +5 -7
package/package.json
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<TransitionRoot
|
|
2
|
+
<TransitionRoot
|
|
3
|
+
as="template"
|
|
4
|
+
:show="open"
|
|
5
|
+
@after-leave="$emit('after-leave')"
|
|
6
|
+
>
|
|
3
7
|
<HDialog
|
|
4
8
|
as="div"
|
|
5
9
|
class="fixed inset-0 z-10 overflow-y-auto"
|
|
@@ -137,7 +141,7 @@ export default {
|
|
|
137
141
|
},
|
|
138
142
|
},
|
|
139
143
|
},
|
|
140
|
-
emits: ['update:modelValue', 'close'],
|
|
144
|
+
emits: ['update:modelValue', 'close', 'after-leave'],
|
|
141
145
|
components: {
|
|
142
146
|
HDialog,
|
|
143
147
|
DialogOverlay,
|
|
@@ -67,6 +67,39 @@
|
|
|
67
67
|
</Button>
|
|
68
68
|
</template>
|
|
69
69
|
</Dialog>
|
|
70
|
+
<Dialog
|
|
71
|
+
:options="{ title: 'Add Image' }"
|
|
72
|
+
v-model="addImageDialog.show"
|
|
73
|
+
@after-leave="resetAddImage"
|
|
74
|
+
>
|
|
75
|
+
<template #body-content>
|
|
76
|
+
<label
|
|
77
|
+
class="relative py-1 bg-gray-100 rounded-lg cursor-pointer focus-within:bg-gray-200 hover:bg-gray-200"
|
|
78
|
+
>
|
|
79
|
+
<input
|
|
80
|
+
type="file"
|
|
81
|
+
class="w-full opacity-0"
|
|
82
|
+
@change="onImageSelect"
|
|
83
|
+
accept="image/*"
|
|
84
|
+
/>
|
|
85
|
+
<span class="absolute inset-0 px-2 py-1 text-base select-none">
|
|
86
|
+
{{
|
|
87
|
+
addImageDialog.file ? 'Select another image' : 'Select an image'
|
|
88
|
+
}}
|
|
89
|
+
</span>
|
|
90
|
+
</label>
|
|
91
|
+
<img
|
|
92
|
+
v-if="addImageDialog.url"
|
|
93
|
+
:src="addImageDialog.url"
|
|
94
|
+
class="w-full mt-2 rounded-lg"
|
|
95
|
+
/>
|
|
96
|
+
</template>
|
|
97
|
+
<template #actions>
|
|
98
|
+
<Button appearance="primary" @click="addImage(addImageDialog.url)">
|
|
99
|
+
Insert Image
|
|
100
|
+
</Button>
|
|
101
|
+
</template>
|
|
102
|
+
</Dialog>
|
|
70
103
|
</div>
|
|
71
104
|
</template>
|
|
72
105
|
<script>
|
|
@@ -83,6 +116,7 @@ export default {
|
|
|
83
116
|
data() {
|
|
84
117
|
return {
|
|
85
118
|
setLinkDialog: { url: '', show: false },
|
|
119
|
+
addImageDialog: { url: '', file: null, show: false },
|
|
86
120
|
}
|
|
87
121
|
},
|
|
88
122
|
methods: {
|
|
@@ -93,6 +127,8 @@ export default {
|
|
|
93
127
|
if (existingURL) {
|
|
94
128
|
this.setLinkDialog.url = existingURL
|
|
95
129
|
}
|
|
130
|
+
} else if (button.label === 'Image') {
|
|
131
|
+
this.addImageDialog.show = true
|
|
96
132
|
} else {
|
|
97
133
|
button.action(this.editor)
|
|
98
134
|
}
|
|
@@ -114,6 +150,26 @@ export default {
|
|
|
114
150
|
this.setLinkDialog.show = false
|
|
115
151
|
this.setLinkDialog.url = ''
|
|
116
152
|
},
|
|
153
|
+
onImageSelect(e) {
|
|
154
|
+
let file = e.target.files[0]
|
|
155
|
+
if (!file) {
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
this.addImageDialog.file = file
|
|
159
|
+
let reader = new FileReader()
|
|
160
|
+
reader.onloadend = () => {
|
|
161
|
+
let base64string = reader.result
|
|
162
|
+
this.addImageDialog.url = base64string
|
|
163
|
+
}
|
|
164
|
+
reader.readAsDataURL(file)
|
|
165
|
+
},
|
|
166
|
+
addImage(src) {
|
|
167
|
+
this.editor.chain().focus().setImage({ src }).run()
|
|
168
|
+
this.resetAddImage()
|
|
169
|
+
},
|
|
170
|
+
resetAddImage() {
|
|
171
|
+
this.addImageDialog = { show: false, url: null, file: null }
|
|
172
|
+
},
|
|
117
173
|
},
|
|
118
174
|
}
|
|
119
175
|
</script>
|
|
@@ -119,7 +119,9 @@ export default {
|
|
|
119
119
|
TextAlign.configure({
|
|
120
120
|
types: ['heading', 'paragraph'],
|
|
121
121
|
}),
|
|
122
|
-
Image
|
|
122
|
+
Image.configure({
|
|
123
|
+
allowBase64: true,
|
|
124
|
+
}),
|
|
123
125
|
Link,
|
|
124
126
|
Placeholder.configure({
|
|
125
127
|
placeholder: this.placeholder || 'Write something...',
|
|
@@ -163,6 +165,7 @@ export default {
|
|
|
163
165
|
'Align Center',
|
|
164
166
|
'Align Right',
|
|
165
167
|
'Separator',
|
|
168
|
+
'Image',
|
|
166
169
|
'Blockquote',
|
|
167
170
|
'Code',
|
|
168
171
|
'Horizontal Rule',
|
|
@@ -220,10 +223,7 @@ export default {
|
|
|
220
223
|
editorProps() {
|
|
221
224
|
return {
|
|
222
225
|
attributes: {
|
|
223
|
-
class: normalizeClass([
|
|
224
|
-
'prose prose-sm prose-p:my-1',
|
|
225
|
-
this.editorClass,
|
|
226
|
-
]),
|
|
226
|
+
class: normalizeClass(['prose prose-p:my-1', this.editorClass]),
|
|
227
227
|
},
|
|
228
228
|
}
|
|
229
229
|
},
|
|
@@ -16,6 +16,7 @@ import ListUnordered from './icons/list-unordered.vue'
|
|
|
16
16
|
import DoubleQuotes from './icons/double-quotes-r.vue'
|
|
17
17
|
import CodeView from './icons/code-view.vue'
|
|
18
18
|
import Link from './icons/link.vue'
|
|
19
|
+
import Image from './icons/image-add-line.vue'
|
|
19
20
|
import ArrowGoBack from './icons/arrow-go-back-line.vue'
|
|
20
21
|
import ArrowGoForward from './icons/arrow-go-forward-line.vue'
|
|
21
22
|
import Separator from './icons/separator.vue'
|
|
@@ -146,6 +147,11 @@ export default {
|
|
|
146
147
|
icon: Link,
|
|
147
148
|
isActive: (editor) => editor.isActive('link'),
|
|
148
149
|
},
|
|
150
|
+
Image: {
|
|
151
|
+
label: 'Image',
|
|
152
|
+
icon: Image,
|
|
153
|
+
isActive: (editor) => false,
|
|
154
|
+
},
|
|
149
155
|
Undo: {
|
|
150
156
|
label: 'Undo',
|
|
151
157
|
icon: ArrowGoBack,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg
|
|
3
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
4
|
+
viewBox="0 0 24 24"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
>
|
|
8
|
+
<path fill="none" d="M0 0h24v24H0z" />
|
|
9
|
+
<path
|
|
10
|
+
d="M21 15v3h3v2h-3v3h-2v-3h-3v-2h3v-3h2zm.008-12c.548 0 .992.445.992.993V13h-2V5H4v13.999L14 9l3 3v2.829l-3-3L6.827 19H14v2H2.992A.993.993 0 0 1 2 20.007V3.993A1 1 0 0 1 2.992 3h18.016zM8 7a2 2 0 1 1 0 4 2 2 0 0 1 0-4z"
|
|
11
|
+
fill="currentColor"
|
|
12
|
+
/>
|
|
13
|
+
</svg>
|
|
14
|
+
</template>
|
package/src/utils/plugin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import resources from './resources'
|
|
2
2
|
import call from './call'
|
|
3
|
-
import
|
|
3
|
+
import initSocket from './socketio'
|
|
4
4
|
|
|
5
5
|
let defaultOptions = {
|
|
6
6
|
resources: true,
|
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
app.config.globalProperties.$call = callFunction
|
|
19
19
|
}
|
|
20
20
|
if (options.socketio) {
|
|
21
|
-
app.config.globalProperties.$socket =
|
|
21
|
+
app.config.globalProperties.$socket = initSocket(options.socketio)
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
}
|
package/src/utils/resources.js
CHANGED
|
@@ -212,6 +212,7 @@ export function createDocumentResource(options, vm) {
|
|
|
212
212
|
},
|
|
213
213
|
onSuccess(data) {
|
|
214
214
|
out.doc = transform(data)
|
|
215
|
+
options.onSuccess?.call(vm, out.doc)
|
|
215
216
|
},
|
|
216
217
|
onError: options.onError,
|
|
217
218
|
},
|
|
@@ -316,10 +317,12 @@ export function createListResource(options, vm, getResource) {
|
|
|
316
317
|
fields: options.fields,
|
|
317
318
|
filters: options.filters,
|
|
318
319
|
order_by: options.order_by,
|
|
319
|
-
start: options.start,
|
|
320
|
-
limit: options.limit,
|
|
320
|
+
start: options.start || 0,
|
|
321
|
+
limit: options.limit || 20,
|
|
321
322
|
originalData: null,
|
|
322
323
|
data: null,
|
|
324
|
+
next,
|
|
325
|
+
hasNextPage: true,
|
|
323
326
|
list: createResource(
|
|
324
327
|
{
|
|
325
328
|
method: 'frappe.client.get_list',
|
|
@@ -334,8 +337,15 @@ export function createListResource(options, vm, getResource) {
|
|
|
334
337
|
}
|
|
335
338
|
},
|
|
336
339
|
onSuccess(data) {
|
|
337
|
-
out.
|
|
338
|
-
|
|
340
|
+
if (data.length < out.limit) {
|
|
341
|
+
out.hasNextPage = false
|
|
342
|
+
}
|
|
343
|
+
if (!out.start || out.start == 0) {
|
|
344
|
+
out.originalData = data
|
|
345
|
+
} else if (out.start > 0) {
|
|
346
|
+
out.originalData = out.originalData.concat(data)
|
|
347
|
+
}
|
|
348
|
+
out.data = transform(out.originalData)
|
|
339
349
|
options.onSuccess?.call(vm, out.data)
|
|
340
350
|
},
|
|
341
351
|
onError: options.onError,
|
|
@@ -455,6 +465,7 @@ export function createListResource(options, vm, getResource) {
|
|
|
455
465
|
}
|
|
456
466
|
|
|
457
467
|
function reload() {
|
|
468
|
+
out.start = 0
|
|
458
469
|
return out.list.fetch()
|
|
459
470
|
}
|
|
460
471
|
|
|
@@ -465,6 +476,11 @@ export function createListResource(options, vm, getResource) {
|
|
|
465
476
|
out.data = data
|
|
466
477
|
}
|
|
467
478
|
|
|
479
|
+
function next() {
|
|
480
|
+
out.start = out.start + out.limit
|
|
481
|
+
out.list.fetch()
|
|
482
|
+
}
|
|
483
|
+
|
|
468
484
|
// fetch list
|
|
469
485
|
out.list.fetch()
|
|
470
486
|
|
|
@@ -480,7 +496,7 @@ export function createListResource(options, vm, getResource) {
|
|
|
480
496
|
}
|
|
481
497
|
|
|
482
498
|
function updateRowInListResource(doctype, doc) {
|
|
483
|
-
let resources = listResources[doctype]
|
|
499
|
+
let resources = listResources[doctype] || []
|
|
484
500
|
for (let resource of resources) {
|
|
485
501
|
if (resource.originalData) {
|
|
486
502
|
for (let row of resource.originalData) {
|
|
@@ -500,7 +516,7 @@ function updateRowInListResource(doctype, doc) {
|
|
|
500
516
|
}
|
|
501
517
|
|
|
502
518
|
function revertRowInListResource(doctype, doc) {
|
|
503
|
-
let resources = listResources[doctype]
|
|
519
|
+
let resources = listResources[doctype] || []
|
|
504
520
|
for (let resource of resources) {
|
|
505
521
|
if (resource.originalData) {
|
|
506
522
|
for (let row of resource.originalData) {
|
package/src/utils/socketio.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { io } from 'socket.io-client'
|
|
2
2
|
|
|
3
|
-
function initSocket() {
|
|
3
|
+
export default function initSocket(options = {}) {
|
|
4
4
|
let host = window.location.hostname
|
|
5
|
-
let
|
|
5
|
+
let socketio_port = options.port || 9000
|
|
6
|
+
let port = window.location.port ? `:${socketio_port}` : ''
|
|
6
7
|
let protocol = port ? 'http' : 'https'
|
|
7
8
|
let url = `${protocol}://${host}${port}`
|
|
8
|
-
|
|
9
|
+
let socket = io(url)
|
|
10
|
+
return socket
|
|
9
11
|
}
|
|
10
|
-
|
|
11
|
-
let socket = initSocket()
|
|
12
|
-
|
|
13
|
-
export default socket
|