saby-customizer 0.0.0-pre.10
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/README.md +8 -0
- package/features/git-branch.js +92 -0
- package/lib/dashboard.js +55 -0
- package/lib/database.js +9 -0
- package/lib/hotkeys.js +21 -0
- package/lib/layout.js +35 -0
- package/lib/material.js +25 -0
- package/lib/popup-dialog.js +111 -0
- package/lib.js +4 -0
- package/material.js +6429 -0
- package/package.json +32 -0
- package/saby-customizer-0.0.0-pre.8.tgz +0 -0
- package/saby-lib/cloud-statistic.js +2 -0
- package/saby-lib/edo.js +161 -0
- package/userscript.js +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { oom } from '@notml/core'
|
|
2
|
+
import { toggleDialog, keysMapping } from '../lib'
|
|
3
|
+
import { getListOfOpenCards } from '../saby-lib/edo.js'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/** Карточка со сведениями о задаче для копирования ветки */
|
|
7
|
+
class GitBranchCard extends oom.extends(HTMLElement) {
|
|
8
|
+
|
|
9
|
+
static tagName = 'sc-git-branch-сard'
|
|
10
|
+
static style = oom.style({
|
|
11
|
+
'display': 'contents',
|
|
12
|
+
'.mdc-card': {
|
|
13
|
+
margin: '16px',
|
|
14
|
+
padding: '12px'
|
|
15
|
+
},
|
|
16
|
+
'.title': {
|
|
17
|
+
fontWeight: 'bold'
|
|
18
|
+
},
|
|
19
|
+
'.link': {
|
|
20
|
+
fontSize: '14px'
|
|
21
|
+
},
|
|
22
|
+
'.description': {
|
|
23
|
+
fontSize: '14px',
|
|
24
|
+
whiteSpace: 'nowrap',
|
|
25
|
+
overflow: 'hidden',
|
|
26
|
+
textOverflow: 'ellipsis'
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
template = oom.div({ class: 'mdc-card' }, oom
|
|
31
|
+
.div({ class: 'title' }, this.getTitle())
|
|
32
|
+
.div({ class: 'link' }, oom.a(this.options.data.url, {
|
|
33
|
+
target: '_blank',
|
|
34
|
+
href: this.options.data.url
|
|
35
|
+
}))
|
|
36
|
+
.div({ class: 'description', title: this.options.data.description }, this.options.data.description))
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @returns {string} Заголовок
|
|
40
|
+
*/
|
|
41
|
+
getTitle() {
|
|
42
|
+
const { name } = this.options.data
|
|
43
|
+
const docNumber = ' № ' + this.options.data.number
|
|
44
|
+
const version = ' веха ' + this.options.data.version
|
|
45
|
+
const date = ' от ' + this.options.data.date
|
|
46
|
+
const author = ' ' + this.options.data.author
|
|
47
|
+
|
|
48
|
+
return name + docNumber + version + date + author
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/** Список веток GIT для копирования на основе открытых карточек задач */
|
|
55
|
+
class GitBranchCardList extends oom.extends(HTMLElement) {
|
|
56
|
+
|
|
57
|
+
static tagName = 'sc-git-branch-сard-list'
|
|
58
|
+
static style = oom.style({
|
|
59
|
+
'display': 'contents',
|
|
60
|
+
'.empty': {
|
|
61
|
+
padding: '100px',
|
|
62
|
+
textAlign: 'center'
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
taskList = getListOfOpenCards({
|
|
67
|
+
names: ['Ошибка', 'Задача'],
|
|
68
|
+
hasVersion: true
|
|
69
|
+
})
|
|
70
|
+
.map(card => new GitBranchCard(card))
|
|
71
|
+
|
|
72
|
+
taskListElement = (this.taskList.length > 0 && oom()(...this.taskList)) || oom
|
|
73
|
+
.div({ class: 'empty' }, 'Открытых задач с вехой не найдено')
|
|
74
|
+
|
|
75
|
+
template = oom()(
|
|
76
|
+
oom
|
|
77
|
+
.mwcTabBar(oom
|
|
78
|
+
.mwcTab({ label: 'Открытые задачи' })
|
|
79
|
+
.mwcTab({ label: 'История задач' })),
|
|
80
|
+
this.taskListElement
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
oom.define(GitBranchCard, GitBranchCardList)
|
|
87
|
+
|
|
88
|
+
keysMapping['alt-KeyB'] = () => toggleDialog({
|
|
89
|
+
key: 'git-branch-dialog',
|
|
90
|
+
title: 'Ветки для Git',
|
|
91
|
+
Element: GitBranchCardList
|
|
92
|
+
})
|
package/lib/dashboard.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { oom } from '@notml/core'
|
|
2
|
+
import { keysMapping } from './hotkeys.js'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/** Главное окно плагина */
|
|
6
|
+
class SabyCustomizerDashBoard extends oom.extends(HTMLElement) {
|
|
7
|
+
|
|
8
|
+
static tagName = 'sc-dash-board'
|
|
9
|
+
|
|
10
|
+
static style = oom.style({
|
|
11
|
+
'sc-dash-board': {
|
|
12
|
+
position: 'fixed',
|
|
13
|
+
left: '0',
|
|
14
|
+
top: '0',
|
|
15
|
+
right: '0',
|
|
16
|
+
height: '100%',
|
|
17
|
+
zIndex: '13000',
|
|
18
|
+
backgroundColor: 'rgba(0,0,0,.32)'
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
template = oom
|
|
23
|
+
.header({ class: 'mdc-top-app-bar' }, oom
|
|
24
|
+
.div({ class: 'mdc-top-app-bar__row' }, oom
|
|
25
|
+
.section({ class: 'mdc-top-app-bar__section mdc-top-app-bar__section--align-start' }, oom
|
|
26
|
+
.button({ class: 'material-icons mdc-top-app-bar__navigation-icon mdc-icon-button' }, oom
|
|
27
|
+
.span({ class: 'mdc-icon-button__ripple' })
|
|
28
|
+
.span('menu', { class: 'mdc-button__label' }))
|
|
29
|
+
.span('Page title', { class: 'mdc-top-app-bar__title' }))
|
|
30
|
+
.section({ class: 'mdc-top-app-bar__section mdc-top-app-bar__section--align-end' }, oom
|
|
31
|
+
.button({ class: 'material-icons mdc-top-app-bar__action-item mdc-icon-button' }, oom
|
|
32
|
+
.span({ class: 'mdc-icon-button__ripple' })
|
|
33
|
+
.span('close', {
|
|
34
|
+
class: 'mdc-button__label',
|
|
35
|
+
onclick: () => this.remove()
|
|
36
|
+
}))
|
|
37
|
+
)))
|
|
38
|
+
.main({ class: 'mdc-top-app-bar--fixed-adjust' }, oom
|
|
39
|
+
.span('test'))
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
oom.define(SabyCustomizerDashBoard)
|
|
45
|
+
|
|
46
|
+
keysMapping['ctrl-shift-KeyU'] = keysMapping['ctrl-alt-KeyU'] = () => {
|
|
47
|
+
const layout = document.getElementById('saby-customizer-layout').shadowRoot
|
|
48
|
+
const dashboard = layout.getElementById('sc-dash-board')
|
|
49
|
+
|
|
50
|
+
if (dashboard) {
|
|
51
|
+
dashboard.remove()
|
|
52
|
+
} else {
|
|
53
|
+
oom(layout, oom.scDashBoard({ id: 'sc-dash-board' }))
|
|
54
|
+
}
|
|
55
|
+
}
|
package/lib/database.js
ADDED
package/lib/hotkeys.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const keysMapping = {}
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
document.addEventListener('keydown', (event) => {
|
|
5
|
+
let hKey = ''
|
|
6
|
+
|
|
7
|
+
if (event.ctrlKey) {
|
|
8
|
+
hKey += 'ctrl-'
|
|
9
|
+
}
|
|
10
|
+
if (event.shiftKey) {
|
|
11
|
+
hKey += 'shift-'
|
|
12
|
+
}
|
|
13
|
+
if (event.altKey) {
|
|
14
|
+
hKey += 'alt-'
|
|
15
|
+
}
|
|
16
|
+
hKey += event.code
|
|
17
|
+
if (hKey in keysMapping) {
|
|
18
|
+
keysMapping[hKey]()
|
|
19
|
+
event.stopPropagation()
|
|
20
|
+
}
|
|
21
|
+
}, { capture: true })
|
package/lib/layout.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { oom } from '@notml/core'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/** Подложка в теневым DOM для размещения в ней элементов плагина, для изоляции их от основной верстки */
|
|
5
|
+
oom.define(class SabyCustomizerLayout extends oom.extends(HTMLElement) {
|
|
6
|
+
|
|
7
|
+
static tagName = 'saby-customizer-layout'
|
|
8
|
+
static attachShadow = true
|
|
9
|
+
|
|
10
|
+
template = oom().head(oom
|
|
11
|
+
// Предзагрузка стилей material внутри теневого DOM
|
|
12
|
+
.link({ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap' })
|
|
13
|
+
.link({ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons' })
|
|
14
|
+
// https://material.io/resources/color/
|
|
15
|
+
.style({
|
|
16
|
+
':host': {
|
|
17
|
+
'--mdc-theme-primary': '#0d47a1',
|
|
18
|
+
'--mdc-theme-secondary': '#0d47a1',
|
|
19
|
+
'--mdc-theme-background': '#e1e1e1',
|
|
20
|
+
'--mdc-theme-surface': '#fff',
|
|
21
|
+
'--mdc-theme-on-primary': '#fff',
|
|
22
|
+
'--mdc-theme-on-secondary': '#fff',
|
|
23
|
+
'--mdc-theme-on-surface': '#000'
|
|
24
|
+
}
|
|
25
|
+
}))
|
|
26
|
+
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
const layoutElement = oom.sabyCustomizerLayout({ id: 'saby-customizer-layout' })
|
|
31
|
+
|
|
32
|
+
oom(document.documentElement, layoutElement)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
export const layout = layoutElement.dom.shadowRoot
|
package/lib/material.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// https://github.com/material-components/material-web
|
|
2
|
+
|
|
3
|
+
// В ожидании правки
|
|
4
|
+
// https://github.com/material-components/material-web/issues/2780
|
|
5
|
+
// import 'https://unpkg.com/@material/mwc-dialog@0.25.1?module'
|
|
6
|
+
// import 'https://unpkg.com/@material/mwc-icon-button@0.25.1?module'
|
|
7
|
+
// import 'https://unpkg.com/@material/mwc-tab-bar@0.25.1?module'
|
|
8
|
+
// import 'https://unpkg.com/@material/mwc-top-app-bar@0.25.1?module'
|
|
9
|
+
|
|
10
|
+
import '@material/mwc-dialog'
|
|
11
|
+
import '@material/mwc-icon-button'
|
|
12
|
+
import '@material/mwc-tab-bar'
|
|
13
|
+
import '@material/mwc-top-app-bar'
|
|
14
|
+
/*
|
|
15
|
+
* PS
|
|
16
|
+
* unpkg не вывозит новый JS:
|
|
17
|
+
* https://github.com/mjackson/unpkg/issues/303
|
|
18
|
+
*
|
|
19
|
+
* jsdelivr не вывозит модульность:
|
|
20
|
+
* https://github.com/jsdelivr/jsdelivr/issues/18263
|
|
21
|
+
* https://github.com/jsdelivr/jsdelivr/issues/18215
|
|
22
|
+
* https://github.com/jsdelivr/jsdelivr/issues/18298
|
|
23
|
+
*
|
|
24
|
+
* Поэтому зависимости разбиты на 2 CDN до решения проблем в любом их них
|
|
25
|
+
*/
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { oom } from '@notml/core'
|
|
2
|
+
import { layout } from './layout.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef PopupDialogOptions
|
|
6
|
+
* @property {string} [key] Уникальный идентификатор вида диалога
|
|
7
|
+
* @property {string} [title] Текст заголовка диалога
|
|
8
|
+
* @property {typeof HTMLElement|string} Element Элемент с содержимым диалога
|
|
9
|
+
*/
|
|
10
|
+
/** @type {PopupDialogOptions} */
|
|
11
|
+
const PopupDialogDefaults = {
|
|
12
|
+
title: 'SABY Customizer',
|
|
13
|
+
Element: ''
|
|
14
|
+
}
|
|
15
|
+
/** @type {PopupDialog} */
|
|
16
|
+
let lastDialog = null
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/** Компонент всплывающего диалога */
|
|
20
|
+
export class PopupDialog extends oom.extends(HTMLElement, PopupDialogDefaults) {
|
|
21
|
+
|
|
22
|
+
static tagName = 'sc-popup-dialog'
|
|
23
|
+
// static className = 'mdc-dialog'
|
|
24
|
+
static style = oom.style({
|
|
25
|
+
'sc-popup-dialog': {
|
|
26
|
+
display: 'contents'
|
|
27
|
+
},
|
|
28
|
+
'mwc-dialog': {
|
|
29
|
+
'--mdc-dialog-z-index': '10000',
|
|
30
|
+
'--mdc-dialog-max-width': '600px'
|
|
31
|
+
},
|
|
32
|
+
'header': {
|
|
33
|
+
margin: '-20px -24px 0px -24px',
|
|
34
|
+
display: 'flex',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
justifyContent: 'space-between',
|
|
37
|
+
padding: '2px 2px 2px 14px',
|
|
38
|
+
fontSize: '20px',
|
|
39
|
+
backgroundColor: 'var(--mdc-theme-primary, #6200ee)',
|
|
40
|
+
color: 'var(--mdc-theme-on-primary, #fff)',
|
|
41
|
+
overflow: 'hidden'
|
|
42
|
+
},
|
|
43
|
+
'main': {
|
|
44
|
+
margin: '0px -24px -20px -24px'
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
key = this.options.key
|
|
49
|
+
content = typeof this.options.Element === 'string' ? this.options.Element : new this.options.Element()
|
|
50
|
+
|
|
51
|
+
template = async () => {
|
|
52
|
+
// Открытый диалог может быть только один
|
|
53
|
+
this.id = 'sc-popup-dialog'
|
|
54
|
+
/** @type {import('@material/mwc-dialog').Dialog} */// @ts-ignore
|
|
55
|
+
this.dialog = oom
|
|
56
|
+
.mwcDialog({ hideActions: true }, oom
|
|
57
|
+
.header(oom
|
|
58
|
+
.span(this.options.title)
|
|
59
|
+
.mwcIconButton({ icon: 'close', onclick: () => this.close() }))
|
|
60
|
+
.main(this.content))
|
|
61
|
+
.dom
|
|
62
|
+
|
|
63
|
+
oom(this, this.dialog)
|
|
64
|
+
|
|
65
|
+
this.dialog.addEventListener('closed', () => this.closed())
|
|
66
|
+
|
|
67
|
+
await this.open()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Функция открытия диалога с асинхронной задержкой, что бы успело построиться дерево компонента */
|
|
71
|
+
async open() {
|
|
72
|
+
lastDialog = this
|
|
73
|
+
await new Promise(resolve => setTimeout(resolve))
|
|
74
|
+
this.dialog.show()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Функция закрытия диалога */
|
|
78
|
+
close() {
|
|
79
|
+
if (this.dialog) {
|
|
80
|
+
this.dialog.close()
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Обработчик завершения закрытия одиалога */
|
|
85
|
+
closed() {
|
|
86
|
+
this.dialog = lastDialog = null
|
|
87
|
+
this.remove()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
oom.define(PopupDialog)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Переключает открытый диалог с учетом уникального ключа диалога.
|
|
97
|
+
* Открывает с закрытием другого диалога, или скрывает если открыт тот же диалог
|
|
98
|
+
*
|
|
99
|
+
* @param {PopupDialogOptions} options Опции PopupDialog
|
|
100
|
+
*/
|
|
101
|
+
export function toggleDialog(options) {
|
|
102
|
+
const exists = lastDialog && lastDialog.key === options.key
|
|
103
|
+
|
|
104
|
+
if (lastDialog) {
|
|
105
|
+
// Открытый диалог может быть только один
|
|
106
|
+
lastDialog.close()
|
|
107
|
+
}
|
|
108
|
+
if (!exists) {
|
|
109
|
+
oom(layout, new PopupDialog(options))
|
|
110
|
+
}
|
|
111
|
+
}
|
package/lib.js
ADDED