@qtoggle/qui 0.0.0
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/.eslintignore +2 -0
- package/.eslintrc.json +492 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- package/.github/ISSUE_TEMPLATE/improvement_proposal.md +20 -0
- package/.github/workflows/main.yml +74 -0
- package/.pre-commit-config.yaml +8 -0
- package/LICENSE.txt +177 -0
- package/README.md +4 -0
- package/font/dejavusans-bold.woff +0 -0
- package/font/dejavusans-bolditalic.woff +0 -0
- package/font/dejavusans-italic.woff +0 -0
- package/font/dejavusans-regular.woff +0 -0
- package/img/qui-icons.svg +1937 -0
- package/js/base/base.js +47 -0
- package/js/base/condition-variable.js +92 -0
- package/js/base/errors.js +36 -0
- package/js/base/i18n.js +20 -0
- package/js/base/mixwith.js +135 -0
- package/js/base/require-js-compat.js +78 -0
- package/js/base/signal.js +91 -0
- package/js/base/singleton.js +66 -0
- package/js/base/timer.js +126 -0
- package/js/config.js +184 -0
- package/js/forms/common-fields/check-field.js +42 -0
- package/js/forms/common-fields/choice-buttons-field.js +30 -0
- package/js/forms/common-fields/color-combo-field.js +37 -0
- package/js/forms/common-fields/combo-field.js +108 -0
- package/js/forms/common-fields/common-fields.js +23 -0
- package/js/forms/common-fields/composite-field.js +132 -0
- package/js/forms/common-fields/custom-html-field.js +51 -0
- package/js/forms/common-fields/email-field.js +30 -0
- package/js/forms/common-fields/file-picker-field.js +46 -0
- package/js/forms/common-fields/jquery-ui-field.js +111 -0
- package/js/forms/common-fields/labels-field.js +69 -0
- package/js/forms/common-fields/numeric-field.js +39 -0
- package/js/forms/common-fields/password-field.js +28 -0
- package/js/forms/common-fields/phone-field.js +26 -0
- package/js/forms/common-fields/progress-disk-field.js +69 -0
- package/js/forms/common-fields/push-button-field.js +138 -0
- package/js/forms/common-fields/slider-field.js +51 -0
- package/js/forms/common-fields/text-area-field.js +34 -0
- package/js/forms/common-fields/text-field.js +89 -0
- package/js/forms/common-fields/up-down-field.js +85 -0
- package/js/forms/common-forms/common-forms.js +16 -0
- package/js/forms/common-forms/options-form.js +77 -0
- package/js/forms/common-forms/page-form.js +115 -0
- package/js/forms/form-button.js +202 -0
- package/js/forms/form-field.js +1183 -0
- package/js/forms/form.js +1181 -0
- package/js/forms/forms.js +68 -0
- package/js/global-glass.js +100 -0
- package/js/icons/default-stock.js +173 -0
- package/js/icons/icon.js +64 -0
- package/js/icons/icons.js +16 -0
- package/js/icons/multi-state-sprites-icon.js +362 -0
- package/js/icons/stock-icon.js +219 -0
- package/js/icons/stock.js +98 -0
- package/js/icons/stocks.js +57 -0
- package/js/index.js +232 -0
- package/js/lib/jquery.longpress.js +79 -0
- package/js/lib/jquery.module.js +4 -0
- package/js/lib/logger.module.js +4 -0
- package/js/lib/pep.module.js +4 -0
- package/js/lists/common-items/common-items.js +5 -0
- package/js/lists/common-items/icon-label-list-item.js +86 -0
- package/js/lists/common-lists/common-lists.js +5 -0
- package/js/lists/common-lists/page-list.js +53 -0
- package/js/lists/list-item.js +147 -0
- package/js/lists/list.js +636 -0
- package/js/lists/lists.js +26 -0
- package/js/main-ui/main-ui.js +64 -0
- package/js/main-ui/menu-bar.js +144 -0
- package/js/main-ui/options-bar.js +181 -0
- package/js/main-ui/status.js +185 -0
- package/js/main-ui/top-bar.js +59 -0
- package/js/messages/common-message-forms/common-message-forms.js +7 -0
- package/js/messages/common-message-forms/confirm-message-form.js +81 -0
- package/js/messages/common-message-forms/simple-message-form.js +67 -0
- package/js/messages/common-message-forms/sticky-simple-message-form.js +27 -0
- package/js/messages/message-form.js +107 -0
- package/js/messages/messages.js +21 -0
- package/js/messages/sticky-modal-page.js +98 -0
- package/js/messages/sticky-modal-progress-message.js +27 -0
- package/js/messages/toast.js +164 -0
- package/js/navigation.js +654 -0
- package/js/pages/breadcrumbs.js +124 -0
- package/js/pages/common-pages/common-pages.js +6 -0
- package/js/pages/common-pages/modal-progress-page.js +83 -0
- package/js/pages/common-pages/structured-page.js +46 -0
- package/js/pages/page.js +1018 -0
- package/js/pages/pages-context.js +154 -0
- package/js/pages/pages.js +252 -0
- package/js/pwa.js +337 -0
- package/js/sections/section.js +612 -0
- package/js/sections/sections.js +300 -0
- package/js/tables/common-cells/common-cells.js +7 -0
- package/js/tables/common-cells/icon-label-table-cell.js +68 -0
- package/js/tables/common-cells/push-button-table-cell.js +133 -0
- package/js/tables/common-cells/simple-table-cell.js +37 -0
- package/js/tables/common-tables/common-tables.js +5 -0
- package/js/tables/common-tables/page-table.js +55 -0
- package/js/tables/table-cell.js +198 -0
- package/js/tables/table-row.js +126 -0
- package/js/tables/table.js +492 -0
- package/js/tables/tables.js +36 -0
- package/js/theme.js +304 -0
- package/js/utils/ajax.js +126 -0
- package/js/utils/array.js +194 -0
- package/js/utils/colors.js +445 -0
- package/js/utils/cookies.js +65 -0
- package/js/utils/crypto.js +439 -0
- package/js/utils/css.js +234 -0
- package/js/utils/date.js +300 -0
- package/js/utils/files.js +27 -0
- package/js/utils/gestures.js +165 -0
- package/js/utils/html.js +76 -0
- package/js/utils/misc.js +81 -0
- package/js/utils/object.js +324 -0
- package/js/utils/promise.js +49 -0
- package/js/utils/string.js +192 -0
- package/js/utils/url.js +187 -0
- package/js/utils/utils.js +3 -0
- package/js/utils/visibility-manager.js +211 -0
- package/js/views/common-views/common-views.js +7 -0
- package/js/views/common-views/icon-label-view.js +210 -0
- package/js/views/common-views/progress-view.js +89 -0
- package/js/views/common-views/structured-view.js +368 -0
- package/js/views/view.js +467 -0
- package/js/views/views.js +3 -0
- package/js/widgets/base-widget.js +23 -0
- package/js/widgets/common-widgets/check-button.js +109 -0
- package/js/widgets/common-widgets/choice-buttons.js +322 -0
- package/js/widgets/common-widgets/color-combo.js +104 -0
- package/js/widgets/common-widgets/combo.js +645 -0
- package/js/widgets/common-widgets/common-widgets.js +17 -0
- package/js/widgets/common-widgets/email-input.js +7 -0
- package/js/widgets/common-widgets/file-picker.js +133 -0
- package/js/widgets/common-widgets/labels.js +132 -0
- package/js/widgets/common-widgets/numeric-input.js +49 -0
- package/js/widgets/common-widgets/password-input.js +91 -0
- package/js/widgets/common-widgets/phone-input.js +7 -0
- package/js/widgets/common-widgets/progress-disk.js +174 -0
- package/js/widgets/common-widgets/push-button.js +155 -0
- package/js/widgets/common-widgets/slider.js +455 -0
- package/js/widgets/common-widgets/text-area.js +52 -0
- package/js/widgets/common-widgets/text-input.js +174 -0
- package/js/widgets/common-widgets/up-down.js +351 -0
- package/js/widgets/widgets.js +57 -0
- package/js/window.js +557 -0
- package/jsdoc.conf.json +20 -0
- package/less/base.less +123 -0
- package/less/forms/common-fields.less +101 -0
- package/less/forms/common-forms.less +5 -0
- package/less/forms/form-button.less +21 -0
- package/less/forms/form-field.less +266 -0
- package/less/forms/form.less +131 -0
- package/less/global-glass.less +64 -0
- package/less/icon-label-view.less +82 -0
- package/less/icons.less +144 -0
- package/less/lists.less +105 -0
- package/less/main-ui.less +328 -0
- package/less/messages.less +189 -0
- package/less/no-effects.less +24 -0
- package/less/pages/breadcrumbs.less +98 -0
- package/less/pages/common-pages.less +36 -0
- package/less/pages/page.less +70 -0
- package/less/progress-view.less +51 -0
- package/less/stock-icons.less +43 -0
- package/less/structured-view.less +245 -0
- package/less/tables.less +84 -0
- package/less/theme-dark.less +133 -0
- package/less/theme-light.less +132 -0
- package/less/theme.less +419 -0
- package/less/visibility-manager.less +11 -0
- package/less/widgets/check-button.less +96 -0
- package/less/widgets/choice-buttons.less +160 -0
- package/less/widgets/color-combo.less +33 -0
- package/less/widgets/combo.less +230 -0
- package/less/widgets/common-buttons.less +120 -0
- package/less/widgets/common.less +24 -0
- package/less/widgets/input.less +258 -0
- package/less/widgets/labels.less +81 -0
- package/less/widgets/progress-disk.less +70 -0
- package/less/widgets/slider.less +199 -0
- package/less/widgets/updown.less +115 -0
- package/less/widgets/various.less +36 -0
- package/package.json +47 -0
- package/pyproject.toml +45 -0
- package/qui/__init__.py +110 -0
- package/qui/constants.py +1 -0
- package/qui/exceptions.py +2 -0
- package/qui/j2template.py +71 -0
- package/qui/settings.py +60 -0
- package/qui/templates/manifest.json +25 -0
- package/qui/templates/qui.html +126 -0
- package/qui/templates/service-worker.js +188 -0
- package/qui/web/__init__.py +0 -0
- package/qui/web/tornado.py +220 -0
- package/scripts/postinstall.sh +10 -0
- package/webpack/webpack-adjust-css-urls-loader.js +36 -0
- package/webpack/webpack-common.js +384 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @namespace qui.mainui
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
6
|
+
|
|
7
|
+
import URL from '$qui/utils/url.js'
|
|
8
|
+
import VisibilityManager from '$qui/utils/visibility-manager.js'
|
|
9
|
+
import * as Window from '$qui/window.js'
|
|
10
|
+
|
|
11
|
+
import * as MenuBar from './menu-bar.js'
|
|
12
|
+
import * as OptionsBar from './options-bar.js'
|
|
13
|
+
import * as TopBar from './top-bar.js'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
let mainContainer = null
|
|
17
|
+
let mainContainerGlass = null
|
|
18
|
+
let mainContainerGlassVisibilityManager = null
|
|
19
|
+
|
|
20
|
+
let messageContainer = null
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
function initMainContainer() {
|
|
24
|
+
mainContainer = $('<div></div>', {class: 'qui-main-container'})
|
|
25
|
+
mainContainer.append($('<div></div>', {class: 'qui-pages-container'}))
|
|
26
|
+
|
|
27
|
+
mainContainerGlass = $('<div></div>', {class: 'qui-main-container-glass', style: 'display: none;'})
|
|
28
|
+
mainContainerGlassVisibilityManager = new VisibilityManager({element: mainContainerGlass})
|
|
29
|
+
mainContainer.append(mainContainerGlass)
|
|
30
|
+
|
|
31
|
+
messageContainer = $('div.qui-toast-message-container')
|
|
32
|
+
|
|
33
|
+
/* Close menu and option bars when clicking on main container glass */
|
|
34
|
+
mainContainer.find('div.qui-main-container-glass').on('click', function () {
|
|
35
|
+
MenuBar.close()
|
|
36
|
+
OptionsBar.close()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
Window.$body.append(mainContainer)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function adjustRelativeLinks() {
|
|
43
|
+
/* Set absolute paths on links before the window location changes */
|
|
44
|
+
$('link[rel=icon], link[rel=apple-touch-icon], link[theme]').each(function () {
|
|
45
|
+
this.href = URL.parse(this.href).toString()
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function showMainContainerGlass() {
|
|
50
|
+
mainContainerGlassVisibilityManager.showElement()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function hideMainContainerGlass() {
|
|
54
|
+
mainContainerGlassVisibilityManager.hideElement()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function init() {
|
|
58
|
+
initMainContainer()
|
|
59
|
+
adjustRelativeLinks()
|
|
60
|
+
|
|
61
|
+
TopBar.init()
|
|
62
|
+
MenuBar.init()
|
|
63
|
+
OptionsBar.init()
|
|
64
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @namespace qui.mainui.menubar
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
6
|
+
import Logger from '$qui/lib/logger.module.js'
|
|
7
|
+
|
|
8
|
+
import {gettext} from '$qui/base/i18n.js'
|
|
9
|
+
import StockIcon from '$qui/icons/stock-icon.js'
|
|
10
|
+
import * as Gestures from '$qui/utils/gestures.js'
|
|
11
|
+
import * as Window from '$qui/window.js'
|
|
12
|
+
|
|
13
|
+
import * as MainUI from './main-ui.js'
|
|
14
|
+
import * as OptionsBar from './options-bar.js'
|
|
15
|
+
import * as TopBar from './top-bar.js'
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const logger = Logger.get('qui.mainui.menubar')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
let barHTML = null
|
|
22
|
+
let menuButton = null
|
|
23
|
+
let opened = false
|
|
24
|
+
let transitionPromise = Promise.resolve()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Return the menu bar HTML element.
|
|
29
|
+
* @returns {jQuery}
|
|
30
|
+
*/
|
|
31
|
+
export function getHTML() {
|
|
32
|
+
return barHTML
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Tell if the menu bar is opened or not.
|
|
37
|
+
* @alias qui.mainui.menubar.isOpened
|
|
38
|
+
* @returns {Boolean}
|
|
39
|
+
*/
|
|
40
|
+
export function isOpened() {
|
|
41
|
+
return opened
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Open the menu bar.
|
|
46
|
+
* @alias qui.mainui.menubar.open
|
|
47
|
+
*/
|
|
48
|
+
export function open() {
|
|
49
|
+
if (opened) {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
if (OptionsBar.isOpened()) {
|
|
53
|
+
OptionsBar.close()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
MainUI.showMainContainerGlass()
|
|
57
|
+
|
|
58
|
+
opened = true
|
|
59
|
+
logger.debug('menu bar opened')
|
|
60
|
+
|
|
61
|
+
transitionPromise = transitionPromise.then(function () {
|
|
62
|
+
menuButton.addClass('selected')
|
|
63
|
+
Window.$body.addClass('menu-bar-open')
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Close the menu bar.
|
|
69
|
+
* @alias qui.mainui.menubar.close
|
|
70
|
+
*/
|
|
71
|
+
export function close() {
|
|
72
|
+
if (!opened) {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
MainUI.hideMainContainerGlass()
|
|
77
|
+
|
|
78
|
+
opened = false
|
|
79
|
+
logger.debug('menu bar closed')
|
|
80
|
+
|
|
81
|
+
transitionPromise = transitionPromise.then(function () {
|
|
82
|
+
menuButton.removeClass('selected')
|
|
83
|
+
Window.$body.removeClass('menu-bar-open')
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Add a button to the menu bar.
|
|
89
|
+
* @alias qui.mainui.menubar.addButton
|
|
90
|
+
* @param {jQuery} button the button to add
|
|
91
|
+
*/
|
|
92
|
+
export function addButton(button) {
|
|
93
|
+
button.addClass('qui-menu-bar-button')
|
|
94
|
+
barHTML.append(button)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function init() {
|
|
98
|
+
barHTML = $('<div></div>', {class: 'qui-menu-bar'})
|
|
99
|
+
menuButton = TopBar.getHTML().find('div.qui-menu-button')
|
|
100
|
+
let variant = Window.isSmallScreen() ? 'white' : 'interactive'
|
|
101
|
+
new StockIcon({name: 'menu', variant: variant}).applyTo(menuButton.find('.qui-icon'))
|
|
102
|
+
|
|
103
|
+
menuButton.attr('title', gettext('Menu'))
|
|
104
|
+
menuButton.on('click', function () {
|
|
105
|
+
if (opened) {
|
|
106
|
+
close()
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
open()
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
Gestures.enableDragging(
|
|
114
|
+
barHTML,
|
|
115
|
+
/* onMove = */ function (elemX, elemY, deltaX, deltaY, pageX, pageY) {
|
|
116
|
+
if (deltaX > 0) {
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
barHTML.css('transition', 'none')
|
|
120
|
+
barHTML.css('left', elemX)
|
|
121
|
+
},
|
|
122
|
+
/* onBegin = */ function () {
|
|
123
|
+
/* Allow closing the menu bar with touch drag, but only on small screens */
|
|
124
|
+
if (!Window.isSmallScreen()) {
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
/* onEnd = */ function (elemX, elemY, deltaX, deltaY, pageX, pageY) {
|
|
129
|
+
barHTML.css('transition', '')
|
|
130
|
+
barHTML.css('left', '')
|
|
131
|
+
|
|
132
|
+
if (deltaX < 0 && Math.abs(deltaX) > barHTML.width() / 2) {
|
|
133
|
+
close()
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
/* Automatically update menu icon according to small screen state */
|
|
139
|
+
Window.screenLayoutChangeSignal.connect(function (smallScreen, landscape) {
|
|
140
|
+
StockIcon.alterElement(menuButton.find('div.qui-icon'), {variant: smallScreen ? 'white' : 'interactive'})
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
Window.$body.append(barHTML)
|
|
144
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @namespace qui.mainui.optionsbar
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
6
|
+
import Logger from '$qui/lib/logger.module.js'
|
|
7
|
+
|
|
8
|
+
import {gettext} from '$qui/base/i18n.js'
|
|
9
|
+
import Signal from '$qui/base/signal.js'
|
|
10
|
+
import StockIcon from '$qui/icons/stock-icon.js'
|
|
11
|
+
import * as Theme from '$qui/theme.js'
|
|
12
|
+
import * as Gestures from '$qui/utils/gestures.js'
|
|
13
|
+
import {asap} from '$qui/utils/misc.js'
|
|
14
|
+
import * as PromiseUtils from '$qui/utils/promise.js'
|
|
15
|
+
import * as Window from '$qui/window.js'
|
|
16
|
+
|
|
17
|
+
import * as MainUI from './main-ui.js'
|
|
18
|
+
import * as MenuBar from './menu-bar.js'
|
|
19
|
+
import * as TopBar from './top-bar.js'
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const logger = Logger.get('qui.mainui.optionsbar')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
let barHTML = null
|
|
26
|
+
let barContainer = null
|
|
27
|
+
let optionsButton = null
|
|
28
|
+
let updateHandle = null
|
|
29
|
+
let opened = false
|
|
30
|
+
let transitionPromise = Promise.resolve()
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Emitted whenever the options bar is opened or closed. Handlers are called with the following parameters:
|
|
34
|
+
* * `opened: Boolean`, the opened status
|
|
35
|
+
* @alias qui.mainui.optionsbar.openCloseSignal
|
|
36
|
+
*/
|
|
37
|
+
export const openCloseSignal = new Signal(barHTML)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Tell if the options bar is opened or not.
|
|
42
|
+
* @alias qui.mainui.optionsbar.isOpened
|
|
43
|
+
* @returns {Boolean}
|
|
44
|
+
*/
|
|
45
|
+
export function isOpened() {
|
|
46
|
+
return opened
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Open the options bar.
|
|
51
|
+
* @alias qui.mainui.optionsbar.open
|
|
52
|
+
*/
|
|
53
|
+
export function open() {
|
|
54
|
+
if (opened) {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
if (MenuBar.isOpened()) {
|
|
58
|
+
MenuBar.close()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
MainUI.showMainContainerGlass()
|
|
62
|
+
|
|
63
|
+
opened = true
|
|
64
|
+
logger.debug('options bar opened')
|
|
65
|
+
openCloseSignal.emit(true)
|
|
66
|
+
|
|
67
|
+
transitionPromise = transitionPromise.then(function () {
|
|
68
|
+
barHTML.css('display', '')
|
|
69
|
+
optionsButton.addClass('selected')
|
|
70
|
+
return PromiseUtils.asap().then(function () {
|
|
71
|
+
Window.$body.addClass('options-bar-open')
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Close the options bar.
|
|
78
|
+
* @alias qui.mainui.optionsbar.close
|
|
79
|
+
*/
|
|
80
|
+
export function close() {
|
|
81
|
+
if (!opened) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
MainUI.hideMainContainerGlass()
|
|
86
|
+
|
|
87
|
+
opened = false
|
|
88
|
+
logger.debug('options bar closed')
|
|
89
|
+
openCloseSignal.emit(false)
|
|
90
|
+
|
|
91
|
+
transitionPromise = transitionPromise.then(function () {
|
|
92
|
+
Window.$body.removeClass('options-bar-open')
|
|
93
|
+
optionsButton.removeClass('selected')
|
|
94
|
+
|
|
95
|
+
return PromiseUtils.later(Theme.getTransitionDuration()).then(function () {
|
|
96
|
+
barHTML.css('display', 'none')
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Set the content of the options bar.
|
|
103
|
+
* @alias qui.mainui.optionsbar.setContent
|
|
104
|
+
* @param {?jQuery} content the new options bar content; `null` closes/disables the options bar
|
|
105
|
+
*/
|
|
106
|
+
export function setContent(content) {
|
|
107
|
+
if (updateHandle) {
|
|
108
|
+
clearTimeout(updateHandle)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
barHTML.addClass('updating')
|
|
112
|
+
updateHandle = asap(function () {
|
|
113
|
+
updateHandle = null
|
|
114
|
+
|
|
115
|
+
barContainer.children().detach()
|
|
116
|
+
|
|
117
|
+
if (content) {
|
|
118
|
+
/* Using detach + append prevents triggering remove/destroy on widgets */
|
|
119
|
+
barContainer.append(content)
|
|
120
|
+
optionsButton.removeClass('hidden')
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
optionsButton.addClass('hidden')
|
|
124
|
+
close()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
barHTML.removeClass('updating')
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function init() {
|
|
132
|
+
barHTML = $('<div></div>', {class: 'qui-options-bar'})
|
|
133
|
+
barHTML.append($('<div></div>', {class: 'qui-options-bar-container'}))
|
|
134
|
+
|
|
135
|
+
barContainer = barHTML.find('div.qui-options-bar-container')
|
|
136
|
+
optionsButton = TopBar.getHTML().find('div.qui-options-button')
|
|
137
|
+
let variant = Window.isSmallScreen() ? 'white' : 'interactive'
|
|
138
|
+
new StockIcon({name: 'options', variant: variant}).applyTo(optionsButton.find('.qui-icon'))
|
|
139
|
+
|
|
140
|
+
optionsButton.attr('title', gettext('Options'))
|
|
141
|
+
optionsButton.on('click', function () {
|
|
142
|
+
if (isOpened()) {
|
|
143
|
+
close()
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
open()
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
Gestures.enableDragging(
|
|
151
|
+
barHTML,
|
|
152
|
+
/* onMove = */ function (elemX, elemY, deltaX, deltaY, pageX, pageY) {
|
|
153
|
+
if (deltaX < 0) {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
barHTML.css('transition', 'none')
|
|
157
|
+
barHTML.css('right', -deltaX)
|
|
158
|
+
},
|
|
159
|
+
/* onBegin = */ function () {
|
|
160
|
+
/* Allow closing the options bar with touch drag, but only on small screens */
|
|
161
|
+
if (!Window.isSmallScreen()) {
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
/* onEnd = */ function (elemX, elemY, deltaX, deltaY, pageX, pageY) {
|
|
166
|
+
barHTML.css('transition', '')
|
|
167
|
+
barHTML.css('right', '')
|
|
168
|
+
|
|
169
|
+
if (deltaX > 0 && deltaX > barHTML.width() / 2) {
|
|
170
|
+
close()
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
/* Automatically update options icon according to small screen state */
|
|
176
|
+
Window.screenLayoutChangeSignal.connect(function (smallScreen, landscape) {
|
|
177
|
+
StockIcon.alterElement(optionsButton.find('div.qui-icon'), {variant: smallScreen ? 'white' : 'interactive'})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
Window.$body.append(barHTML)
|
|
181
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @namespace qui.mainui.status
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
6
|
+
|
|
7
|
+
import StockIcon from '$qui/icons/stock-icon.js'
|
|
8
|
+
import * as Icons from '$qui/icons/icons.js'
|
|
9
|
+
import * as Toast from '$qui/messages/toast.js'
|
|
10
|
+
import * as Theme from '$qui/theme.js'
|
|
11
|
+
import VisibilityManager from '$qui/utils/visibility-manager.js'
|
|
12
|
+
import * as Window from '$qui/window.js'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
const STATUS_LOCK_TIMEOUT = 500
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @alias qui.mainui.status.STATUS_OK
|
|
19
|
+
*/
|
|
20
|
+
export const STATUS_OK = 'ok'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @alias qui.mainui.status.STATUS_INFO
|
|
24
|
+
*/
|
|
25
|
+
export const STATUS_INFO = 'info'
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @alias qui.mainui.status.STATUS_WARNING
|
|
29
|
+
*/
|
|
30
|
+
export const STATUS_WARNING = 'warning'
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @alias qui.mainui.status.STATUS_ERROR
|
|
34
|
+
*/
|
|
35
|
+
export const STATUS_ERROR = 'error'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @alias qui.mainui.status.STATUS_SYNC
|
|
39
|
+
*/
|
|
40
|
+
export const STATUS_SYNC = 'sync'
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
let statusIndicator = null
|
|
44
|
+
let pendingStatusParams = null
|
|
45
|
+
let statusLockTimeoutHandle = null
|
|
46
|
+
let statusIndicatorVisibilityManager = null
|
|
47
|
+
let lastStatus = null
|
|
48
|
+
let lastMessage = null
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Update the status indicator.
|
|
53
|
+
* @alias qui.mainui.status.set
|
|
54
|
+
* @param {String} status one of the following statuses:
|
|
55
|
+
* * {@link qui.mainui.status.STATUS_INFO}
|
|
56
|
+
* * {@link qui.mainui.status.STATUS_WARNING}
|
|
57
|
+
* * {@link qui.mainui.status.STATUS_ERROR}
|
|
58
|
+
* * {@link qui.mainui.status.STATUS_SYNC}
|
|
59
|
+
* * {@link qui.mainui.status.STATUS_OK}
|
|
60
|
+
* @param {String} [message] an optional status message
|
|
61
|
+
*/
|
|
62
|
+
export function set(status, message = null) {
|
|
63
|
+
if (statusLockTimeoutHandle) {
|
|
64
|
+
pendingStatusParams = {status, message}
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
lastStatus = status
|
|
69
|
+
lastMessage = message
|
|
70
|
+
|
|
71
|
+
if (status === 'ok') {
|
|
72
|
+
statusIndicatorVisibilityManager.hideElement()
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
statusIndicatorVisibilityManager.showElement()
|
|
76
|
+
/* Keep status locked for STATUS_LOCK_TIMEOUT milliseconds, unless "ok" */
|
|
77
|
+
statusLockTimeoutHandle = setTimeout(function () {
|
|
78
|
+
|
|
79
|
+
statusLockTimeoutHandle = null
|
|
80
|
+
if (pendingStatusParams) {
|
|
81
|
+
set(pendingStatusParams.status, pendingStatusParams.message)
|
|
82
|
+
pendingStatusParams = null
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
}, STATUS_LOCK_TIMEOUT)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let type = status
|
|
89
|
+
let iconName = null
|
|
90
|
+
let decoration = status
|
|
91
|
+
let animation = null
|
|
92
|
+
|
|
93
|
+
switch (status) {
|
|
94
|
+
case STATUS_INFO: {
|
|
95
|
+
iconName = 'info'
|
|
96
|
+
break
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
case STATUS_WARNING: {
|
|
100
|
+
iconName = 'exclam'
|
|
101
|
+
break
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
case STATUS_ERROR: {
|
|
105
|
+
iconName = 'exclam'
|
|
106
|
+
break
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
case STATUS_SYNC: {
|
|
110
|
+
type = 'info'
|
|
111
|
+
decoration = null
|
|
112
|
+
iconName = 'sync'
|
|
113
|
+
animation = Icons.ANIMATION_SPIN
|
|
114
|
+
break
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
case STATUS_OK: {
|
|
118
|
+
type = 'info'
|
|
119
|
+
decoration = 'info'
|
|
120
|
+
iconName = 'check'
|
|
121
|
+
break
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (iconName) {
|
|
126
|
+
if (decoration === 'info') {
|
|
127
|
+
decoration = null
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
decoration = Theme.getVar(`${decoration}-color`)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let variant = 'foreground'
|
|
134
|
+
if (Window.isSmallScreen()) {
|
|
135
|
+
/* On small screens, we always want white icons on top bar */
|
|
136
|
+
variant = 'white'
|
|
137
|
+
}
|
|
138
|
+
else if (message) {
|
|
139
|
+
variant = 'interactive'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
new StockIcon({
|
|
143
|
+
name: iconName,
|
|
144
|
+
decoration: decoration,
|
|
145
|
+
variant: variant,
|
|
146
|
+
animation: animation
|
|
147
|
+
}).applyTo(statusIndicator.find('.qui-icon'))
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (message) {
|
|
151
|
+
statusIndicator.attr('data-message', message)
|
|
152
|
+
statusIndicator.attr('data-type', type)
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
statusIndicator.attr('data-message', '')
|
|
156
|
+
statusIndicator.attr('data-type', type)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
export function init() {
|
|
162
|
+
statusIndicator = $('div.qui-top-bar div.qui-status-indicator')
|
|
163
|
+
statusIndicator.on('click', function () {
|
|
164
|
+
let message = statusIndicator.attr('data-message')
|
|
165
|
+
if (!message) {
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
let type = statusIndicator.attr('data-type')
|
|
170
|
+
|
|
171
|
+
Toast.show({message, type})
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
statusIndicatorVisibilityManager = new VisibilityManager({element: statusIndicator})
|
|
175
|
+
|
|
176
|
+
Window.screenLayoutChangeSignal.connect(function () {
|
|
177
|
+
set(lastStatus, lastMessage)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
Theme.changeSignal.connect(function () {
|
|
181
|
+
set(lastStatus, lastMessage)
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
set(STATUS_OK)
|
|
185
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @namespace qui.mainui.topbar
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import $ from '$qui/lib/jquery.module.js'
|
|
6
|
+
|
|
7
|
+
import * as Window from '$qui/window.js'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
let barHTML = null
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Return the top bar HTML element.
|
|
15
|
+
* @returns {jQuery}
|
|
16
|
+
*/
|
|
17
|
+
export function getHTML() {
|
|
18
|
+
return barHTML
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Add a button to the top bar.
|
|
23
|
+
* @alias qui.mainui.topbar.addButton
|
|
24
|
+
* @param {jQuery} button the button to add
|
|
25
|
+
*/
|
|
26
|
+
export function addButton(button) {
|
|
27
|
+
button.addClass('qui-top-button')
|
|
28
|
+
$('div.qui-status-indicator').before(button)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Set or clear the top bar title.
|
|
33
|
+
* @alias qui.mainui.topbar.setTitle
|
|
34
|
+
* @param {?String} title
|
|
35
|
+
*/
|
|
36
|
+
export function setTitle(title) {
|
|
37
|
+
barHTML.children('div.qui-top-bar-title-container').html(title || '')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function init() {
|
|
41
|
+
barHTML = $('<div></div>', {class: 'qui-top-bar'})
|
|
42
|
+
|
|
43
|
+
let menuButton = $('<div></div>', {class: 'qui-base-button qui-top-button qui-menu-button'})
|
|
44
|
+
menuButton.append($('<div></div>', {class: 'qui-icon'}))
|
|
45
|
+
barHTML.append(menuButton)
|
|
46
|
+
|
|
47
|
+
barHTML.append($('<div></div>', {class: 'qui-breadcrumbs-container'}))
|
|
48
|
+
barHTML.append($('<div></div>', {class: 'qui-top-bar-title-container'}))
|
|
49
|
+
|
|
50
|
+
let optionsButton = $('<div></div>', {class: 'qui-base-button qui-top-button qui-options-button hidden'})
|
|
51
|
+
optionsButton.append($('<div></div>', {class: 'qui-icon'}))
|
|
52
|
+
barHTML.append(optionsButton)
|
|
53
|
+
|
|
54
|
+
let statusIndicator = $('<div></div>', {class: 'qui-base-button qui-top-button qui-status-indicator'})
|
|
55
|
+
statusIndicator.append($('<div></div>', {class: 'qui-icon'}))
|
|
56
|
+
barHTML.append(statusIndicator)
|
|
57
|
+
|
|
58
|
+
Window.$body.append(barHTML)
|
|
59
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @namespace qui.messages.commonmessageforms
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export {default as SimpleMessageForm} from './simple-message-form.js'
|
|
6
|
+
export {default as ConfirmMessageForm} from './confirm-message-form.js'
|
|
7
|
+
export {default as StickySimpleMessageForm} from './sticky-simple-message-form.js'
|