@openremote/or-rules 1.8.0-snapshot.20250725074716 → 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.
Files changed (73) hide show
  1. package/README.md +30 -30
  2. package/custom-elements.json +13 -13
  3. package/dist/umd/index.bundle.js +4744 -4744
  4. package/dist/umd/index.bundle.js.map +1 -1
  5. package/lib/flow-viewer/components/confirmation-dialog.js +61 -24
  6. package/lib/flow-viewer/components/connection-container.js +35 -1
  7. package/lib/flow-viewer/components/connection-line.js +117 -28
  8. package/lib/flow-viewer/components/context-menu.js +140 -45
  9. package/lib/flow-viewer/components/editor-workspace.js +282 -20
  10. package/lib/flow-viewer/components/flow-editor.js +160 -47
  11. package/lib/flow-viewer/components/flow-node-socket.js +146 -31
  12. package/lib/flow-viewer/components/flow-node.js +192 -29
  13. package/lib/flow-viewer/components/internal-picker.js +271 -54
  14. package/lib/flow-viewer/components/node-menu-item.js +132 -32
  15. package/lib/flow-viewer/components/node-panel.js +104 -60
  16. package/lib/flow-viewer/components/notification-dialog.js +55 -23
  17. package/lib/flow-viewer/components/popup-modal.js +113 -54
  18. package/lib/flow-viewer/components/rule-browser.js +119 -30
  19. package/lib/flow-viewer/components/selectable-element.js +71 -1
  20. package/lib/flow-viewer/components/selection-box.js +119 -15
  21. package/lib/flow-viewer/components/top-bar.js +116 -49
  22. package/lib/flow-viewer/components/workspace-contextmenu-options.js +128 -5
  23. package/lib/flow-viewer/components/writable-dropdown.js +51 -5
  24. package/lib/flow-viewer/converters/node-converter.js +10 -1
  25. package/lib/flow-viewer/flow-viewer.js +19 -1
  26. package/lib/flow-viewer/models/camera.js +2 -1
  27. package/lib/flow-viewer/models/context-menu-button.js +2 -1
  28. package/lib/flow-viewer/models/light-node-collection.js +2 -1
  29. package/lib/flow-viewer/models/status.js +8 -1
  30. package/lib/flow-viewer/node-structure/copy.machine.js +34 -1
  31. package/lib/flow-viewer/node-structure/identity.assigner.js +10 -1
  32. package/lib/flow-viewer/node-structure/identity.dom.link.js +4 -1
  33. package/lib/flow-viewer/node-structure/index.js +5 -1
  34. package/lib/flow-viewer/node-structure/socket.type.matcher.js +50 -1
  35. package/lib/flow-viewer/node-structure/utils.js +109 -1
  36. package/lib/flow-viewer/services/copy-paste-manager.js +59 -1
  37. package/lib/flow-viewer/services/exporter.js +67 -1
  38. package/lib/flow-viewer/services/input.js +80 -1
  39. package/lib/flow-viewer/services/integration.js +27 -1
  40. package/lib/flow-viewer/services/modal.js +29 -8
  41. package/lib/flow-viewer/services/project.js +222 -1
  42. package/lib/flow-viewer/services/shortcuts.js +63 -1
  43. package/lib/flow-viewer/styles/editor-workspace-style.js +55 -53
  44. package/lib/flow-viewer/styles/flow-node-style.js +95 -93
  45. package/lib/flow-viewer/styles/picker-styles.js +31 -29
  46. package/lib/flow-viewer/utils.js +49 -1
  47. package/lib/index.js +953 -56
  48. package/lib/json-viewer/forms/or-rule-form-alarm.js +91 -18
  49. package/lib/json-viewer/forms/or-rule-form-email-message.js +51 -12
  50. package/lib/json-viewer/forms/or-rule-form-localized.js +269 -43
  51. package/lib/json-viewer/forms/or-rule-form-push-notification.js +152 -63
  52. package/lib/json-viewer/forms/or-rule-form-webhook.js +296 -101
  53. package/lib/json-viewer/modals/or-rule-alarm-modal.js +173 -17
  54. package/lib/json-viewer/modals/or-rule-notification-modal.js +196 -11
  55. package/lib/json-viewer/modals/or-rule-radial-modal.js +142 -17
  56. package/lib/json-viewer/modals/or-rule-webhook-modal.js +78 -8
  57. package/lib/json-viewer/or-rule-action-alarm.js +97 -5
  58. package/lib/json-viewer/or-rule-action-attribute.js +235 -33
  59. package/lib/json-viewer/or-rule-action-notification.js +465 -56
  60. package/lib/json-viewer/or-rule-action-webhook.js +49 -18
  61. package/lib/json-viewer/or-rule-asset-query.js +849 -126
  62. package/lib/json-viewer/or-rule-condition.js +216 -29
  63. package/lib/json-viewer/or-rule-json-viewer.js +393 -34
  64. package/lib/json-viewer/or-rule-then-otherwise.js +609 -113
  65. package/lib/json-viewer/or-rule-trigger-query.js +227 -57
  66. package/lib/json-viewer/or-rule-when.js +343 -126
  67. package/lib/or-rule-group-viewer.js +106 -12
  68. package/lib/or-rule-text-viewer.js +133 -22
  69. package/lib/or-rule-tree.js +601 -57
  70. package/lib/or-rule-validity.js +373 -62
  71. package/lib/or-rule-viewer.js +361 -81
  72. package/lib/style.js +89 -64
  73. package/package.json +11 -11
