@openremote/or-log-viewer 1.8.0-snapshot.20250725070921 → 1.8.0-snapshot.20250725120000

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,181 +1,583 @@
1
- var OrLogViewer_1,__decorate=this&&this.__decorate||function(e,t,i,o){var a,r=arguments.length,s=r<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,i,o);else for(var l=e.length-1;l>=0;l--)(a=e[l])&&(s=(r<3?a(s):r>3?a(t,i,s):a(t,i))||s);return r>3&&s&&Object.defineProperty(t,i,s),s},__awaiter=this&&this.__awaiter||function(e,t,i,o){return new(i||(i=Promise))(function(a,r){function s(e){try{n(o.next(e))}catch(e){r(e)}}function l(e){try{n(o.throw(e))}catch(e){r(e)}}function n(e){var t;e.done?a(e.value):((t=e.value)instanceof i?t:new i(function(e){e(t)})).then(s,l)}n((o=o.apply(e,t||[])).next())})};import{css as e,html as t,LitElement as i,unsafeCSS as o}from"lit";import{customElement as a,property as r,query as s}from"lit/decorators.js";import l from"i18next";import{translate as n}from"@openremote/or-translate";import*as c from"@openremote/model";import d,{DefaultColor2 as h,DefaultColor3 as p,DefaultColor4 as g,DefaultColor5 as m,Util as _}from"@openremote/core";import"@openremote/or-mwc-components/or-mwc-input";import"@openremote/or-components/or-panel";import"@openremote/or-translate";import{InputType as u}from"@openremote/or-mwc-components/or-mwc-input";import v from"moment";import"@openremote/or-mwc-components/or-mwc-menu";import{getContentWithMenuTemplate as w}from"@openremote/or-mwc-components/or-mwc-menu";import{showSnackbar as b}from"@openremote/or-mwc-components/or-mwc-snackbar";import{when as f}from"lit/directives/when.js";let linkParser=require("http-link-header"),tableStyle=require("@material/data-table/dist/mdc.data-table.css"),style=e`
2
- :host {
3
- --internal-or-log-viewer-background-color: var(--or-log-viewer-background-color, var(--or-app-color2, ${o(h)}));
4
- --internal-or-log-viewer-text-color: var(--or-log-viewer-text-color, var(--or-app-color3, ${o(p)}));
5
- --internal-or-log-viewer-controls-margin: var(--or-log-viewer-controls-margin, 0);
6
-
7
- display: block;
8
- }
9
-
10
- :host([hidden]) {
11
- display: none;
12
- }
13
-
14
- #container {
15
- display: flex;
16
- min-width: 0;
17
- width: 100%;
18
- height: 100%;
19
- flex-direction: column;
20
- }
21
-
22
- #msg {
23
- height: 100%;
24
- width: 100%;
25
- justify-content: center;
26
- align-items: center;
27
- text-align: center;
28
- }
29
-
30
- #msg:not([hidden]) {
31
- display: flex;
32
- }
33
-
34
- #controls {
35
- flex: 0;
36
- display: flex;
37
- flex-wrap: wrap;
38
- justify-content: space-between;
39
- margin: var(--internal-or-log-viewer-controls-margin);
40
- padding: 0 20px 20px 20px;
41
- }
42
-
43
- #controls > * {
44
- margin-top: 20px;
45
- }
46
-
47
- #time-controls {
48
- display: flex;
49
- align-items: center;
50
- }
51
-
52
- #live-button {
53
- margin-right: 40px;
54
- }
55
-
56
- /* min-width of selects is 200px somehow
57
- #period-select {
58
- width: 90px;
59
- }
60
-
61
- #level-select {
62
- width: 120px;
63
- }
64
-
65
- #limit-select {
66
- width: 80px;
67
- }
68
- */
69
-
70
- #log-controls, #ending-controls, #page-controls {
71
- display: flex;
72
- max-width: 100%;
73
- align-items: center;
74
- }
75
-
76
- #ending-controls {
77
- float: right;
78
- margin: 0 10px;
79
- }
80
-
81
- #log-controls > *, #ending-controls > *, #page-controls > * {
82
- padding: 0 5px;
83
- }
84
-
85
- #page-controls[hidden] {
86
- visibility: hidden;
87
- }
88
-
89
- #ending-date {
90
- min-width: 0;
91
- }
92
-
93
- #table-container {
94
- height: 100%;
95
- overflow: auto;
96
- }
97
-
98
- #table {
99
- width: 100%;
100
- margin-bottom: 10px;
101
- }
102
-
103
- #table > table {
104
- width: 100%;
105
- table-layout: fixed;
106
- }
107
-
108
- #table th:not(.icon-cell), #table td:not(.icon-cell) {
109
- word-wrap: break-word;
110
- white-space: pre-wrap;
111
- }
112
-
113
- .copy-button {
114
- --or-mwc-input-color: var(--or-app-color5, ${o(m)});
115
- }
116
-
117
- .copy-button:hover {
118
- --or-mwc-input-color: var(--or-app-color4, ${o(g)});
119
- }
120
- `,OrLogViewer=OrLogViewer_1=class extends n(l)(i){constructor(){super(...arguments),this.live=!1,this._loading=!1,this._currentPage=1}static get styles(){return[e`${o(tableStyle)}`,style]}connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),this._cleanup(),this._unsubscribeEvents()}shouldUpdate(e){return(e.has("level")||e.has("interval")||e.has("timestamp")||e.has("limit")||e.has("categories")||e.has("filter")||e.has("live"))&&!this.live&&(this._pageCount=void 0,this._currentPage=1,this._data=void 0),this.interval||(this.interval=OrLogViewer_1.DEFAULT_INTERVAL),!this.categories&&this.config&&this.config.initialCategories&&(this.categories=[...this.config.initialCategories]),void 0===this.filter&&this.config&&this.config.initialFilter&&(this.filter=this.config.initialFilter),this.level||(this.config&&this.config.initialLevel?this.level=this.config.initialLevel:this.level=OrLogViewer_1.DEFAULT_LEVEL),this.live||this.timestamp||(this.timestamp=new Date),this._data||this.live||this._loadData(),e.has("live")&&(this.live?this._subscribeEvents():this._unsubscribeEvents()),super.shouldUpdate(e)}render(){let e=this._loading,i=this.live,o=this.config&&this.config.hideCategories,a=this.config&&this.config.hideFilter,r=this.config&&this.config.hideLevel;return t`
121
- <div id="container">
122
- <div id="controls">
123
- <div id="log-controls">
124
- ${o?"":w(t`<or-mwc-input .type=${u.BUTTON} raised ?disabled="${e}" .label="${l.t("categories")}" icontrailing="chevron-down"></or-mwc-input>`,this._getCategoryMenuItems(),this.categories,e=>this._onCategoriesChanged(e),()=>this._onCategoriesClosed(),!0)}
125
- <or-mwc-input ?hidden="${a}" .type="${u.TEXT}" outlined ?disabled="${e}" icontrailing="magnify" .label="${l.t("subCategoryFilters")}" .value="${this.filter}" @or-mwc-input-changed="${e=>this._onFilterChanged(e.detail.value)}"></or-mwc-input>
126
- <or-mwc-input ?hidden="${r}" .type="${u.SELECT}" id="level-select" ?disabled="${e}" .label="${l.t("level")}" @or-mwc-input-changed="${e=>this._onLevelChanged(e.detail.value)}" .value="${this.level}" .options="${this._getLevelOptions()}"></or-mwc-input>
127
- <or-mwc-input .type="${u.SELECT}" id="limit-select" ?disabled="${e}" .label="${l.t("limit")}" @or-mwc-input-changed="${e=>this._onLimitChanged(e.detail.value)}" .value="${""+this.getLimit()}" .options="${this._getLimitOptions()}"></or-mwc-input>
128
- </div>
129
- <div id="page-controls" ?hidden="${i||!this._pageCount||!this._data||0===this._data.length}">
130
- <or-mwc-input class="button" .type="${u.BUTTON}" ?disabled="${e||i||1===this._currentPage}" icon="chevron-left" @or-mwc-input-changed="${()=>this._updatePage(!1)}"></or-mwc-input>
131
- <span>${this._currentPage}</span><or-translate value="of"></or-translate><span>${this._pageCount}</span>
132
- <or-mwc-input class="button" .type="${u.BUTTON}" ?disabled="${e||i||this._currentPage===this._pageCount||this._data&&this._data.length<this.getLimit()}" icon="chevron-right" @or-mwc-input-changed="${()=>this._updatePage(!0)}"></or-mwc-input>
133
- </div>
134
- <div id="time-controls">
135
- <or-mwc-input id="live-button" .type="${u.CHECKBOX}" ?disabled="${e}" .label="${l.t("live")}" @or-mwc-input-changed="${e=>this._onLiveChanged(e.detail.value)}" .value="${this.live}"></or-mwc-input>
136
- <or-mwc-input .type="${u.SELECT}" id="period-select" ?disabled="${e||i}" .label="${l.t("period")}" @or-mwc-input-changed="${e=>this.interval=e.detail.value}" .value="${this.interval}" .options="${this._getIntervalOptions()}"></or-mwc-input>
137
- <div id="ending-controls">
138
- <or-mwc-input class="button" .type="${u.BUTTON}" ?disabled="${e||i}" icon="chevron-left" @or-mwc-input-changed="${()=>this.timestamp=this._calculateTimestamp(this.timestamp,!1)}"></or-mwc-input>
139
- <or-mwc-input id="ending-date" .type="${u.DATETIME}" ?disabled="${e||i}" label="${l.t("ending")}" .value="${this.timestamp}" @or-mwc-input-changed="${e=>this.timestamp=this._calculateTimestamp(v(e.detail.value).toDate())}"></or-mwc-input>
140
- <or-mwc-input class="button" .type="${u.BUTTON}" ?disabled="${e||i}" icon="chevron-right" @or-mwc-input-changed="${()=>this.timestamp=this._calculateTimestamp(this.timestamp,!0)}"></or-mwc-input>
141
- <or-mwc-input class="button" .type="${u.BUTTON}" ?disabled="${e||i}" icon="chevron-double-right" @or-mwc-input-changed="${()=>this.timestamp=this._calculateTimestamp(new Date)}"></or-mwc-input>
142
- </div>
143
- </div>
144
- </div>
145
-
146
- ${e?t`<div id="msg">${l.t("loading")}</div>`:t`<div id="table-container">
147
- ${this._data?this._getTable():""}
148
- </div>`}
149
- </div>
150
- `}_getLimitOptions(){return["25","50","100","200"]}_getLevelOptions(){return Object.keys(c.SyslogLevel).map(e=>[e,l.t(e.toLocaleLowerCase())])}_getCategoryMenuItems(){return(this.config&&this.config.allowedCategories?this.config.allowedCategories:Object.keys(c.SyslogCategory)).map(e=>({text:l.t("logCategory."+e,{defaultValue:_.capitaliseFirstLetter(e.toLowerCase().replace(/_/g," "))}),value:e}))}getLimit(){return this.limit||OrLogViewer_1.DEFAULT_LIMIT}_onCategoriesChanged(e){this._pendingCategories=e}_onCategoriesClosed(){this._pendingCategories&&(this.categories=[...this._pendingCategories],this.categories&&this.live&&(this._data=this._data.filter(e=>this.categories.find(t=>t===e.category))),this._pendingCategories=void 0)}_onLiveChanged(e){this.live=e,e&&(this._data=[],this._pageCount=void 0,this._currentPage=1)}_onLimitChanged(e){if(!e){this.limit=void 0;return}this.limit=parseInt(e);let t=this.getLimit();this.live&&this._data.length>t&&this._data.splice(t-1)}_onFilterChanged(e){if(this.filter=e,this.filter&&this.live){let e=this.filter.split(";");this._data=this._data.filter(t=>e.find(e=>e===t.subCategory))}}_onLevelChanged(e){this.level=e,this.level&&this.live&&(this._data=this._data.filter(e=>this._eventMatchesLevel(e)))}_getTable(){return t`
151
- <div id="table" class="mdc-data-table">
152
- <table class="mdc-data-table__table" aria-label="logs list">
153
- <thead>
154
- <tr class="mdc-data-table__header-row">
155
- <th style="width: 180px" class="mdc-data-table__header-cell" role="columnheader" scope="col">${l.t("timestamp")}</th>
156
- <th style="width: 80px" class="mdc-data-table__header-cell" role="columnheader" scope="col">${l.t("level")}</th>
157
- <th style="width: 130px" class="mdc-data-table__header-cell" role="columnheader" scope="col">${l.t("category")}</th>
158
- <th style="width: 180px" class="mdc-data-table__header-cell" role="columnheader" scope="col">${l.t("subCategory")}</th>
159
- <th style="width: 100%; min-width: 300px;" class="mdc-data-table__header-cell" role="columnheader" scope="col">${l.t("message")}</th>
160
- <th style="width: 80px;" class="mdc-data-table__header-cell" role="columnheader" scope="col"></th>
161
- </tr>
162
- </thead>
163
- <tbody class="mdc-data-table__content">
164
- ${this._data.map(e=>t`
165
- <tr class="mdc-data-table__row">
166
- <td class="mdc-data-table__cell">${v(e.timestamp).format(OrLogViewer_1.DEFAULT_TIMESTAMP_FORMAT)}</td>
167
- <td class="mdc-data-table__cell">${l.t(e.level)}</td>
168
- <td class="mdc-data-table__cell">${l.t(e.category)}</td>
169
- <td class="mdc-data-table__cell">${l.t(e.subCategory)}</td>
170
- <td class="mdc-data-table__cell">${e.message}</td>
171
- <td class="mdc-data-table__cell icon-cell">
172
- ${f(window.isSecureContext,()=>t`
173
- <or-mwc-input type="${u.BUTTON}" class="copy-button" icon="content-copy" @or-mwc-input-changed=${()=>this._copyRow(e)}></or-mwc-input>
174
- `)}
175
- </td>
176
- </tr>
177
- `)}
178
- </tbody>
179
- </table>
180
- </div>
181
- `}_copyRow(e){return __awaiter(this,void 0,void 0,function*(){try{let t=e.message||"";yield navigator.clipboard.writeText(t),b(void 0,l.t("copiedToClipboard"))}catch(e){console.error("Failed to copy:",e)}})}_getIntervalOptions(){return["HOUR","DAY","WEEK","MONTH","YEAR"].map(e=>[e,l.t(e.toLowerCase())])}_loadData(){return __awaiter(this,void 0,void 0,function*(){if(this._loading)return;this._loading=!0;let e=yield d.rest.api.SyslogResource.getEvents({level:this.level,per_page:this.getLimit(),page:this._currentPage,from:this._getFrom(),to:this.timestamp?this.timestamp.getTime():void 0,category:this.categories,subCategory:this.filter?this.filter.split(";"):void 0});this._loading=!1,200===e.status&&(this._data=e.data,this._pageCount=this._getPageCount(e))})}_getPageCount(e){let t=e.headers.link;if(t){let e=linkParser.parse(t).rel("last");if(Array.isArray(e)&&e.length>0&&(e=e[0]),e&&e.uri){let t=new URL(e.uri);return parseInt(_.getQueryParameters(t.search).page)}}}_updatePage(e){this._pageCount&&(e?this._currentPage<this._pageCount&&(this._data=void 0,this._currentPage++):this._currentPage>1&&(this._data=void 0,this._currentPage--))}_subscribeEvents(){return __awaiter(this,void 0,void 0,function*(){d.events&&(this._eventSubscriptionId=yield d.events.subscribe({eventType:"syslog"},e=>this._onEvent(e)))})}_unsubscribeEvents(){this._eventSubscriptionId&&(d.events.unsubscribe(this._eventSubscriptionId),this._eventSubscriptionId=void 0)}_getFrom(){if(this.timestamp&&this.interval)return this._calculateTimestamp(this.timestamp,!1).getTime()}_calculateTimestamp(e,t){if(!this.interval)return;let i=v(e);if(void 0!==t)switch(this.interval){case"HOUR":i.add(t?1:-1,"hour");break;case"DAY":i.add(t?1:-1,"day");break;case"WEEK":i.add(t?1:-1,"week");break;case"MONTH":i.add(t?1:-1,"month");break;case"YEAR":i.add(t?1:-1,"year")}return i.toDate()}_onEvent(e){if(this.categories&&!this.categories.find(t=>t===e.category)||this.filter&&!this.filter.split(";").find(t=>t===e.subCategory)||!this._eventMatchesLevel(e))return;let t=this.getLimit();this._data.length===t-1&&this._data.pop(),this._data.splice(0,0,e),this._refresh&&window.clearTimeout(this._refresh),this._refresh=window.setTimeout(()=>this.requestUpdate("_data"),2e3)}_eventMatchesLevel(e){return!this.level||"INFO"===this.level||"WARN"===this.level&&("WARN"===e.level||"ERROR"===e.level)||"ERROR"===this.level&&"ERROR"===e.level}_cleanup(){this._table&&(this._table.destroy(),this._table=void 0),this._refresh&&window.clearTimeout(this._refresh)}};OrLogViewer.DEFAULT_TIMESTAMP_FORMAT="L HH:mm:ss",OrLogViewer.DEFAULT_LIMIT=50,OrLogViewer.DEFAULT_LEVEL="INFO",OrLogViewer.DEFAULT_INTERVAL="HOUR",__decorate([r({type:String})],OrLogViewer.prototype,"interval",void 0),__decorate([r({type:Number})],OrLogViewer.prototype,"timestamp",void 0),__decorate([r({type:Number})],OrLogViewer.prototype,"limit",void 0),__decorate([r({type:Array})],OrLogViewer.prototype,"categories",void 0),__decorate([r({type:String})],OrLogViewer.prototype,"filter",void 0),__decorate([r({type:String})],OrLogViewer.prototype,"level",void 0),__decorate([r({type:Boolean})],OrLogViewer.prototype,"live",void 0),__decorate([r({type:Object})],OrLogViewer.prototype,"config",void 0),__decorate([r()],OrLogViewer.prototype,"_loading",void 0),__decorate([r()],OrLogViewer.prototype,"_data",void 0),__decorate([s("#table")],OrLogViewer.prototype,"_tableElem",void 0),OrLogViewer=OrLogViewer_1=__decorate([a("or-log-viewer")],OrLogViewer);export{OrLogViewer};
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
+ var OrLogViewer_1;
17
+ import { css, html, LitElement, unsafeCSS } from "lit";
18
+ import { customElement, property, query } from "lit/decorators.js";
19
+ import i18next from "i18next";
20
+ import { translate } from "@openremote/or-translate";
21
+ import * as Model from "@openremote/model";
22
+ import manager, { DefaultColor2, DefaultColor3, DefaultColor4, DefaultColor5, Util } from "@openremote/core";
23
+ import "@openremote/or-mwc-components/or-mwc-input";
24
+ import "@openremote/or-components/or-panel";
25
+ import "@openremote/or-translate";
26
+ import { InputType } from "@openremote/or-mwc-components/or-mwc-input";
27
+ import moment from "moment";
28
+ import "@openremote/or-mwc-components/or-mwc-menu";
29
+ import { getContentWithMenuTemplate } from "@openremote/or-mwc-components/or-mwc-menu";
30
+ import { showSnackbar } from "@openremote/or-mwc-components/or-mwc-snackbar";
31
+ import { when } from "lit/directives/when.js";
32
+ // TODO: Add webpack/rollup to build so consumers aren't forced to use the same tooling
33
+ const linkParser = require("http-link-header");
34
+ const tableStyle = require("@material/data-table/dist/mdc.data-table.css");
35
+ // language=CSS
36
+ const style = css `
37
+ :host {
38
+ --internal-or-log-viewer-background-color: var(--or-log-viewer-background-color, var(--or-app-color2, ${unsafeCSS(DefaultColor2)}));
39
+ --internal-or-log-viewer-text-color: var(--or-log-viewer-text-color, var(--or-app-color3, ${unsafeCSS(DefaultColor3)}));
40
+ --internal-or-log-viewer-controls-margin: var(--or-log-viewer-controls-margin, 0);
41
+
42
+ display: block;
43
+ }
44
+
45
+ :host([hidden]) {
46
+ display: none;
47
+ }
48
+
49
+ #container {
50
+ display: flex;
51
+ min-width: 0;
52
+ width: 100%;
53
+ height: 100%;
54
+ flex-direction: column;
55
+ }
56
+
57
+ #msg {
58
+ height: 100%;
59
+ width: 100%;
60
+ justify-content: center;
61
+ align-items: center;
62
+ text-align: center;
63
+ }
64
+
65
+ #msg:not([hidden]) {
66
+ display: flex;
67
+ }
68
+
69
+ #controls {
70
+ flex: 0;
71
+ display: flex;
72
+ flex-wrap: wrap;
73
+ justify-content: space-between;
74
+ margin: var(--internal-or-log-viewer-controls-margin);
75
+ padding: 0 20px 20px 20px;
76
+ }
77
+
78
+ #controls > * {
79
+ margin-top: 20px;
80
+ }
81
+
82
+ #time-controls {
83
+ display: flex;
84
+ align-items: center;
85
+ }
86
+
87
+ #live-button {
88
+ margin-right: 40px;
89
+ }
90
+
91
+ /* min-width of selects is 200px somehow
92
+ #period-select {
93
+ width: 90px;
94
+ }
95
+
96
+ #level-select {
97
+ width: 120px;
98
+ }
99
+
100
+ #limit-select {
101
+ width: 80px;
102
+ }
103
+ */
104
+
105
+ #log-controls, #ending-controls, #page-controls {
106
+ display: flex;
107
+ max-width: 100%;
108
+ align-items: center;
109
+ }
110
+
111
+ #ending-controls {
112
+ float: right;
113
+ margin: 0 10px;
114
+ }
115
+
116
+ #log-controls > *, #ending-controls > *, #page-controls > * {
117
+ padding: 0 5px;
118
+ }
119
+
120
+ #page-controls[hidden] {
121
+ visibility: hidden;
122
+ }
123
+
124
+ #ending-date {
125
+ min-width: 0;
126
+ }
127
+
128
+ #table-container {
129
+ height: 100%;
130
+ overflow: auto;
131
+ }
132
+
133
+ #table {
134
+ width: 100%;
135
+ margin-bottom: 10px;
136
+ }
137
+
138
+ #table > table {
139
+ width: 100%;
140
+ table-layout: fixed;
141
+ }
142
+
143
+ #table th:not(.icon-cell), #table td:not(.icon-cell) {
144
+ word-wrap: break-word;
145
+ white-space: pre-wrap;
146
+ }
147
+
148
+ .copy-button {
149
+ --or-mwc-input-color: var(--or-app-color5, ${unsafeCSS(DefaultColor5)});
150
+ }
151
+
152
+ .copy-button:hover {
153
+ --or-mwc-input-color: var(--or-app-color4, ${unsafeCSS(DefaultColor4)});
154
+ }
155
+ `;
156
+ let OrLogViewer = OrLogViewer_1 = class OrLogViewer extends translate(i18next)(LitElement) {
157
+ constructor() {
158
+ super(...arguments);
159
+ this.live = false;
160
+ this._loading = false;
161
+ this._currentPage = 1;
162
+ }
163
+ static get styles() {
164
+ return [
165
+ css `${unsafeCSS(tableStyle)}`,
166
+ style
167
+ ];
168
+ }
169
+ connectedCallback() {
170
+ super.connectedCallback();
171
+ }
172
+ disconnectedCallback() {
173
+ super.disconnectedCallback();
174
+ this._cleanup();
175
+ this._unsubscribeEvents();
176
+ }
177
+ shouldUpdate(_changedProperties) {
178
+ if (_changedProperties.has("level")
179
+ || _changedProperties.has("interval")
180
+ || _changedProperties.has("timestamp")
181
+ || _changedProperties.has("limit")
182
+ || _changedProperties.has("categories")
183
+ || _changedProperties.has("filter")
184
+ || _changedProperties.has("live")) {
185
+ if (!this.live) {
186
+ this._pageCount = undefined;
187
+ this._currentPage = 1;
188
+ this._data = undefined;
189
+ }
190
+ }
191
+ if (!this.interval) {
192
+ this.interval = OrLogViewer_1.DEFAULT_INTERVAL;
193
+ }
194
+ if (!this.categories) {
195
+ if (this.config && this.config.initialCategories) {
196
+ this.categories = [...this.config.initialCategories];
197
+ }
198
+ }
199
+ if (this.filter === undefined && this.config && this.config.initialFilter) {
200
+ this.filter = this.config.initialFilter;
201
+ }
202
+ if (!this.level) {
203
+ if (this.config && this.config.initialLevel) {
204
+ this.level = this.config.initialLevel;
205
+ }
206
+ else {
207
+ this.level = OrLogViewer_1.DEFAULT_LEVEL;
208
+ }
209
+ }
210
+ if (!this.live && !this.timestamp) {
211
+ this.timestamp = new Date();
212
+ }
213
+ if (!this._data && !this.live) {
214
+ this._loadData();
215
+ }
216
+ if (_changedProperties.has("live")) {
217
+ if (this.live) {
218
+ this._subscribeEvents();
219
+ }
220
+ else {
221
+ this._unsubscribeEvents();
222
+ }
223
+ }
224
+ return super.shouldUpdate(_changedProperties);
225
+ }
226
+ render() {
227
+ const disabled = this._loading;
228
+ const isLive = this.live;
229
+ const hideCategories = this.config && this.config.hideCategories;
230
+ const hideFilter = this.config && this.config.hideFilter;
231
+ const hideLevel = this.config && this.config.hideLevel;
232
+ return html `
233
+ <div id="container">
234
+ <div id="controls">
235
+ <div id="log-controls">
236
+ ${hideCategories ? `` : getContentWithMenuTemplate(html `<or-mwc-input .type=${InputType.BUTTON} raised ?disabled="${disabled}" .label="${i18next.t("categories")}" icontrailing="chevron-down"></or-mwc-input>`, this._getCategoryMenuItems(), this.categories, (v) => this._onCategoriesChanged(v), () => this._onCategoriesClosed(), true)}
237
+ <or-mwc-input ?hidden="${hideFilter}" .type="${InputType.TEXT}" outlined ?disabled="${disabled}" icontrailing="magnify" .label="${i18next.t("subCategoryFilters")}" .value="${this.filter}" @or-mwc-input-changed="${(evt) => this._onFilterChanged(evt.detail.value)}"></or-mwc-input>
238
+ <or-mwc-input ?hidden="${hideLevel}" .type="${InputType.SELECT}" id="level-select" ?disabled="${disabled}" .label="${i18next.t("level")}" @or-mwc-input-changed="${(evt) => this._onLevelChanged(evt.detail.value)}" .value="${this.level}" .options="${this._getLevelOptions()}"></or-mwc-input>
239
+ <or-mwc-input .type="${InputType.SELECT}" id="limit-select" ?disabled="${disabled}" .label="${i18next.t("limit")}" @or-mwc-input-changed="${(evt) => this._onLimitChanged(evt.detail.value)}" .value="${"" + this.getLimit()}" .options="${this._getLimitOptions()}"></or-mwc-input>
240
+ </div>
241
+ <div id="page-controls" ?hidden="${isLive || !this._pageCount || !this._data || this._data.length === 0}">
242
+ <or-mwc-input class="button" .type="${InputType.BUTTON}" ?disabled="${disabled || isLive || this._currentPage === 1}" icon="chevron-left" @or-mwc-input-changed="${() => this._updatePage(false)}"></or-mwc-input>
243
+ <span>${this._currentPage}</span><or-translate value="of"></or-translate><span>${this._pageCount}</span>
244
+ <or-mwc-input class="button" .type="${InputType.BUTTON}" ?disabled="${disabled || isLive || this._currentPage === this._pageCount || (this._data && this._data.length < this.getLimit())}" icon="chevron-right" @or-mwc-input-changed="${() => this._updatePage(true)}"></or-mwc-input>
245
+ </div>
246
+ <div id="time-controls">
247
+ <or-mwc-input id="live-button" .type="${InputType.CHECKBOX}" ?disabled="${disabled}" .label="${i18next.t("live")}" @or-mwc-input-changed="${(evt) => this._onLiveChanged(evt.detail.value)}" .value="${this.live}"></or-mwc-input>
248
+ <or-mwc-input .type="${InputType.SELECT}" id="period-select" ?disabled="${disabled || isLive}" .label="${i18next.t("period")}" @or-mwc-input-changed="${(evt) => this.interval = evt.detail.value}" .value="${this.interval}" .options="${this._getIntervalOptions()}"></or-mwc-input>
249
+ <div id="ending-controls">
250
+ <or-mwc-input class="button" .type="${InputType.BUTTON}" ?disabled="${disabled || isLive}" icon="chevron-left" @or-mwc-input-changed="${() => this.timestamp = this._calculateTimestamp(this.timestamp, false)}"></or-mwc-input>
251
+ <or-mwc-input id="ending-date" .type="${InputType.DATETIME}" ?disabled="${disabled || isLive}" label="${i18next.t("ending")}" .value="${this.timestamp}" @or-mwc-input-changed="${(evt) => this.timestamp = this._calculateTimestamp(moment(evt.detail.value).toDate())}"></or-mwc-input>
252
+ <or-mwc-input class="button" .type="${InputType.BUTTON}" ?disabled="${disabled || isLive}" icon="chevron-right" @or-mwc-input-changed="${() => this.timestamp = this._calculateTimestamp(this.timestamp, true)}"></or-mwc-input>
253
+ <or-mwc-input class="button" .type="${InputType.BUTTON}" ?disabled="${disabled || isLive}" icon="chevron-double-right" @or-mwc-input-changed="${() => this.timestamp = this._calculateTimestamp(new Date())}"></or-mwc-input>
254
+ </div>
255
+ </div>
256
+ </div>
257
+
258
+ ${disabled ? html `<div id="msg">${i18next.t("loading")}</div>` :
259
+ html `<div id="table-container">
260
+ ${this._data ? this._getTable() : ``}
261
+ </div>`}
262
+ </div>
263
+ `;
264
+ }
265
+ _getLimitOptions() {
266
+ return ["25", "50", "100", "200"];
267
+ }
268
+ _getLevelOptions() {
269
+ return Object.keys(Model["SyslogLevel"]).map((key) => [key, i18next.t(key.toLocaleLowerCase())]);
270
+ }
271
+ _getCategoryMenuItems() {
272
+ const categories = this.config && this.config.allowedCategories ? this.config.allowedCategories : Object.keys(Model["SyslogCategory"]);
273
+ return categories.map((cat) => {
274
+ return {
275
+ text: i18next.t("logCategory." + cat, { defaultValue: Util.capitaliseFirstLetter(cat.toLowerCase().replace(/_/g, " ")) }),
276
+ value: cat
277
+ };
278
+ });
279
+ }
280
+ getLimit() {
281
+ return this.limit || OrLogViewer_1.DEFAULT_LIMIT;
282
+ }
283
+ _onCategoriesChanged(values) {
284
+ this._pendingCategories = values;
285
+ }
286
+ _onCategoriesClosed() {
287
+ if (!this._pendingCategories) {
288
+ return;
289
+ }
290
+ this.categories = [...this._pendingCategories];
291
+ if (this.categories && this.live) {
292
+ this._data = this._data.filter((e) => this.categories.find((c) => c === e.category));
293
+ }
294
+ this._pendingCategories = undefined;
295
+ }
296
+ _onLiveChanged(live) {
297
+ this.live = live;
298
+ if (live) {
299
+ this._data = [];
300
+ this._pageCount = undefined;
301
+ this._currentPage = 1;
302
+ }
303
+ }
304
+ _onLimitChanged(limit) {
305
+ if (!limit) {
306
+ this.limit = undefined;
307
+ return;
308
+ }
309
+ this.limit = parseInt(limit);
310
+ const newLimit = this.getLimit();
311
+ if (this.live && this._data.length > newLimit) {
312
+ this._data.splice(newLimit - 1);
313
+ }
314
+ }
315
+ _onFilterChanged(filter) {
316
+ this.filter = filter;
317
+ if (!this.filter) {
318
+ return;
319
+ }
320
+ if (this.live) {
321
+ const filters = this.filter.split(";");
322
+ this._data = this._data.filter((e) => filters.find((f) => f === e.subCategory));
323
+ }
324
+ }
325
+ _onLevelChanged(level) {
326
+ this.level = level;
327
+ if (!this.level) {
328
+ return;
329
+ }
330
+ if (this.live) {
331
+ this._data = this._data.filter((e) => this._eventMatchesLevel(e));
332
+ }
333
+ }
334
+ _getTable() {
335
+ return html `
336
+ <div id="table" class="mdc-data-table">
337
+ <table class="mdc-data-table__table" aria-label="logs list">
338
+ <thead>
339
+ <tr class="mdc-data-table__header-row">
340
+ <th style="width: 180px" class="mdc-data-table__header-cell" role="columnheader" scope="col">${i18next.t("timestamp")}</th>
341
+ <th style="width: 80px" class="mdc-data-table__header-cell" role="columnheader" scope="col">${i18next.t("level")}</th>
342
+ <th style="width: 130px" class="mdc-data-table__header-cell" role="columnheader" scope="col">${i18next.t("category")}</th>
343
+ <th style="width: 180px" class="mdc-data-table__header-cell" role="columnheader" scope="col">${i18next.t("subCategory")}</th>
344
+ <th style="width: 100%; min-width: 300px;" class="mdc-data-table__header-cell" role="columnheader" scope="col">${i18next.t("message")}</th>
345
+ <th style="width: 80px;" class="mdc-data-table__header-cell" role="columnheader" scope="col"></th>
346
+ </tr>
347
+ </thead>
348
+ <tbody class="mdc-data-table__content">
349
+ ${this._data.map((ev) => {
350
+ return html `
351
+ <tr class="mdc-data-table__row">
352
+ <td class="mdc-data-table__cell">${moment(ev.timestamp).format(OrLogViewer_1.DEFAULT_TIMESTAMP_FORMAT)}</td>
353
+ <td class="mdc-data-table__cell">${i18next.t(ev.level)}</td>
354
+ <td class="mdc-data-table__cell">${i18next.t(ev.category)}</td>
355
+ <td class="mdc-data-table__cell">${i18next.t(ev.subCategory)}</td>
356
+ <td class="mdc-data-table__cell">${ev.message}</td>
357
+ <td class="mdc-data-table__cell icon-cell">
358
+ ${when(window.isSecureContext, () => html `
359
+ <or-mwc-input type="${InputType.BUTTON}" class="copy-button" icon="content-copy" @or-mwc-input-changed=${() => this._copyRow(ev)}></or-mwc-input>
360
+ `)}
361
+ </td>
362
+ </tr>
363
+ `;
364
+ })}
365
+ </tbody>
366
+ </table>
367
+ </div>
368
+ `;
369
+ }
370
+ /** Copy a single log event to the clipboard as JSON */
371
+ _copyRow(row) {
372
+ return __awaiter(this, void 0, void 0, function* () {
373
+ try {
374
+ const text = row.message || "";
375
+ yield navigator.clipboard.writeText(text);
376
+ showSnackbar(undefined, i18next.t("copiedToClipboard"));
377
+ }
378
+ catch (err) {
379
+ console.error("Failed to copy:", err);
380
+ }
381
+ });
382
+ }
383
+ _getIntervalOptions() {
384
+ return [
385
+ "HOUR" /* Model.DatapointInterval.HOUR */,
386
+ "DAY" /* Model.DatapointInterval.DAY */,
387
+ "WEEK" /* Model.DatapointInterval.WEEK */,
388
+ "MONTH" /* Model.DatapointInterval.MONTH */,
389
+ "YEAR" /* Model.DatapointInterval.YEAR */
390
+ ].map((interval) => {
391
+ return [interval, i18next.t(interval.toLowerCase())];
392
+ });
393
+ }
394
+ _loadData() {
395
+ return __awaiter(this, void 0, void 0, function* () {
396
+ if (this._loading) {
397
+ return;
398
+ }
399
+ this._loading = true;
400
+ const response = yield manager.rest.api.SyslogResource.getEvents({
401
+ level: this.level,
402
+ per_page: this.getLimit(),
403
+ page: this._currentPage,
404
+ from: this._getFrom(),
405
+ to: this.timestamp ? this.timestamp.getTime() : undefined,
406
+ category: this.categories,
407
+ subCategory: this.filter ? this.filter.split(";") : undefined
408
+ });
409
+ this._loading = false;
410
+ if (response.status === 200) {
411
+ this._data = response.data;
412
+ // Get page count
413
+ this._pageCount = this._getPageCount(response);
414
+ }
415
+ });
416
+ }
417
+ _getPageCount(response) {
418
+ const linkHeaders = response.headers["link"];
419
+ if (linkHeaders) {
420
+ const links = linkParser.parse(linkHeaders);
421
+ let lastLink = links.rel("last");
422
+ if (Array.isArray(lastLink) && lastLink.length > 0) {
423
+ lastLink = lastLink[0];
424
+ }
425
+ if (lastLink && lastLink.uri) {
426
+ const url = new URL(lastLink.uri);
427
+ return parseInt(Util.getQueryParameters(url.search)['page']);
428
+ }
429
+ }
430
+ }
431
+ _updatePage(forward) {
432
+ if (!this._pageCount) {
433
+ return;
434
+ }
435
+ if (forward) {
436
+ if (this._currentPage < this._pageCount) {
437
+ this._data = undefined;
438
+ this._currentPage++;
439
+ }
440
+ }
441
+ else {
442
+ if (this._currentPage > 1) {
443
+ this._data = undefined;
444
+ this._currentPage--;
445
+ }
446
+ }
447
+ }
448
+ _subscribeEvents() {
449
+ return __awaiter(this, void 0, void 0, function* () {
450
+ if (manager.events) {
451
+ this._eventSubscriptionId = yield manager.events.subscribe({
452
+ eventType: "syslog"
453
+ }, (ev) => this._onEvent(ev));
454
+ }
455
+ });
456
+ }
457
+ _unsubscribeEvents() {
458
+ if (this._eventSubscriptionId) {
459
+ manager.events.unsubscribe(this._eventSubscriptionId);
460
+ this._eventSubscriptionId = undefined;
461
+ }
462
+ }
463
+ _getFrom() {
464
+ if (!this.timestamp || !this.interval) {
465
+ return;
466
+ }
467
+ return this._calculateTimestamp(this.timestamp, false).getTime();
468
+ }
469
+ _calculateTimestamp(timestamp, forward) {
470
+ if (!this.interval) {
471
+ return;
472
+ }
473
+ const newMoment = moment(timestamp);
474
+ if (forward !== undefined) {
475
+ switch (this.interval) {
476
+ case "HOUR" /* Model.DatapointInterval.HOUR */:
477
+ newMoment.add(forward ? 1 : -1, "hour");
478
+ break;
479
+ case "DAY" /* Model.DatapointInterval.DAY */:
480
+ newMoment.add(forward ? 1 : -1, "day");
481
+ break;
482
+ case "WEEK" /* Model.DatapointInterval.WEEK */:
483
+ newMoment.add(forward ? 1 : -1, "week");
484
+ break;
485
+ case "MONTH" /* Model.DatapointInterval.MONTH */:
486
+ newMoment.add(forward ? 1 : -1, "month");
487
+ break;
488
+ case "YEAR" /* Model.DatapointInterval.YEAR */:
489
+ newMoment.add(forward ? 1 : -1, "year");
490
+ break;
491
+ }
492
+ }
493
+ return newMoment.toDate();
494
+ }
495
+ _onEvent(event) {
496
+ // TODO: Move filtering to server side
497
+ if (this.categories && !this.categories.find((c) => c === event.category)) {
498
+ return;
499
+ }
500
+ if (this.filter) {
501
+ const filters = this.filter.split(";");
502
+ if (!filters.find((f) => f === event.subCategory)) {
503
+ return;
504
+ }
505
+ }
506
+ if (!this._eventMatchesLevel(event)) {
507
+ return;
508
+ }
509
+ const limit = this.getLimit();
510
+ if (this._data.length === limit - 1) {
511
+ this._data.pop();
512
+ }
513
+ this._data.splice(0, 0, event);
514
+ if (this._refresh) {
515
+ window.clearTimeout(this._refresh);
516
+ }
517
+ // Buffer updates to prevent excessive re-renders
518
+ this._refresh = window.setTimeout(() => this.requestUpdate("_data"), 2000);
519
+ }
520
+ _eventMatchesLevel(event) {
521
+ if (!this.level || this.level === "INFO" /* Model.SyslogLevel.INFO */) {
522
+ return true;
523
+ }
524
+ if (this.level === "WARN" /* Model.SyslogLevel.WARN */ && (event.level === "WARN" /* Model.SyslogLevel.WARN */ || event.level === "ERROR" /* Model.SyslogLevel.ERROR */)) {
525
+ return true;
526
+ }
527
+ if (this.level === "ERROR" /* Model.SyslogLevel.ERROR */ && event.level === "ERROR" /* Model.SyslogLevel.ERROR */) {
528
+ return true;
529
+ }
530
+ return false;
531
+ }
532
+ _cleanup() {
533
+ if (this._table) {
534
+ this._table.destroy();
535
+ this._table = undefined;
536
+ }
537
+ if (this._refresh) {
538
+ window.clearTimeout(this._refresh);
539
+ }
540
+ }
541
+ };
542
+ OrLogViewer.DEFAULT_TIMESTAMP_FORMAT = "L HH:mm:ss";
543
+ OrLogViewer.DEFAULT_LIMIT = 50;
544
+ OrLogViewer.DEFAULT_LEVEL = "INFO" /* Model.SyslogLevel.INFO */;
545
+ OrLogViewer.DEFAULT_INTERVAL = "HOUR" /* Model.DatapointInterval.HOUR */;
546
+ __decorate([
547
+ property({ type: String })
548
+ ], OrLogViewer.prototype, "interval", void 0);
549
+ __decorate([
550
+ property({ type: Number })
551
+ ], OrLogViewer.prototype, "timestamp", void 0);
552
+ __decorate([
553
+ property({ type: Number })
554
+ ], OrLogViewer.prototype, "limit", void 0);
555
+ __decorate([
556
+ property({ type: Array })
557
+ ], OrLogViewer.prototype, "categories", void 0);
558
+ __decorate([
559
+ property({ type: String })
560
+ ], OrLogViewer.prototype, "filter", void 0);
561
+ __decorate([
562
+ property({ type: String })
563
+ ], OrLogViewer.prototype, "level", void 0);
564
+ __decorate([
565
+ property({ type: Boolean })
566
+ ], OrLogViewer.prototype, "live", void 0);
567
+ __decorate([
568
+ property({ type: Object })
569
+ ], OrLogViewer.prototype, "config", void 0);
570
+ __decorate([
571
+ property()
572
+ ], OrLogViewer.prototype, "_loading", void 0);
573
+ __decorate([
574
+ property()
575
+ ], OrLogViewer.prototype, "_data", void 0);
576
+ __decorate([
577
+ query("#table")
578
+ ], OrLogViewer.prototype, "_tableElem", void 0);
579
+ OrLogViewer = OrLogViewer_1 = __decorate([
580
+ customElement("or-log-viewer")
581
+ ], OrLogViewer);
582
+ export { OrLogViewer };
583
+ //# sourceMappingURL=index.js.map