@aaqu/fromcubes-react 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +435 -2
- package/THIRD-PARTY-NOTICES.md +164 -0
- package/examples/D3 Poland Map.json +90 -0
- package/examples/Live Chart.json +101 -0
- package/examples/PixiJS Sprites.json +114 -0
- package/examples/Sensor Portal.json +93 -0
- package/examples/Shared Components.json +68 -0
- package/examples/Three.js Scene.json +118 -0
- package/examples/Utility Hooks.json +94 -0
- package/examples/WebGPU Shader.json +110 -0
- package/nodes/editor/ark-pixel.LICENSE.txt +96 -0
- package/nodes/editor/ark-pixel.woff2 +0 -0
- package/nodes/editor/file-tree.js +403 -0
- package/nodes/editor/format.js +182 -0
- package/nodes/editor/icons.svg +46 -0
- package/nodes/editor/mark.svg +5 -0
- package/nodes/editor/provider-settings.js +192 -0
- package/nodes/editor/workspace.css +660 -0
- package/nodes/editor/workspace.js +1565 -0
- package/nodes/icons/fromcubes-component.svg +27 -0
- package/nodes/icons/fromcubes-react.svg +25 -0
- package/nodes/icons/fromcubes-utility.svg +21 -0
- package/nodes/lib/admin-api.js +238 -0
- package/nodes/lib/admin-security.js +161 -0
- package/nodes/lib/api.js +29 -0
- package/nodes/lib/helpers.js +990 -0
- package/nodes/lib/hooks.js +145 -0
- package/nodes/lib/page-builder.js +499 -0
- package/nodes/lib/portal-page-route.js +131 -0
- package/nodes/lib/providers.js +581 -0
- package/nodes/lib/registry-nodes.js +331 -0
- package/nodes/lib/router.js +103 -0
- package/nodes/lib/ws-heartbeat.js +58 -0
- package/nodes/portal-react.html +2539 -0
- package/nodes/portal-react.js +1652 -0
- package/package.json +73 -4
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings → Fromcubes: choose the identity provider and the CSS engine.
|
|
3
|
+
*
|
|
4
|
+
* Exactly one provider per kind, shown as a radio list, so two can never be
|
|
5
|
+
* active at once. Reads and writes `/fromcubes-react/providers`; the server
|
|
6
|
+
* validates, persists to <userDir>/fromcubes/providers.json, and applies the
|
|
7
|
+
* change (identity: every portal session reloads; css: every portal rebuilds).
|
|
8
|
+
* A kind set in settings.js is shown locked.
|
|
9
|
+
*
|
|
10
|
+
* Node-RED shows a pane by the element id `red-ui-settings-tab-<pane id>`,
|
|
11
|
+
* and calls get() every time the Settings tray opens — so each call builds
|
|
12
|
+
* a fresh element and loads fresh data.
|
|
13
|
+
*/
|
|
14
|
+
(function () {
|
|
15
|
+
"use strict";
|
|
16
|
+
|
|
17
|
+
var PANE_ID = "fromcubes";
|
|
18
|
+
var URL = "fromcubes-react/providers";
|
|
19
|
+
|
|
20
|
+
var KINDS = [
|
|
21
|
+
{
|
|
22
|
+
kind: "identity",
|
|
23
|
+
title: "Identity provider",
|
|
24
|
+
hint: "Who is behind a portal session — used by Portal Auth, auth-cast and per-user delivery.",
|
|
25
|
+
setting: "identityProvider",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
kind: "css",
|
|
29
|
+
title: "CSS engine",
|
|
30
|
+
hint: "Generates each portal's stylesheet at deploy. Changing it rebuilds every portal.",
|
|
31
|
+
setting: "cssEngine",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
function errorText(xhr) {
|
|
36
|
+
var body = xhr && xhr.responseJSON;
|
|
37
|
+
return (body && body.error) || (xhr && xhr.statusText) || "request failed";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function renderKind(container, def, info, onPick) {
|
|
41
|
+
var section = $('<div class="fc-ps-section"></div>').appendTo(container);
|
|
42
|
+
$("<h3></h3>").text(def.title).appendTo(section);
|
|
43
|
+
$('<p class="fc-ps-hint"></p>').text(def.hint).appendTo(section);
|
|
44
|
+
|
|
45
|
+
if (info.locked) {
|
|
46
|
+
$('<p class="fc-ps-note"></p>')
|
|
47
|
+
.append($("<i></i>").addClass("fa fa-lock"))
|
|
48
|
+
.append(
|
|
49
|
+
document.createTextNode(
|
|
50
|
+
" Set in settings.js (portalReact." + def.setting + ") — change it there.",
|
|
51
|
+
),
|
|
52
|
+
)
|
|
53
|
+
.appendTo(section);
|
|
54
|
+
}
|
|
55
|
+
if (info.missing) {
|
|
56
|
+
$('<p class="fc-ps-warn"></p>')
|
|
57
|
+
.append($("<i></i>").addClass("fa fa-warning"))
|
|
58
|
+
.append(
|
|
59
|
+
document.createTextNode(
|
|
60
|
+
' "' + info.selected + '" is selected but not installed' +
|
|
61
|
+
(def.kind === "identity"
|
|
62
|
+
? " — every session is anonymous."
|
|
63
|
+
: " — portals are served without CSS."),
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
.appendTo(section);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var name = "fc-ps-" + def.kind;
|
|
70
|
+
info.options.forEach(function (opt) {
|
|
71
|
+
var inputId = name + "-" + opt.id.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
72
|
+
var row = $('<div class="red-ui-settings-row fc-ps-row"></div>').appendTo(section);
|
|
73
|
+
var input = $('<input type="radio">')
|
|
74
|
+
.attr({ id: inputId, name: name, value: opt.id })
|
|
75
|
+
.prop("checked", opt.id === info.selected)
|
|
76
|
+
.prop("disabled", info.locked || opt.missing || !!opt.problem)
|
|
77
|
+
.appendTo(row);
|
|
78
|
+
var label = $("<label></label>").attr("for", inputId).appendTo(row);
|
|
79
|
+
$('<span class="fc-ps-id"></span>').text(opt.id).appendTo(label);
|
|
80
|
+
$('<span class="fc-ps-module"></span>')
|
|
81
|
+
.text(opt.missing ? "not installed" : opt.module)
|
|
82
|
+
.appendTo(label);
|
|
83
|
+
if (opt.label) $('<span class="fc-ps-label"></span>').text(opt.label).appendTo(label);
|
|
84
|
+
if (opt.problem) $('<span class="fc-ps-problem"></span>').text(opt.problem).appendTo(label);
|
|
85
|
+
input.on("change", function () {
|
|
86
|
+
if (this.checked) onPick(def, opt.id, info.selected);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function createPane() {
|
|
92
|
+
var pane = $('<div class="red-ui-help fc-ps"></div>').attr(
|
|
93
|
+
"id",
|
|
94
|
+
"red-ui-settings-tab-" + PANE_ID,
|
|
95
|
+
);
|
|
96
|
+
var body = $('<div class="fc-ps-body"></div>').appendTo(pane);
|
|
97
|
+
|
|
98
|
+
function render(data) {
|
|
99
|
+
body.empty();
|
|
100
|
+
KINDS.forEach(function (def) {
|
|
101
|
+
if (data[def.kind]) renderKind(body, def, data[def.kind], pick);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function load() {
|
|
106
|
+
body.empty().append($('<p class="fc-ps-hint"></p>').text("Loading…"));
|
|
107
|
+
$.ajax({ url: URL, method: "GET", dataType: "json" })
|
|
108
|
+
.done(render)
|
|
109
|
+
.fail(function (xhr) {
|
|
110
|
+
body.empty();
|
|
111
|
+
$('<p class="fc-ps-warn"></p>')
|
|
112
|
+
.text("Cannot load providers: " + errorText(xhr))
|
|
113
|
+
.appendTo(body);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function save(def, id) {
|
|
118
|
+
$.ajax({
|
|
119
|
+
url: URL,
|
|
120
|
+
method: "PUT",
|
|
121
|
+
contentType: "application/json",
|
|
122
|
+
dataType: "json",
|
|
123
|
+
data: JSON.stringify({ kind: def.kind, id: id }),
|
|
124
|
+
})
|
|
125
|
+
.done(function (data) {
|
|
126
|
+
RED.notify(def.title + ": " + id, "success");
|
|
127
|
+
render(data);
|
|
128
|
+
// className completion follows the engine (portal-react.html).
|
|
129
|
+
if (def.kind === "css" && window.__fcRefreshCssClasses) {
|
|
130
|
+
window.__fcRefreshCssClasses();
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
.fail(function (xhr) {
|
|
134
|
+
RED.notify(def.title + " not changed: " + errorText(xhr), "error");
|
|
135
|
+
load();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Identity decides who counts as logged in on every portal, and every
|
|
140
|
+
// open portal tab reloads when it changes — so it asks first. CSS only
|
|
141
|
+
// restyles, and applies straight away.
|
|
142
|
+
function pick(def, id, previous) {
|
|
143
|
+
if (def.kind !== "identity") {
|
|
144
|
+
save(def, id);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
var note = RED.notify(
|
|
148
|
+
"<p>Switch the identity provider from <b>" +
|
|
149
|
+
RED.utils.sanitize(previous) +
|
|
150
|
+
"</b> to <b>" +
|
|
151
|
+
RED.utils.sanitize(id) +
|
|
152
|
+
"</b>?</p><p>This changes who counts as logged in on every portal. " +
|
|
153
|
+
"Every open portal tab reloads.</p>",
|
|
154
|
+
{
|
|
155
|
+
modal: true,
|
|
156
|
+
fixed: true,
|
|
157
|
+
type: "warning",
|
|
158
|
+
buttons: [
|
|
159
|
+
{
|
|
160
|
+
text: RED._("common.label.cancel"),
|
|
161
|
+
click: function () {
|
|
162
|
+
note.close();
|
|
163
|
+
load(); // put the radio back on the provider still in force
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
text: "Switch",
|
|
168
|
+
class: "primary",
|
|
169
|
+
click: function () {
|
|
170
|
+
note.close();
|
|
171
|
+
save(def, id);
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
load();
|
|
180
|
+
return pane;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function init() {
|
|
184
|
+
if (!window.RED || !RED.userSettings || typeof RED.userSettings.add !== "function") {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
RED.userSettings.add({ id: PANE_ID, title: "Fromcubes", get: createPane });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (window.RED && RED.userSettings) init();
|
|
191
|
+
else $(init);
|
|
192
|
+
})();
|