@@ -1,93 +1,373 @@
1
- var __decorate=this&&this.__decorate||function(e,t,r,i){var l,s=arguments.length,a=s<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,r,i);else for(var o=e.length-1;o>=0;o--)(l=e[o])&&(a=(s<3?l(a):s>3?l(t,r,a):l(t,r))||a);return s>3&&a&&Object.defineProperty(t,r,a),a},__awaiter=this&&this.__awaiter||function(e,t,r,i){return new(r||(r=Promise))(function(l,s){function a(e){try{n(i.next(e))}catch(e){s(e)}}function o(e){try{n(i.throw(e))}catch(e){s(e)}}function n(e){var t;e.done?l(e.value):((t=e.value)instanceof r?t:new r(function(e){e(t)})).then(a,o)}n((i=i.apply(e,t||[])).next())})};import{css as e,html as t,LitElement as r}from"lit";import{customElement as i,property as l,query as s}from"lit/decorators.js";import{OrRulesRequestSaveEvent as a,OrRulesRuleChangedEvent as o,OrRulesRuleUnsupportedEvent as n,OrRulesSaveEvent as d,RuleViewInfoMap as u}from"./index";import c,{Util as p}from"@openremote/core";import"./json-viewer/or-rule-json-viewer";import"./or-rule-text-viewer";import"./or-rule-validity";import"./flow-viewer/components/flow-editor";import"@openremote/or-mwc-components/or-mwc-input";import{translate as h}from"@openremote/or-translate";import{InputType as m}from"@openremote/or-mwc-components/or-mwc-input";import v from"i18next";import{showErrorDialog as f}from"@openremote/or-mwc-components/or-mwc-dialog";import{project as w}from"./flow-viewer/components/flow-editor";export const style=e`
2
-
3
- :host {
4
- display: block;
5
- height: 100%;
6
- width: 100%;
7
- overflow-y: auto;
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
+ /*
17
+ * Copyright 2025, OpenRemote Inc.
18
+ *
19
+ * See the CONTRIBUTORS.txt file in the distribution for a
20
+ * full listing of individual contributors.
21
+ *
22
+ * This program is free software: you can redistribute it and/or modify
23
+ * it under the terms of the GNU Affero General Public License as
24
+ * published by the Free Software Foundation, either version 3 of the
25
+ * License, or (at your option) any later version.
26
+ *
27
+ * This program is distributed in the hope that it will be useful,
28
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30
+ * GNU Affero General Public License for more details.
31
+ *
32
+ * You should have received a copy of the GNU Affero General Public License
33
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
34
+ */
35
+ import { css, html, LitElement } from "lit";
36
+ import { customElement, property, query } from "lit/decorators.js";
37
+ import { OrRulesRequestSaveEvent, OrRulesRuleChangedEvent, OrRulesRuleUnsupportedEvent, OrRulesSaveEvent, RuleViewInfoMap } from "./index";
38
+ import manager, { Util } from "@openremote/core";
39
+ import "./json-viewer/or-rule-json-viewer";
40
+ import "./or-rule-text-viewer";
41
+ import "./or-rule-validity";
42
+ import "./flow-viewer/components/flow-editor";
43
+ import "@openremote/or-mwc-components/or-mwc-input";
44
+ import { translate } from "@openremote/or-translate";
45
+ import { InputType } from "@openremote/or-mwc-components/or-mwc-input";
46
+ import i18next from "i18next";
47
+ import { showErrorDialog } from "@openremote/or-mwc-components/or-mwc-dialog";
48
+ import { project } from "./flow-viewer/components/flow-editor";
49
+ // language=CSS
50
+ export const style = css `
51
+
52
+ :host {
53
+ display: block;
54
+ height: 100%;
55
+ width: 100%;
56
+ overflow-y: auto;
57
+ }
58
+
59
+ or-rule-validity {
60
+ margin-left: 10px;
61
+ margin-right: 20px;
62
+ }
63
+
64
+ .wrapper {
65
+ display: flex;
66
+ flex-direction: column;
67
+ align-items: center;
68
+ height: 100%;
69
+ }
70
+
71
+ #main-wrapper.saving {
72
+ opacity: 0.5;
73
+ pointer-events: none;
74
+ }
75
+
76
+ #rule-name {
77
+ max-width: 400px;
78
+ flex: 1 1 0;
79
+ display: flex;
80
+ }
81
+
82
+ #rule-header {
83
+ display: flex;
84
+ align-items: center;
85
+ width: 100%;
86
+ box-sizing: border-box;
87
+ min-height: var(--internal-or-rules-header-height);
88
+ height: var(--internal-or-rules-header-height);
89
+ z-index: 7;
90
+ padding: 15px 20px;
91
+ --or-icon-fill: var(--internal-or-rules-panel-color);
92
+ }
93
+
94
+ #rule-header-controls {
95
+ margin-left: auto;
96
+ display: flex;
97
+ align-items: center;
98
+ }
99
+
100
+ #rule-id {
101
+ margin-left: 10px;
102
+ font-size: small;
103
+ }
104
+
105
+ #active-wrapper {
106
+ display: flex;
107
+ align-items: center;
108
+ }
109
+
110
+ #rule-view {
111
+ flex-grow: 1;
112
+ background-color: var(--internal-or-rules-background-color);
113
+ }
114
+
115
+ .iconfill-gray {
116
+ margin-left: 10px;
117
+ --or-icon-fill: var(--internal-or-rules-list-icon-color-ok);
118
+ }
119
+
120
+ .iconfill-red {
121
+ margin-left: 10px;
122
+ --or-icon-fill: var(--internal-or-rules-list-icon-color-error);
123
+ }
124
+ `;
125
+ let OrRuleViewer = class OrRuleViewer extends translate(i18next)(LitElement) {
126
+ static get styles() {
127
+ return [
128
+ style
129
+ ];
8
130
  }
9
-
10
- or-rule-validity {
11
- margin-left: 10px;
12
- margin-right: 20px;
131
+ constructor() {
132
+ super();
133
+ this.readonly = false;
134
+ this.disabled = false;
135
+ this.modified = false;
136
+ this._ruleValid = false;
137
+ this._supported = true;
138
+ this._focusName = false;
139
+ this.addEventListener(OrRulesRuleChangedEvent.NAME, this._onRuleChanged);
140
+ this.addEventListener(OrRulesRuleUnsupportedEvent.NAME, this._onRuleUnsupported);
13
141
  }
14
-
15
- .wrapper {
16
- display: flex;
17
- flex-direction: column;
18
- align-items: center;
19
- height: 100%;
142
+ get valid() {
143
+ return this.ruleset && this.view && this._ruleValid && this.ruleset.name && this.ruleset.name.length >= 1 && this.ruleset.name.length < 255;
20
144
  }
21
-
22
- #main-wrapper.saving {
23
- opacity: 0.5;
24
- pointer-events: none;
145
+ shouldUpdate(_changedProperties) {
146
+ if (_changedProperties.has("ruleset")) {
147
+ this._supported = true;
148
+ this.modified = false;
149
+ this._ruleValid = false;
150
+ if (this.ruleset) {
151
+ this._focusName = true;
152
+ this.modified = !this.ruleset.id;
153
+ }
154
+ }
155
+ return super.shouldUpdate(_changedProperties);
25
156
  }
26
-
27
- #rule-name {
28
- max-width: 400px;
29
- flex: 1 1 0;
30
- display: flex;
157
+ render() {
158
+ if (!this.ruleset) {
159
+ return html `<div class="wrapper" style="justify-content: center"><or-translate value="noRuleSelected"></or-translate></div>`;
160
+ }
161
+ let viewer = RuleViewInfoMap[this.ruleset.lang].viewTemplateProvider(this.ruleset, this.config, this.readonly);
162
+ let statusIcon = "help";
163
+ let statusClass = "iconfill-gray";
164
+ let statusText = "NOSTATUS";
165
+ if (this.ruleset.status)
166
+ statusText = this.ruleset.status;
167
+ switch (this.ruleset.status) {
168
+ case "DEPLOYED":
169
+ statusIcon = "play";
170
+ statusClass = "iconfill-gray";
171
+ break;
172
+ case "READY":
173
+ statusIcon = "check";
174
+ statusClass = "iconfill-gray";
175
+ break;
176
+ case "COMPILATION_ERROR":
177
+ case "LOOP_ERROR":
178
+ case "VALIDITY_PERIOD_ERROR":
179
+ case "EXECUTION_ERROR":
180
+ statusIcon = "alert-octagon";
181
+ statusClass = "iconfill-red";
182
+ statusText = this.ruleset.error;
183
+ break;
184
+ case "DISABLED":
185
+ statusIcon = "minus-circle";
186
+ statusClass = "iconfill-gray";
187
+ break;
188
+ case "PAUSED":
189
+ statusIcon = "calendar-arrow-right";
190
+ statusClass = "iconfill-gray";
191
+ break;
192
+ case "EXPIRED":
193
+ statusIcon = "calendar-remove";
194
+ statusClass = "iconfill-gray";
195
+ break;
196
+ case "REMOVED":
197
+ statusIcon = "close";
198
+ statusClass = "iconfill-gray";
199
+ break;
200
+ default:
201
+ statusIcon = "stop";
202
+ statusClass = "iconfill-gray";
203
+ statusText = "NOSTATUS";
204
+ }
205
+ return html `
206
+ <div id="main-wrapper" class="wrapper">
207
+ <div id="rule-header">
208
+ <or-mwc-input id="rule-name" outlined .type="${InputType.TEXT}" .label="${i18next.t("ruleName")}" ?focused="${this._focusName}" .value="${this.ruleset ? this.ruleset.name : null}" ?disabled="${this._isReadonly()}" required minlength="1" maxlength="255" @or-mwc-input-changed="${(e) => this._changeName(e.detail.value)}"></or-mwc-input>
209
+ <or-icon class="${statusClass}" title="${i18next.t("rulesetStatus." + statusText)}" icon="${statusIcon}"></or-icon>
210
+ <span id="rule-id">${this.ruleset.id ? "ID: " + this.ruleset.id : ""}</span>
211
+ <div id="rule-header-controls">
212
+ <span id="active-wrapper">
213
+ <or-translate value="enabled"></or-translate>
214
+ <or-mwc-input .type="${InputType.CHECKBOX}" .value="${this.ruleset && this.ruleset.enabled}" ?disabled="${!this.ruleset.id}" @or-mwc-input-changed="${this._toggleEnabled}"></or-mwc-input>
215
+ </span>
216
+ <or-rule-validity id="rule-header-validity" .ruleset="${this.ruleset}"></or-rule-validity>
217
+ <or-mwc-input .type="${InputType.BUTTON}" id="save-btn" label="save" raised ?disabled="${this._cannotSave()}" @or-mwc-input-changed="${this._onSaveClicked}"></or-mwc-input>
218
+ </div>
219
+ </div>
220
+
221
+ ${viewer}
222
+ </div>
223
+ `;
31
224
  }
32
-
33
- #rule-header {
34
- display: flex;
35
- align-items: center;
36
- width: 100%;
37
- box-sizing: border-box;
38
- min-height: var(--internal-or-rules-header-height);
39
- height: var(--internal-or-rules-header-height);
40
- z-index: 7;
41
- padding: 15px 20px;
42
- --or-icon-fill: var(--internal-or-rules-panel-color);
225
+ updated(_changedProperties) {
226
+ if (_changedProperties.has("ruleset") || _changedProperties.has("modified")) {
227
+ if (this.ruleset && this.view) {
228
+ this._ruleValid = this.view.validate();
229
+ }
230
+ }
43
231
  }
44
-
45
- #rule-header-controls {
46
- margin-left: auto;
47
- display: flex;
48
- align-items: center;
232
+ _isReadonly() {
233
+ return this.readonly || !manager.hasRole("write:rules" /* ClientRole.WRITE_RULES */);
49
234
  }
50
-
51
- #rule-id {
52
- margin-left: 10px;
53
- font-size: small;
235
+ _cannotSave() {
236
+ return this._isReadonly() || !this.ruleset || !this.modified || !this.valid;
54
237
  }
55
-
56
- #active-wrapper {
57
- display: flex;
58
- align-items: center;
238
+ _changeName(name) {
239
+ if (this.ruleset && this.ruleset.name !== name) {
240
+ this.ruleset.name = name;
241
+ this.modified = true;
242
+ this.requestUpdate();
243
+ }
59
244
  }
60
-
61
- #rule-view {
62
- flex-grow: 1;
63
- background-color: var(--internal-or-rules-background-color);
245
+ _onRuleChanged(e) {
246
+ this.modified = true;
247
+ this._ruleValid = e.detail;
64
248
  }
65
-
66
- .iconfill-gray {
67
- margin-left: 10px;
68
- --or-icon-fill: var(--internal-or-rules-list-icon-color-ok);
249
+ _onSaveClicked() {
250
+ if (!this.ruleset || !this.view) {
251
+ return;
252
+ }
253
+ project.emit("fitview");
254
+ if (this.config && this.config.rulesetSaveHandler && !this.config.rulesetSaveHandler(this.ruleset)) {
255
+ return;
256
+ }
257
+ Util.dispatchCancellableEvent(this, new OrRulesRequestSaveEvent(this.ruleset))
258
+ .then((detail) => {
259
+ if (detail.allow) {
260
+ this._doSave();
261
+ }
262
+ });
69
263
  }
70
-
71
- .iconfill-red {
72
- margin-left: 10px;
73
- --or-icon-fill: var(--internal-or-rules-list-icon-color-error);
264
+ _doSave() {
265
+ return __awaiter(this, void 0, void 0, function* () {
266
+ const ruleset = this.ruleset;
267
+ if (!ruleset || !this.view) {
268
+ return;
269
+ }
270
+ let fail = false;
271
+ const isNew = !ruleset.id;
272
+ this.saveBtnElem.disabled = true;
273
+ this.wrapperElem.classList.add("saving");
274
+ this.view.beforeSave();
275
+ let response;
276
+ try {
277
+ switch (ruleset.type) {
278
+ case "asset":
279
+ if (isNew) {
280
+ response = yield manager.rest.api.RulesResource.createAssetRuleset(ruleset);
281
+ }
282
+ else {
283
+ response = yield manager.rest.api.RulesResource.updateAssetRuleset(ruleset.id, ruleset);
284
+ }
285
+ break;
286
+ case "realm":
287
+ if (isNew) {
288
+ response = yield manager.rest.api.RulesResource.createRealmRuleset(ruleset);
289
+ }
290
+ else {
291
+ response = yield manager.rest.api.RulesResource.updateRealmRuleset(ruleset.id, ruleset);
292
+ }
293
+ break;
294
+ case "global":
295
+ if (isNew) {
296
+ response = yield manager.rest.api.RulesResource.createGlobalRuleset(ruleset);
297
+ }
298
+ else {
299
+ response = yield manager.rest.api.RulesResource.updateGlobalRuleset(ruleset.id, ruleset);
300
+ }
301
+ break;
302
+ }
303
+ if (response.status !== (isNew ? 200 : 204)) {
304
+ fail = true;
305
+ showErrorDialog("Create ruleset returned unexpected status: " + response.status);
306
+ return;
307
+ }
308
+ else if (response.data) {
309
+ ruleset.id = response.data;
310
+ }
311
+ }
312
+ catch (e) {
313
+ fail = true;
314
+ console.error("Failed to save ruleset", e);
315
+ }
316
+ this.wrapperElem.classList.remove("saving");
317
+ this.saveBtnElem.disabled = false;
318
+ if (fail) {
319
+ showErrorDialog(i18next.t("saveRulesetFailed"));
320
+ }
321
+ this.dispatchEvent(new OrRulesSaveEvent({
322
+ ruleset: ruleset,
323
+ isNew: isNew,
324
+ success: !fail
325
+ }));
326
+ });
74
327
  }
75
- `;let OrRuleViewer=class extends h(v)(r){static get styles(){return[style]}constructor(){super(),this.readonly=!1,this.disabled=!1,this.modified=!1,this._ruleValid=!1,this._supported=!0,this._focusName=!1,this.addEventListener(o.NAME,this._onRuleChanged),this.addEventListener(n.NAME,this._onRuleUnsupported)}get valid(){return this.ruleset&&this.view&&this._ruleValid&&this.ruleset.name&&this.ruleset.name.length>=1&&this.ruleset.name.length<255}shouldUpdate(e){return e.has("ruleset")&&(this._supported=!0,this.modified=!1,this._ruleValid=!1,this.ruleset&&(this._focusName=!0,this.modified=!this.ruleset.id)),super.shouldUpdate(e)}render(){if(!this.ruleset)return t`<div class="wrapper" style="justify-content: center"><or-translate value="noRuleSelected"></or-translate></div>`;let e=u[this.ruleset.lang].viewTemplateProvider(this.ruleset,this.config,this.readonly),r="help",i="iconfill-gray",l="NOSTATUS";switch(this.ruleset.status&&(l=this.ruleset.status),this.ruleset.status){case"DEPLOYED":r="play",i="iconfill-gray";break;case"READY":r="check",i="iconfill-gray";break;case"COMPILATION_ERROR":case"LOOP_ERROR":case"VALIDITY_PERIOD_ERROR":case"EXECUTION_ERROR":r="alert-octagon",i="iconfill-red",l=this.ruleset.error;break;case"DISABLED":r="minus-circle",i="iconfill-gray";break;case"PAUSED":r="calendar-arrow-right",i="iconfill-gray";break;case"EXPIRED":r="calendar-remove",i="iconfill-gray";break;case"REMOVED":r="close",i="iconfill-gray";break;default:r="stop",i="iconfill-gray",l="NOSTATUS"}return t`
76
- <div id="main-wrapper" class="wrapper">
77
- <div id="rule-header">
78
- <or-mwc-input id="rule-name" outlined .type="${m.TEXT}" .label="${v.t("ruleName")}" ?focused="${this._focusName}" .value="${this.ruleset?this.ruleset.name:null}" ?disabled="${this._isReadonly()}" required minlength="1" maxlength="255" @or-mwc-input-changed="${e=>this._changeName(e.detail.value)}"></or-mwc-input>
79
- <or-icon class="${i}" title="${v.t("rulesetStatus."+l)}" icon="${r}"></or-icon>
80
- <span id="rule-id">${this.ruleset.id?"ID: "+this.ruleset.id:""}</span>
81
- <div id="rule-header-controls">
82
- <span id="active-wrapper">
83
- <or-translate value="enabled"></or-translate>
84
- <or-mwc-input .type="${m.CHECKBOX}" .value="${this.ruleset&&this.ruleset.enabled}" ?disabled="${!this.ruleset.id}" @or-mwc-input-changed="${this._toggleEnabled}"></or-mwc-input>
85
- </span>
86
- <or-rule-validity id="rule-header-validity" .ruleset="${this.ruleset}"></or-rule-validity>
87
- <or-mwc-input .type="${m.BUTTON}" id="save-btn" label="save" raised ?disabled="${this._cannotSave()}" @or-mwc-input-changed="${this._onSaveClicked}"></or-mwc-input>
88
- </div>
89
- </div>
90
-
91
- ${e}
92
- </div>
93
- `}updated(e){(e.has("ruleset")||e.has("modified"))&&this.ruleset&&this.view&&(this._ruleValid=this.view.validate())}_isReadonly(){return this.readonly||!c.hasRole("write:rules")}_cannotSave(){return this._isReadonly()||!this.ruleset||!this.modified||!this.valid}_changeName(e){this.ruleset&&this.ruleset.name!==e&&(this.ruleset.name=e,this.modified=!0,this.requestUpdate())}_onRuleChanged(e){this.modified=!0,this._ruleValid=e.detail}_onSaveClicked(){this.ruleset&&this.view&&(w.emit("fitview"),(!this.config||!this.config.rulesetSaveHandler||this.config.rulesetSaveHandler(this.ruleset))&&p.dispatchCancellableEvent(this,new a(this.ruleset)).then(e=>{e.allow&&this._doSave()}))}_doSave(){return __awaiter(this,void 0,void 0,function*(){let e,t=this.ruleset;if(!t||!this.view)return;let r=!1,i=!t.id;this.saveBtnElem.disabled=!0,this.wrapperElem.classList.add("saving"),this.view.beforeSave();try{switch(t.type){case"asset":e=i?yield c.rest.api.RulesResource.createAssetRuleset(t):yield c.rest.api.RulesResource.updateAssetRuleset(t.id,t);break;case"realm":e=i?yield c.rest.api.RulesResource.createRealmRuleset(t):yield c.rest.api.RulesResource.updateRealmRuleset(t.id,t);break;case"global":e=i?yield c.rest.api.RulesResource.createGlobalRuleset(t):yield c.rest.api.RulesResource.updateGlobalRuleset(t.id,t)}if(e.status!==(i?200:204)){r=!0,f("Create ruleset returned unexpected status: "+e.status);return}e.data&&(t.id=e.data)}catch(e){r=!0,console.error("Failed to save ruleset",e)}this.wrapperElem.classList.remove("saving"),this.saveBtnElem.disabled=!1,r&&f(v.t("saveRulesetFailed")),this.dispatchEvent(new d({ruleset:t,isNew:i,success:!r}))})}_onRuleUnsupported(){this._supported=!1}_toggleEnabled(){this.ruleset&&(this.ruleset.enabled=!this.ruleset.enabled,this.modified=!0,this.requestUpdate())}};__decorate([l({type:Object})],OrRuleViewer.prototype,"ruleset",void 0),__decorate([l({type:Boolean})],OrRuleViewer.prototype,"readonly",void 0),__decorate([l({type:Boolean})],OrRuleViewer.prototype,"disabled",void 0),__decorate([l({type:Object})],OrRuleViewer.prototype,"config",void 0),__decorate([l({attribute:!1})],OrRuleViewer.prototype,"modified",void 0),__decorate([l({attribute:!1})],OrRuleViewer.prototype,"_ruleValid",void 0),__decorate([l({attribute:!1})],OrRuleViewer.prototype,"_supported",void 0),__decorate([s("#rule-view")],OrRuleViewer.prototype,"view",void 0),__decorate([s("#main-wrapper")],OrRuleViewer.prototype,"wrapperElem",void 0),__decorate([s("#save-btn")],OrRuleViewer.prototype,"saveBtnElem",void 0),OrRuleViewer=__decorate([i("or-rule-viewer")],OrRuleViewer);export{OrRuleViewer};
328
+ _onRuleUnsupported() {
329
+ this._supported = false;
330
+ }
331
+ _toggleEnabled() {
332
+ if (this.ruleset) {
333
+ this.ruleset.enabled = !this.ruleset.enabled;
334
+ this.modified = true;
335
+ this.requestUpdate();
336
+ }
337
+ }
338
+ };
339
+ __decorate([
340
+ property({ type: Object })
341
+ ], OrRuleViewer.prototype, "ruleset", void 0);
342
+ __decorate([
343
+ property({ type: Boolean })
344
+ ], OrRuleViewer.prototype, "readonly", void 0);
345
+ __decorate([
346
+ property({ type: Boolean })
347
+ ], OrRuleViewer.prototype, "disabled", void 0);
348
+ __decorate([
349
+ property({ type: Object })
350
+ ], OrRuleViewer.prototype, "config", void 0);
351
+ __decorate([
352
+ property({ attribute: false })
353
+ ], OrRuleViewer.prototype, "modified", void 0);
354
+ __decorate([
355
+ property({ attribute: false })
356
+ ], OrRuleViewer.prototype, "_ruleValid", void 0);
357
+ __decorate([
358
+ property({ attribute: false })
359
+ ], OrRuleViewer.prototype, "_supported", void 0);
360
+ __decorate([
361
+ query("#rule-view")
362
+ ], OrRuleViewer.prototype, "view", void 0);
363
+ __decorate([
364
+ query("#main-wrapper")
365
+ ], OrRuleViewer.prototype, "wrapperElem", void 0);
366
+ __decorate([
367
+ query("#save-btn")
368
+ ], OrRuleViewer.prototype, "saveBtnElem", void 0);
369
+ OrRuleViewer = __decorate([
370
+ customElement("or-rule-viewer")
371
+ ], OrRuleViewer);
372
+ export { OrRuleViewer };
373
+ //# sourceMappingURL=or-rule-viewer.js.map
package/lib/style.js CHANGED
@@ -1,64 +1,89 @@
1
- import{DefaultColor5 as o}from"@openremote/core";import{css as n,unsafeCSS as t}from"lit";export const invalidStyle=n`
2
- *:invalid {
3
- border-bottom: 2px solid var(--internal-or-rules-invalid-color);
4
- }
5
- `;export const buttonStyle=n`
6
- .button-clear {
7
- background: none;
8
- color: ${t(o)};
9
- --or-icon-fill: ${t(o)};
10
- visibility: hidden;
11
- display: inline-block;
12
- border: none;
13
- padding: 0;
14
- cursor: pointer;
15
- }
16
-
17
- .button-clear:hover {
18
- --or-icon-fill: var(--internal-or-rules-button-color);
19
- }
20
-
21
- .button-clear:focus {
22
- outline: 0;
23
- }
24
-
25
- .button-clear.hidden {
26
- visibility: hidden;
27
- }
28
-
29
- .plus-button {
30
- --or-icon-fill: var(--internal-or-rules-button-color);
31
- }
32
-
33
- .add-button {
34
- display: inline-block;
35
- font-weight: bold;
36
- font-size: 15px;
37
- line-height: 24px;
38
- }
39
-
40
- .add-buttons-container {
41
- display: flex;
42
- flex-direction: column;
43
- margin-top: 10px;
44
- margin-bottom: -10px;
45
- padding-top: 5px;
46
- border-top-width: 1px;
47
- border-top-style: solid;
48
- border-color: var(--internal-or-rules-line-color);
49
- }
50
-
51
- .add-buttons-container.hidden {
52
- border: none;
53
- margin: 0;
54
- padding: 0;
55
- }
56
-
57
- .add-buttons-container > button {
58
- display: inline-flex;
59
- }
60
-
61
- .add-buttons-container > button > or-icon {
62
- margin-right: 5px;
63
- }
64
- `;
1
+ /*
2
+ * Copyright 2025, OpenRemote Inc.
3
+ *
4
+ * See the CONTRIBUTORS.txt file in the distribution for a
5
+ * full listing of individual contributors.
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU Affero General Public License as
9
+ * published by the Free Software Foundation, either version 3 of the
10
+ * License, or (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU Affero General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Affero General Public License
18
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+ import { DefaultColor5 } from "@openremote/core";
21
+ import { css, unsafeCSS } from "lit";
22
+ // language=CSS
23
+ export const invalidStyle = css `
24
+ *:invalid {
25
+ border-bottom: 2px solid var(--internal-or-rules-invalid-color);
26
+ }
27
+ `;
28
+ // language=CSS
29
+ export const buttonStyle = css `
30
+ .button-clear {
31
+ background: none;
32
+ color: ${unsafeCSS(DefaultColor5)};
33
+ --or-icon-fill: ${unsafeCSS(DefaultColor5)};
34
+ visibility: hidden;
35
+ display: inline-block;
36
+ border: none;
37
+ padding: 0;
38
+ cursor: pointer;
39
+ }
40
+
41
+ .button-clear:hover {
42
+ --or-icon-fill: var(--internal-or-rules-button-color);
43
+ }
44
+
45
+ .button-clear:focus {
46
+ outline: 0;
47
+ }
48
+
49
+ .button-clear.hidden {
50
+ visibility: hidden;
51
+ }
52
+
53
+ .plus-button {
54
+ --or-icon-fill: var(--internal-or-rules-button-color);
55
+ }
56
+
57
+ .add-button {
58
+ display: inline-block;
59
+ font-weight: bold;
60
+ font-size: 15px;
61
+ line-height: 24px;
62
+ }
63
+
64
+ .add-buttons-container {
65
+ display: flex;
66
+ flex-direction: column;
67
+ margin-top: 10px;
68
+ margin-bottom: -10px;
69
+ padding-top: 5px;
70
+ border-top-width: 1px;
71
+ border-top-style: solid;
72
+ border-color: var(--internal-or-rules-line-color);
73
+ }
74
+
75
+ .add-buttons-container.hidden {
76
+ border: none;
77
+ margin: 0;
78
+ padding: 0;
79
+ }
80
+
81
+ .add-buttons-container > button {
82
+ display: inline-flex;
83
+ }
84
+
85
+ .add-buttons-container > button > or-icon {
86
+ margin-right: 5px;
87
+ }
88
+ `;
89
+ //# sourceMappingURL=style.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openremote/or-rules",
3
- "version": "1.8.0-snapshot.20250725074716",
3
+ "version": "1.8.0-snapshot.20250725120000",
4
4
  "description": "OpenRemote rules related UI components",
5
5
  "customElements": "custom-elements.json",
6
6
  "main": "dist/umd/index.bundle.js",
@@ -18,15 +18,15 @@
18
18
  "author": "OpenRemote",
19
19
  "license": "AGPL-3.0-or-later",
20
20
  "dependencies": {
21
- "@openremote/core": "1.8.0-snapshot.20250725074716",
22
- "@openremote/model": "1.8.0-snapshot.20250725074716",
23
- "@openremote/or-attribute-input": "1.8.0-snapshot.20250725074716",
24
- "@openremote/or-components": "1.8.0-snapshot.20250725074716",
25
- "@openremote/or-icon": "1.8.0-snapshot.20250725074716",
26
- "@openremote/or-mwc-components": "1.8.0-snapshot.20250725074716",
27
- "@openremote/or-translate": "1.8.0-snapshot.20250725074716",
28
- "@openremote/or-tree-menu": "1.8.0-snapshot.20250725074716",
29
- "@openremote/rest": "1.8.0-snapshot.20250725074716",
21
+ "@openremote/core": "1.8.0-snapshot.20250725120000",
22
+ "@openremote/model": "1.8.0-snapshot.20250725120000",
23
+ "@openremote/or-attribute-input": "1.8.0-snapshot.20250725120000",
24
+ "@openremote/or-components": "1.8.0-snapshot.20250725120000",
25
+ "@openremote/or-icon": "1.8.0-snapshot.20250725120000",
26
+ "@openremote/or-mwc-components": "1.8.0-snapshot.20250725120000",
27
+ "@openremote/or-translate": "1.8.0-snapshot.20250725120000",
28
+ "@openremote/or-tree-menu": "1.8.0-snapshot.20250725120000",
29
+ "@openremote/rest": "1.8.0-snapshot.20250725120000",
30
30
  "ace-builds": "^1.41.0",
31
31
  "iso-639-1": "^3.1.3",
32
32
  "linqts": "^1.12.6",
@@ -37,7 +37,7 @@
37
37
  "shortid": "^2.2.15"
38
38
  },
39
39
  "devDependencies": {
40
- "@openremote/util": "1.8.0-snapshot.20250725074716",
40
+ "@openremote/util": "1.8.0-snapshot.20250725120000",
41
41
  "@types/shortid": "^0.0.29"
42
42
  },
43
43
  "publishConfig": {