@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.
Files changed (202) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.json +492 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  5. package/.github/ISSUE_TEMPLATE/improvement_proposal.md +20 -0
  6. package/.github/workflows/main.yml +74 -0
  7. package/.pre-commit-config.yaml +8 -0
  8. package/LICENSE.txt +177 -0
  9. package/README.md +4 -0
  10. package/font/dejavusans-bold.woff +0 -0
  11. package/font/dejavusans-bolditalic.woff +0 -0
  12. package/font/dejavusans-italic.woff +0 -0
  13. package/font/dejavusans-regular.woff +0 -0
  14. package/img/qui-icons.svg +1937 -0
  15. package/js/base/base.js +47 -0
  16. package/js/base/condition-variable.js +92 -0
  17. package/js/base/errors.js +36 -0
  18. package/js/base/i18n.js +20 -0
  19. package/js/base/mixwith.js +135 -0
  20. package/js/base/require-js-compat.js +78 -0
  21. package/js/base/signal.js +91 -0
  22. package/js/base/singleton.js +66 -0
  23. package/js/base/timer.js +126 -0
  24. package/js/config.js +184 -0
  25. package/js/forms/common-fields/check-field.js +42 -0
  26. package/js/forms/common-fields/choice-buttons-field.js +30 -0
  27. package/js/forms/common-fields/color-combo-field.js +37 -0
  28. package/js/forms/common-fields/combo-field.js +108 -0
  29. package/js/forms/common-fields/common-fields.js +23 -0
  30. package/js/forms/common-fields/composite-field.js +132 -0
  31. package/js/forms/common-fields/custom-html-field.js +51 -0
  32. package/js/forms/common-fields/email-field.js +30 -0
  33. package/js/forms/common-fields/file-picker-field.js +46 -0
  34. package/js/forms/common-fields/jquery-ui-field.js +111 -0
  35. package/js/forms/common-fields/labels-field.js +69 -0
  36. package/js/forms/common-fields/numeric-field.js +39 -0
  37. package/js/forms/common-fields/password-field.js +28 -0
  38. package/js/forms/common-fields/phone-field.js +26 -0
  39. package/js/forms/common-fields/progress-disk-field.js +69 -0
  40. package/js/forms/common-fields/push-button-field.js +138 -0
  41. package/js/forms/common-fields/slider-field.js +51 -0
  42. package/js/forms/common-fields/text-area-field.js +34 -0
  43. package/js/forms/common-fields/text-field.js +89 -0
  44. package/js/forms/common-fields/up-down-field.js +85 -0
  45. package/js/forms/common-forms/common-forms.js +16 -0
  46. package/js/forms/common-forms/options-form.js +77 -0
  47. package/js/forms/common-forms/page-form.js +115 -0
  48. package/js/forms/form-button.js +202 -0
  49. package/js/forms/form-field.js +1183 -0
  50. package/js/forms/form.js +1181 -0
  51. package/js/forms/forms.js +68 -0
  52. package/js/global-glass.js +100 -0
  53. package/js/icons/default-stock.js +173 -0
  54. package/js/icons/icon.js +64 -0
  55. package/js/icons/icons.js +16 -0
  56. package/js/icons/multi-state-sprites-icon.js +362 -0
  57. package/js/icons/stock-icon.js +219 -0
  58. package/js/icons/stock.js +98 -0
  59. package/js/icons/stocks.js +57 -0
  60. package/js/index.js +232 -0
  61. package/js/lib/jquery.longpress.js +79 -0
  62. package/js/lib/jquery.module.js +4 -0
  63. package/js/lib/logger.module.js +4 -0
  64. package/js/lib/pep.module.js +4 -0
  65. package/js/lists/common-items/common-items.js +5 -0
  66. package/js/lists/common-items/icon-label-list-item.js +86 -0
  67. package/js/lists/common-lists/common-lists.js +5 -0
  68. package/js/lists/common-lists/page-list.js +53 -0
  69. package/js/lists/list-item.js +147 -0
  70. package/js/lists/list.js +636 -0
  71. package/js/lists/lists.js +26 -0
  72. package/js/main-ui/main-ui.js +64 -0
  73. package/js/main-ui/menu-bar.js +144 -0
  74. package/js/main-ui/options-bar.js +181 -0
  75. package/js/main-ui/status.js +185 -0
  76. package/js/main-ui/top-bar.js +59 -0
  77. package/js/messages/common-message-forms/common-message-forms.js +7 -0
  78. package/js/messages/common-message-forms/confirm-message-form.js +81 -0
  79. package/js/messages/common-message-forms/simple-message-form.js +67 -0
  80. package/js/messages/common-message-forms/sticky-simple-message-form.js +27 -0
  81. package/js/messages/message-form.js +107 -0
  82. package/js/messages/messages.js +21 -0
  83. package/js/messages/sticky-modal-page.js +98 -0
  84. package/js/messages/sticky-modal-progress-message.js +27 -0
  85. package/js/messages/toast.js +164 -0
  86. package/js/navigation.js +654 -0
  87. package/js/pages/breadcrumbs.js +124 -0
  88. package/js/pages/common-pages/common-pages.js +6 -0
  89. package/js/pages/common-pages/modal-progress-page.js +83 -0
  90. package/js/pages/common-pages/structured-page.js +46 -0
  91. package/js/pages/page.js +1018 -0
  92. package/js/pages/pages-context.js +154 -0
  93. package/js/pages/pages.js +252 -0
  94. package/js/pwa.js +337 -0
  95. package/js/sections/section.js +612 -0
  96. package/js/sections/sections.js +300 -0
  97. package/js/tables/common-cells/common-cells.js +7 -0
  98. package/js/tables/common-cells/icon-label-table-cell.js +68 -0
  99. package/js/tables/common-cells/push-button-table-cell.js +133 -0
  100. package/js/tables/common-cells/simple-table-cell.js +37 -0
  101. package/js/tables/common-tables/common-tables.js +5 -0
  102. package/js/tables/common-tables/page-table.js +55 -0
  103. package/js/tables/table-cell.js +198 -0
  104. package/js/tables/table-row.js +126 -0
  105. package/js/tables/table.js +492 -0
  106. package/js/tables/tables.js +36 -0
  107. package/js/theme.js +304 -0
  108. package/js/utils/ajax.js +126 -0
  109. package/js/utils/array.js +194 -0
  110. package/js/utils/colors.js +445 -0
  111. package/js/utils/cookies.js +65 -0
  112. package/js/utils/crypto.js +439 -0
  113. package/js/utils/css.js +234 -0
  114. package/js/utils/date.js +300 -0
  115. package/js/utils/files.js +27 -0
  116. package/js/utils/gestures.js +165 -0
  117. package/js/utils/html.js +76 -0
  118. package/js/utils/misc.js +81 -0
  119. package/js/utils/object.js +324 -0
  120. package/js/utils/promise.js +49 -0
  121. package/js/utils/string.js +192 -0
  122. package/js/utils/url.js +187 -0
  123. package/js/utils/utils.js +3 -0
  124. package/js/utils/visibility-manager.js +211 -0
  125. package/js/views/common-views/common-views.js +7 -0
  126. package/js/views/common-views/icon-label-view.js +210 -0
  127. package/js/views/common-views/progress-view.js +89 -0
  128. package/js/views/common-views/structured-view.js +368 -0
  129. package/js/views/view.js +467 -0
  130. package/js/views/views.js +3 -0
  131. package/js/widgets/base-widget.js +23 -0
  132. package/js/widgets/common-widgets/check-button.js +109 -0
  133. package/js/widgets/common-widgets/choice-buttons.js +322 -0
  134. package/js/widgets/common-widgets/color-combo.js +104 -0
  135. package/js/widgets/common-widgets/combo.js +645 -0
  136. package/js/widgets/common-widgets/common-widgets.js +17 -0
  137. package/js/widgets/common-widgets/email-input.js +7 -0
  138. package/js/widgets/common-widgets/file-picker.js +133 -0
  139. package/js/widgets/common-widgets/labels.js +132 -0
  140. package/js/widgets/common-widgets/numeric-input.js +49 -0
  141. package/js/widgets/common-widgets/password-input.js +91 -0
  142. package/js/widgets/common-widgets/phone-input.js +7 -0
  143. package/js/widgets/common-widgets/progress-disk.js +174 -0
  144. package/js/widgets/common-widgets/push-button.js +155 -0
  145. package/js/widgets/common-widgets/slider.js +455 -0
  146. package/js/widgets/common-widgets/text-area.js +52 -0
  147. package/js/widgets/common-widgets/text-input.js +174 -0
  148. package/js/widgets/common-widgets/up-down.js +351 -0
  149. package/js/widgets/widgets.js +57 -0
  150. package/js/window.js +557 -0
  151. package/jsdoc.conf.json +20 -0
  152. package/less/base.less +123 -0
  153. package/less/forms/common-fields.less +101 -0
  154. package/less/forms/common-forms.less +5 -0
  155. package/less/forms/form-button.less +21 -0
  156. package/less/forms/form-field.less +266 -0
  157. package/less/forms/form.less +131 -0
  158. package/less/global-glass.less +64 -0
  159. package/less/icon-label-view.less +82 -0
  160. package/less/icons.less +144 -0
  161. package/less/lists.less +105 -0
  162. package/less/main-ui.less +328 -0
  163. package/less/messages.less +189 -0
  164. package/less/no-effects.less +24 -0
  165. package/less/pages/breadcrumbs.less +98 -0
  166. package/less/pages/common-pages.less +36 -0
  167. package/less/pages/page.less +70 -0
  168. package/less/progress-view.less +51 -0
  169. package/less/stock-icons.less +43 -0
  170. package/less/structured-view.less +245 -0
  171. package/less/tables.less +84 -0
  172. package/less/theme-dark.less +133 -0
  173. package/less/theme-light.less +132 -0
  174. package/less/theme.less +419 -0
  175. package/less/visibility-manager.less +11 -0
  176. package/less/widgets/check-button.less +96 -0
  177. package/less/widgets/choice-buttons.less +160 -0
  178. package/less/widgets/color-combo.less +33 -0
  179. package/less/widgets/combo.less +230 -0
  180. package/less/widgets/common-buttons.less +120 -0
  181. package/less/widgets/common.less +24 -0
  182. package/less/widgets/input.less +258 -0
  183. package/less/widgets/labels.less +81 -0
  184. package/less/widgets/progress-disk.less +70 -0
  185. package/less/widgets/slider.less +199 -0
  186. package/less/widgets/updown.less +115 -0
  187. package/less/widgets/various.less +36 -0
  188. package/package.json +47 -0
  189. package/pyproject.toml +45 -0
  190. package/qui/__init__.py +110 -0
  191. package/qui/constants.py +1 -0
  192. package/qui/exceptions.py +2 -0
  193. package/qui/j2template.py +71 -0
  194. package/qui/settings.py +60 -0
  195. package/qui/templates/manifest.json +25 -0
  196. package/qui/templates/qui.html +126 -0
  197. package/qui/templates/service-worker.js +188 -0
  198. package/qui/web/__init__.py +0 -0
  199. package/qui/web/tornado.py +220 -0
  200. package/scripts/postinstall.sh +10 -0
  201. package/webpack/webpack-adjust-css-urls-loader.js +36 -0
  202. 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'