saby-customizer 0.0.0-pre.27 → 0.0.0-pre.28
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/features/git-branch.js +223 -105
- package/lib/saby-lib/edo.js +11 -1
- package/lib/saby-lib/toolbar.js +66 -24
- package/material.js +2334 -494
- package/octicons.js +15 -0
- package/package.json +1 -1
- package/userscript.js +2 -1
package/features/git-branch.js
CHANGED
|
@@ -3,6 +3,187 @@ import { keysMapping, toolbar, PopupDialog, getListOfOpenCards, snackbar, contex
|
|
|
3
3
|
import { octicons } from 'saby-customizer/octicons.js'
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
/** Класс для управления данными карточки задачи */
|
|
7
|
+
class GitBranchCardData {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef GitCardData
|
|
11
|
+
* @property {string} [branchSubName] Имя ветки указанное пользователем
|
|
12
|
+
*/
|
|
13
|
+
/** @param {import('saby-customizer/lib.js').CardData & GitCardData} data Данные о задаче */
|
|
14
|
+
constructor(data) {
|
|
15
|
+
/** @type {import('saby-customizer/lib.js').CardData & GitCardData} Данные о задаче */
|
|
16
|
+
this.raw = {
|
|
17
|
+
id: data.id,
|
|
18
|
+
number: data.number,
|
|
19
|
+
branchSubName: data.branchSubName || data.number,
|
|
20
|
+
date: data.date,
|
|
21
|
+
name: data.name,
|
|
22
|
+
uuid: data.uuid,
|
|
23
|
+
url: data.url,
|
|
24
|
+
author: data.author,
|
|
25
|
+
milestones: data.milestones,
|
|
26
|
+
version: data.version,
|
|
27
|
+
description: data.description
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** @returns {string} Название регламента Задача/Ошибка и т.д. */
|
|
32
|
+
get name() {
|
|
33
|
+
return this.raw.name
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @returns {string} Заголовок для описания задачи */
|
|
37
|
+
get branchTitle() {
|
|
38
|
+
const { name } = this.raw
|
|
39
|
+
const docNumber = ' № ' + this.raw.number
|
|
40
|
+
const version = ' веха ' + this.raw.version
|
|
41
|
+
const date = ' от ' + this.raw.date
|
|
42
|
+
const author = ' ' + this.raw.author
|
|
43
|
+
|
|
44
|
+
return name + docNumber + version + date + author
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** @returns {string} Версия задачи (веха), выбранная пользователем */
|
|
48
|
+
get version() {
|
|
49
|
+
return this.raw.version
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Обновление выбранной версии и обновление карточки задачи
|
|
54
|
+
*
|
|
55
|
+
* @param {string} value Версия
|
|
56
|
+
*/
|
|
57
|
+
set version(value) {
|
|
58
|
+
if (this.raw.milestones && this.raw.milestones.includes(value)) {
|
|
59
|
+
this.raw.version = value
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** @returns {string} Часть имени ветки, зависящая от регламента задачи */
|
|
64
|
+
get branchType() {
|
|
65
|
+
return this.raw.name === 'Ошибка' ? 'bugfix' : 'feature'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** @returns {string} Часть имени ветки, определяемая пользователем */
|
|
69
|
+
get branchSubName() {
|
|
70
|
+
return this.raw.branchSubName
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Обновление доп. имени ветки и обновление карточки задачи
|
|
75
|
+
*
|
|
76
|
+
* @param {string} value Доп. имя ветки
|
|
77
|
+
*/
|
|
78
|
+
set branchSubName(value) {
|
|
79
|
+
this.raw.branchSubName = value || this.raw.number
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** @returns {string} Краткое описание задачи */
|
|
83
|
+
get description() {
|
|
84
|
+
return this.raw.description
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Обновление краткого описания и карточки задачи
|
|
89
|
+
*
|
|
90
|
+
* @param {string} value Доп. имя ветки
|
|
91
|
+
*/
|
|
92
|
+
set description(value) {
|
|
93
|
+
this.raw.description = value || ''
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** @returns {string[]} Список доступных вех (версий) */
|
|
97
|
+
get milestones() {
|
|
98
|
+
return this.raw.milestones
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** @returns {string} Ссылка на документ в отдельной вкладке */
|
|
102
|
+
get url() {
|
|
103
|
+
return this.raw.url
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Получение имени ветки с учетом выбора вехи и доп. имени ветки
|
|
108
|
+
*
|
|
109
|
+
* @returns {Promise<string>} Имя ветки
|
|
110
|
+
*/
|
|
111
|
+
async getBranchName() {
|
|
112
|
+
const userLogin = await context.userLogin
|
|
113
|
+
|
|
114
|
+
return `${this.version}/${this.branchType}/${userLogin}/${this.branchSubName}`
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Копирование ссылки на задачу */
|
|
118
|
+
copyLink() {
|
|
119
|
+
navigator.clipboard.writeText(this.raw.url)
|
|
120
|
+
snackbar.show(`Скопирована ссылка: ${this.raw.url}`)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Копирование имени ветки */
|
|
124
|
+
async copyBranchName() {
|
|
125
|
+
const branchName = await this.getBranchName()
|
|
126
|
+
|
|
127
|
+
navigator.clipboard.writeText(branchName)
|
|
128
|
+
snackbar.show(`Скопировано имя ветки: ${branchName}`)
|
|
129
|
+
|
|
130
|
+
await this.saveToHistory()
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Копирование описания для git commit */
|
|
134
|
+
async copyDescription() {
|
|
135
|
+
const description = this.branchTitle + '\n' +
|
|
136
|
+
this.raw.url + '\n' +
|
|
137
|
+
this.raw.description
|
|
138
|
+
|
|
139
|
+
navigator.clipboard.writeText(description)
|
|
140
|
+
snackbar.show(`Скопировано описание для git commit:\n${description}`)
|
|
141
|
+
|
|
142
|
+
await this.saveToHistory()
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Сохраняет данные в историю по карточкам для которых копировали имя ветки или описание */
|
|
146
|
+
async saveToHistory() {
|
|
147
|
+
const branchName = await this.getBranchName()
|
|
148
|
+
const gitBranchHistory = db.table('gitBranchHistory')
|
|
149
|
+
const historyOldData = await gitBranchHistory.get({
|
|
150
|
+
id: this.raw.id,
|
|
151
|
+
branch: branchName
|
|
152
|
+
})
|
|
153
|
+
const historyData = {
|
|
154
|
+
id: this.raw.id,
|
|
155
|
+
branch: branchName,
|
|
156
|
+
version: this.version,
|
|
157
|
+
useDate: new Date(),
|
|
158
|
+
data: this.raw
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (historyOldData) {
|
|
162
|
+
await gitBranchHistory.update(historyOldData.pk, historyData)
|
|
163
|
+
} else {
|
|
164
|
+
await gitBranchHistory.add(historyData)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Восстановление из истории последнего сохраненного состояния карточки */
|
|
169
|
+
async restoreFromHistory() {
|
|
170
|
+
const gitBranchHistory = db.table('gitBranchHistory')
|
|
171
|
+
const historyData = await gitBranchHistory
|
|
172
|
+
.where({ id: this.raw.id })
|
|
173
|
+
.reverse()
|
|
174
|
+
.sortBy('useDate')
|
|
175
|
+
|
|
176
|
+
if (historyData && historyData.length > 0) {
|
|
177
|
+
const [{ data: { version, branchSubName, description } }] = historyData
|
|
178
|
+
|
|
179
|
+
this.version = version
|
|
180
|
+
this.branchSubName = branchSubName
|
|
181
|
+
this.description = description
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
|
|
6
187
|
/** Карточка со сведениями о задаче для копирования ветки */
|
|
7
188
|
class GitBranchCard extends oom.extends(HTMLElement) {
|
|
8
189
|
|
|
@@ -105,28 +286,11 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
105
286
|
return String(Math.min(Math.max(1, rows), 5))
|
|
106
287
|
}
|
|
107
288
|
|
|
108
|
-
|
|
109
|
-
* @typedef GitCardData
|
|
110
|
-
* @property {string} [branchSubName] Имя ветки указанное пользователем
|
|
111
|
-
*/
|
|
112
|
-
/** @type {import('saby-customizer/lib.js').CardData & GitCardData} Данные о задаче */
|
|
113
|
-
data = {
|
|
114
|
-
id: this.options.data.id,
|
|
115
|
-
number: this.options.data.number,
|
|
116
|
-
branchSubName: this.options.data.branchSubName || this.options.data.number,
|
|
117
|
-
date: this.options.data.date,
|
|
118
|
-
name: this.options.data.name,
|
|
119
|
-
uuid: this.options.data.uuid,
|
|
120
|
-
url: this.options.data.url,
|
|
121
|
-
author: this.options.data.author,
|
|
122
|
-
milestones: this.options.data.milestones,
|
|
123
|
-
version: this.options.data.version,
|
|
124
|
-
description: this.options.data.description
|
|
125
|
-
}
|
|
289
|
+
data = new GitBranchCardData(this.options.data)
|
|
126
290
|
|
|
127
291
|
elements = {
|
|
128
292
|
/** @type {HTMLSpanElement} */
|
|
129
|
-
cardTitle: oom.span(this.branchTitle, { title: this.branchTitle }).dom,
|
|
293
|
+
cardTitle: oom.span(this.data.branchTitle, { title: this.data.branchTitle }).dom,
|
|
130
294
|
/** @type {import('@material/mwc-icon-button').IconButton} */// @ts-ignore
|
|
131
295
|
copyLinkButton: oom.mwcIconButton({
|
|
132
296
|
title: 'Скопировать ссылку',
|
|
@@ -167,7 +331,7 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
167
331
|
/** @type {HTMLSpanElement} */
|
|
168
332
|
branchNamePart: oom.span({
|
|
169
333
|
class: 'branch-part'
|
|
170
|
-
}, `/${this.branchType}/***/`).dom,
|
|
334
|
+
}, `/${this.data.branchType}/***/`).dom,
|
|
171
335
|
/** @type {HTMLSpanElement} */
|
|
172
336
|
branchSubName: oom.span({
|
|
173
337
|
title: this.data.branchSubName,
|
|
@@ -199,17 +363,6 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
199
363
|
}).dom
|
|
200
364
|
}
|
|
201
365
|
|
|
202
|
-
/** @returns {string} Заголовок для описания задачи */
|
|
203
|
-
get branchTitle() {
|
|
204
|
-
const { name } = this.data
|
|
205
|
-
const docNumber = ' № ' + this.data.number
|
|
206
|
-
const version = ' веха ' + this.version
|
|
207
|
-
const date = ' от ' + this.data.date
|
|
208
|
-
const author = ' ' + this.data.author
|
|
209
|
-
|
|
210
|
-
return name + docNumber + version + date + author
|
|
211
|
-
}
|
|
212
|
-
|
|
213
366
|
/** @returns {string} Версия задачи (веха), выбранная пользователем */
|
|
214
367
|
get version() {
|
|
215
368
|
return this.data.version
|
|
@@ -221,18 +374,13 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
221
374
|
* @param {string} value Версия
|
|
222
375
|
*/
|
|
223
376
|
set version(value) {
|
|
224
|
-
|
|
225
|
-
|
|
377
|
+
this.data.version = value
|
|
378
|
+
if (this.data.version === value) {
|
|
226
379
|
this.elements.branchButton.textContent = this.data.version
|
|
227
|
-
this.elements.cardTitle.textContent = this.branchTitle
|
|
380
|
+
this.elements.cardTitle.textContent = this.data.branchTitle
|
|
228
381
|
}
|
|
229
382
|
}
|
|
230
383
|
|
|
231
|
-
/** @returns {string} Часть имени ветки, зависящая от регламента задачи */
|
|
232
|
-
get branchType() {
|
|
233
|
-
return this.data.name === 'Ошибка' ? 'bugfix' : 'feature'
|
|
234
|
-
}
|
|
235
|
-
|
|
236
384
|
/** @returns {string} Часть имени ветки, определяемая пользователем */
|
|
237
385
|
get branchSubName() {
|
|
238
386
|
return this.data.branchSubName
|
|
@@ -244,7 +392,7 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
244
392
|
* @param {string} value Доп. имя ветки
|
|
245
393
|
*/
|
|
246
394
|
set branchSubName(value) {
|
|
247
|
-
this.data.branchSubName = value
|
|
395
|
+
this.data.branchSubName = value
|
|
248
396
|
oom(this.elements.branchSubName, { innerHTML: '', title: this.data.branchSubName }, this.data.branchSubName)
|
|
249
397
|
if (this.elements.branchSubNameTextfield.value !== this.data.branchSubName) {
|
|
250
398
|
this.elements.branchSubNameTextfield.value = this.data.branchSubName
|
|
@@ -262,7 +410,7 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
262
410
|
* @param {string} value Доп. имя ветки
|
|
263
411
|
*/
|
|
264
412
|
set description(value) {
|
|
265
|
-
this.data.description = value
|
|
413
|
+
this.data.description = value
|
|
266
414
|
this.elements.description.title = this.data.description
|
|
267
415
|
this.elements.description.textContent = this.data.description
|
|
268
416
|
if (this.elements.descriptionTextarea.value !== this.data.description) {
|
|
@@ -305,7 +453,7 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
305
453
|
async updateBranchNamePart() {
|
|
306
454
|
const userLogin = await context.userLogin
|
|
307
455
|
|
|
308
|
-
this.elements.branchNamePart.textContent = `/${this.branchType}/${userLogin}/`
|
|
456
|
+
this.elements.branchNamePart.textContent = `/${this.data.branchType}/${userLogin}/`
|
|
309
457
|
}
|
|
310
458
|
|
|
311
459
|
/** Открывает форму редактирования редактирование описания для коммита */
|
|
@@ -344,85 +492,29 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
344
492
|
}
|
|
345
493
|
}
|
|
346
494
|
|
|
347
|
-
/**
|
|
348
|
-
* Получение имени ветки с учетом выбора вехи и доп. имени ветки
|
|
349
|
-
*
|
|
350
|
-
* @returns {Promise<string>} Имя ветки
|
|
351
|
-
*/
|
|
352
|
-
async getBranchName() {
|
|
353
|
-
const userLogin = await context.userLogin
|
|
354
|
-
|
|
355
|
-
return `${this.version}/${this.branchType}/${userLogin}/${this.branchSubName}`
|
|
356
|
-
}
|
|
357
|
-
|
|
358
495
|
/** Копирование ссылки на задачу */
|
|
359
496
|
copyLink() {
|
|
360
|
-
|
|
361
|
-
snackbar.show(`Скопирована ссылка: ${this.data.url}`)
|
|
497
|
+
this.data.copyLink()
|
|
362
498
|
}
|
|
363
499
|
|
|
364
500
|
/** Копирование имени ветки */
|
|
365
501
|
async copyBranchName() {
|
|
366
502
|
if (this.elements.branchSubNameTextfield.checkValidity()) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
navigator.clipboard.writeText(branchName)
|
|
370
|
-
snackbar.show(`Скопировано имя ветки: ${branchName}`)
|
|
371
|
-
|
|
372
|
-
await this.saveToHistory()
|
|
503
|
+
await this.data.copyBranchName()
|
|
373
504
|
}
|
|
374
505
|
}
|
|
375
506
|
|
|
376
507
|
/** Копирование описания для git commit */
|
|
377
508
|
async copyDescription() {
|
|
378
|
-
|
|
379
|
-
this.data.url + '\n' +
|
|
380
|
-
this.description
|
|
381
|
-
|
|
382
|
-
navigator.clipboard.writeText(description)
|
|
383
|
-
snackbar.show(`Скопировано описание для git commit:\n${description}`)
|
|
384
|
-
|
|
385
|
-
await this.saveToHistory()
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/** Сохраняет данные в историю по карточкам для которых копировали имя ветки или описание */
|
|
389
|
-
async saveToHistory() {
|
|
390
|
-
const branchName = await this.getBranchName()
|
|
391
|
-
const gitBranchHistory = db.table('gitBranchHistory')
|
|
392
|
-
const historyOldData = await gitBranchHistory.get({
|
|
393
|
-
id: this.data.id,
|
|
394
|
-
branch: branchName
|
|
395
|
-
})
|
|
396
|
-
const historyData = {
|
|
397
|
-
id: this.data.id,
|
|
398
|
-
branch: branchName,
|
|
399
|
-
version: this.version,
|
|
400
|
-
useDate: new Date(),
|
|
401
|
-
data: this.data
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
if (historyOldData) {
|
|
405
|
-
await gitBranchHistory.update(historyOldData.pk, historyData)
|
|
406
|
-
} else {
|
|
407
|
-
await gitBranchHistory.add(historyData)
|
|
408
|
-
}
|
|
509
|
+
await this.data.copyDescription()
|
|
409
510
|
}
|
|
410
511
|
|
|
411
512
|
/** Восстановление из истории последнего сохраненного состояния карточки */
|
|
412
513
|
async restoreFromHistory() {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
.sortBy('useDate')
|
|
418
|
-
|
|
419
|
-
if (historyData && historyData.length > 0) {
|
|
420
|
-
const [{ data: { version, branchSubName, description } }] = historyData
|
|
421
|
-
|
|
422
|
-
this.version = version
|
|
423
|
-
this.branchSubName = branchSubName
|
|
424
|
-
this.description = description
|
|
425
|
-
}
|
|
514
|
+
await this.data.restoreFromHistory()
|
|
515
|
+
this.version = this.data.version
|
|
516
|
+
this.branchSubName = this.data.branchSubName
|
|
517
|
+
this.description = this.data.description
|
|
426
518
|
}
|
|
427
519
|
|
|
428
520
|
}
|
|
@@ -493,7 +585,33 @@ keysMapping['alt-KeyB'] = () => PopupDialog.toggle({
|
|
|
493
585
|
})
|
|
494
586
|
|
|
495
587
|
toolbar.addButton({
|
|
588
|
+
position: 'right',
|
|
496
589
|
title: 'Ветки для Git',
|
|
497
590
|
iconSVG: octicons['git-branch'].toSVG({ width: 24 }),
|
|
498
591
|
onclick: keysMapping['alt-KeyB']
|
|
499
592
|
})
|
|
593
|
+
|
|
594
|
+
toolbar.addButton({
|
|
595
|
+
position: 'top',
|
|
596
|
+
title: 'Скопировать имя ветки для Git',
|
|
597
|
+
iconSVG: octicons['git-branch'].toSVG({ width: 24 }),
|
|
598
|
+
onclick: card => {
|
|
599
|
+
const gitCard = new GitBranchCardData(card.data)
|
|
600
|
+
|
|
601
|
+
gitCard.restoreFromHistory()
|
|
602
|
+
.then(() => gitCard.copyBranchName().catch(console.error))
|
|
603
|
+
.catch(console.error)
|
|
604
|
+
}
|
|
605
|
+
})
|
|
606
|
+
toolbar.addButton({
|
|
607
|
+
position: 'top',
|
|
608
|
+
title: 'Скопировать описание для Git коммита',
|
|
609
|
+
iconSVG: octicons['git-commit'].toSVG({ width: 24 }),
|
|
610
|
+
onclick: card => {
|
|
611
|
+
const gitCard = new GitBranchCardData(card.data)
|
|
612
|
+
|
|
613
|
+
gitCard.restoreFromHistory()
|
|
614
|
+
.then(() => gitCard.copyDescription().catch(console.error))
|
|
615
|
+
.catch(console.error)
|
|
616
|
+
}
|
|
617
|
+
})
|
package/lib/saby-lib/edo.js
CHANGED
|
@@ -79,9 +79,15 @@ function parseRichEditorJSON(json) {
|
|
|
79
79
|
* @property {string} version Ближайшая версия
|
|
80
80
|
* @property {string} description Краткий текст описания задачи
|
|
81
81
|
*/
|
|
82
|
+
/**
|
|
83
|
+
* @typedef Card Экземпляр карточки документа
|
|
84
|
+
* @property {HTMLElement} element DOM элемент карточки
|
|
85
|
+
* @property {CardData} data Данные карточки
|
|
86
|
+
*/
|
|
82
87
|
/**
|
|
83
88
|
* @typedef OpenCardsFilter Фильтры для выборки документов
|
|
84
89
|
* @property {Array<string>} [names] Фильтр по названию документа
|
|
90
|
+
* @property {string} [id] Идентификатор документа
|
|
85
91
|
* @property {boolean} [hasVersion] Документ включен хотя бы в 1 веху
|
|
86
92
|
* @property {boolean} [duplicates] Показать/скрыть из ответа документы которые открыты дважды
|
|
87
93
|
*/
|
|
@@ -89,7 +95,7 @@ function parseRichEditorJSON(json) {
|
|
|
89
95
|
* Собирает из верстки страницы список открытых в данный момент карточек документов ЭДО
|
|
90
96
|
*
|
|
91
97
|
* @param {OpenCardsFilter} [filter] Параметры фильтрации документов
|
|
92
|
-
* @returns {Array<
|
|
98
|
+
* @returns {Array<Card>} Список открытых карточке документов
|
|
93
99
|
*/
|
|
94
100
|
export function getListOfOpenCards(filter = {}) {
|
|
95
101
|
const cardNodes = document.querySelectorAll('.edo3-Dialog')
|
|
@@ -118,6 +124,10 @@ export function getListOfOpenCards(filter = {}) {
|
|
|
118
124
|
description: ''
|
|
119
125
|
}
|
|
120
126
|
|
|
127
|
+
if (filter.id && filter.id !== data.id) {
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
|
|
121
131
|
if (data && (filter.duplicates || !exists.includes(data.id))) {
|
|
122
132
|
const milestonesRS = record.get('РП.ВехаДокумента') || []
|
|
123
133
|
|
package/lib/saby-lib/toolbar.js
CHANGED
|
@@ -2,26 +2,48 @@ import { oom } from '@notml/core'
|
|
|
2
2
|
import { getListOfOpenCards } from './edo.js'
|
|
3
3
|
|
|
4
4
|
const { MutationObserver } = window
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
/**
|
|
6
|
+
* @typedef ToolbarContainerOptions Опции по умолчанию для панели
|
|
7
|
+
* @property {boolean} global Признак глобальной панели
|
|
8
|
+
* @property {import('saby-customizer/lib.js').Card} [card] Ссылка на экземпляр карточки задачи
|
|
9
|
+
* @property {string} [position='right'] Положение панели на сайте right|top
|
|
10
|
+
*/
|
|
11
|
+
/** @type {ToolbarContainerOptions} */
|
|
12
|
+
const optionsDefaults = { global: false, card: null, position: 'right' }
|
|
13
|
+
|
|
14
|
+
/** Класс контейнера для расширения панели сайта дополнительными кнопками */
|
|
15
|
+
class ToolbarContainer extends oom.extends(HTMLElement, optionsDefaults) {
|
|
9
16
|
|
|
10
17
|
static tagName = 'saby-customizer-toolbar'
|
|
11
18
|
static style = oom.style({
|
|
12
|
-
'
|
|
13
|
-
|
|
19
|
+
'display': 'flex',
|
|
20
|
+
'alignItems': 'center',
|
|
21
|
+
'saby-customizer-toolbar.right': {
|
|
22
|
+
flexDirection: 'column',
|
|
23
|
+
marginBottom: '6px'
|
|
24
|
+
},
|
|
25
|
+
'saby-customizer-toolbar.top': {
|
|
26
|
+
marginRight: '8px'
|
|
14
27
|
},
|
|
15
28
|
'.button': {
|
|
29
|
+
padding: '4px',
|
|
16
30
|
color: 'var(--secondary_icon-color)',
|
|
17
31
|
fill: 'var(--secondary_icon-color)',
|
|
18
32
|
cursor: 'pointer',
|
|
19
|
-
height: '32px',
|
|
20
|
-
width: '32px',
|
|
21
33
|
display: 'flex',
|
|
22
34
|
justifyContent: 'center',
|
|
23
35
|
alignItems: 'center'
|
|
24
36
|
},
|
|
37
|
+
'saby-customizer-toolbar.right .button': {
|
|
38
|
+
height: '32px',
|
|
39
|
+
width: '32px',
|
|
40
|
+
marginBottom: '4px'
|
|
41
|
+
},
|
|
42
|
+
'saby-customizer-toolbar.top .button': {
|
|
43
|
+
height: '20px',
|
|
44
|
+
width: '20px',
|
|
45
|
+
marginRight: '4px'
|
|
46
|
+
},
|
|
25
47
|
'.button:hover': {
|
|
26
48
|
color: 'var(--link_hover_text-color)',
|
|
27
49
|
fill: 'var(--link_hover_text-color)',
|
|
@@ -34,6 +56,7 @@ class ToolbarContainer extends oom.extends(HTMLElement, { global: false }) {
|
|
|
34
56
|
|
|
35
57
|
/**
|
|
36
58
|
* @typedef ButtonOptions
|
|
59
|
+
* @property {string} [position='right'] Позиция панели в которой отображается кнопка
|
|
37
60
|
* @property {string} title Всплывающая подсказка на кнопке
|
|
38
61
|
* @property {string} iconSVG Верстка иконки в формате SVG
|
|
39
62
|
* @property {Function} onclick Обработчик клика на иконку
|
|
@@ -51,11 +74,12 @@ class ToolbarContainer extends oom.extends(HTMLElement, { global: false }) {
|
|
|
51
74
|
static observer = null
|
|
52
75
|
|
|
53
76
|
/**
|
|
54
|
-
* Регистрирует новую общую кнопку в
|
|
77
|
+
* Регистрирует новую общую кнопку в панели сайта
|
|
55
78
|
*
|
|
56
79
|
* @param {ButtonOptions} options Опции кнопки
|
|
57
80
|
*/
|
|
58
81
|
static addButton(options) {
|
|
82
|
+
options = Object.assign({ position: 'right' }, options)
|
|
59
83
|
this.buttons.push(options)
|
|
60
84
|
|
|
61
85
|
this.containers.forEach(container => container.addButton(options))
|
|
@@ -70,7 +94,7 @@ class ToolbarContainer extends oom.extends(HTMLElement, { global: false }) {
|
|
|
70
94
|
}
|
|
71
95
|
|
|
72
96
|
/**
|
|
73
|
-
* Добавляет в вертску сайта глобальный контейнер в
|
|
97
|
+
* Добавляет в вертску сайта глобальный контейнер в панели для добавления кнопок
|
|
74
98
|
*/
|
|
75
99
|
static addGlobalContainer() {
|
|
76
100
|
const sabyPageRightPanel = document.querySelector('.sabyPage-MainLayout__rightPanel .sabyPage-MainLayout__wrapper')
|
|
@@ -81,7 +105,7 @@ class ToolbarContainer extends oom.extends(HTMLElement, { global: false }) {
|
|
|
81
105
|
}
|
|
82
106
|
}
|
|
83
107
|
|
|
84
|
-
/** Регистрирует обработчик для поиска открытых задач и добавления в них
|
|
108
|
+
/** Регистрирует обработчик для поиска открытых задач и добавления в них панели */
|
|
85
109
|
static registerTaskPanelWatcher() {
|
|
86
110
|
const popupContainer = document.getElementById('popup')
|
|
87
111
|
|
|
@@ -95,10 +119,11 @@ class ToolbarContainer extends oom.extends(HTMLElement, { global: false }) {
|
|
|
95
119
|
static addTaskPanelContainer() {
|
|
96
120
|
const openTaskList = getListOfOpenCards({ duplicates: true })
|
|
97
121
|
|
|
98
|
-
openTaskList.forEach(
|
|
99
|
-
const rightPanel = element.querySelector('.controls-StackTemplate__rightPanel .sabyPage-MainLayout__wrapper') ||
|
|
122
|
+
openTaskList.forEach(card => {
|
|
123
|
+
const rightPanel = card.element.querySelector('.controls-StackTemplate__rightPanel .sabyPage-MainLayout__wrapper') ||
|
|
100
124
|
// Кнопки для всплывающий панелей в карточке открытой в отдельной вкладке
|
|
101
|
-
element.querySelector('.controls-StackTemplate__rightPanel .sabyPage-widgets__wrapper')
|
|
125
|
+
card.element.querySelector('.controls-StackTemplate__rightPanel .sabyPage-widgets__wrapper')
|
|
126
|
+
const topPanel = card.element.querySelector('.edo3-Dialog__head-firstLine-buttons')
|
|
102
127
|
|
|
103
128
|
if (rightPanel) {
|
|
104
129
|
const rightSidebar = rightPanel.querySelector('saby-customizer-toolbar')
|
|
@@ -107,6 +132,13 @@ class ToolbarContainer extends oom.extends(HTMLElement, { global: false }) {
|
|
|
107
132
|
rightPanel.prepend(new ToolbarContainer())
|
|
108
133
|
}
|
|
109
134
|
}
|
|
135
|
+
if (topPanel) {
|
|
136
|
+
const topSidebar = topPanel.querySelector('saby-customizer-toolbar')
|
|
137
|
+
|
|
138
|
+
if (!topSidebar) {
|
|
139
|
+
topPanel.prepend(new ToolbarContainer({ card, position: 'top' }))
|
|
140
|
+
}
|
|
141
|
+
}
|
|
110
142
|
})
|
|
111
143
|
}
|
|
112
144
|
|
|
@@ -114,10 +146,12 @@ class ToolbarContainer extends oom.extends(HTMLElement, { global: false }) {
|
|
|
114
146
|
// Атрибуты для игнорирования контейнера платформой wasaby
|
|
115
147
|
this.setAttribute('data-vdomignore', 'true')
|
|
116
148
|
this.setAttribute('contenteditable', 'true')
|
|
149
|
+
this.classList.add(this.options.position)
|
|
117
150
|
}
|
|
118
151
|
|
|
119
152
|
/** Будем запоминать все контейнеры для синхронизации кнопок */
|
|
120
153
|
connectedCallback() {
|
|
154
|
+
super.connectedCallback()
|
|
121
155
|
ToolbarContainer.containers.add(this)
|
|
122
156
|
ToolbarContainer.buttons.forEach(options => this.addButton(options))
|
|
123
157
|
}
|
|
@@ -133,22 +167,30 @@ class ToolbarContainer extends oom.extends(HTMLElement, { global: false }) {
|
|
|
133
167
|
}
|
|
134
168
|
|
|
135
169
|
/**
|
|
136
|
-
* Добавляет новую общую кнопку в текущий контейнер
|
|
170
|
+
* Добавляет новую общую кнопку в текущий контейнер панели
|
|
137
171
|
*
|
|
138
172
|
* @param {ButtonOptions} options Опции кнопки
|
|
139
173
|
*/
|
|
140
174
|
addButton(options) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
175
|
+
if (this.options.position === options.position) {
|
|
176
|
+
const button = oom.div({
|
|
177
|
+
class: 'button',
|
|
178
|
+
title: options.title,
|
|
179
|
+
onclick: () => {
|
|
180
|
+
const [card] = this.options.card
|
|
181
|
+
? getListOfOpenCards({ id: this.options.card.data.id })
|
|
182
|
+
: [null]
|
|
183
|
+
|
|
184
|
+
options.onclick(card)
|
|
185
|
+
}
|
|
186
|
+
})
|
|
146
187
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
188
|
+
if (options.iconSVG) {
|
|
189
|
+
button({ innerHTML: options.iconSVG })
|
|
190
|
+
}
|
|
150
191
|
|
|
151
|
-
|
|
192
|
+
oom(this, button)
|
|
193
|
+
}
|
|
152
194
|
}
|
|
153
195
|
|
|
154
196
|
}
|