@openremote/or-app 1.8.0-snapshot.20250725074716 → 1.8.0-snapshot.20250725120001

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/lib/index.js CHANGED
@@ -1,76 +1,547 @@
1
- var __decorate=this&&this.__decorate||function(e,i,t,o){var r,n=arguments.length,a=n<3?i:null===o?o=Object.getOwnPropertyDescriptor(i,t):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,i,t,o);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(a=(n<3?r(a):n>3?r(i,t,a):r(i,t))||a);return n>3&&a&&Object.defineProperty(i,t,a),a},__awaiter=this&&this.__awaiter||function(e,i,t,o){return new(t||(t=Promise))(function(r,n){function a(e){try{l(o.next(e))}catch(e){n(e)}}function s(e){try{l(o.throw(e))}catch(e){n(e)}}function l(e){var i;e.done?r(e.value):((i=e.value)instanceof t?i:new t(function(e){e(i)})).then(a,s)}l((o=o.apply(e,i||[])).next())})};import{css as e,html as i,LitElement as t,unsafeCSS as o}from"lit";import{customElement as r,property as n,query as a,state as s}from"lit/decorators.js";import{router as l}from"./types";import"@openremote/or-translate";import"@openremote/or-mwc-components/or-mwc-menu";import"@openremote/or-mwc-components/or-mwc-snackbar";import"./or-header";import"@openremote/or-icon";import{updateMetadata as p}from"pwa-helpers/metadata";import c from"i18next";import h,{DefaultColor2 as f,DefaultColor3 as d,DefaultColor4 as g,normaliseConfig as m,ORError as _,OREvent as u,Util as v}from"@openremote/core";import{DEFAULT_LANGUAGES as y}from"./or-header";import{OrMwcDialog as b,showDialog as C,showErrorDialog as w}from"@openremote/or-mwc-components/or-mwc-dialog";import{OrMwcSnackbar as E}from"@openremote/or-mwc-components/or-mwc-snackbar";import{setOffline as A,setVisibility as O,updatePage as k,updateRealm as F}from"./app";import{InputType as $}from"@openremote/or-mwc-components/or-mwc-input";import{pageOfflineProvider as L}from"./page-offline";export const DefaultLogo=require("../images/logo.svg");export const DefaultMobileLogo=require("../images/logo-mobile.svg");export const DefaultFavIcon=require("../images/favicon.ico");export*from"./app";export*from"./or-header";export*from"./types";export function getDefaultManagerConfig(){return m(DEFAULT_MANAGER_CONFIG)}let DEFAULT_MANAGER_CONFIG={managerUrl:MANAGER_URL||"",keycloakUrl:KEYCLOAK_URL||"",auth:"KEYCLOAK",autoLogin:!0,realm:void 0,consoleAutoEnable:!0,loadTranslations:["or"]},OrApp=class extends t{static get styles(){return e`
2
- :host {
3
- --or-app-color2: ${o(f)};
4
- --or-app-color3: ${o(d)};
5
- --or-app-color4: ${o(g)};
6
- --or-console-primary-color: #4D9D2A;
7
- color: ${o(d)};
8
- fill: ${o(d)};
9
- font-size: 14px;
10
-
11
- height: 100vh; /* Fallback */
12
- height: 100dvh; /* Stretch to dynamic viewport height */
13
- display: flex;
14
- flex: 1;
15
- flex-direction: column;
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
8
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
9
+ return new (P || (P = Promise))(function (resolve, reject) {
10
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
11
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
12
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
13
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
14
+ });
15
+ };
16
+ import { css, html, LitElement, unsafeCSS } from "lit";
17
+ import { customElement, property, query, state } from "lit/decorators.js";
18
+ import { router } from "./types";
19
+ import "@openremote/or-translate";
20
+ import "@openremote/or-mwc-components/or-mwc-menu";
21
+ import "@openremote/or-mwc-components/or-mwc-snackbar";
22
+ import "./or-header";
23
+ import "@openremote/or-icon";
24
+ import { updateMetadata } from "pwa-helpers/metadata";
25
+ import i18next from "i18next";
26
+ import manager, { DefaultColor2, DefaultColor3, DefaultColor4, normaliseConfig, ORError, OREvent, Util } from "@openremote/core";
27
+ import { DEFAULT_LANGUAGES } from "./or-header";
28
+ import { OrMwcDialog, showDialog, showErrorDialog } from "@openremote/or-mwc-components/or-mwc-dialog";
29
+ import { OrMwcSnackbar } from "@openremote/or-mwc-components/or-mwc-snackbar";
30
+ import { setOffline, setVisibility, updatePage, updateRealm } from "./app";
31
+ import { InputType } from "@openremote/or-mwc-components/or-mwc-input";
32
+ import { pageOfflineProvider } from "./page-offline";
33
+ export const DefaultLogo = require("../images/logo.svg");
34
+ export const DefaultMobileLogo = require("../images/logo-mobile.svg");
35
+ export const DefaultFavIcon = require("../images/favicon.ico");
36
+ export * from "./app";
37
+ export * from "./or-header";
38
+ export * from "./types";
39
+ export { DEFAULT_LANGUAGES };
40
+ export function getDefaultManagerConfig() {
41
+ return normaliseConfig(DEFAULT_MANAGER_CONFIG);
42
+ }
43
+ const DEFAULT_MANAGER_CONFIG = {
44
+ managerUrl: (MANAGER_URL || ""),
45
+ keycloakUrl: (KEYCLOAK_URL || ""),
46
+ auth: "KEYCLOAK" /* Auth.KEYCLOAK */,
47
+ autoLogin: true,
48
+ realm: undefined,
49
+ consoleAutoEnable: true,
50
+ loadTranslations: ["or"]
51
+ };
52
+ let OrApp = class OrApp extends LitElement {
53
+ // language=CSS
54
+ static get styles() {
55
+ return css `
56
+ :host {
57
+ --or-app-color2: ${unsafeCSS(DefaultColor2)};
58
+ --or-app-color3: ${unsafeCSS(DefaultColor3)};
59
+ --or-app-color4: ${unsafeCSS(DefaultColor4)};
60
+ --or-console-primary-color: #4D9D2A;
61
+ color: ${unsafeCSS(DefaultColor3)};
62
+ fill: ${unsafeCSS(DefaultColor3)};
63
+ font-size: 14px;
64
+
65
+ height: 100vh; /* Fallback */
66
+ height: 100dvh; /* Stretch to dynamic viewport height */
67
+ display: flex;
68
+ flex: 1;
69
+ flex-direction: column;
70
+ }
71
+
72
+ .main-content {
73
+ display: flex;
74
+ flex: 1;
75
+ box-sizing: border-box;
76
+ background-color: var(--or-app-color2);
77
+ overflow: auto;
78
+ }
79
+
80
+ .no-scroll {
81
+ overflow: hidden;
82
+ }
83
+
84
+ main > * {
85
+ display: flex;
86
+ flex: 1;
87
+ position: relative;
88
+ }
89
+
90
+ .desktop-hidden {
91
+ display: none !important;
92
+ }
93
+
94
+ @media only screen and (max-width: 780px) {
95
+ .desktop-hidden {
96
+ display: inline-block !important;
97
+ }
98
+ }
99
+
100
+ /* HEADER STYLES */
101
+ or-header a > or-icon {
102
+ margin-right: 10px;
103
+ }
104
+ `;
105
+ }
106
+ constructor(store) {
107
+ super();
108
+ this._initialised = false;
109
+ this._offline = false;
110
+ this._showOfflineFallback = false;
111
+ this._onEvent = (ev) => this._handleEvent(ev);
112
+ this._onVisibilityChanged = (ev) => this._handleVisibilityChange(ev);
113
+ this._store = store;
114
+ // Set this element as the host for dialogs
115
+ OrMwcDialog.DialogHostElement = this;
116
+ OrMwcSnackbar.DialogHostElement = this;
117
+ }
118
+ getState() {
119
+ return this._store.getState();
120
+ }
121
+ // Using HTML 'visibilitychange' listener to see whether the Manager is visible for the user.
122
+ // TODO; Add an ConsoleProvider that listens to background/foreground changes, and dispatch the respective OREvent. This will improve responsiveness of logic attached to it.
123
+ // For example used for triggering reconnecting logic once the UI becomes visible again.
124
+ _handleVisibilityChange(ev) {
125
+ var _a;
126
+ if (document.visibilityState === "visible") {
127
+ this._store.dispatch((setVisibility(true)));
128
+ // When the manager appears on Mobile devices, but the connection is OFFLINE,
129
+ // we reset the timer to the {appConfig.offlineTimeout} seconds. This is because we saw issues with reopening the app,
130
+ // and seeing a connection interval of 30+ seconds. We now give the user the benefit of the doubt, by resetting the timer.
131
+ if (((_a = manager.console) === null || _a === void 0 ? void 0 : _a.isMobile) && this._offline) {
132
+ this._startOfflineFallbackTimer(true);
16
133
  }
17
-
18
- .main-content {
19
- display: flex;
20
- flex: 1;
21
- box-sizing: border-box;
22
- background-color: var(--or-app-color2);
23
- overflow: auto;
134
+ // Always try reconnecting (just in case we are disconnected)
135
+ manager.reconnect();
136
+ }
137
+ else {
138
+ this._store.dispatch((setVisibility(false)));
139
+ }
140
+ }
141
+ connectedCallback() {
142
+ super.connectedCallback();
143
+ this._storeUnsubscribe = this._store.subscribe(() => this.stateChanged(this.getState()));
144
+ document.addEventListener("visibilitychange", this._onVisibilityChanged);
145
+ this.stateChanged(this.getState());
146
+ }
147
+ disconnectedCallback() {
148
+ this._storeUnsubscribe();
149
+ document.removeEventListener("visibilityChange", this._onVisibilityChanged);
150
+ manager.removeListener(this._onEvent);
151
+ super.disconnectedCallback();
152
+ }
153
+ firstUpdated(_changedProperties) {
154
+ super.firstUpdated(_changedProperties);
155
+ const managerConfig = this.managerConfig ? Object.assign(Object.assign({}, DEFAULT_MANAGER_CONFIG), this.managerConfig) : DEFAULT_MANAGER_CONFIG;
156
+ if (!managerConfig.realm) {
157
+ // Use realm query parameter if no specific realm provided
158
+ managerConfig.realm = Util.getQueryParameter("realm");
159
+ }
160
+ if (!managerConfig.defaultLanguage) {
161
+ managerConfig.defaultLanguage = Util.getBrowserLanguage();
162
+ }
163
+ managerConfig.skipFallbackToBasicAuth = true; // We do this so we can load styling config before displaying basic login
164
+ managerConfig.basicLoginProvider = (u, p) => this.doBasicLogin(u, p);
165
+ console.info("Initialising the manager");
166
+ manager.init(managerConfig).then((success) => __awaiter(this, void 0, void 0, function* () {
167
+ if (!success && manager.error === ORError.AUTH_FAILED && (!managerConfig.auth || managerConfig.auth === "KEYCLOAK" /* Auth.KEYCLOAK */)) {
168
+ this.doAppConfigInit();
169
+ // Fallback to basic auth now styling is loaded
170
+ managerConfig.auth = "BASIC" /* Auth.BASIC */;
171
+ success = yield manager.init(managerConfig);
24
172
  }
25
-
26
- .no-scroll {
27
- overflow: hidden;
28
- }
29
-
30
- main > * {
31
- display: flex;
32
- flex: 1;
33
- position: relative;
173
+ if (success) {
174
+ this.doAppConfigInit();
175
+ if (!this.appConfig) {
176
+ showErrorDialog("appError.noConfig", document.body);
177
+ console.error("No AppConfig supplied");
178
+ return;
179
+ }
180
+ if (!this._config) {
181
+ showErrorDialog("appError.noConfig", document.body);
182
+ console.error("No default AppConfig or realm specific config provided so cannot render");
183
+ return;
184
+ }
185
+ if (!this._store) {
186
+ showErrorDialog("appError.noReduxStore", document.body);
187
+ console.error("No Redux store supplied");
188
+ return;
189
+ }
190
+ if (!this.appConfig.pages || Object.keys(this.appConfig.pages).length === 0) {
191
+ showErrorDialog("appError.noPages", document.body);
192
+ console.error("No page providers");
193
+ return;
194
+ }
195
+ // Load available realm info
196
+ const response = yield manager.rest.api.RealmResource.getAccessible();
197
+ this._realms = response.data;
198
+ let realm = undefined;
199
+ // Set current display realm if super user
200
+ if (manager.isSuperUser()) {
201
+ // Look in session storage
202
+ realm = window.sessionStorage.getItem("realm");
203
+ if (realm && !this._realms.some(r => r.name === realm)) {
204
+ realm = undefined;
205
+ }
206
+ }
207
+ this._store.dispatch(updateRealm(realm || manager.getRealm() || "master"));
208
+ this._initialised = true;
209
+ // Register listener to change global state based on certain events
210
+ manager.addListener(this._onEvent);
211
+ // Create route listener to set header active item (this must be done before any routes added)
212
+ const headerUpdater = (activeMenu) => {
213
+ this._activeMenu = activeMenu;
214
+ };
215
+ router.hooks({
216
+ before(done, match) {
217
+ headerUpdater(match ? match.url.split('/')[0] : undefined);
218
+ done();
219
+ }
220
+ });
221
+ // Configure routes
222
+ this.appConfig.pages.forEach((pageProvider, index) => {
223
+ if (pageProvider.routes) {
224
+ pageProvider.routes.forEach((route) => {
225
+ router.on(route, (match) => {
226
+ this._store.dispatch(updatePage({ page: pageProvider.name, params: match.data }));
227
+ });
228
+ });
229
+ }
230
+ });
231
+ if (this.appConfig.pages.length > 0) {
232
+ router.notFound(() => {
233
+ this._store.dispatch(updatePage(this.appConfig.pages[0].name));
234
+ });
235
+ }
236
+ router.resolve();
34
237
  }
35
-
36
- .desktop-hidden {
37
- display: none !important;
238
+ else {
239
+ showErrorDialog(manager.isError ? "managerError." + manager.error : "");
38
240
  }
39
-
40
- @media only screen and (max-width: 780px) {
41
- .desktop-hidden {
42
- display: inline-block !important;
241
+ }));
242
+ }
243
+ updated(changedProps) {
244
+ var _a, _b;
245
+ super.updated(changedProps);
246
+ if (!this._initialised) {
247
+ return;
248
+ }
249
+ // If either page or 'offline'-status is changed, it should update to the correct page,
250
+ // by appending the page to the HTML content
251
+ if (changedProps.has("_page") || changedProps.has("_offline") || changedProps.has("_showOfflineFallback")) {
252
+ if (this._mainElem) {
253
+ const pageProvider = this.appConfig.pages.find((page) => page.name === this._page);
254
+ const showOfflineFallback = (this._showOfflineFallback && !(pageProvider === null || pageProvider === void 0 ? void 0 : pageProvider.allowOffline));
255
+ const offlinePage = this._mainElem.querySelector('#offline-page');
256
+ // If page has changed, replace the previous content with the new page.
257
+ // However, if no page is present yet, append it to the page.
258
+ if (changedProps.has('_page') && pageProvider) {
259
+ const currentPage = this._mainElem.firstElementChild;
260
+ if (currentPage) {
261
+ const newPage = pageProvider.pageCreator();
262
+ if (showOfflineFallback) {
263
+ newPage.style.setProperty('display', 'none'); // hide the new page while offline overlay page is shown
264
+ newPage.setAttribute('loadedDuringOffline', 'true'); // mark the page as "loaded during offline", since the content is either empty or invalid
265
+ }
266
+ this._mainElem.replaceChild(newPage, currentPage); // replace content
267
+ }
268
+ else {
269
+ this._mainElem.appendChild(pageProvider.pageCreator());
270
+ }
271
+ }
272
+ // CASE: "Offline overlay page is present, but should not be shown"
273
+ if (offlinePage && !showOfflineFallback) {
274
+ this._mainElem.removeChild(offlinePage); // remove offline overlay
275
+ const elem = this._mainElem.firstElementChild;
276
+ elem === null || elem === void 0 ? void 0 : elem.style.removeProperty('display'); // show the current page again (back to the foreground)
277
+ if (elem === null || elem === void 0 ? void 0 : elem.onRefresh) {
278
+ elem.onRefresh(); // If custom onRefresh() is set by the page, run that function.
279
+ }
280
+ }
281
+ // CASE: "Offline overlay page is NOT present, but needs to be there"
282
+ // It either shows the default offline fallback page, or a custom one defined in the AppConfig.
283
+ else if (!offlinePage && showOfflineFallback) {
284
+ const newOfflinePage = ((_a = this.appConfig) === null || _a === void 0 ? void 0 : _a.offlinePage) ? this.appConfig.offlinePage.pageCreator() : pageOfflineProvider(this._store).pageCreator();
285
+ (_b = this._mainElem.firstElementChild) === null || _b === void 0 ? void 0 : _b.style.setProperty('display', 'none'); // Hide the current page (to the background)
286
+ newOfflinePage.id = "offline-page";
287
+ this._mainElem.appendChild(newOfflinePage);
43
288
  }
44
289
  }
45
-
46
- /* HEADER STYLES */
47
- or-header a > or-icon {
48
- margin-right: 10px;
290
+ this.updateWindowTitle();
291
+ }
292
+ }
293
+ shouldUpdate(changedProps) {
294
+ var _a, _b;
295
+ if (changedProps.has("_realm")) {
296
+ this._config = this._getConfig();
297
+ if (this._realm) {
298
+ manager.displayRealm = this._realm;
299
+ window.sessionStorage.setItem("realm", this._realm);
49
300
  }
50
- `}constructor(e){super(),this._initialised=!1,this._offline=!1,this._showOfflineFallback=!1,this._onEvent=e=>this._handleEvent(e),this._onVisibilityChanged=e=>this._handleVisibilityChange(e),this._store=e,b.DialogHostElement=this,E.DialogHostElement=this}getState(){return this._store.getState()}_handleVisibilityChange(e){var i;"visible"===document.visibilityState?(this._store.dispatch(O(!0)),(null==(i=h.console)?void 0:i.isMobile)&&this._offline&&this._startOfflineFallbackTimer(!0),h.reconnect()):this._store.dispatch(O(!1))}connectedCallback(){super.connectedCallback(),this._storeUnsubscribe=this._store.subscribe(()=>this.stateChanged(this.getState())),document.addEventListener("visibilitychange",this._onVisibilityChanged),this.stateChanged(this.getState())}disconnectedCallback(){this._storeUnsubscribe(),document.removeEventListener("visibilityChange",this._onVisibilityChanged),h.removeListener(this._onEvent),super.disconnectedCallback()}firstUpdated(e){super.firstUpdated(e);let i=this.managerConfig?Object.assign(Object.assign({},DEFAULT_MANAGER_CONFIG),this.managerConfig):DEFAULT_MANAGER_CONFIG;i.realm||(i.realm=v.getQueryParameter("realm")),i.defaultLanguage||(i.defaultLanguage=v.getBrowserLanguage()),i.skipFallbackToBasicAuth=!0,i.basicLoginProvider=(e,i)=>this.doBasicLogin(e,i),console.info("Initialising the manager"),h.init(i).then(e=>__awaiter(this,void 0,void 0,function*(){if(e||h.error!==_.AUTH_FAILED||i.auth&&"KEYCLOAK"!==i.auth||(this.doAppConfigInit(),i.auth="BASIC",e=yield h.init(i)),e){let e;if(this.doAppConfigInit(),!this.appConfig){w("appError.noConfig",document.body),console.error("No AppConfig supplied");return}if(!this._config){w("appError.noConfig",document.body),console.error("No default AppConfig or realm specific config provided so cannot render");return}if(!this._store){w("appError.noReduxStore",document.body),console.error("No Redux store supplied");return}if(!this.appConfig.pages||0===Object.keys(this.appConfig.pages).length){w("appError.noPages",document.body),console.error("No page providers");return}let i=yield h.rest.api.RealmResource.getAccessible();this._realms=i.data,h.isSuperUser()&&(e=window.sessionStorage.getItem("realm"))&&!this._realms.some(i=>i.name===e)&&(e=void 0),this._store.dispatch(F(e||h.getRealm()||"master")),this._initialised=!0,h.addListener(this._onEvent),l.hooks({before(e,i){var t;t=i?i.url.split("/")[0]:void 0,this._activeMenu=t,e()}}),this.appConfig.pages.forEach((e,i)=>{e.routes&&e.routes.forEach(i=>{l.on(i,i=>{this._store.dispatch(k({page:e.name,params:i.data}))})})}),this.appConfig.pages.length>0&&l.notFound(()=>{this._store.dispatch(k(this.appConfig.pages[0].name))}),l.resolve()}else w(h.isError?"managerError."+h.error:"")}))}updated(e){var i,t;if(super.updated(e),this._initialised&&(e.has("_page")||e.has("_offline")||e.has("_showOfflineFallback"))){if(this._mainElem){let o=this.appConfig.pages.find(e=>e.name===this._page),r=this._showOfflineFallback&&!(null==o?void 0:o.allowOffline),n=this._mainElem.querySelector("#offline-page");if(e.has("_page")&&o){let e=this._mainElem.firstElementChild;if(e){let i=o.pageCreator();r&&(i.style.setProperty("display","none"),i.setAttribute("loadedDuringOffline","true")),this._mainElem.replaceChild(i,e)}else this._mainElem.appendChild(o.pageCreator())}if(n&&!r){this._mainElem.removeChild(n);let e=this._mainElem.firstElementChild;null==e||e.style.removeProperty("display"),(null==e?void 0:e.onRefresh)&&e.onRefresh()}else if(!n&&r){let e=(null==(i=this.appConfig)?void 0:i.offlinePage)?this.appConfig.offlinePage.pageCreator():L(this._store).pageCreator();null==(t=this._mainElem.firstElementChild)||t.style.setProperty("display","none"),e.id="offline-page",this._mainElem.appendChild(e)}}this.updateWindowTitle()}}shouldUpdate(e){var i,t;if(e.has("_realm")&&(this._config=this._getConfig(),this._realm?(h.displayRealm=this._realm,window.sessionStorage.setItem("realm",this._realm)):window.sessionStorage.removeItem("realm")),e.has("_config")&&this._config){this._config.logo?this._config.logo=(null!=(i=h.managerUrl)?i:"")+this._config.logo:this._config.logo=DefaultLogo,this._config.logoMobile?this._config.logoMobile=(null!=(t=h.managerUrl)?t:"")+this._config.logoMobile:this._config.logoMobile=DefaultMobileLogo;let e=this._config&&this._config.favicon?(h.managerUrl||"")+this._config.favicon:DefaultFavIcon,o=document.querySelector("link[rel~='icon']");o||((o=document.createElement("link")).rel="icon",document.getElementsByTagName("head")[0].appendChild(o)),o.href=e}return this.updateWindowTitle(),super.shouldUpdate(e)}render(){let e;if(!this._initialised)return i`<or-mwc-dialog id="app-modal"></or-mwc-dialog>`;if(h.consoleAppConfig){let t=h.consoleAppConfig,o=t.primaryColor,r=t.secondaryColor;e=i`<style>:host {--or-console-primary-color:${o};--or-console-secondary-color:${r};}</style>`}return i`
51
- ${this._config.styles?"string"==typeof this._config.styles?i`<style>${this._config.styles}</style>`:this._config.styles.strings:""}
52
- ${e}
53
- ${this._config.header?i`
54
- <or-header .activeMenu="${this._activeMenu}" .store="${this._store}" .realm="${this._realm}" .realms="${this._realms}" .logo="${this._config.logo}" .logoMobile="${this._config.logoMobile}" .config="${this._config.header}"></or-header>
55
- `:""}
56
-
57
- <!-- Main content -->
58
- <main role="main" class="main-content d-none"></main>
59
-
60
- <slot></slot>
61
- `}stateChanged(e){this._realm=e.app.realm,this._page=e.app.page,this._offline=e.app.offline}_handleEvent(e){e===u.OFFLINE?(this._offline||this._store.dispatch(A(!0)),this._startOfflineFallbackTimer()):e===u.ONLINE&&this._offline&&(this._showOfflineFallback=!1,this._completeOfflineFallbackTimer(),this._store.dispatch(A(!1)))}_startOfflineFallbackTimer(e=!1){var i;if(e)this._completeOfflineFallbackTimer(!0);else if(this._offlineFallbackDeferred||this._showOfflineFallback)return;let t=new v.Deferred,o=!1;t.promise.then(()=>{this._showOfflineFallback=this._offline}).finally(()=>{o=!0}),setTimeout(()=>{o||t.resolve()},(null==(i=this.appConfig)?void 0:i.offlineTimeout)||2e4),this._offlineFallbackDeferred=t}_completeOfflineFallbackTimer(e=!1){var i,t;e?null==(i=this._offlineFallbackDeferred)||i.reject():null==(t=this._offlineFallbackDeferred)||t.resolve(),this._offlineFallbackDeferred=void 0}logout(){h.logout()}setLanguage(e){h.language=e}showLanguageModal(){C(new b().setHeading("language").setDismissAction(null).setStyles(i`<style>.selected { color: ${o(g)} }</style>`).setActions(Object.entries(this.appConfig.languages||y).map(([e,t])=>({content:i`<span class="${e===h.language?"selected":""}">${c.t(t)}</span>`,actionName:e,action:()=>{h.language=e}}))))}doAppConfigInit(){this.appConfig=this.appConfig||(this.appConfigProvider?this.appConfigProvider(h):void 0),this.appConfig&&(this._config||(this._config=this._getConfig()))}doBasicLogin(e,t){let o=new v.Deferred,r=e,n=t,a=i`
62
- #login-logo {
63
- width: 24px;
64
- height: 24px;
301
+ else {
302
+ window.sessionStorage.removeItem("realm");
65
303
  }
66
-
67
- #login_wrapper > or-mwc-input {
68
- margin: 10px 0;
69
- width: 100%;
304
+ }
305
+ if (changedProps.has("_config") && this._config) {
306
+ if (!this._config.logo) {
307
+ this._config.logo = DefaultLogo;
308
+ }
309
+ else {
310
+ this._config.logo = ((_a = manager.managerUrl) !== null && _a !== void 0 ? _a : "") + this._config.logo;
311
+ }
312
+ if (!this._config.logoMobile) {
313
+ this._config.logoMobile = DefaultMobileLogo;
314
+ }
315
+ else {
316
+ this._config.logoMobile = ((_b = manager.managerUrl) !== null && _b !== void 0 ? _b : "") + this._config.logoMobile;
317
+ }
318
+ const favIcon = this._config && this._config.favicon ? (manager.managerUrl || "") + this._config.favicon : DefaultFavIcon;
319
+ let link = document.querySelector("link[rel~='icon']");
320
+ if (!link) {
321
+ link = document.createElement("link");
322
+ link.rel = "icon";
323
+ document.getElementsByTagName("head")[0].appendChild(link);
324
+ }
325
+ link.href = favIcon;
326
+ }
327
+ this.updateWindowTitle();
328
+ return super.shouldUpdate(changedProps);
329
+ }
330
+ render() {
331
+ if (!this._initialised) {
332
+ return html `<or-mwc-dialog id="app-modal"></or-mwc-dialog>`;
333
+ }
334
+ let consoleStyles;
335
+ if (manager.consoleAppConfig) {
336
+ const consoleAppConfig = manager.consoleAppConfig;
337
+ const primary = consoleAppConfig.primaryColor;
338
+ const secondary = consoleAppConfig.secondaryColor;
339
+ consoleStyles = html `<style>:host {--or-console-primary-color:${primary};--or-console-secondary-color:${secondary};}</style>`;
340
+ }
341
+ return html `
342
+ ${this._config.styles ? typeof (this._config.styles) === "string" ? html `<style>${this._config.styles}</style>` : this._config.styles.strings : ``}
343
+ ${consoleStyles}
344
+ ${this._config.header ? html `
345
+ <or-header .activeMenu="${this._activeMenu}" .store="${this._store}" .realm="${this._realm}" .realms="${this._realms}" .logo="${this._config.logo}" .logoMobile="${this._config.logoMobile}" .config="${this._config.header}"></or-header>
346
+ ` : ``}
347
+
348
+ <!-- Main content -->
349
+ <main role="main" class="main-content d-none"></main>
350
+
351
+ <slot></slot>
352
+ `;
353
+ }
354
+ stateChanged(state) {
355
+ this._realm = state.app.realm;
356
+ this._page = state.app.page;
357
+ this._offline = state.app.offline;
358
+ }
359
+ _handleEvent(event) {
360
+ if (event === OREvent.OFFLINE) {
361
+ if (!this._offline) {
362
+ this._store.dispatch((setOffline(true)));
363
+ }
364
+ this._startOfflineFallbackTimer(); // start fallback timer (if not done yet)
365
+ }
366
+ else if (event === OREvent.ONLINE) {
367
+ if (this._offline) {
368
+ this._showOfflineFallback = false;
369
+ this._completeOfflineFallbackTimer(); // complete fallback timer
370
+ this._store.dispatch((setOffline(false)));
371
+ }
372
+ }
373
+ }
374
+ // Offline timer logic
375
+ //
376
+ // This will start a Deferred promise that keeps track of the 'wait before showing offline page' timer.
377
+ // - Resolving the promise updates the 'show offline fallback' variable based on OFFLINE state.
378
+ // - Rejecting the promise 'aborts the process' and skips that logic and does nothing.
379
+ //
380
+ // To explain; when the Manager reports "We're offline!" it will wait 10+ seconds before visually reporting the user that he/she is offline.
381
+ // However, if the user reconnects within that time period, we resolve this promise early. (which is why using Deferred is useful)
382
+ _startOfflineFallbackTimer(force = false) {
383
+ var _a;
384
+ if (force) {
385
+ this._completeOfflineFallbackTimer(true);
386
+ }
387
+ else if (this._offlineFallbackDeferred || this._showOfflineFallback) {
388
+ return;
389
+ }
390
+ const deferred = new Util.Deferred();
391
+ let finished = false;
392
+ deferred.promise.then(() => {
393
+ this._showOfflineFallback = this._offline;
394
+ }).finally(() => {
395
+ finished = true;
396
+ });
397
+ setTimeout(() => {
398
+ if (!finished) {
399
+ deferred.resolve();
400
+ } // resolve THIS timer if not done yet.
401
+ }, ((_a = this.appConfig) === null || _a === void 0 ? void 0 : _a.offlineTimeout) || 20000);
402
+ this._offlineFallbackDeferred = deferred;
403
+ }
404
+ // Completes and removes the 'show offline page' timer
405
+ // Resolving the timer updates the 'show offline fallback' variable based on OFFLINE state.
406
+ // if 'aborted' is TRUE it will skip that logic. See startOfflineTimer() for more details.
407
+ _completeOfflineFallbackTimer(aborted = false) {
408
+ var _a, _b;
409
+ if (aborted) {
410
+ (_a = this._offlineFallbackDeferred) === null || _a === void 0 ? void 0 : _a.reject();
411
+ }
412
+ else {
413
+ (_b = this._offlineFallbackDeferred) === null || _b === void 0 ? void 0 : _b.resolve();
414
+ }
415
+ this._offlineFallbackDeferred = undefined;
416
+ }
417
+ logout() {
418
+ manager.logout();
419
+ }
420
+ setLanguage(lang) {
421
+ manager.language = lang;
422
+ }
423
+ showLanguageModal() {
424
+ showDialog(new OrMwcDialog()
425
+ .setHeading("language")
426
+ .setDismissAction(null)
427
+ .setStyles(html `<style>.selected { color: ${unsafeCSS(DefaultColor4)} }</style>`)
428
+ .setActions(Object.entries(this.appConfig.languages || DEFAULT_LANGUAGES).map(([key, value]) => {
429
+ return {
430
+ content: html `<span class="${(key === manager.language) ? 'selected' : ''}">${i18next.t(value)}</span>`,
431
+ actionName: key,
432
+ action: () => {
433
+ manager.language = key;
434
+ }
435
+ };
436
+ })));
437
+ }
438
+ doAppConfigInit() {
439
+ this.appConfig = this.appConfig || (this.appConfigProvider ? this.appConfigProvider(manager) : undefined);
440
+ if (!this.appConfig) {
441
+ return;
442
+ }
443
+ if (!this._config) {
444
+ this._config = this._getConfig();
445
+ }
446
+ }
447
+ doBasicLogin(username, password) {
448
+ const deferred = new Util.Deferred();
449
+ let u = username;
450
+ let p = password;
451
+ // language=CSS
452
+ const styles = html `
453
+ #login-logo {
454
+ width: 24px;
455
+ height: 24px;
456
+ }
457
+
458
+ #login_wrapper > or-mwc-input {
459
+ margin: 10px 0;
460
+ width: 100%;
461
+ }
462
+ `;
463
+ const dialog = showDialog(new OrMwcDialog()
464
+ .setStyles(html `<style>${styles}</style>`)
465
+ .setHeading(html `<img id="login-logo" src="${this._config.logoMobile || this._config.logo}" /></or-icon><or-translate value="login"></or-translate>`)
466
+ .setContent(html `
467
+ <div id="login_wrapper">
468
+ <or-mwc-input .label="${i18next.t("user")}" .type="${InputType.TEXT}" min="1" required .value="${username}" @or-mwc-input-changed="${(e) => u = e.detail.value}"></or-mwc-input>
469
+ <or-mwc-input .label="${i18next.t("password")}" .type="${InputType.PASSWORD}" min="1" required .value="${password}" @or-mwc-input-changed="${(e) => p = e.detail.value}"></or-mwc-input>
470
+ </div>
471
+ `)
472
+ .setActions([
473
+ {
474
+ actionName: "submit",
475
+ default: true,
476
+ action: () => {
477
+ deferred.resolve({
478
+ cancel: false,
479
+ username: u,
480
+ password: p
481
+ });
482
+ },
483
+ content: html `<or-mwc-input .type=${InputType.BUTTON} .label="${i18next.t("submit")}" raised></or-mwc-input>`
70
484
  }
71
- `;return C(new b().setStyles(i`<style>${a}</style>`).setHeading(i`<img id="login-logo" src="${this._config.logoMobile||this._config.logo}" /></or-icon><or-translate value="login"></or-translate>`).setContent(i`
72
- <div id="login_wrapper">
73
- <or-mwc-input .label="${c.t("user")}" .type="${$.TEXT}" min="1" required .value="${e}" @or-mwc-input-changed="${e=>r=e.detail.value}"></or-mwc-input>
74
- <or-mwc-input .label="${c.t("password")}" .type="${$.PASSWORD}" min="1" required .value="${t}" @or-mwc-input-changed="${e=>n=e.detail.value}"></or-mwc-input>
75
- </div>
76
- `).setActions([{actionName:"submit",default:!0,action:()=>{o.resolve({cancel:!1,username:r,password:n})},content:i`<or-mwc-input .type=${$.BUTTON} .label="${c.t("submit")}" raised></or-mwc-input>`}]),document.body),o.promise}updateWindowTitle(){if(!this._initialised)return;let e=this._config.appTitle||"",i=c.isInitialized?c.t(e):e,t=this._mainElem?this._mainElem.firstElementChild:void 0;t&&(i+=c.isInitialized?" - "+c.t(t.name):" - "+t.name),p({title:i,description:i})}_getConfig(){let e=this.appConfig.realms?this.appConfig.realms.default:{},i=this.appConfig.realms?this.appConfig.realms[this._realm||""]:void 0;return i=v.mergeObjects(e,i,!1),this.appConfig&&this.appConfig.superUserHeader&&h.isSuperUser()&&(i.header=this.appConfig.superUserHeader),i}};__decorate([n({type:Object})],OrApp.prototype,"appConfig",void 0),__decorate([n({type:Object})],OrApp.prototype,"managerConfig",void 0),__decorate([a("main")],OrApp.prototype,"_mainElem",void 0),__decorate([s()],OrApp.prototype,"_initialised",void 0),__decorate([s()],OrApp.prototype,"_page",void 0),__decorate([s()],OrApp.prototype,"_config",void 0),__decorate([s()],OrApp.prototype,"_realm",void 0),__decorate([s()],OrApp.prototype,"_offline",void 0),__decorate([s()],OrApp.prototype,"_showOfflineFallback",void 0),__decorate([s()],OrApp.prototype,"_activeMenu",void 0),OrApp=__decorate([r("or-app")],OrApp);export{y as DEFAULT_LANGUAGES,OrApp};
485
+ ]), document.body); // Attach to document as or-app isn't visible until initialised
486
+ return deferred.promise;
487
+ }
488
+ updateWindowTitle() {
489
+ if (!this._initialised) {
490
+ return;
491
+ }
492
+ const appTitle = this._config.appTitle || "";
493
+ let pageTitle = (i18next.isInitialized ? i18next.t(appTitle) : appTitle);
494
+ const pageElem = (this._mainElem ? this._mainElem.firstElementChild : undefined);
495
+ if (pageElem) {
496
+ pageTitle += (i18next.isInitialized ? " - " + i18next.t(pageElem.name) : " - " + pageElem.name);
497
+ }
498
+ updateMetadata({
499
+ title: pageTitle,
500
+ description: pageTitle
501
+ });
502
+ }
503
+ _getConfig() {
504
+ const defaultConfig = this.appConfig.realms ? this.appConfig.realms.default : {};
505
+ let realmConfig = this.appConfig.realms ? this.appConfig.realms[this._realm || ""] : undefined;
506
+ realmConfig = Util.mergeObjects(defaultConfig, realmConfig, false);
507
+ if (this.appConfig && this.appConfig.superUserHeader && manager.isSuperUser()) {
508
+ realmConfig.header = this.appConfig.superUserHeader;
509
+ }
510
+ return realmConfig;
511
+ }
512
+ };
513
+ __decorate([
514
+ property({ type: Object })
515
+ ], OrApp.prototype, "appConfig", void 0);
516
+ __decorate([
517
+ property({ type: Object })
518
+ ], OrApp.prototype, "managerConfig", void 0);
519
+ __decorate([
520
+ query("main")
521
+ ], OrApp.prototype, "_mainElem", void 0);
522
+ __decorate([
523
+ state()
524
+ ], OrApp.prototype, "_initialised", void 0);
525
+ __decorate([
526
+ state()
527
+ ], OrApp.prototype, "_page", void 0);
528
+ __decorate([
529
+ state()
530
+ ], OrApp.prototype, "_config", void 0);
531
+ __decorate([
532
+ state()
533
+ ], OrApp.prototype, "_realm", void 0);
534
+ __decorate([
535
+ state()
536
+ ], OrApp.prototype, "_offline", void 0);
537
+ __decorate([
538
+ state()
539
+ ], OrApp.prototype, "_showOfflineFallback", void 0);
540
+ __decorate([
541
+ state()
542
+ ], OrApp.prototype, "_activeMenu", void 0);
543
+ OrApp = __decorate([
544
+ customElement("or-app")
545
+ ], OrApp);
546
+ export { OrApp };
547
+ //# sourceMappingURL=index.js.map