saby-customizer 0.0.0-pre.16 → 0.0.0-pre.20
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 +324 -149
- package/lib/context.js +43 -0
- package/lib/database.js +4 -1
- package/lib/layout.js +42 -2
- package/lib/popup-dialog.js +5 -2
- package/lib/saby-lib/cloud-statistic.js +1 -0
- package/lib/saby-lib/edo.js +14 -2
- package/lib/saby-lib/right-sidebar.js +164 -0
- package/lib/saby-lib/rpc.js +19 -0
- package/lib.js +3 -0
- package/material.js +1004 -455
- package/octicons.js +31 -1
- package/package.json +11 -10
- package/third-party/material.js +1 -0
package/features/git-branch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { oom } from '@notml/core'
|
|
2
|
-
import {
|
|
2
|
+
import { keysMapping, rightSidebar, PopupDialog, getListOfOpenCards, snackbar, context, db } from 'saby-customizer/lib.js'
|
|
3
3
|
import { octicons } from 'saby-customizer/octicons.js'
|
|
4
4
|
|
|
5
5
|
|
|
@@ -9,9 +9,12 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
9
9
|
static tagName = 'sc-git-branch-сard'
|
|
10
10
|
static style = oom.style({
|
|
11
11
|
'display': 'flex',
|
|
12
|
-
'padding': '12px',
|
|
12
|
+
'padding': '12px 12px 0',
|
|
13
13
|
'width': '600px',
|
|
14
14
|
'background': 'var(--mdc-theme-background)',
|
|
15
|
+
'sc-git-branch-сard:last-child': {
|
|
16
|
+
paddingBottom: '12px'
|
|
17
|
+
},
|
|
15
18
|
'.mdc-card': {
|
|
16
19
|
padding: '12px',
|
|
17
20
|
minWidth: '0',
|
|
@@ -75,7 +78,8 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
75
78
|
fontSize: '14px',
|
|
76
79
|
whiteSpace: 'nowrap',
|
|
77
80
|
overflow: 'hidden',
|
|
78
|
-
textOverflow: 'ellipsis'
|
|
81
|
+
textOverflow: 'ellipsis',
|
|
82
|
+
flexGrow: '1'
|
|
79
83
|
},
|
|
80
84
|
'.description-textarea': {
|
|
81
85
|
width: '100%'
|
|
@@ -101,179 +105,320 @@ class GitBranchCard extends oom.extends(HTMLElement) {
|
|
|
101
105
|
return String(Math.min(Math.max(1, rows), 5))
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}).dom
|
|
123
|
-
|
|
124
|
-
description = oom.span({
|
|
125
|
-
class: 'description',
|
|
126
|
-
title: this.options.data.description,
|
|
127
|
-
onclick: () => this.editDescription()
|
|
128
|
-
}, this.options.data.description).dom
|
|
129
|
-
|
|
130
|
-
/** @type {HTMLTextAreaElement} */// @ts-ignore
|
|
131
|
-
descriptionTextarea = oom.mwcTextarea({
|
|
132
|
-
class: 'description-textarea hide',
|
|
133
|
-
rows: GitBranchCard.maxRows(this.options.data.description),
|
|
134
|
-
label: 'Описание для git commit',
|
|
135
|
-
value: this.options.data.description,
|
|
136
|
-
oninput: () => {
|
|
137
|
-
this.descriptionTextarea.setAttribute('rows', GitBranchCard.maxRows(this.descriptionTextarea.value))
|
|
138
|
-
}
|
|
139
|
-
}).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
|
+
}
|
|
140
126
|
|
|
141
|
-
|
|
142
|
-
|
|
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
|
+
onblur: event => this.saveBranchSubName(event)
|
|
185
|
+
}).dom,
|
|
186
|
+
/** @type {import('@material/mwc-icon-button').IconButton} */// @ts-ignore
|
|
187
|
+
copyBranchButton: oom.mwcIconButton({
|
|
188
|
+
title: 'Скопировать имя ветки',
|
|
189
|
+
class: 'primary-action',
|
|
190
|
+
innerHTML: octicons['git-branch'].toSVG({ width: 24 }),
|
|
191
|
+
onclick: () => this.copyBranchName().catch(console.error)
|
|
192
|
+
}).dom,
|
|
193
|
+
/** @type {import('@material/mwc-icon-button').IconButton} */// @ts-ignore
|
|
194
|
+
copyDescriptionButton: oom.mwcIconButton({
|
|
195
|
+
title: 'Скопировать описание',
|
|
196
|
+
innerHTML: octicons.copy.toSVG({ width: 24 }),
|
|
197
|
+
onclick: () => this.copyDescription().catch(console.error)
|
|
198
|
+
}).dom
|
|
199
|
+
}
|
|
143
200
|
|
|
144
|
-
|
|
145
|
-
|
|
201
|
+
/** @returns {string} Заголовок для описания задачи */
|
|
202
|
+
get branchTitle() {
|
|
203
|
+
const { name } = this.data
|
|
204
|
+
const docNumber = ' № ' + this.data.number
|
|
205
|
+
const version = ' веха ' + this.version
|
|
206
|
+
const date = ' от ' + this.data.date
|
|
207
|
+
const author = ' ' + this.data.author
|
|
146
208
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
this.
|
|
163
|
-
this.
|
|
164
|
-
this.
|
|
165
|
-
this.branchSubNameTextfield.select()
|
|
166
|
-
}
|
|
167
|
-
}, this.options.data.number).dom
|
|
168
|
-
|
|
169
|
-
/** @type {HTMLInputElement} */// @ts-ignore
|
|
170
|
-
branchSubNameTextfield = oom.mwcTextfield({
|
|
171
|
-
class: 'branch-sub-name hide',
|
|
172
|
-
value: this.options.data.number,
|
|
173
|
-
placeholder: this.options.data.number,
|
|
174
|
-
pattern: '^\\w+$',
|
|
175
|
-
validationmessage: 'Латинские буквы и цифры',
|
|
176
|
-
onblur: ({ target }) => {
|
|
177
|
-
if (target.isUiValid) {
|
|
178
|
-
this.branchSubName.textContent = target.value || this.options.data.number
|
|
179
|
-
this.branchSubName.title = this.branchSubName.textContent
|
|
180
|
-
this.branchSubName.classList.toggle('hide')
|
|
181
|
-
this.branchSubNameTextfield.classList.toggle('hide')
|
|
182
|
-
}
|
|
209
|
+
return name + docNumber + version + date + author
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** @returns {string} Версия задачи (веха), выбранная пользователем */
|
|
213
|
+
get version() {
|
|
214
|
+
return this.data.version
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Обновление выбранной версии и обновление карточки задачи
|
|
219
|
+
*
|
|
220
|
+
* @param {string} value Версия
|
|
221
|
+
*/
|
|
222
|
+
set version(value) {
|
|
223
|
+
if (this.data.milestones && this.data.milestones.includes(value)) {
|
|
224
|
+
this.data.version = value
|
|
225
|
+
this.elements.branchButton.textContent = this.data.version
|
|
226
|
+
this.elements.cardTitle.textContent = this.branchTitle
|
|
183
227
|
}
|
|
184
|
-
}
|
|
228
|
+
}
|
|
185
229
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
230
|
+
/** @returns {string} Часть имени ветки, зависящая от регламента задачи */
|
|
231
|
+
get branchType() {
|
|
232
|
+
return this.data.name === 'Ошибка' ? 'bugfix' : 'feature'
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** @returns {string} Часть имени ветки, определяемая пользователем */
|
|
236
|
+
get branchSubName() {
|
|
237
|
+
return this.data.branchSubName
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Обновление доп. имени ветки и обновление карточки задачи
|
|
242
|
+
*
|
|
243
|
+
* @param {string} value Доп. имя ветки
|
|
244
|
+
*/
|
|
245
|
+
set branchSubName(value) {
|
|
246
|
+
this.data.branchSubName = value || this.data.number
|
|
247
|
+
this.elements.branchSubName.textContent = this.data.branchSubName
|
|
248
|
+
this.elements.branchSubName.title = this.data.branchSubName
|
|
249
|
+
this.elements.branchSubNameTextfield.value = this.data.branchSubName
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** @returns {string} Краткое описание задачи */
|
|
253
|
+
get description() {
|
|
254
|
+
return this.data.description
|
|
255
|
+
}
|
|
191
256
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Обновление краткого описания и карточки задачи
|
|
259
|
+
*
|
|
260
|
+
* @param {string} value Доп. имя ветки
|
|
261
|
+
*/
|
|
262
|
+
set description(value) {
|
|
263
|
+
this.data.description = value || ''
|
|
264
|
+
this.elements.description.title = this.data.description
|
|
265
|
+
this.elements.description.textContent = this.data.description
|
|
266
|
+
if (this.elements.descriptionTextarea.value !== this.data.description) {
|
|
267
|
+
this.elements.descriptionTextarea.value = this.data.description
|
|
268
|
+
}
|
|
269
|
+
oom(this.elements.descriptionTextarea, { rows: GitBranchCard.maxRows(this.data.description) })
|
|
270
|
+
}
|
|
196
271
|
|
|
197
272
|
template = () => {
|
|
198
|
-
this.
|
|
199
|
-
this.
|
|
200
|
-
|
|
201
|
-
this.descriptionEdit.innerHTML = octicons.pencil.toSVG()
|
|
202
|
-
|
|
203
|
-
this.versions.anchor = this.branchButton
|
|
204
|
-
this.versions.addEventListener('selected', (event) => {
|
|
205
|
-
this.version = this.milestones[event.detail.index]
|
|
206
|
-
this.cardTitle.textContent = this.getTitle()
|
|
207
|
-
this.branchButton.textContent = this.version
|
|
273
|
+
this.elements.versions.anchor = this.elements.branchButton
|
|
274
|
+
this.elements.versions.addEventListener('selected', (/** @type {CustomEvent<import('@material/mwc-list/mwc-list-foundation').ActionDetail>} */event) => {
|
|
275
|
+
this.version = this.data.milestones[event.detail.index]
|
|
208
276
|
})
|
|
209
277
|
|
|
278
|
+
this.updateBranchNamePart().catch(console.error)
|
|
279
|
+
|
|
210
280
|
return oom.div({ class: 'mdc-card' }, oom
|
|
211
|
-
.div({ class: 'title' }, this.cardTitle)
|
|
281
|
+
.div({ class: 'title' }, this.elements.cardTitle)
|
|
212
282
|
.div(oom
|
|
213
|
-
.a({ class: 'link' }, this.url, {
|
|
283
|
+
.a({ class: 'link' }, this.data.url, {
|
|
214
284
|
target: '_blank',
|
|
215
|
-
href: this.url
|
|
216
|
-
}), this.copyLinkButton)
|
|
285
|
+
href: this.data.url
|
|
286
|
+
}), this.elements.copyLinkButton)
|
|
217
287
|
.div({
|
|
218
288
|
class: 'description-line'
|
|
219
|
-
}, this.descriptionEdit, this.description, this.descriptionTextarea)
|
|
289
|
+
}, this.elements.descriptionEdit, this.elements.description, this.elements.descriptionTextarea)
|
|
220
290
|
.div({ class: 'branch-line' }, oom
|
|
221
291
|
.div({ class: 'branch' },
|
|
222
|
-
this.branchButton,
|
|
223
|
-
this.versions,
|
|
224
|
-
this.branchNamePart,
|
|
225
|
-
this.branchSubName,
|
|
226
|
-
this.branchSubNameTextfield)
|
|
227
|
-
.div({ class: 'actions' }, this.copyBranchButton, this.copyDescriptionButton)
|
|
292
|
+
this.elements.branchButton,
|
|
293
|
+
this.elements.versions,
|
|
294
|
+
this.elements.branchNamePart,
|
|
295
|
+
this.elements.branchSubName,
|
|
296
|
+
this.elements.branchSubNameTextfield)
|
|
297
|
+
.div({ class: 'actions' }, this.elements.copyBranchButton, this.elements.copyDescriptionButton)
|
|
228
298
|
)
|
|
229
299
|
)
|
|
230
300
|
}
|
|
231
301
|
|
|
232
|
-
/**
|
|
302
|
+
/** Обновляет имя ветки после получения данных пользователя */
|
|
303
|
+
async updateBranchNamePart() {
|
|
304
|
+
const userLogin = await context.userLogin
|
|
305
|
+
|
|
306
|
+
this.elements.branchNamePart.textContent = `/${this.branchType}/${userLogin}/`
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** Открывает форму редактирования редактирование описания для коммита */
|
|
233
310
|
editDescription() {
|
|
234
|
-
this.descriptionEdit.classList.toggle('hide')
|
|
235
|
-
this.description.classList.toggle('hide')
|
|
236
|
-
this.descriptionTextarea.classList.toggle('hide')
|
|
237
|
-
this.descriptionTextarea.focus()
|
|
311
|
+
this.elements.descriptionEdit.classList.toggle('hide')
|
|
312
|
+
this.elements.description.classList.toggle('hide')
|
|
313
|
+
this.elements.descriptionTextarea.classList.toggle('hide')
|
|
314
|
+
this.elements.descriptionTextarea.focus()
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/** Обработка события при вводе текста в описание для расчета отображаемого кол-ва строк */
|
|
318
|
+
oninputDescription() {
|
|
319
|
+
this.description = this.elements.descriptionTextarea.value
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/** Открывает форму редактирования доп. имени ветки */
|
|
323
|
+
editBranchSubName() {
|
|
324
|
+
this.elements.branchSubName.classList.toggle('hide')
|
|
325
|
+
this.elements.branchSubNameTextfield.classList.toggle('hide')
|
|
326
|
+
this.elements.branchSubNameTextfield.focus()
|
|
327
|
+
this.elements.branchSubNameTextfield.select()
|
|
238
328
|
}
|
|
239
329
|
|
|
240
330
|
/**
|
|
241
|
-
*
|
|
331
|
+
* Сохранение данных о доп. имени ветки при потере фокуса с поля ввода
|
|
332
|
+
*
|
|
333
|
+
* @param {{target:import('@material/mwc-textfield').TextField}} event Данные о событи onblur
|
|
242
334
|
*/
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
return name + docNumber + version + date + author
|
|
335
|
+
saveBranchSubName({ target }) {
|
|
336
|
+
if (target.checkValidity()) {
|
|
337
|
+
this.branchSubName = target.value
|
|
338
|
+
this.elements.branchSubName.classList.toggle('hide')
|
|
339
|
+
this.elements.branchSubNameTextfield.classList.toggle('hide')
|
|
340
|
+
}
|
|
251
341
|
}
|
|
252
342
|
|
|
253
343
|
/**
|
|
254
|
-
*
|
|
344
|
+
* Получение имени ветки с учетом выбора вехи и доп. имени ветки
|
|
345
|
+
*
|
|
346
|
+
* @returns {Promise<string>} Имя ветки
|
|
255
347
|
*/
|
|
256
|
-
getBranchName() {
|
|
257
|
-
const
|
|
348
|
+
async getBranchName() {
|
|
349
|
+
const userLogin = await context.userLogin
|
|
258
350
|
|
|
259
|
-
return `${this.version}/${this.branchType}/${
|
|
351
|
+
return `${this.version}/${this.branchType}/${userLogin}/${this.branchSubName}`
|
|
260
352
|
}
|
|
261
353
|
|
|
262
354
|
/** Копирование ссылки на задачу */
|
|
263
355
|
copyLink() {
|
|
264
|
-
navigator.clipboard.writeText(this.url)
|
|
356
|
+
navigator.clipboard.writeText(this.data.url)
|
|
357
|
+
snackbar.show(`Скопирована ссылка: ${this.data.url}`)
|
|
265
358
|
}
|
|
266
359
|
|
|
267
360
|
/** Копирование имени ветки */
|
|
268
|
-
copyBranchName() {
|
|
269
|
-
|
|
361
|
+
async copyBranchName() {
|
|
362
|
+
if (this.elements.branchSubNameTextfield.checkValidity()) {
|
|
363
|
+
const branchName = await this.getBranchName()
|
|
364
|
+
|
|
365
|
+
navigator.clipboard.writeText(branchName)
|
|
366
|
+
snackbar.show(`Скопировано имя ветки: ${branchName}`)
|
|
367
|
+
|
|
368
|
+
await this.saveToHistory()
|
|
369
|
+
}
|
|
270
370
|
}
|
|
271
371
|
|
|
272
372
|
/** Копирование описания для git commit */
|
|
273
|
-
copyDescription() {
|
|
274
|
-
|
|
275
|
-
this.url + '\n' +
|
|
276
|
-
this.
|
|
373
|
+
async copyDescription() {
|
|
374
|
+
const description = this.branchTitle + '\n' +
|
|
375
|
+
this.data.url + '\n' +
|
|
376
|
+
this.description
|
|
377
|
+
|
|
378
|
+
navigator.clipboard.writeText(description)
|
|
379
|
+
snackbar.show(`Скопировано описание для git commit:\n${description}`)
|
|
380
|
+
|
|
381
|
+
await this.saveToHistory()
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/** Сохраняет данные в историю по карточкам для которых копировали имя ветки или описание */
|
|
385
|
+
async saveToHistory() {
|
|
386
|
+
const branchName = await this.getBranchName()
|
|
387
|
+
const gitBranchHistory = db.table('gitBranchHistory')
|
|
388
|
+
const historyOldData = await gitBranchHistory.get({
|
|
389
|
+
id: this.data.id,
|
|
390
|
+
branch: branchName
|
|
391
|
+
})
|
|
392
|
+
const historyData = {
|
|
393
|
+
id: this.data.id,
|
|
394
|
+
branch: branchName,
|
|
395
|
+
version: this.version,
|
|
396
|
+
useDate: new Date(),
|
|
397
|
+
data: this.data
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (historyOldData) {
|
|
401
|
+
await gitBranchHistory.update(historyOldData.pk, historyData)
|
|
402
|
+
} else {
|
|
403
|
+
await gitBranchHistory.add(historyData)
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/** Восстановление из истории последнего сохраненного состояния карточки */
|
|
408
|
+
async restoreFromHistory() {
|
|
409
|
+
const gitBranchHistory = db.table('gitBranchHistory')
|
|
410
|
+
const historyData = await gitBranchHistory
|
|
411
|
+
.where({ id: this.options.data.id })
|
|
412
|
+
.reverse()
|
|
413
|
+
.sortBy('useDate')
|
|
414
|
+
|
|
415
|
+
if (historyData && historyData.length > 0) {
|
|
416
|
+
const [{ data: { version, branchSubName, description } }] = historyData
|
|
417
|
+
|
|
418
|
+
this.version = version
|
|
419
|
+
this.branchSubName = branchSubName
|
|
420
|
+
this.description = description
|
|
421
|
+
}
|
|
277
422
|
}
|
|
278
423
|
|
|
279
424
|
}
|
|
@@ -288,25 +433,49 @@ class GitBranchCardList extends oom.extends(HTMLElement) {
|
|
|
288
433
|
'.empty': {
|
|
289
434
|
padding: '100px',
|
|
290
435
|
textAlign: 'center'
|
|
436
|
+
},
|
|
437
|
+
'.content': {
|
|
438
|
+
overflow: 'auto',
|
|
439
|
+
maxHeight: 'calc(var(--mdc-dialog-max-height) - 100px)'
|
|
291
440
|
}
|
|
292
441
|
})
|
|
293
442
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
443
|
+
tabs = oom
|
|
444
|
+
.mwcTabBar(oom
|
|
445
|
+
.mwcTab({ label: 'Открытые задачи' })
|
|
446
|
+
// .mwcTab({ label: 'Список задач' })
|
|
447
|
+
.mwcTab({ label: 'История задач' }))
|
|
448
|
+
|
|
449
|
+
list = oom.div({ class: 'content' })
|
|
450
|
+
|
|
451
|
+
template = async () => {
|
|
452
|
+
// if (this.openTaskList.length === 0) {
|
|
453
|
+
// this.tabs({ activeindex: '1' })
|
|
454
|
+
// }
|
|
455
|
+
oom(this, this.tabs, this.list)
|
|
456
|
+
oom(this.list, oom.div({ class: 'empty' }, 'Загрузка ...'))
|
|
299
457
|
|
|
300
|
-
|
|
301
|
-
|
|
458
|
+
this.list({ innerHTML: '' }, await this.buildTaskList())
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** @returns {Promise<HTMLElement|DocumentFragment>} Вернет готовый список задач с учетом аинхронной загрузки данных */
|
|
462
|
+
async buildTaskList() {
|
|
463
|
+
let taskTist = null
|
|
464
|
+
const openTaskList = (await getListOfOpenCards({
|
|
465
|
+
names: ['Ошибка', 'Задача'],
|
|
466
|
+
hasVersion: true
|
|
467
|
+
})).map(card => new GitBranchCard(card))
|
|
302
468
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
469
|
+
await Promise.all(openTaskList.map(card => card.restoreFromHistory()))
|
|
470
|
+
|
|
471
|
+
if (openTaskList.length > 0) {
|
|
472
|
+
taskTist = oom()(...openTaskList)
|
|
473
|
+
} else {
|
|
474
|
+
taskTist = oom.div({ class: 'empty' }, 'Открытых задач с вехой не найдено')
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return taskTist.dom
|
|
478
|
+
}
|
|
310
479
|
|
|
311
480
|
}
|
|
312
481
|
|
|
@@ -318,3 +487,9 @@ keysMapping['alt-KeyB'] = () => PopupDialog.toggle({
|
|
|
318
487
|
title: 'Ветки для Git',
|
|
319
488
|
Element: GitBranchCardList
|
|
320
489
|
})
|
|
490
|
+
|
|
491
|
+
rightSidebar.addButton({
|
|
492
|
+
title: 'Ветки для Git',
|
|
493
|
+
iconSVG: octicons['git-branch'].toSVG({ width: 24 }),
|
|
494
|
+
onclick: keysMapping['alt-KeyB']
|
|
495
|
+
})
|
package/lib/context.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { sabyRPC } from 'saby-customizer/lib.js'
|
|
2
|
+
|
|
3
|
+
const handlers = {}
|
|
4
|
+
/** @type {any} */
|
|
5
|
+
const origin = {
|
|
6
|
+
register: (name, handler) => {
|
|
7
|
+
handlers[name] = handler
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export const context = new Proxy(origin, {
|
|
13
|
+
get: (target, name) => {
|
|
14
|
+
if (name in target) {
|
|
15
|
+
return target[name]
|
|
16
|
+
}
|
|
17
|
+
if (name in handlers) {
|
|
18
|
+
return handlers[name](target, name)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/** Получение сведений о текущем пользователе */
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
* @param {object} target Общий объект с данными
|
|
28
|
+
* @param {string} name Имя получаемого параметра
|
|
29
|
+
* @returns {Promise<any>} Значение параметра, определяется реализацией
|
|
30
|
+
*/
|
|
31
|
+
async function userInfo(target, name) {
|
|
32
|
+
const result = (await sabyRPC.call({
|
|
33
|
+
service: 'auth',
|
|
34
|
+
method: 'САП.ТекущийПользователь'
|
|
35
|
+
})).getRow()
|
|
36
|
+
|
|
37
|
+
target.userLogin = result.get('ЛогинПользователя')
|
|
38
|
+
|
|
39
|
+
return target[name]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
context.register('userLogin', userInfo)
|
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 }
|