@silexlabs/silex 3.5.1-1 → 3.5.1-2
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/dist/client/client/grapesjs/PublicationManager.d.ts +43 -0
- package/dist/client/css/admin.css +29 -5
- package/dist/client/index.html +2 -2
- package/dist/client/js/main.js +157 -154
- package/package.json +4 -4
- package/src/css/grapesjs.scss +5 -0
- package/src/css/page-panel.scss +24 -5
- package/src/ts/client/grapesjs/PublicationManager.ts +159 -1
- package/src/ts/client/grapesjs/cms/buttons.ts +67 -41
- package/src/ts/client/grapesjs/cms/collection-pages.ts +22 -13
- package/src/ts/client/grapesjs/css-props.ts +15 -16
- package/src/ts/client/grapesjs/page-panel.ts +119 -5
- package/src/ts/client/grapesjs/semantic.ts +4 -0
- package/src/ts/client/grapesjs/storage.ts +6 -2
|
@@ -59,13 +59,27 @@ function clonePage(editor: Editor, page: Page) {
|
|
|
59
59
|
while(pages.find(p => p.getName() === pageName)) {
|
|
60
60
|
pageName = `${newPageName} ${idx++}`
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
|
|
63
|
+
// Clone components using Backbone approach
|
|
64
|
+
const sourceBody = page.getMainComponent()
|
|
65
|
+
const clonedComponents = sourceBody.clone()
|
|
66
|
+
|
|
67
|
+
// Get custom props but exclude frames (Backbone collection) using toJSON and delete
|
|
68
|
+
const customProps = { ...page.toJSON() }
|
|
69
|
+
delete customProps.frames
|
|
70
|
+
delete customProps.id
|
|
71
|
+
delete customProps._undo
|
|
72
|
+
|
|
73
|
+
// Create new page with custom props (but not frames collection)
|
|
65
74
|
const newPage = editor.Pages.add({
|
|
75
|
+
...customProps,
|
|
66
76
|
name: pageName,
|
|
67
|
-
component: body.toJSON(),
|
|
68
77
|
})
|
|
78
|
+
|
|
79
|
+
// Reset components with cloned ones
|
|
80
|
+
const targetBody = newPage.getMainComponent()
|
|
81
|
+
targetBody.components().reset(clonedComponents.components().models)
|
|
82
|
+
|
|
69
83
|
// Select the new page
|
|
70
84
|
editor.Pages.select(newPage)
|
|
71
85
|
}
|
|
@@ -142,6 +156,92 @@ function renderPages(editor, config) {
|
|
|
142
156
|
e.stopPropagation()
|
|
143
157
|
return editor.Pages.get(el.getAttribute('data-page-id'))
|
|
144
158
|
}
|
|
159
|
+
|
|
160
|
+
// Drag and drop handlers
|
|
161
|
+
let draggedPage: Page | null = null
|
|
162
|
+
let draggedPageElement: HTMLElement | null = null
|
|
163
|
+
|
|
164
|
+
const handleDragStart = (e: DragEvent, page: Page) => {
|
|
165
|
+
e.stopPropagation()
|
|
166
|
+
draggedPage = page
|
|
167
|
+
// Find the parent page element
|
|
168
|
+
draggedPageElement = (e.target as HTMLElement).closest('.pages__page') as HTMLElement
|
|
169
|
+
if (e.dataTransfer && draggedPageElement) {
|
|
170
|
+
e.dataTransfer.effectAllowed = 'move'
|
|
171
|
+
e.dataTransfer.setData('text/html', draggedPageElement.innerHTML)
|
|
172
|
+
draggedPageElement.classList.add('pages__page-dragging')
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const handleDragEnd = (e: DragEvent) => {
|
|
177
|
+
if (draggedPageElement) {
|
|
178
|
+
draggedPageElement.classList.remove('pages__page-dragging')
|
|
179
|
+
}
|
|
180
|
+
draggedPage = null
|
|
181
|
+
draggedPageElement = null
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const handleDragOver = (e: DragEvent) => {
|
|
185
|
+
if (!draggedPage) return
|
|
186
|
+
e.preventDefault()
|
|
187
|
+
e.stopPropagation()
|
|
188
|
+
if (e.dataTransfer) {
|
|
189
|
+
e.dataTransfer.dropEffect = 'move'
|
|
190
|
+
}
|
|
191
|
+
return false
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const handleDragEnter = (e: DragEvent, page: Page) => {
|
|
195
|
+
if (draggedPage && draggedPage !== page) {
|
|
196
|
+
e.preventDefault()
|
|
197
|
+
e.stopPropagation()
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const handleDragLeave = (e: DragEvent) => {
|
|
202
|
+
// No-op: visual indicator removed
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const handleDrop = (e: DragEvent, targetPage: Page) => {
|
|
206
|
+
e.stopPropagation()
|
|
207
|
+
e.preventDefault()
|
|
208
|
+
|
|
209
|
+
if (draggedPage && draggedPage !== targetPage) {
|
|
210
|
+
const pages = editor.Pages.getAll()
|
|
211
|
+
const fromIndex = pages.indexOf(draggedPage)
|
|
212
|
+
const toIndex = pages.indexOf(targetPage)
|
|
213
|
+
|
|
214
|
+
if (fromIndex !== -1 && toIndex !== -1 && fromIndex !== toIndex) {
|
|
215
|
+
// Access the internal Backbone collection
|
|
216
|
+
const pagesCollection = (editor.Pages as any).pages
|
|
217
|
+
|
|
218
|
+
// Assign temporary order attributes for sorting
|
|
219
|
+
pages.forEach((page, idx) => {
|
|
220
|
+
let newOrder = idx
|
|
221
|
+
if (idx === fromIndex) {
|
|
222
|
+
newOrder = toIndex
|
|
223
|
+
} else if (fromIndex < toIndex && idx > fromIndex && idx <= toIndex) {
|
|
224
|
+
newOrder = idx - 1
|
|
225
|
+
} else if (fromIndex > toIndex && idx >= toIndex && idx < fromIndex) {
|
|
226
|
+
newOrder = idx + 1
|
|
227
|
+
}
|
|
228
|
+
page.set('_tempOrder', newOrder, { silent: true })
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
// Sort the collection by the temporary order
|
|
232
|
+
const originalComparator = pagesCollection.comparator
|
|
233
|
+
pagesCollection.comparator = (page: Page) => page.get('_tempOrder')
|
|
234
|
+
pagesCollection.sort()
|
|
235
|
+
pagesCollection.comparator = originalComparator
|
|
236
|
+
|
|
237
|
+
// Clean up temporary attributes
|
|
238
|
+
pages.forEach(page => page.unset('_tempOrder', { silent: true }))
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return false
|
|
243
|
+
}
|
|
244
|
+
|
|
145
245
|
return html`<section class="pages">
|
|
146
246
|
<main class="pages__main ${pages.length === 1 ? 'pages__single-page' : ''}">
|
|
147
247
|
<div class="pages__list">
|
|
@@ -150,8 +250,22 @@ function renderPages(editor, config) {
|
|
|
150
250
|
const name = page.getName() || type
|
|
151
251
|
// keep the same structure as the layers panel
|
|
152
252
|
return html`
|
|
153
|
-
<div
|
|
253
|
+
<div
|
|
254
|
+
class="pages__page ${selected === page ? 'pages__page-selected' : ''}"
|
|
255
|
+
data-page-id=${page.id}
|
|
256
|
+
@click=${e => selectPage(editor, getPageFromEvent(e))}
|
|
257
|
+
@dragover=${handleDragOver}
|
|
258
|
+
@dragenter=${(e: DragEvent) => handleDragEnter(e, page)}
|
|
259
|
+
@dragleave=${handleDragLeave}
|
|
260
|
+
@drop=${(e: DragEvent) => handleDrop(e, page)}
|
|
261
|
+
>
|
|
154
262
|
<div class="pages__page-name">
|
|
263
|
+
<i
|
|
264
|
+
class="pages__icon pages__drag-handle fa fa-grip-vertical"
|
|
265
|
+
draggable="true"
|
|
266
|
+
@dragstart=${(e: DragEvent) => handleDragStart(e, page)}
|
|
267
|
+
@dragend=${handleDragEnd}
|
|
268
|
+
></i>
|
|
155
269
|
${ name }
|
|
156
270
|
</div>
|
|
157
271
|
<i class="pages__icon pages__remove-btn fa fa-trash" @click=${e => removePage(editor, getPageFromEvent(e))}></i>
|
|
@@ -104,7 +104,11 @@ export const storagePlugin = (editor: PublishableEditor) => {
|
|
|
104
104
|
if (firstPage) editor.Pages.select(firstPage)
|
|
105
105
|
loader && render(getLoaderHtml('Starting', 1, 1), loader)
|
|
106
106
|
await nextFrame()
|
|
107
|
-
editor.once('canvas:frame:load', () =>
|
|
107
|
+
editor.once('canvas:frame:load', () => {
|
|
108
|
+
setTimeout(() => { // This is needed in chrome, otherwise a save is triggered
|
|
109
|
+
editor.stopCommand(cmdPauseAutoSave)
|
|
110
|
+
}, 500)
|
|
111
|
+
})
|
|
108
112
|
return data
|
|
109
113
|
}
|
|
110
114
|
} catch (err) {
|
|
@@ -142,7 +146,7 @@ export const storagePlugin = (editor: PublishableEditor) => {
|
|
|
142
146
|
},
|
|
143
147
|
|
|
144
148
|
async doStore(data: WebsiteData, options: { id: WebsiteId, connectorId: ConnectorId }) {
|
|
145
|
-
if (editor.PublicationManager
|
|
149
|
+
if (editor.PublicationManager?.status === PublicationStatus.STATUS_PENDING) {
|
|
146
150
|
// Publication is pending, save is delayed
|
|
147
151
|
return new Promise((resolve) => {
|
|
148
152
|
editor.once(ClientEvent.PUBLISH_END, () => {
|