saby-customizer 0.0.0-pre.19 → 0.0.0-pre.23
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 +287 -145
- package/lib/database.js +4 -1
- package/lib/saby-lib/cloud-statistic.js +1 -0
- package/lib/saby-lib/edo.js +21 -3
- package/lib/saby-lib/{right-sidebar.js → toolbar.js} +37 -35
- package/lib.js +1 -1
- package/material.js +122 -3250
- package/octicons.js +1 -48
- package/package.json +2 -2
- package/userscript.js +1 -1
package/features/git-branch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { oom } from '@notml/core'
|
|
2
|
-
import { keysMapping,
|
|
2
|
+
import { keysMapping, toolbar, PopupDialog, getListOfOpenCards, snackbar, context, db } from 'saby-customizer/lib.js'
|
|
3
3
|
import { octicons } from 'saby-customizer/octicons.js'
|
|
4
4
|
|
|
5
5
|
|
|
@@ -78,7 +78,8 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
78
78
|
fontSize: '14px',
|
|
79
79
|
whiteSpace: 'nowrap',
|
|
80
80
|
overflow: 'hidden',
|
|
81
|
-
textOverflow: 'ellipsis'
|
|
81
|
+
textOverflow: 'ellipsis',
|
|
82
|
+
flexGrow: '1'
|
|
82
83
|
},
|
|
83
84
|
'.description-textarea': {
|
|
84
85
|
width: '100%'
|
|
@@ -104,130 +105,198 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
104
105
|
return String(Math.min(Math.max(1, rows), 5))
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
onclick: () => this.editDescription()
|
|
126
|
-
}).dom
|
|
127
|
-
|
|
128
|
-
description = oom.span({
|
|
129
|
-
class: 'description',
|
|
130
|
-
title: this.options.data.description,
|
|
131
|
-
onclick: () => this.editDescription()
|
|
132
|
-
}, this.options.data.description).dom
|
|
133
|
-
|
|
134
|
-
/** @type {HTMLTextAreaElement} */// @ts-ignore
|
|
135
|
-
descriptionTextarea = oom.mwcTextarea({
|
|
136
|
-
class: 'description-textarea hide',
|
|
137
|
-
rows: GitBranchCard.maxRows(this.options.data.description),
|
|
138
|
-
label: 'Описание для git commit',
|
|
139
|
-
value: this.options.data.description,
|
|
140
|
-
oninput: () => {
|
|
141
|
-
this.descriptionTextarea.setAttribute('rows', GitBranchCard.maxRows(this.descriptionTextarea.value))
|
|
142
|
-
}
|
|
143
|
-
}).dom
|
|
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
|
+
}
|
|
144
126
|
|
|
145
|
-
|
|
146
|
-
|
|
127
|
+
elements = {
|
|
128
|
+
/** @type {HTMLSpanElement} */
|
|
129
|
+
cardTitle: oom.span(this.branchTitle, { title: this.branchTitle }).dom,
|
|
130
|
+
/** @type {import('@material/mwc-icon-button').IconButton} */// @ts-ignore
|
|
131
|
+
copyLinkButton: oom.mwcIconButton({
|
|
132
|
+
title: 'Скопировать ссылку',
|
|
133
|
+
class: 'icon_18',
|
|
134
|
+
innerHTML: octicons.link.toSVG({ width: 18 }),
|
|
135
|
+
onclick: () => this.copyLink()
|
|
136
|
+
}).dom,
|
|
137
|
+
/** @type {import('@material/mwc-icon-button').IconButton} */// @ts-ignore
|
|
138
|
+
descriptionEdit: oom.mwcIconButton({
|
|
139
|
+
title: 'Редактировать описание для git commit',
|
|
140
|
+
class: 'icon_18',
|
|
141
|
+
innerHTML: octicons.pencil.toSVG({ width: 18 }),
|
|
142
|
+
onclick: () => this.editDescription()
|
|
143
|
+
}).dom,
|
|
144
|
+
/** @type {HTMLSpanElement} */
|
|
145
|
+
description: oom.span({
|
|
146
|
+
class: 'description',
|
|
147
|
+
title: this.data.description,
|
|
148
|
+
onclick: () => this.editDescription()
|
|
149
|
+
}, this.data.description).dom,
|
|
150
|
+
/** @type {import('@material/mwc-textarea').TextArea} */// @ts-ignore
|
|
151
|
+
descriptionTextarea: oom.mwcTextarea({
|
|
152
|
+
class: 'description-textarea hide',
|
|
153
|
+
rows: GitBranchCard.maxRows(this.data.description),
|
|
154
|
+
label: 'Описание для git commit',
|
|
155
|
+
value: this.data.description,
|
|
156
|
+
oninput: () => this.oninputDescription()
|
|
157
|
+
}).dom,
|
|
158
|
+
/** @type {import('@material/mwc-menu').Menu} */// @ts-ignore
|
|
159
|
+
versions: this.data.milestones.reduce((mwcMenu, item) => {
|
|
160
|
+
return mwcMenu(oom.mwcListItem(item))
|
|
161
|
+
}, oom.mwcMenu({ fixed: true, activatable: true })).dom,
|
|
162
|
+
/** @type {HTMLDivElement} */// @ts-ignore
|
|
163
|
+
branchButton: oom.div({
|
|
164
|
+
class: 'version-button',
|
|
165
|
+
onclick: () => { this.elements.versions.open = true }
|
|
166
|
+
}, this.data.version).dom,
|
|
167
|
+
/** @type {HTMLSpanElement} */
|
|
168
|
+
branchNamePart: oom.span({
|
|
169
|
+
class: 'branch-part'
|
|
170
|
+
}, `/${this.branchType}/***/`).dom,
|
|
171
|
+
/** @type {HTMLSpanElement} */
|
|
172
|
+
branchSubName: oom.span({
|
|
173
|
+
title: this.data.branchSubName,
|
|
174
|
+
class: 'sub-name-button',
|
|
175
|
+
onclick: () => this.editBranchSubName()
|
|
176
|
+
}, this.data.branchSubName).dom,
|
|
177
|
+
/** @type {import('@material/mwc-textfield').TextField} */// @ts-ignore
|
|
178
|
+
branchSubNameTextfield: oom.mwcTextfield({
|
|
179
|
+
class: 'branch-sub-name hide',
|
|
180
|
+
value: this.data.branchSubName,
|
|
181
|
+
placeholder: this.data.branchSubName,
|
|
182
|
+
pattern: '^\\w+[\\w()-]*$',
|
|
183
|
+
validationmessage: 'Латинские буквы, цифры и _()-',
|
|
184
|
+
oninput: () => this.oninputBranchSubName(),
|
|
185
|
+
onblur: () => this.onblurBranchSubName()
|
|
186
|
+
}).dom,
|
|
187
|
+
/** @type {import('@material/mwc-icon-button').IconButton} */// @ts-ignore
|
|
188
|
+
copyBranchButton: oom.mwcIconButton({
|
|
189
|
+
title: 'Скопировать имя ветки',
|
|
190
|
+
class: 'primary-action',
|
|
191
|
+
innerHTML: octicons['git-branch'].toSVG({ width: 24 }),
|
|
192
|
+
onclick: () => this.copyBranchName().catch(console.error)
|
|
193
|
+
}).dom,
|
|
194
|
+
/** @type {import('@material/mwc-icon-button').IconButton} */// @ts-ignore
|
|
195
|
+
copyDescriptionButton: oom.mwcIconButton({
|
|
196
|
+
title: 'Скопировать описание',
|
|
197
|
+
innerHTML: octicons.copy.toSVG({ width: 24 }),
|
|
198
|
+
onclick: () => this.copyDescription().catch(console.error)
|
|
199
|
+
}).dom
|
|
200
|
+
}
|
|
147
201
|
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
150
209
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
this.
|
|
167
|
-
this.
|
|
168
|
-
this.
|
|
169
|
-
this.branchSubNameTextfield.select()
|
|
210
|
+
return name + docNumber + version + date + author
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** @returns {string} Версия задачи (веха), выбранная пользователем */
|
|
214
|
+
get version() {
|
|
215
|
+
return this.data.version
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Обновление выбранной версии и обновление карточки задачи
|
|
220
|
+
*
|
|
221
|
+
* @param {string} value Версия
|
|
222
|
+
*/
|
|
223
|
+
set version(value) {
|
|
224
|
+
if (this.data.milestones && this.data.milestones.includes(value)) {
|
|
225
|
+
this.data.version = value
|
|
226
|
+
this.elements.branchButton.textContent = this.data.version
|
|
227
|
+
this.elements.cardTitle.textContent = this.branchTitle
|
|
170
228
|
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/** @
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** @returns {string} Часть имени ветки, зависящая от регламента задачи */
|
|
232
|
+
get branchType() {
|
|
233
|
+
return this.data.name === 'Ошибка' ? 'bugfix' : 'feature'
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** @returns {string} Часть имени ветки, определяемая пользователем */
|
|
237
|
+
get branchSubName() {
|
|
238
|
+
return this.data.branchSubName
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Обновление доп. имени ветки и обновление карточки задачи
|
|
243
|
+
*
|
|
244
|
+
* @param {string} value Доп. имя ветки
|
|
245
|
+
*/
|
|
246
|
+
set branchSubName(value) {
|
|
247
|
+
this.data.branchSubName = value || this.data.number
|
|
248
|
+
oom(this.elements.branchSubName, { innerHTML: '', title: this.data.branchSubName }, this.data.branchSubName)
|
|
249
|
+
if (this.elements.branchSubNameTextfield.value !== this.data.branchSubName) {
|
|
250
|
+
this.elements.branchSubNameTextfield.value = this.data.branchSubName
|
|
187
251
|
}
|
|
188
|
-
}
|
|
252
|
+
}
|
|
189
253
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
onclick: () => this.copyBranchName().catch(console.error)
|
|
195
|
-
}).dom
|
|
254
|
+
/** @returns {string} Краткое описание задачи */
|
|
255
|
+
get description() {
|
|
256
|
+
return this.data.description
|
|
257
|
+
}
|
|
196
258
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Обновление краткого описания и карточки задачи
|
|
261
|
+
*
|
|
262
|
+
* @param {string} value Доп. имя ветки
|
|
263
|
+
*/
|
|
264
|
+
set description(value) {
|
|
265
|
+
this.data.description = value || ''
|
|
266
|
+
this.elements.description.title = this.data.description
|
|
267
|
+
this.elements.description.textContent = this.data.description
|
|
268
|
+
if (this.elements.descriptionTextarea.value !== this.data.description) {
|
|
269
|
+
this.elements.descriptionTextarea.value = this.data.description
|
|
270
|
+
}
|
|
271
|
+
oom(this.elements.descriptionTextarea, { rows: GitBranchCard.maxRows(this.data.description) })
|
|
272
|
+
}
|
|
202
273
|
|
|
203
274
|
template = () => {
|
|
204
|
-
this.versions.anchor = this.branchButton
|
|
205
|
-
this.versions.addEventListener('selected', (event) => {
|
|
206
|
-
this.version = this.milestones[event.detail.index]
|
|
207
|
-
this.cardTitle.textContent = this.getTitle()
|
|
208
|
-
this.branchButton.textContent = this.version
|
|
275
|
+
this.elements.versions.anchor = this.elements.branchButton
|
|
276
|
+
this.elements.versions.addEventListener('selected', (/** @type {CustomEvent<import('@material/mwc-list/mwc-list-foundation').ActionDetail>} */event) => {
|
|
277
|
+
this.version = this.data.milestones[event.detail.index]
|
|
209
278
|
})
|
|
210
279
|
|
|
211
280
|
this.updateBranchNamePart().catch(console.error)
|
|
212
281
|
|
|
213
282
|
return oom.div({ class: 'mdc-card' }, oom
|
|
214
|
-
.div({ class: 'title' }, this.cardTitle)
|
|
283
|
+
.div({ class: 'title' }, this.elements.cardTitle)
|
|
215
284
|
.div(oom
|
|
216
|
-
.a({ class: 'link' }, this.url, {
|
|
285
|
+
.a({ class: 'link' }, this.data.url, {
|
|
217
286
|
target: '_blank',
|
|
218
|
-
href: this.url
|
|
219
|
-
}), this.copyLinkButton)
|
|
287
|
+
href: this.data.url
|
|
288
|
+
}), this.elements.copyLinkButton)
|
|
220
289
|
.div({
|
|
221
290
|
class: 'description-line'
|
|
222
|
-
}, this.descriptionEdit, this.description, this.descriptionTextarea)
|
|
291
|
+
}, this.elements.descriptionEdit, this.elements.description, this.elements.descriptionTextarea)
|
|
223
292
|
.div({ class: 'branch-line' }, oom
|
|
224
293
|
.div({ class: 'branch' },
|
|
225
|
-
this.branchButton,
|
|
226
|
-
this.versions,
|
|
227
|
-
this.branchNamePart,
|
|
228
|
-
this.branchSubName,
|
|
229
|
-
this.branchSubNameTextfield)
|
|
230
|
-
.div({ class: 'actions' }, this.copyBranchButton, this.copyDescriptionButton)
|
|
294
|
+
this.elements.branchButton,
|
|
295
|
+
this.elements.versions,
|
|
296
|
+
this.elements.branchNamePart,
|
|
297
|
+
this.elements.branchSubName,
|
|
298
|
+
this.elements.branchSubNameTextfield)
|
|
299
|
+
.div({ class: 'actions' }, this.elements.copyBranchButton, this.elements.copyDescriptionButton)
|
|
231
300
|
)
|
|
232
301
|
)
|
|
233
302
|
}
|
|
@@ -236,64 +305,124 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
236
305
|
async updateBranchNamePart() {
|
|
237
306
|
const userLogin = await context.userLogin
|
|
238
307
|
|
|
239
|
-
this.branchNamePart.textContent = `/${this.branchType}/${userLogin}/`
|
|
308
|
+
this.elements.branchNamePart.textContent = `/${this.branchType}/${userLogin}/`
|
|
240
309
|
}
|
|
241
310
|
|
|
242
|
-
/**
|
|
311
|
+
/** Открывает форму редактирования редактирование описания для коммита */
|
|
243
312
|
editDescription() {
|
|
244
|
-
this.descriptionEdit.classList.toggle('hide')
|
|
245
|
-
this.description.classList.toggle('hide')
|
|
246
|
-
this.descriptionTextarea.classList.toggle('hide')
|
|
247
|
-
this.descriptionTextarea.focus()
|
|
313
|
+
this.elements.descriptionEdit.classList.toggle('hide')
|
|
314
|
+
this.elements.description.classList.toggle('hide')
|
|
315
|
+
this.elements.descriptionTextarea.classList.toggle('hide')
|
|
316
|
+
this.elements.descriptionTextarea.focus()
|
|
248
317
|
}
|
|
249
318
|
|
|
250
|
-
/**
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const { name } = this.options.data
|
|
255
|
-
const docNumber = ' № ' + this.options.data.number
|
|
256
|
-
const version = ' веха ' + this.version
|
|
257
|
-
const date = ' от ' + this.options.data.date
|
|
258
|
-
const author = ' ' + this.options.data.author
|
|
319
|
+
/** Обработка события при вводе текста в описание для расчета отображаемого кол-ва строк */
|
|
320
|
+
oninputDescription() {
|
|
321
|
+
this.description = this.elements.descriptionTextarea.value
|
|
322
|
+
}
|
|
259
323
|
|
|
260
|
-
|
|
324
|
+
/** Открывает форму редактирования доп. имени ветки */
|
|
325
|
+
editBranchSubName() {
|
|
326
|
+
this.elements.branchSubName.classList.toggle('hide')
|
|
327
|
+
this.elements.branchSubNameTextfield.classList.toggle('hide')
|
|
328
|
+
this.elements.branchSubNameTextfield.focus()
|
|
329
|
+
this.elements.branchSubNameTextfield.select()
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** Сохранение данных о доп. имени ветки при вводе */
|
|
333
|
+
oninputBranchSubName() {
|
|
334
|
+
if (this.elements.branchSubNameTextfield.checkValidity()) {
|
|
335
|
+
this.branchSubName = this.elements.branchSubNameTextfield.value
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** Скрывает поле ввода доп. имени ветки при потере фокуса */
|
|
340
|
+
onblurBranchSubName() {
|
|
341
|
+
if (this.elements.branchSubNameTextfield.checkValidity()) {
|
|
342
|
+
this.elements.branchSubName.classList.toggle('hide')
|
|
343
|
+
this.elements.branchSubNameTextfield.classList.toggle('hide')
|
|
344
|
+
}
|
|
261
345
|
}
|
|
262
346
|
|
|
263
347
|
/**
|
|
348
|
+
* Получение имени ветки с учетом выбора вехи и доп. имени ветки
|
|
349
|
+
*
|
|
264
350
|
* @returns {Promise<string>} Имя ветки
|
|
265
351
|
*/
|
|
266
352
|
async getBranchName() {
|
|
267
|
-
const branchSubName = this.branchSubNameTextfield.value || this.options.data.number
|
|
268
353
|
const userLogin = await context.userLogin
|
|
269
354
|
|
|
270
|
-
return `${this.version}/${this.branchType}/${userLogin}/${branchSubName}`
|
|
355
|
+
return `${this.version}/${this.branchType}/${userLogin}/${this.branchSubName}`
|
|
271
356
|
}
|
|
272
357
|
|
|
273
358
|
/** Копирование ссылки на задачу */
|
|
274
359
|
copyLink() {
|
|
275
|
-
navigator.clipboard.writeText(this.url)
|
|
276
|
-
snackbar.show(`Скопирована ссылка: ${this.url}`)
|
|
360
|
+
navigator.clipboard.writeText(this.data.url)
|
|
361
|
+
snackbar.show(`Скопирована ссылка: ${this.data.url}`)
|
|
277
362
|
}
|
|
278
363
|
|
|
279
364
|
/** Копирование имени ветки */
|
|
280
365
|
async copyBranchName() {
|
|
281
|
-
if (this.branchSubNameTextfield.checkValidity()) {
|
|
366
|
+
if (this.elements.branchSubNameTextfield.checkValidity()) {
|
|
282
367
|
const branchName = await this.getBranchName()
|
|
283
368
|
|
|
284
369
|
navigator.clipboard.writeText(branchName)
|
|
285
370
|
snackbar.show(`Скопировано имя ветки: ${branchName}`)
|
|
371
|
+
|
|
372
|
+
await this.saveToHistory()
|
|
286
373
|
}
|
|
287
374
|
}
|
|
288
375
|
|
|
289
376
|
/** Копирование описания для git commit */
|
|
290
|
-
copyDescription() {
|
|
291
|
-
const description = this.
|
|
292
|
-
this.url + '\n' +
|
|
293
|
-
this.
|
|
377
|
+
async copyDescription() {
|
|
378
|
+
const description = this.branchTitle + '\n' +
|
|
379
|
+
this.data.url + '\n' +
|
|
380
|
+
this.description
|
|
294
381
|
|
|
295
382
|
navigator.clipboard.writeText(description)
|
|
296
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
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** Восстановление из истории последнего сохраненного состояния карточки */
|
|
412
|
+
async restoreFromHistory() {
|
|
413
|
+
const gitBranchHistory = db.table('gitBranchHistory')
|
|
414
|
+
const historyData = await gitBranchHistory
|
|
415
|
+
.where({ id: this.options.data.id })
|
|
416
|
+
.reverse()
|
|
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
|
+
}
|
|
297
426
|
}
|
|
298
427
|
|
|
299
428
|
}
|
|
@@ -321,22 +450,35 @@ class GitBranchCardList extends oom.extends(HTMLElement) {
|
|
|
321
450
|
// .mwcTab({ label: 'Список задач' })
|
|
322
451
|
.mwcTab({ label: 'История задач' }))
|
|
323
452
|
|
|
324
|
-
|
|
325
|
-
names: ['Ошибка', 'Задача'],
|
|
326
|
-
hasVersion: true
|
|
327
|
-
})
|
|
328
|
-
.map(card => new GitBranchCard(card))
|
|
453
|
+
list = oom.div({ class: 'content' })
|
|
329
454
|
|
|
330
|
-
|
|
331
|
-
|
|
455
|
+
template = async () => {
|
|
456
|
+
// if (this.openTaskList.length === 0) {
|
|
457
|
+
// this.tabs({ activeindex: '1' })
|
|
458
|
+
// }
|
|
459
|
+
oom(this, this.tabs, this.list)
|
|
460
|
+
oom(this.list, oom.div({ class: 'empty' }, 'Загрузка ...'))
|
|
332
461
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
462
|
+
this.list({ innerHTML: '' }, await this.buildTaskList())
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/** @returns {Promise<HTMLElement|DocumentFragment>} Вернет готовый список задач с учетом аинхронной загрузки данных */
|
|
466
|
+
async buildTaskList() {
|
|
467
|
+
let taskTist = null
|
|
468
|
+
const openTaskList = (await getListOfOpenCards({
|
|
469
|
+
names: ['Ошибка', 'Задача'],
|
|
470
|
+
hasVersion: true
|
|
471
|
+
})).map(card => new GitBranchCard(card))
|
|
472
|
+
|
|
473
|
+
await Promise.all(openTaskList.map(card => card.restoreFromHistory()))
|
|
474
|
+
|
|
475
|
+
if (openTaskList.length > 0) {
|
|
476
|
+
taskTist = oom()(...openTaskList)
|
|
477
|
+
} else {
|
|
478
|
+
taskTist = oom.div({ class: 'empty' }, 'Открытых задач с вехой не найдено')
|
|
336
479
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}, this.openTaskListElement))
|
|
480
|
+
|
|
481
|
+
return taskTist.dom
|
|
340
482
|
}
|
|
341
483
|
|
|
342
484
|
}
|
|
@@ -350,7 +492,7 @@ keysMapping['alt-KeyB'] = () => PopupDialog.toggle({
|
|
|
350
492
|
Element: GitBranchCardList
|
|
351
493
|
})
|
|
352
494
|
|
|
353
|
-
|
|
495
|
+
toolbar.addButton({
|
|
354
496
|
title: 'Ветки для Git',
|
|
355
497
|
iconSVG: octicons['git-branch'].toSVG({ width: 24 }),
|
|
356
498
|
onclick: keysMapping['alt-KeyB']
|
package/lib/database.js
CHANGED
|
@@ -3,7 +3,10 @@ import { Dexie } from 'dexie'
|
|
|
3
3
|
const db = new Dexie('saby-customizer-database')
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
db.version(
|
|
6
|
+
db.version(2).stores({
|
|
7
|
+
settings: '&key',
|
|
8
|
+
gitBranchHistory: '++pk, &[id+branch], version, useDate'
|
|
9
|
+
})
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
export { db }
|
package/lib/saby-lib/edo.js
CHANGED
|
@@ -68,12 +68,22 @@ function parseRichEditorJSON(json) {
|
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* @typedef CardData Данные карточки документа
|
|
71
|
+
* @property {string} id Идентификатор документа
|
|
71
72
|
* @property {string} number Номер документа
|
|
73
|
+
* @property {string} date Дата создания документа
|
|
74
|
+
* @property {string} name Название регламента Задача/Ошибка и т.д.
|
|
75
|
+
* @property {string} uuid UUID документа (для открытия ссылки)
|
|
76
|
+
* @property {string} url Ссылка на документ в отдельной вкладке
|
|
77
|
+
* @property {string} author Автор документа
|
|
78
|
+
* @property {string[]} milestones Список доступных вех (версий)
|
|
79
|
+
* @property {string} version Ближайшая версия
|
|
80
|
+
* @property {string} description Краткий текст описания задачи
|
|
72
81
|
*/
|
|
73
82
|
/**
|
|
74
83
|
* @typedef OpenCardsFilter Фильтры для выборки документов
|
|
75
84
|
* @property {Array<string>} [names] Фильтр по названию документа
|
|
76
85
|
* @property {boolean} [hasVersion] Документ включен хотя бы в 1 веху
|
|
86
|
+
* @property {boolean} [duplicates] Показать/скрыть из ответа документы которые открыты дважды
|
|
77
87
|
*/
|
|
78
88
|
/**
|
|
79
89
|
* Собирает из верстки страницы список открытых в данный момент карточек документов ЭДО
|
|
@@ -84,6 +94,7 @@ function parseRichEditorJSON(json) {
|
|
|
84
94
|
export function getListOfOpenCards(filter = {}) {
|
|
85
95
|
const cardNodes = document.querySelectorAll('.edo3-Dialog')
|
|
86
96
|
const cards = []
|
|
97
|
+
const exists = []
|
|
87
98
|
|
|
88
99
|
for (const cardNode of Array.from(cardNodes)) {
|
|
89
100
|
// @ts-ignore
|
|
@@ -95,17 +106,24 @@ export function getListOfOpenCards(filter = {}) {
|
|
|
95
106
|
const { element } = control
|
|
96
107
|
const record = control?.options?.record
|
|
97
108
|
const data = record && {
|
|
109
|
+
id: record.get('@Документ'),
|
|
98
110
|
number: record.get('Номер'),
|
|
99
111
|
date: getStrDate(record.get('Дата')),
|
|
100
112
|
name: record.get('РП.Документ').get('Регламент').get('Название'),
|
|
101
113
|
uuid: record.get('РП.Документ').get('ИдентификаторПереписки'),
|
|
114
|
+
url: '',
|
|
102
115
|
author: record.get('ЛицоСоздал.Название') || record.get('Сотрудник.Название'),
|
|
103
116
|
milestones: [],
|
|
104
|
-
version: 'dev'
|
|
117
|
+
version: 'dev',
|
|
118
|
+
description: ''
|
|
105
119
|
}
|
|
106
120
|
|
|
107
|
-
if (data) {
|
|
108
|
-
const milestonesRS = record.get('РП.ВехаДокумента')
|
|
121
|
+
if (data && (filter.duplicates || !exists.includes(data.id))) {
|
|
122
|
+
const milestonesRS = record.get('РП.ВехаДокумента') || []
|
|
123
|
+
|
|
124
|
+
if (!filter.duplicates) {
|
|
125
|
+
exists.push(data.id)
|
|
126
|
+
}
|
|
109
127
|
|
|
110
128
|
data.name = replaceDocTypeName[data.name] || data.name
|
|
111
129
|
if (filter.names) {
|