@silexlabs/silex 3.3.1-0 → 3.3.1-1
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/flex.d.ts +7 -0
- package/dist/client/client/grapesjs/li.d.ts +7 -0
- package/dist/client/client/grapesjs/sectors.d.ts +11 -0
- package/dist/client/client/grapesjs/symbolDialogs.d.ts +2 -1
- package/dist/client/css/admin.css.map +1 -0
- package/dist/client/index.html +2 -2
- package/dist/client/js/main.js +194 -194
- package/dist/client/silex-lib/src/ts/client/grapesjs/flex.d.ts +7 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/li.d.ts +7 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/scroll.d.ts +7 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/sectors.d.ts +11 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.js +3 -67
- package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -1
- package/package.json +3 -3
- package/src/ts/client/grapesjs/LoginDialog.ts +1 -0
- package/src/ts/client/grapesjs/css-props.ts +57 -0
- package/src/ts/client/grapesjs/flex.ts +83 -0
- package/src/ts/client/grapesjs/img.ts +45 -6
- package/src/ts/client/grapesjs/index.ts +6 -0
- package/src/ts/client/grapesjs/li.ts +77 -0
- package/src/ts/client/grapesjs/sectors.ts +59 -0
- package/src/ts/client/grapesjs/semantic.ts +132 -58
- package/src/ts/client/grapesjs/symbolDialogs.ts +10 -6
- package/src/ts/client/index.ts +0 -38
- package/src/ts/plugins/server/GitlabConnector.ts +2 -67
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Silex website builder, free/libre no-code tool for makers.
|
|
3
|
+
* Copyright (c) 2023 lexoyo and Silex Labs foundation
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
import { Component, Editor } from 'grapesjs'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @fileoverview
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export type SectorConfig = {
|
|
25
|
+
name: string
|
|
26
|
+
props: any[]
|
|
27
|
+
shouldShow: (comp: Component) => boolean
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function registerSector(editor: Editor, config: SectorConfig, at?: number) {
|
|
31
|
+
const sm = editor.StyleManager
|
|
32
|
+
let sector = sm.getSector(config.name)
|
|
33
|
+
if (!sector) {
|
|
34
|
+
sector = sm.addSector(config.name, { name: config.name, open: false, visible: false }, { at })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Add props if not already present
|
|
38
|
+
const existingProps = sector.get('properties')//.map(p => p.get('property'))
|
|
39
|
+
config.props.forEach(p => {
|
|
40
|
+
if (!existingProps.includes(p.property)) {
|
|
41
|
+
sector.addProperty(p, {})
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// Keep sector in sync with internal visibility state
|
|
46
|
+
sector.on('change:visible', () => {
|
|
47
|
+
const shouldBeVisible = sector.get('visible')
|
|
48
|
+
if (shouldBeVisible !== config.shouldShow(editor.getSelected() as Component)) {
|
|
49
|
+
sector.set('visible', !shouldBeVisible)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
editor.on('component:selected', comp => {
|
|
54
|
+
const shouldShow = config.shouldShow(comp)
|
|
55
|
+
if (sector.get('visible') !== shouldShow) {
|
|
56
|
+
sector.set('visible', shouldShow)
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
}
|
|
@@ -21,94 +21,168 @@ import {map} from 'lit-html/directives/map.js'
|
|
|
21
21
|
// constants
|
|
22
22
|
const pluginName = 'semantic'
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
'BLOCKQUOTE',
|
|
24
|
+
// Group tags by category
|
|
25
|
+
const tagCategories = [
|
|
26
|
+
{
|
|
27
|
+
label: 'Containers',
|
|
28
|
+
tags: ['DIV', 'SPAN', 'P'],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
label: 'Headings',
|
|
32
|
+
tags: ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'Main document structure',
|
|
36
|
+
tags: ['MAIN', 'SECTION', 'ARTICLE', 'NAV', 'ASIDE', 'HEADER', 'FOOTER'],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: 'Content grouping',
|
|
40
|
+
tags: ['ADDRESS', 'BLOCKQUOTE', 'PRE'],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: 'Interactive/form',
|
|
44
|
+
tags: ['BUTTON', 'LABEL', 'DETAILS', 'SUMMARY'],
|
|
45
|
+
},
|
|
47
46
|
]
|
|
48
47
|
|
|
48
|
+
// Flatten all tags for lookup
|
|
49
|
+
const tags = tagCategories.flatMap(cat => cat.tags)
|
|
50
|
+
|
|
49
51
|
// plugin code
|
|
50
52
|
export const semanticPlugin = (editor, opts) => {
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
+
// Helper to merge extra traits into a type's default traits
|
|
54
|
+
function withExtraTraits(type, extraTraits) {
|
|
55
|
+
const origTraits = editor.DomComponents.getType(type.id).model.prototype.defaults.traits
|
|
56
|
+
return [
|
|
57
|
+
...origTraits,
|
|
58
|
+
...extraTraits,
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Traits to add to all components
|
|
63
|
+
const extraTraits = [
|
|
64
|
+
{
|
|
65
|
+
label: 'Tag name',
|
|
66
|
+
type: 'tag-name',
|
|
67
|
+
name: 'tag-name',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
label: 'For',
|
|
71
|
+
name: 'for',
|
|
72
|
+
type: 'for-trait',
|
|
73
|
+
placeholder: 'ID of input',
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
// Add the extra traits to all component types
|
|
78
|
+
editor.DomComponents.getTypes().forEach(type => {
|
|
53
79
|
editor.DomComponents.addType(type.id, {
|
|
54
80
|
model: {
|
|
55
81
|
defaults: {
|
|
56
|
-
traits:
|
|
57
|
-
// Keep the type original traits
|
|
58
|
-
...editor.DomComponents.getType(type.id).model.prototype.defaults.traits,
|
|
59
|
-
// Add the new trait
|
|
60
|
-
{
|
|
61
|
-
label: 'Tag name',
|
|
62
|
-
type: 'tag-name',
|
|
63
|
-
name: 'tag-name',
|
|
64
|
-
},
|
|
65
|
-
]
|
|
82
|
+
traits: withExtraTraits(type, extraTraits),
|
|
66
83
|
}
|
|
67
84
|
}
|
|
68
85
|
})
|
|
69
86
|
})
|
|
70
87
|
|
|
71
|
-
function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
// Shared render function for select and for-trait
|
|
89
|
+
function renderTrait(el: HTMLElement, opts: {
|
|
90
|
+
tagName?: string,
|
|
91
|
+
forAttr?: string,
|
|
92
|
+
type: 'tag' | 'for'
|
|
93
|
+
}) {
|
|
94
|
+
const tagName = (opts.tagName || '').toUpperCase()
|
|
95
|
+
if (opts.type === 'tag') {
|
|
96
|
+
// Render tag select
|
|
97
|
+
let categoriesWithCurrent = tagCategories.map(cat => ({
|
|
98
|
+
...cat,
|
|
99
|
+
tags: cat.tags.slice(),
|
|
100
|
+
}))
|
|
101
|
+
if (tagName && !tags.includes(tagName)) {
|
|
102
|
+
categoriesWithCurrent = [
|
|
103
|
+
...categoriesWithCurrent,
|
|
104
|
+
{ label: 'Other', tags: [tagName] }
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
render(html`
|
|
108
|
+
<select @change=${event => renderTrait(el, { tagName: event.target.value, type: 'tag' })}>
|
|
109
|
+
${map(categoriesWithCurrent, cat => html`
|
|
110
|
+
<optgroup label="${cat.label}">
|
|
111
|
+
${map(cat.tags, tag => html`
|
|
112
|
+
<option value="${tag}" ?selected=${tagName === tag}>${tag}</option>
|
|
113
|
+
`)}
|
|
114
|
+
</optgroup>
|
|
115
|
+
`)}
|
|
116
|
+
</select>
|
|
117
|
+
`, el)
|
|
118
|
+
} else if (opts.type === 'for') {
|
|
119
|
+
// Render "for" input, hide if not LABEL
|
|
120
|
+
const wrapper = el.closest('.gjs-trt-trait__wrp-for') as HTMLElement
|
|
121
|
+
if (tagName !== 'LABEL') {
|
|
122
|
+
if(wrapper) wrapper.style.display = 'none'
|
|
123
|
+
render(html``, el)
|
|
124
|
+
} else {
|
|
125
|
+
if(wrapper) wrapper.style.display = 'initial'
|
|
126
|
+
render(html`
|
|
127
|
+
<input type="text" placeholder="ID of input" value="${opts.forAttr || ''}"
|
|
128
|
+
@input=${event => renderTrait(el, { forAttr: (event.target as HTMLInputElement).value, tagName, type: 'for' })}
|
|
129
|
+
>
|
|
130
|
+
`, el)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
81
133
|
}
|
|
134
|
+
|
|
82
135
|
function doRenderCurrent(el: HTMLElement) {
|
|
83
|
-
|
|
136
|
+
renderTrait(el, { tagName: editor.getSelected()?.get('tagName') || '', type: 'tag' })
|
|
137
|
+
}
|
|
138
|
+
function doRenderCurrentFor(el: HTMLElement) {
|
|
139
|
+
const selected = editor.getSelected()
|
|
140
|
+
renderTrait(el, {
|
|
141
|
+
tagName: selected?.get('tagName') || '',
|
|
142
|
+
forAttr: selected?.getAttributes().for || '',
|
|
143
|
+
type: 'for'
|
|
144
|
+
})
|
|
84
145
|
}
|
|
85
146
|
|
|
86
147
|
// Add semantic traits
|
|
87
148
|
// inspired by https://github.com/olivmonnier/grapesjs-plugin-header/blob/master/src/components.js
|
|
88
149
|
editor.TraitManager.addType('tag-name', {
|
|
89
|
-
createInput({ trait }) {
|
|
90
|
-
// Create a new element container and add some content
|
|
150
|
+
createInput({ trait, component }) {
|
|
91
151
|
const el = document.createElement('div')
|
|
92
|
-
// update the UI when a page is added/renamed/removed
|
|
93
152
|
editor.on('page', () => doRenderCurrent(el))
|
|
94
153
|
doRenderCurrent(el)
|
|
95
|
-
// this will be the element passed to onEvent and onUpdate
|
|
96
154
|
return el
|
|
97
155
|
},
|
|
98
|
-
// Update the component based on UI changes
|
|
99
|
-
// `elInput` is the result HTMLElement you get from `createInput`
|
|
100
156
|
onEvent({ elInput, component, event }) {
|
|
101
|
-
const value =
|
|
102
|
-
if(component.get('tagName').toUpperCase()
|
|
103
|
-
// Already done
|
|
104
|
-
} else {
|
|
157
|
+
const value = (event.target as HTMLSelectElement).value
|
|
158
|
+
if(component.get('tagName').toUpperCase() !== value.toUpperCase()){
|
|
105
159
|
component.set('tagName', value)
|
|
106
160
|
}
|
|
107
161
|
},
|
|
108
|
-
// Update UI on the component change
|
|
109
162
|
onUpdate({ elInput, component }) {
|
|
110
163
|
const tagName = component.get('tagName')
|
|
111
|
-
|
|
164
|
+
renderTrait(elInput, { tagName, type: 'tag' })
|
|
165
|
+
},
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
editor.TraitManager.addType('for-trait', {
|
|
169
|
+
createInput({ trait, component }) {
|
|
170
|
+
const el = document.createElement('div')
|
|
171
|
+
editor.on('page', () => doRenderCurrentFor(el))
|
|
172
|
+
editor.on('component:update', () => doRenderCurrentFor(el))
|
|
173
|
+
doRenderCurrentFor(el)
|
|
174
|
+
return el
|
|
175
|
+
},
|
|
176
|
+
onEvent({ elInput, component, event }) {
|
|
177
|
+
const value = (event.target as HTMLInputElement).value
|
|
178
|
+
if(component.getAttributes().for !== value){
|
|
179
|
+
component.setAttributes({ for: value })
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
onUpdate({ elInput, component }) {
|
|
183
|
+
const forAttr = component.getAttributes().for || ''
|
|
184
|
+
const tagName = component.get('tagName') || ''
|
|
185
|
+
renderTrait(elInput, { forAttr, tagName, type: 'for' })
|
|
112
186
|
},
|
|
113
187
|
})
|
|
114
188
|
}
|
|
@@ -15,21 +15,25 @@
|
|
|
15
15
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
import { Component, Editor } from 'grapesjs'
|
|
19
|
+
|
|
18
20
|
export const cmdPromptAddSymbol = 'symbol-prompt-add'
|
|
19
21
|
|
|
20
|
-
export default (editor
|
|
21
|
-
function getNext(prefix) {
|
|
22
|
+
export default (editor: Editor) => {
|
|
23
|
+
function getNext(prefix: string) {
|
|
22
24
|
let idx = 1
|
|
23
|
-
while(
|
|
25
|
+
while(
|
|
26
|
+
editor.Components.getSymbols()
|
|
27
|
+
.find((symbol: Component) => symbol.get('custom-name') === prefix + idx)
|
|
28
|
+
) {
|
|
24
29
|
idx++
|
|
25
30
|
}
|
|
26
31
|
return prefix + idx
|
|
27
32
|
}
|
|
28
33
|
editor.Commands.add(cmdPromptAddSymbol, {
|
|
29
|
-
run: (_
|
|
34
|
+
run: (_) => {
|
|
30
35
|
const label = prompt('Label', getNext('Symbol '))
|
|
31
|
-
|
|
32
|
-
editor.runCommand('symbols:add', { label, icon })
|
|
36
|
+
editor.runCommand('symbols:add', { label })
|
|
33
37
|
}
|
|
34
38
|
})
|
|
35
39
|
}
|
package/src/ts/client/index.ts
CHANGED
|
@@ -21,13 +21,11 @@
|
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { Component, ComponentView } from 'grapesjs'
|
|
25
24
|
import { DEV_MESSAGE } from '../constants'
|
|
26
25
|
import { ClientConfig } from './config'
|
|
27
26
|
import { ClientEvent } from './events'
|
|
28
27
|
import { initEditor, getEditor } from './grapesjs/index'
|
|
29
28
|
import { cmdPauseAutoSave } from './grapesjs/storage'
|
|
30
|
-
import { displayedToStored, storedToDisplayed } from './assetUrl'
|
|
31
29
|
|
|
32
30
|
// Expose API to calling app as window.silex
|
|
33
31
|
export * from './expose'
|
|
@@ -85,42 +83,6 @@ export async function start(options = {}): Promise<void> {
|
|
|
85
83
|
// Add default plugins
|
|
86
84
|
await config.addDefaultPlugins()
|
|
87
85
|
|
|
88
|
-
const domc = editor.DomComponents
|
|
89
|
-
const imgType = domc.getType('image')
|
|
90
|
-
domc.addType('image', {
|
|
91
|
-
...imgType,
|
|
92
|
-
view: {
|
|
93
|
-
...imgType.view,
|
|
94
|
-
onRender() {
|
|
95
|
-
const view = this as ComponentView
|
|
96
|
-
imgType.view.onRender && imgType.view.onRender.call(this) // call original
|
|
97
|
-
const el = view.el
|
|
98
|
-
const elImg = view.el as HTMLImageElement
|
|
99
|
-
const src = this.model.getAttributes().src
|
|
100
|
-
if (src && !src.startsWith('http')) {
|
|
101
|
-
elImg.src = storedToDisplayed(src, config.websiteId, config.storageId)
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
model: {
|
|
106
|
-
...imgType.model,
|
|
107
|
-
init() {
|
|
108
|
-
const model = this as Component
|
|
109
|
-
imgType.model.init && imgType.model.init.call(this) // call original
|
|
110
|
-
// Handle changes by the AssetManager
|
|
111
|
-
model.on('change', () => {
|
|
112
|
-
if(model.get('src')) {
|
|
113
|
-
const newSrc = displayedToStored(model.get('src'))
|
|
114
|
-
if(newSrc !== model.get('src')) {
|
|
115
|
-
model.set('src', newSrc)
|
|
116
|
-
model.view.render()
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
})
|
|
123
|
-
|
|
124
86
|
// Load the site
|
|
125
87
|
try {
|
|
126
88
|
editor.runCommand(cmdPauseAutoSave)
|
|
@@ -656,7 +656,7 @@ export default class GitlabConnector implements StorageConnector {
|
|
|
656
656
|
} while (page <= totalPages)
|
|
657
657
|
|
|
658
658
|
return projects
|
|
659
|
-
.filter(p => p.name.startsWith(this.options.repoPrefix))
|
|
659
|
+
.filter(p => p.name.startsWith(this.options.repoPrefix) && !p.name.includes('-deleted-'))
|
|
660
660
|
.map(p => ({
|
|
661
661
|
websiteId: p.id,
|
|
662
662
|
name: p.name.replace(this.options.repoPrefix, ''),
|
|
@@ -826,75 +826,10 @@ export default class GitlabConnector implements StorageConnector {
|
|
|
826
826
|
await this.callApi({
|
|
827
827
|
session,
|
|
828
828
|
path: `api/v4/projects/${websiteId}`,
|
|
829
|
-
method: 'DELETE'
|
|
829
|
+
method: 'DELETE',
|
|
830
830
|
})
|
|
831
|
-
//// Load the meta repo data
|
|
832
|
-
//const file = await this.callApi(session, `api/v4/projects/${this.getMetaRepoPath(session)}/repository/files/${this.options.metaRepoFile}`, 'GET', null, {
|
|
833
|
-
// ref: this.options.branch,
|
|
834
|
-
//})
|
|
835
|
-
//const metaRepo = JSON.parse(Buffer.from(file.content, 'base64').toString('utf8')) as MetaRepoFileContent
|
|
836
|
-
//const data = metaRepo.websites[websiteId]
|
|
837
|
-
//if(!data) throw new ApiError(`Website ${websiteId} not found`, 404)
|
|
838
|
-
//// Update or create the website meta data
|
|
839
|
-
//delete metaRepo.websites[websiteId]
|
|
840
|
-
//// Save the meta repo data
|
|
841
|
-
//const project = await this.callApi(session, `api/v4/projects/${this.getMetaRepoPath(session)}/repository/files/${this.options.metaRepoFile}`, 'PUT', {
|
|
842
|
-
// branch: this.options.branch,
|
|
843
|
-
// commit_message: `Delete meta data of ${data.meta.name} (${websiteId}) from Silex`,
|
|
844
|
-
// content: JSON.stringify(metaRepo),
|
|
845
|
-
//})
|
|
846
831
|
}
|
|
847
832
|
|
|
848
|
-
// async duplicateWebsite(session: GitlabSession, websiteId: string): Promise<void> {
|
|
849
|
-
// // Get the repo meta data
|
|
850
|
-
// const meta = await this.getWebsiteMeta(session, websiteId)
|
|
851
|
-
// // List all the repository files
|
|
852
|
-
// const files = await this.ls({
|
|
853
|
-
// session,
|
|
854
|
-
// websiteId,
|
|
855
|
-
// recursive: true,
|
|
856
|
-
// })
|
|
857
|
-
|
|
858
|
-
// // Create a new repo
|
|
859
|
-
// const newId = await this.createWebsite(session, {
|
|
860
|
-
// ...meta,
|
|
861
|
-
// name: meta.name + ' Copy ' + new Date().toISOString().replace(/T.*/, '') + ' ' + Math.random().toString(36).substring(2, 4),
|
|
862
|
-
// })
|
|
863
|
-
// // Upload all files
|
|
864
|
-
// const actions: GitlabAction[] = []
|
|
865
|
-
// for (const file of files.keys()) {
|
|
866
|
-
// const content = await this.readFile(session, websiteId, file)
|
|
867
|
-
// // From buffer to string
|
|
868
|
-
// const contentStr = content.toString('base64')
|
|
869
|
-
// const path = encodeURIComponent(file)
|
|
870
|
-
// switch (file) {
|
|
871
|
-
// case WEBSITE_DATA_FILE:
|
|
872
|
-
// actions.push({
|
|
873
|
-
// action: 'update',
|
|
874
|
-
// file_path: path,
|
|
875
|
-
// content: contentStr,
|
|
876
|
-
// })
|
|
877
|
-
// break
|
|
878
|
-
// default:
|
|
879
|
-
// actions.push({
|
|
880
|
-
// action: 'create',
|
|
881
|
-
// file_path: path,
|
|
882
|
-
// content: contentStr,
|
|
883
|
-
// })
|
|
884
|
-
// }
|
|
885
|
-
// }
|
|
886
|
-
// // Perform a batch commit
|
|
887
|
-
// return this.callApi({
|
|
888
|
-
// session,
|
|
889
|
-
// path: `api/v4/projects/${newId}/repository/commits`,
|
|
890
|
-
// method: 'POST',
|
|
891
|
-
// requestBody: {
|
|
892
|
-
// branch: this.options.branch,
|
|
893
|
-
// commit_message: 'Update website data from Silex',
|
|
894
|
-
// actions,
|
|
895
|
-
// },
|
|
896
|
-
// })
|
|
897
|
-
// }
|
|
898
833
|
// Fork the repo
|
|
899
834
|
async duplicateWebsite(session: GitlabSession, websiteId: string): Promise<void> {
|
|
900
835
|
const meta = await this.getWebsiteMeta(session, websiteId)
|