@pb33f/cowboy-components 0.7.5 → 0.7.7
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/dist/components/auth/login-button.d.ts +3 -0
- package/dist/components/auth/login-button.js +29 -8
- package/dist/components/auth/login-panel.d.ts +2 -1
- package/dist/components/auth/login-panel.js +3 -2
- package/dist/components/auth/oauth-login.d.ts +1 -0
- package/dist/components/auth/oauth-login.js +11 -5
- package/dist/components/editor/editor-breadcrumb.css.js +1 -1
- package/dist/components/model-renderer/rendered-node.d.ts +2 -0
- package/dist/components/model-renderer/rendered-node.js +18 -0
- package/dist/components/model-renderer/responses.d.ts +11 -0
- package/dist/components/model-renderer/responses.js +46 -0
- package/dist/components/model-tree/tree.js +1 -1
- package/dist/components/paginator/paginator.css.js +1 -1
- package/dist/components/paginator/paginator.d.ts +2 -0
- package/dist/components/paginator/paginator.js +6 -6
- package/dist/components/problems-overview/problems-overview.js +6 -0
- package/dist/components/rodeo/rodeo.js +1 -1
- package/dist/components/the-doctor/sparks.d.ts +1 -0
- package/dist/components/the-doctor/sparks.js +36 -21
- package/dist/components/the-doctor/status-bar.css.js +10 -8
- package/dist/components/the-doctor/status-bar.d.ts +2 -0
- package/dist/components/the-doctor/status-bar.js +18 -8
- package/dist/components/the-doctor/the-doctor.css.js +1 -1
- package/dist/components/the-doctor/the-doctor.d.ts +113 -120
- package/dist/components/the-doctor/the-doctor.js +141 -1735
- package/dist/components/the-doctor/upload-archive.d.ts +1 -0
- package/dist/components/the-doctor/upload-archive.js +29 -12
- package/dist/controllers/{auth.d.ts → auth-controller.d.ts} +11 -6
- package/dist/controllers/auth-controller.js +165 -0
- package/dist/controllers/broker-controller.d.ts +22 -0
- package/dist/controllers/broker-controller.js +107 -0
- package/dist/controllers/diagnostic-controller.d.ts +6 -0
- package/dist/controllers/diagnostic-controller.js +262 -0
- package/dist/controllers/docs-controller.d.ts +8 -0
- package/dist/controllers/docs-controller.js +144 -0
- package/dist/controllers/model-controller.d.ts +8 -0
- package/dist/controllers/model-controller.js +87 -0
- package/dist/controllers/node-clicker-controller.d.ts +11 -0
- package/dist/controllers/node-clicker-controller.js +362 -0
- package/dist/controllers/problem-controller.d.ts +7 -0
- package/dist/controllers/problem-controller.js +46 -0
- package/dist/controllers/rolodex-controller.d.ts +10 -0
- package/dist/controllers/rolodex-controller.js +126 -0
- package/dist/controllers/rule-controller.d.ts +19 -0
- package/dist/controllers/rule-controller.js +264 -0
- package/dist/controllers/spec-controller.d.ts +8 -0
- package/dist/controllers/spec-controller.js +78 -0
- package/dist/controllers/state-controller.d.ts +9 -0
- package/dist/controllers/state-controller.js +279 -0
- package/dist/cowboy-components.umd.cjs +768 -736
- package/dist/css/pb33f-theme.css +1 -0
- package/dist/css/shared.css.js +5 -0
- package/dist/events/doctor.d.ts +12 -0
- package/dist/events/doctor.js +4 -0
- package/dist/model/api-response.d.ts +7 -0
- package/dist/model/api-response.js +2 -0
- package/dist/services/auth-service.d.ts +1 -0
- package/dist/services/auth-service.js +28 -0
- package/dist/services/linting-service.js +11 -2
- package/dist/services/model-service.d.ts +2 -1
- package/dist/services/model-service.js +31 -5
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/dist/controllers/auth.js +0 -101
|
@@ -16,12 +16,11 @@ import '@shoelace-style/shoelace/dist/components/avatar/avatar.js';
|
|
|
16
16
|
import { customElement, property, query, state } from "lit/decorators.js";
|
|
17
17
|
import { html, LitElement } from "lit";
|
|
18
18
|
import { SpecEditor } from "../editor/editor.js";
|
|
19
|
-
import { ActiveView, AddToast, ArchiveURLRequested, BuiltInRulesetChanged, CustomRulesetEnabled, DocumentReferenceClicked, EditorClicked, EditorUpdated, ExplorerEqualizerChanged, ExplorerEqualizerFiltered, ExplorerNodeClicked, ExportRuleset, LoadRenderedNodeIntoInspector, ModelTreeNodeClicked, NodeReferenceClicked, NukeWorkspaceEvent, OpenProblemDrawer, OpenSettings, ProblemClicked,
|
|
20
|
-
import { ProblemDetailsDrawer
|
|
19
|
+
import { ActiveView, AddToast, ArchiveURLRequested, BuiltInRulesetChanged, CreditEmpty, CustomRulesetEnabled, DocumentReferenceClicked, EditorClicked, EditorUpdated, ExplorerEqualizerChanged, ExplorerEqualizerFiltered, ExplorerNodeClicked, ExportRuleset, LoadRenderedNodeIntoInspector, ModelTreeNodeClicked, NodeReferenceClicked, NukeWorkspaceEvent, OpenProblemDrawer, OpenSettings, ProblemClicked, RolodexRootFileSelected, RolodexTreeNodeClicked, RuleClicked, RulesetSaved, RuleViolationClicked, StartSessionFailed, } from "../../events/doctor.js";
|
|
20
|
+
import { ProblemDetailsDrawer } from "../problem-list/details-drawer.js";
|
|
21
21
|
import { CreateBagManager } from "@pb33f/saddlebag";
|
|
22
22
|
import { LintingService } from "../../services/linting-service.js";
|
|
23
23
|
import { ProblemList } from "../problem-list/problem-list.js";
|
|
24
|
-
import { Problem } from "../../model/problem.js";
|
|
25
24
|
import { ProblemsOverview } from "../problems-overview/problems-overview.js";
|
|
26
25
|
import { ErrorBanner } from "../error-banner/error-banner.js";
|
|
27
26
|
import { StatusBar } from "./status-bar.js";
|
|
@@ -38,29 +37,35 @@ import { ToastType } from "../../model/toast.js";
|
|
|
38
37
|
import dialogCss from "../../css/dialog.css.js";
|
|
39
38
|
import buttonCss from "../../css/button.css.js";
|
|
40
39
|
import radioGroupsCss from "../../css/radiogroups.css.js";
|
|
41
|
-
import { MarkerSeverity } from "monaco-editor";
|
|
42
40
|
import { ModelService } from "../../services/model-service.js";
|
|
43
|
-
import { SearchNodeTreeForPath } from "../../model/graph.js";
|
|
44
41
|
import { ModelTree } from "../model-tree/tree.js";
|
|
45
42
|
import { ExplorerComponent } from "../visualizer/explorer.js";
|
|
46
43
|
import { RenderedNodeComponent } from "../model-renderer/rendered-node.js";
|
|
47
44
|
import tabsCss from "../../css/tabs.css.js";
|
|
48
45
|
import { CreateBus } from "@pb33f/ranch";
|
|
49
|
-
import { Command, CreditStreamChannel, DoctorServiceChannel, isBrokerResponse, QueuePrefix, SpecStreamChannel } from "../../model/channels.js";
|
|
50
46
|
import formsCss from "../../css/forms.css.js";
|
|
51
47
|
import spinnerCss from "../../css/spinner.css.js";
|
|
52
48
|
import { UploadArchiveComponent } from "./upload-archive.js";
|
|
53
|
-
import { NodeType } from "../../model/node_type.js";
|
|
54
49
|
import tooltipCss from "../../css/tooltip.css.js";
|
|
55
50
|
import { NukeWorkspaceComponent } from "./nuke-workspace.js";
|
|
56
51
|
import { CreditTicker } from "../credit-ticker/credit-ticker.js";
|
|
57
|
-
import { AuthController } from "../../controllers/auth
|
|
52
|
+
import { AuthController } from "../../controllers/auth-controller";
|
|
58
53
|
import { AuthService } from "../../services/auth-service.js";
|
|
59
54
|
import { TimeVortex } from "../time-vortex/time-vortex.js";
|
|
60
55
|
import { TimelineService } from "../../services/timeline-service.js";
|
|
61
56
|
import { DoctorSettings } from "./settings.js";
|
|
62
57
|
import panelsCss from "../../css/panels.css.js";
|
|
63
|
-
import nukeCss from "../../css/nuke.css";
|
|
58
|
+
import nukeCss from "../../css/nuke.css.js";
|
|
59
|
+
import { NodeClickerController } from '../../controllers/node-clicker-controller.js';
|
|
60
|
+
import { BrokerController } from '../../controllers/broker-controller.js';
|
|
61
|
+
import { RolodexController } from '../../controllers/rolodex-controller.js';
|
|
62
|
+
import { SpecController } from '../../controllers/spec-controller.js';
|
|
63
|
+
import { RuleController } from '../../controllers/rule-controller.js';
|
|
64
|
+
import { ProblemController } from '../../controllers/problem-controller.js';
|
|
65
|
+
import { DocsController } from '../../controllers/docs-controller.js';
|
|
66
|
+
import { ModelController } from '../../controllers/model-controller.js';
|
|
67
|
+
import { DiagnosticController } from '../../controllers/diagnostic-controller.js';
|
|
68
|
+
import { StateController } from '../../controllers/state-controller.js';
|
|
64
69
|
export const GraphBag = "pb33f-doctor-graph";
|
|
65
70
|
export const PanelStateBag = "pb33f-doctor-panel-state";
|
|
66
71
|
export const RolodexResponseBag = "pb33f-doctor-rolodex-response";
|
|
@@ -91,10 +96,9 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
91
96
|
this.debounceTime = 1000;
|
|
92
97
|
this.debounceTimeRuleset = 900;
|
|
93
98
|
this.bounceId = 0;
|
|
94
|
-
this.
|
|
99
|
+
this.firstRun = true;
|
|
95
100
|
// rolodex divider state (because it may not exist)
|
|
96
101
|
this.rolodexDividerPosition = 40;
|
|
97
|
-
this._firstRun = true;
|
|
98
102
|
// extract the doctor endpoint from session storage.
|
|
99
103
|
const sessionEndpoint = sessionStorage.getItem(DoctorEndpoint);
|
|
100
104
|
if (sessionEndpoint) {
|
|
@@ -110,21 +114,23 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
110
114
|
AuthService.doctorEndpoint = this.doctorEndpoint;
|
|
111
115
|
TimelineService.doctorEndpoint = this.doctorEndpoint;
|
|
112
116
|
this.timeVortex = new TimeVortex();
|
|
113
|
-
//this.authController = new AuthController(this)
|
|
114
117
|
// bus it up
|
|
115
118
|
this.bus = CreateBus();
|
|
116
|
-
this.doctorServiceChannel = this.bus.createChannel(DoctorServiceChannel);
|
|
117
|
-
this.specStreamChannel = this.bus.createChannel(SpecStreamChannel);
|
|
118
|
-
this.creditStreamChannel = this.bus.createChannel(CreditStreamChannel);
|
|
119
|
-
this.bus.mapChannelToBrokerDestination(QueuePrefix + DoctorServiceChannel, DoctorServiceChannel);
|
|
120
|
-
// this.bus.mapChannelToBrokerDestination(QueuePrefix + SpecStreamChannel, SpecStreamChannel);
|
|
121
|
-
// this.bus.mapChannelToBrokerDestination(QueuePrefix + CreditStreamChannel, CreditStreamChannel);
|
|
122
|
-
this.doctorChannelSubscription = this.doctorServiceChannel.subscribe(this.doctorServiceHandler());
|
|
123
|
-
// this.specChannelSubscription = this.specStreamChannel.subscribe(this.specStreamHandler());
|
|
124
|
-
// this.creditChannelSubscription = this.creditStreamChannel.subscribe(this.creditStreamHandler());
|
|
125
|
-
// create a stateful bag manager
|
|
126
119
|
this.bagManager = CreateBagManager(true);
|
|
127
|
-
this.
|
|
120
|
+
this.graphBag = this.bagManager.getBag(GraphBag);
|
|
121
|
+
this.docBag = this.bagManager.getBag(DoctorDocumentBag);
|
|
122
|
+
this.rolodexResponseBag = this.bagManager.getBag(RolodexResponseBag);
|
|
123
|
+
this.rolodexFilesBag = this.bagManager.getBag(RolodexFilesBag);
|
|
124
|
+
this.rolodexStateBag = this.bagManager.getBag(RolodexStateBag);
|
|
125
|
+
this.referenceMapBag = this.bagManager.getBag(ReferenceMapBag);
|
|
126
|
+
this.docExpirationBag = this.bagManager.getBag(DocumentationExpirationBag);
|
|
127
|
+
this.panelStateBag = this.bagManager.getBag(PanelStateBag);
|
|
128
|
+
this.settingsBag = this.bagManager.getBag(SettingsBag);
|
|
129
|
+
// create a stateful bag manager
|
|
130
|
+
this.modelController = new ModelController(this);
|
|
131
|
+
this.stateController = new StateController(this);
|
|
132
|
+
// boot state.
|
|
133
|
+
this.bagManager.loadStatefulBags().then(this.stateController.loadState.bind(this.stateController));
|
|
128
134
|
this.editor = new SpecEditor();
|
|
129
135
|
this.uploadArchive = new UploadArchiveComponent();
|
|
130
136
|
this.nukeWorkspace = new NukeWorkspaceComponent();
|
|
@@ -141,6 +147,15 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
141
147
|
this.manageRuleset = new ManageRuleset();
|
|
142
148
|
this.toastManager = new ToastManager();
|
|
143
149
|
this.creditTicker = new CreditTicker();
|
|
150
|
+
// roll the controllers!
|
|
151
|
+
this.nodeClickerController = new NodeClickerController(this);
|
|
152
|
+
this.brokerController = new BrokerController(this);
|
|
153
|
+
this.rolodexController = new RolodexController(this);
|
|
154
|
+
this.specController = new SpecController(this);
|
|
155
|
+
this.ruleController = new RuleController(this);
|
|
156
|
+
this.problemController = new ProblemController(this);
|
|
157
|
+
this.docsController = new DocsController(this);
|
|
158
|
+
this.diagnosticController = new DiagnosticController(this);
|
|
144
159
|
this.settingsComponent = new DoctorSettings();
|
|
145
160
|
this.editorMap = new Map();
|
|
146
161
|
this.editorMap.set("spec", this.editor);
|
|
@@ -172,7 +187,6 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
172
187
|
this.minimapIconVisible = true;
|
|
173
188
|
this.showDiagnosisButton = false;
|
|
174
189
|
this.nodeLimit = 150;
|
|
175
|
-
this.randomTicker = 0;
|
|
176
190
|
// session call back for when we're online.
|
|
177
191
|
const sessionCallback = (session) => {
|
|
178
192
|
if (session.creditsRemaining) {
|
|
@@ -182,72 +196,68 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
182
196
|
this.creditTicker.credits = session.creditsRemaining;
|
|
183
197
|
}
|
|
184
198
|
this.creditTicker.visible = true;
|
|
185
|
-
this.connectToBroker();
|
|
199
|
+
this.brokerController.connectToBroker();
|
|
186
200
|
};
|
|
187
201
|
// create auth controller
|
|
188
202
|
this.authController = new AuthController(this, sessionCallback, true);
|
|
203
|
+
// listen for auth state changes.
|
|
189
204
|
//@ts-ignore
|
|
190
|
-
this.addEventListener(EditorUpdated, this.specChanged);
|
|
205
|
+
this.addEventListener(EditorUpdated, this.specController.specChanged.bind(this.specController));
|
|
191
206
|
//@ts-ignore
|
|
192
|
-
this.addEventListener(EditorClicked, this.specClicked);
|
|
207
|
+
this.addEventListener(EditorClicked, this.specController.specClicked.bind(this.specController));
|
|
193
208
|
//@ts-ignore
|
|
194
|
-
this.addEventListener(ProblemClicked, this.problemClicked);
|
|
209
|
+
this.addEventListener(ProblemClicked, this.problemController.problemClicked.bind(this.problemController));
|
|
195
210
|
// @ts-ignore
|
|
196
|
-
this.addEventListener(OpenProblemDrawer, this.ruleDocsClicked);
|
|
211
|
+
this.addEventListener(OpenProblemDrawer, this.docsController.ruleDocsClicked.bind(this.docsController));
|
|
197
212
|
// @ts-ignore
|
|
198
|
-
this.addEventListener(RuleViolationClicked, this.ruleGroupClicked);
|
|
213
|
+
this.addEventListener(RuleViolationClicked, this.ruleController.ruleGroupClicked.bind(this.ruleController));
|
|
199
214
|
// @ts-ignore
|
|
200
|
-
this.addEventListener(CustomRulesetEnabled, this.customRulesetEnabled);
|
|
215
|
+
this.addEventListener(CustomRulesetEnabled, this.ruleController.customRulesetEnabled.bind(this.ruleController));
|
|
201
216
|
// @ts-ignore
|
|
202
|
-
this.addEventListener(RulesetSaved, this.rulesetSaved);
|
|
217
|
+
this.addEventListener(RulesetSaved, this.ruleController.rulesetSaved.bind(this.ruleController));
|
|
203
218
|
// @ts-ignore
|
|
204
219
|
this.addEventListener(AddToast, this.addToastEvent);
|
|
205
220
|
this.addEventListener(ExportRuleset, this.exportRuleset);
|
|
206
221
|
// @ts-ignore
|
|
207
|
-
this.addEventListener(RuleClicked, this.ruleClicked);
|
|
222
|
+
this.addEventListener(RuleClicked, this.ruleController.ruleClicked.bind(this.ruleController));
|
|
208
223
|
// @ts-ignore
|
|
209
224
|
this.addEventListener(BuiltInRulesetChanged, this.builtInRulesetSelected);
|
|
210
225
|
// @ts-ignore
|
|
211
|
-
this.addEventListener(ModelTreeNodeClicked, this.modelTreeNodeClicked);
|
|
226
|
+
this.addEventListener(ModelTreeNodeClicked, this.nodeClickerController.modelTreeNodeClicked.bind(this.nodeClickerController));
|
|
212
227
|
// @ts-ignore
|
|
213
|
-
this.addEventListener(RolodexTreeNodeClicked, this.rolodexTreeNodeClicked);
|
|
228
|
+
this.addEventListener(RolodexTreeNodeClicked, this.nodeClickerController.rolodexTreeNodeClicked.bind(this.nodeClickerController));
|
|
214
229
|
// @ts-ignore
|
|
215
|
-
this.addEventListener(
|
|
230
|
+
this.addEventListener(NodeReferenceClicked, this.nodeClickerController.explorerReferenceClicked.bind(this.nodeClickerController));
|
|
216
231
|
// @ts-ignore
|
|
217
|
-
this.addEventListener(
|
|
232
|
+
this.addEventListener(ExplorerNodeClicked, this.nodeClickerController.explorerNodeClicked.bind(this.nodeClickerController));
|
|
218
233
|
// @ts-ignore
|
|
219
|
-
this.addEventListener(
|
|
234
|
+
this.addEventListener(DocumentReferenceClicked, this.nodeClickerController.documentReferenceClicked.bind(this.nodeClickerController));
|
|
220
235
|
// @ts-ignore
|
|
221
|
-
this.addEventListener(
|
|
236
|
+
this.addEventListener(RolodexRootFileSelected, this.rolodexController.rolodexRootFileSelected.bind(this.rolodexController));
|
|
222
237
|
// @ts-ignore
|
|
223
|
-
this.addEventListener(
|
|
238
|
+
this.addEventListener(ArchiveURLRequested, this.fetchUrl.bind(this));
|
|
224
239
|
//@ts-ignore
|
|
225
240
|
this.explorer.equalizer.addEventListener(ExplorerEqualizerChanged, this.filterTreeModel.bind(this));
|
|
226
241
|
//@ts-ignore
|
|
227
242
|
this.explorer.equalizer.addEventListener(ExplorerEqualizerFiltered, this.filterTreeModel.bind(this));
|
|
243
|
+
// @ts-ignore
|
|
228
244
|
this.nukeWorkspace.addEventListener(NukeWorkspaceEvent, this.nukeWorkspaceHandler.bind(this));
|
|
245
|
+
// on logout, nuke it all.
|
|
246
|
+
// @ts-ignore
|
|
247
|
+
this.authController.addEventListener(NukeWorkspaceEvent, this.nukeWorkspaceHandler.bind(this));
|
|
248
|
+
// @ts-ignore
|
|
249
|
+
this.authController.addEventListener(StartSessionFailed, this.platformUnavailable.bind(this));
|
|
229
250
|
this.timeVortex.historyPicker.addEventListener(OpenSettings, this.openSettings.bind(this));
|
|
251
|
+
// @ts-ignore
|
|
252
|
+
this.authController.addEventListener(CreditEmpty, this.creditEmpty.bind(this));
|
|
230
253
|
//@ts-ignore
|
|
231
254
|
this.addEventListener(LoadRenderedNodeIntoInspector, this.loadRenderedNodeIntoInspector.bind(this));
|
|
232
|
-
// extract port from session storage.
|
|
233
|
-
this.busPort = sessionStorage.getItem("pb33f-doctor-port");
|
|
234
|
-
this.busHost = sessionStorage.getItem("pb33f-doctor-host");
|
|
235
|
-
if (!this.busPort) {
|
|
236
|
-
this.busPort = "443"; // default port
|
|
237
|
-
}
|
|
238
|
-
if (!this.busHost) {
|
|
239
|
-
this.busHost = "doctor.pb33f.io"; // default host
|
|
240
|
-
}
|
|
241
|
-
const useTLS = sessionStorage.getItem("pb33f-doctor-tls");
|
|
242
|
-
if (useTLS && useTLS == 'true') {
|
|
243
|
-
this.useTLS = true;
|
|
244
|
-
}
|
|
245
255
|
// hijack navigation buttons.
|
|
246
256
|
window.addEventListener('popstate', (e) => {
|
|
247
257
|
const state = e.state;
|
|
248
258
|
if (state) {
|
|
249
259
|
if (state.activeNode) {
|
|
250
|
-
this.modelTreeNodeClicked(new CustomEvent(ExplorerNodeClicked, {
|
|
260
|
+
this.nodeClickerController.modelTreeNodeClicked(new CustomEvent(ExplorerNodeClicked, {
|
|
251
261
|
detail: {
|
|
252
262
|
nodeHashId: state.activeNode,
|
|
253
263
|
noState: true
|
|
@@ -255,7 +265,7 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
255
265
|
}));
|
|
256
266
|
}
|
|
257
267
|
if (state.ref) {
|
|
258
|
-
this.documentReferenceClicked(new CustomEvent(DocumentReferenceClicked, {
|
|
268
|
+
this.nodeClickerController.documentReferenceClicked(new CustomEvent(DocumentReferenceClicked, {
|
|
259
269
|
detail: {
|
|
260
270
|
jsonPath: state.ref,
|
|
261
271
|
noState: true
|
|
@@ -275,18 +285,18 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
275
285
|
this.showDiagnosisButton = !config.autoDiagnose;
|
|
276
286
|
// if the time vortex is not available, enable skipsState
|
|
277
287
|
this.timeVortex.historyPicker.skipChanges = config.skipTimeline;
|
|
278
|
-
if (config.applicationVersion == this.currentVersion) {
|
|
288
|
+
if (config.applicationVersion == this.brokerController.currentVersion) {
|
|
279
289
|
return;
|
|
280
290
|
}
|
|
281
|
-
if (this.currentVersion && this.currentVersion != 'bootstrap' &&
|
|
291
|
+
if (this.brokerController.currentVersion && this.brokerController.currentVersion != 'bootstrap' &&
|
|
282
292
|
config.applicationVersion &&
|
|
283
293
|
config.applicationVersion != 'bootstrap' &&
|
|
284
|
-
this.currentVersion != config.applicationVersion) {
|
|
285
|
-
console.warn('version changed, reloading', this.currentVersion, config.applicationVersion);
|
|
294
|
+
this.brokerController.currentVersion != config.applicationVersion) {
|
|
295
|
+
console.warn('version changed, reloading', this.brokerController.currentVersion, config.applicationVersion);
|
|
286
296
|
this.nukeWorkspaceHandler();
|
|
287
297
|
}
|
|
288
298
|
else {
|
|
289
|
-
config.applicationVersion = this.currentVersion;
|
|
299
|
+
config.applicationVersion = this.brokerController.currentVersion;
|
|
290
300
|
this.settingsBag?.set(SettingsBag, config);
|
|
291
301
|
}
|
|
292
302
|
}
|
|
@@ -298,15 +308,20 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
298
308
|
this.requestUpdate();
|
|
299
309
|
this.viewerPanel.click();
|
|
300
310
|
}
|
|
301
|
-
|
|
302
|
-
this.randomTicker = Math.floor(Math.random() * 9999999);
|
|
303
|
-
}
|
|
304
|
-
nukeWorkspaceHandler() {
|
|
311
|
+
nukeWorkspaceHandler(e) {
|
|
305
312
|
this.bagManager.resetBags();
|
|
306
313
|
localStorage.removeItem("pb33f-doctor-version");
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
314
|
+
if (!e || !e.detail || e.detail.resetFiles) {
|
|
315
|
+
ModelService.resetWorkspace().then(() => {
|
|
316
|
+
window.location.reload();
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
// no work to do, just reload the page.
|
|
321
|
+
setTimeout(() => {
|
|
322
|
+
window.location.reload();
|
|
323
|
+
}, 50);
|
|
324
|
+
}
|
|
310
325
|
}
|
|
311
326
|
minimapToggled() {
|
|
312
327
|
this.minimapVisible = !this.minimapVisible;
|
|
@@ -318,91 +333,12 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
318
333
|
this.editor = this.querySelector('pb33f-editor#spec-editor');
|
|
319
334
|
this.rulesetEditor = this.querySelector('pb33f-editor#ruleset-editor');
|
|
320
335
|
}
|
|
321
|
-
whoAmI() {
|
|
322
|
-
this.bus.publish({
|
|
323
|
-
destination: "/p/q/" + DoctorServiceChannel,
|
|
324
|
-
body: JSON.stringify({ request: Command.WhoAmI }),
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
connectToBroker() {
|
|
328
|
-
let protocol = "ws://";
|
|
329
|
-
if (this.useTLS) {
|
|
330
|
-
protocol = "wss://";
|
|
331
|
-
}
|
|
332
|
-
// configure wiretap broker.
|
|
333
|
-
const config = {
|
|
334
|
-
brokerURL: protocol + this.busHost + ':' + this.busPort + '/ranch',
|
|
335
|
-
heartbeatIncoming: 0,
|
|
336
|
-
heartbeatOutgoing: 0,
|
|
337
|
-
onConnect: () => {
|
|
338
|
-
console.log("💊 Connected to the %cOpenAPI Doctor%c, we are ready to communicate.", 'background: #0d1117; color: #62C4FFFF; font-weight: bold', 'color: default');
|
|
339
|
-
this.bus.mapChannels();
|
|
340
|
-
this.whoAmI();
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
this.bus.connectToBroker(config);
|
|
344
|
-
}
|
|
345
336
|
addClickTrack(node) {
|
|
346
337
|
history.pushState({ activeNode: node.idHash }, "", `?view=explore&node=${node.idHash}`);
|
|
347
338
|
}
|
|
348
339
|
addRefTrack(ref) {
|
|
349
340
|
history.pushState({ ref: ref }, "", `?view=spec&ref=${ref}`);
|
|
350
341
|
}
|
|
351
|
-
doctorServiceHandler() {
|
|
352
|
-
return (msg) => {
|
|
353
|
-
if (msg.payload?.payload != null) {
|
|
354
|
-
if (isBrokerResponse(msg.payload.payload)) {
|
|
355
|
-
this.brokerConnectionId = msg.payload.payload.broker;
|
|
356
|
-
this.authController.associateBroker(this.brokerConnectionId).then(() => {
|
|
357
|
-
// check version from the server
|
|
358
|
-
const version = msg.payload.payload.version;
|
|
359
|
-
if (version !== "") {
|
|
360
|
-
this.currentVersion = version;
|
|
361
|
-
}
|
|
362
|
-
const memVersion = localStorage.getItem("pb33f-doctor-version");
|
|
363
|
-
if (memVersion) {
|
|
364
|
-
if (this.currentVersion != memVersion) {
|
|
365
|
-
this.nukeWorkspaceHandler();
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
localStorage.setItem("pb33f-doctor-version", this.currentVersion);
|
|
371
|
-
}
|
|
372
|
-
console.log("💊 Welcome to the clinic, the %cdoctor %cis ready to see you. [" + "v" + version + "]", 'color: #62C4FFFF; font-weight: bold', 'color: default');
|
|
373
|
-
this.startTheDoctor();
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
startTheDoctor() {
|
|
380
|
-
this.specChannelSubscription = this.specStreamChannel.subscribe(this.specStreamHandler());
|
|
381
|
-
this.creditChannelSubscription = this.creditStreamChannel.subscribe(this.creditStreamHandler());
|
|
382
|
-
this.bus.mapChannelToBrokerDestination(QueuePrefix + SpecStreamChannel, SpecStreamChannel);
|
|
383
|
-
this.bus.mapChannelToBrokerDestination(QueuePrefix + CreditStreamChannel, CreditStreamChannel);
|
|
384
|
-
this.boostrap();
|
|
385
|
-
}
|
|
386
|
-
specStreamHandler() {
|
|
387
|
-
return (msg) => {
|
|
388
|
-
if (msg.payload?.payload != null) {
|
|
389
|
-
// base64 decode the payload and update the editor!
|
|
390
|
-
const decoded = atob(msg.payload.payload);
|
|
391
|
-
if (this.docBag) {
|
|
392
|
-
this.docBag.set(DefaultDocument, decoded);
|
|
393
|
-
}
|
|
394
|
-
this.editor?.setValue(decoded, true);
|
|
395
|
-
this.requestUpdate();
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
creditStreamHandler() {
|
|
400
|
-
return (msg) => {
|
|
401
|
-
if (msg.payload?.payload != null) {
|
|
402
|
-
this.creditTicker.credits = parseInt(msg.payload.payload);
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
342
|
filterTreeModel(event) {
|
|
407
343
|
this.filteredNodes = new Map();
|
|
408
344
|
event.detail.graph.nodes.forEach((node) => {
|
|
@@ -411,385 +347,6 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
411
347
|
this.modelTree.filteredNodes = this.filteredNodes;
|
|
412
348
|
this.modelTree.renderedNodes = this.renderedNodeMap;
|
|
413
349
|
}
|
|
414
|
-
documentReferenceClicked(evt) {
|
|
415
|
-
let location = '';
|
|
416
|
-
let line, col = 1;
|
|
417
|
-
let path = evt.detail.jsonPath;
|
|
418
|
-
let fullPath = '';
|
|
419
|
-
let file = '';
|
|
420
|
-
let rolodexId = '';
|
|
421
|
-
if (evt.detail.jsonPath.includes('||')) {
|
|
422
|
-
location = evt.detail.jsonPath.split('||')[1];
|
|
423
|
-
path = evt.detail.jsonPath.split('||')[0];
|
|
424
|
-
// location is formatted line:col-endCol
|
|
425
|
-
line = parseInt(location.split(':')[0]);
|
|
426
|
-
col = parseInt(location.split(':')[1]);
|
|
427
|
-
fullPath = evt.detail.jsonPath.split('||')[2];
|
|
428
|
-
if (fullPath != '') {
|
|
429
|
-
file = fullPath.split('#')[0];
|
|
430
|
-
}
|
|
431
|
-
rolodexId = evt.detail.jsonPath.split('||')[3];
|
|
432
|
-
}
|
|
433
|
-
this.editor.editor?.setPosition({ lineNumber: line, column: col });
|
|
434
|
-
this.editor.editor?.revealLineInCenter(line);
|
|
435
|
-
if (this.nodeIdMap.has(path)) {
|
|
436
|
-
const node = this.nodeIdMap.get(path);
|
|
437
|
-
if (node) {
|
|
438
|
-
if (this.nodeIdHashMap.has(node.idHash)) {
|
|
439
|
-
const renderedNode = this.renderedNodeMap.get(node.id);
|
|
440
|
-
if (renderedNode) {
|
|
441
|
-
this.renderedNode.node = renderedNode;
|
|
442
|
-
this.modelTree.explorerClicked(node.id);
|
|
443
|
-
// add a ref click
|
|
444
|
-
if (!evt.detail.noState) {
|
|
445
|
-
this.addRefTrack(evt.detail.jsonPath);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
else {
|
|
451
|
-
this.toastManager.addToastManually({
|
|
452
|
-
id: crypto.randomUUID(),
|
|
453
|
-
type: ToastType.INFO,
|
|
454
|
-
title: "Reference not found",
|
|
455
|
-
body: `Something went wrong, '${path}' not found`
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
else {
|
|
460
|
-
if (this.rolodexActivePath != undefined && this.rolodexActivePath != file) {
|
|
461
|
-
ModelService.queryRolodex(rolodexId, file).then((result) => {
|
|
462
|
-
this.editor.showBreadcrumb = true;
|
|
463
|
-
this.rolodexActivePath = file;
|
|
464
|
-
this.editor.clearDecorations();
|
|
465
|
-
this.editor.setValue(result.rolodexRoot.instance, true);
|
|
466
|
-
this.editor.editor?.setPosition({ lineNumber: line, column: 1 });
|
|
467
|
-
this.editor.editor?.revealLineInCenter(line);
|
|
468
|
-
this.rolodexTree.explorerClicked(rolodexId);
|
|
469
|
-
this.editor.setCurrentPath(file);
|
|
470
|
-
this.fetchRefMap(file);
|
|
471
|
-
//this.lintSpec(result.rolodexRoot.instance);
|
|
472
|
-
// apply problems
|
|
473
|
-
if (this.rolodexProblemMap.has(this.rolodexActivePath)) {
|
|
474
|
-
const probs = this.rolodexProblemMap.get(this.rolodexActivePath);
|
|
475
|
-
if (probs) {
|
|
476
|
-
this.editor.setMarkers(probs);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}).catch((e) => {
|
|
480
|
-
console.error('rolodex query failed', e);
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
explorerReferenceClicked(evt) {
|
|
486
|
-
let nodeId = '';
|
|
487
|
-
this.explorer.nodeComponents.forEach((node) => {
|
|
488
|
-
if (node.body.node.nodePath === evt.detail.nodePath) {
|
|
489
|
-
const renderedNode = this.renderedNodeMap.get(node.body.node.id);
|
|
490
|
-
if (renderedNode) {
|
|
491
|
-
this.editor.editor?.setPosition({ lineNumber: renderedNode.keyLine, column: 0 });
|
|
492
|
-
this.editor.editor?.revealLineInCenter(renderedNode.keyLine);
|
|
493
|
-
this.renderedNode.node = renderedNode;
|
|
494
|
-
nodeId = node.body.node.id;
|
|
495
|
-
this.explorer.moveToNode(node.body.node);
|
|
496
|
-
this.activeNode = node.body.node;
|
|
497
|
-
this.explorer.activeNode = node.body.node;
|
|
498
|
-
this.explorer.equalizer.activeNode = node.body.node;
|
|
499
|
-
}
|
|
500
|
-
node.body.active = true;
|
|
501
|
-
}
|
|
502
|
-
else {
|
|
503
|
-
node.body.active = false;
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
if (nodeId) {
|
|
507
|
-
this.modelTree.explorerClicked(nodeId);
|
|
508
|
-
this.explorer.requestUpdate();
|
|
509
|
-
this.viewerPanel.click();
|
|
510
|
-
}
|
|
511
|
-
if (evt.detail.nodePath) {
|
|
512
|
-
let p = evt.detail.nodePath;
|
|
513
|
-
if (!p.startsWith('/') && !p.includes('#')) {
|
|
514
|
-
const dir = this.rolodexRootPath.substring(0, this.rolodexRootPath.lastIndexOf('/') + 1);
|
|
515
|
-
p = dir + p;
|
|
516
|
-
}
|
|
517
|
-
if (!p.startsWith('#/')) {
|
|
518
|
-
this.rolodexTreeNodeClicked(new CustomEvent(RolodexTreeNodeClicked, {
|
|
519
|
-
detail: {
|
|
520
|
-
path: p,
|
|
521
|
-
}
|
|
522
|
-
}));
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
rolodexTreeNodeClicked(evt) {
|
|
527
|
-
const fileBag = this.rolodexFilesBag?.get(RolodexFilesBag);
|
|
528
|
-
const handleRolodexResponse = (result) => {
|
|
529
|
-
this.rolodexActivePath = evt.detail.path;
|
|
530
|
-
this.rolodexActiveHash = evt.detail.nodeHashId;
|
|
531
|
-
this.editor.setValue(result.instance, true);
|
|
532
|
-
this.editor.setCurrentPath(this.rolodexActivePath);
|
|
533
|
-
this.fetchRefMap(this.rolodexActivePath);
|
|
534
|
-
const probs = this.rolodexProblemMap.get(this.rolodexActivePath);
|
|
535
|
-
if (probs) {
|
|
536
|
-
this.editor.setMarkers(probs);
|
|
537
|
-
}
|
|
538
|
-
// set the editor file type
|
|
539
|
-
let language = 'yaml';
|
|
540
|
-
const ext = evt.detail?.path?.split('.').pop();
|
|
541
|
-
if (ext) {
|
|
542
|
-
switch (ext) {
|
|
543
|
-
case NodeType.JSON:
|
|
544
|
-
language = NodeType.JSON;
|
|
545
|
-
break;
|
|
546
|
-
case NodeType.GO:
|
|
547
|
-
language = NodeType.GO;
|
|
548
|
-
break;
|
|
549
|
-
case NodeType.PY:
|
|
550
|
-
language = 'python';
|
|
551
|
-
break;
|
|
552
|
-
case NodeType.JS:
|
|
553
|
-
language = 'javascript';
|
|
554
|
-
break;
|
|
555
|
-
case NodeType.TS:
|
|
556
|
-
language = 'typescript';
|
|
557
|
-
break;
|
|
558
|
-
case NodeType.PHP:
|
|
559
|
-
language = NodeType.PHP;
|
|
560
|
-
break;
|
|
561
|
-
case NodeType.XML:
|
|
562
|
-
language = NodeType.XML;
|
|
563
|
-
break;
|
|
564
|
-
case NodeType.JAVA:
|
|
565
|
-
language = NodeType.JAVA;
|
|
566
|
-
break;
|
|
567
|
-
case NodeType.RB:
|
|
568
|
-
language = 'ruby';
|
|
569
|
-
break;
|
|
570
|
-
case NodeType.RS:
|
|
571
|
-
language = 'rust';
|
|
572
|
-
break;
|
|
573
|
-
case NodeType.C:
|
|
574
|
-
language = NodeType.C;
|
|
575
|
-
break;
|
|
576
|
-
case NodeType.CPP:
|
|
577
|
-
language = NodeType.CPP;
|
|
578
|
-
break;
|
|
579
|
-
case NodeType.CS:
|
|
580
|
-
language = 'csharp';
|
|
581
|
-
break;
|
|
582
|
-
case NodeType.MD:
|
|
583
|
-
language = 'markdown';
|
|
584
|
-
break;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
const existingState = this.rolodexStateBag?.get(RolodexStateBag);
|
|
588
|
-
if (existingState) {
|
|
589
|
-
existingState.activePath = evt.detail.path;
|
|
590
|
-
existingState.activeHash = evt.detail.nodeHashId;
|
|
591
|
-
existingState.activeLanguage = language;
|
|
592
|
-
existingState.activeNode = result;
|
|
593
|
-
existingState.rootPath = this.rolodexRootPath;
|
|
594
|
-
this.rolodexStateBag?.set(RolodexStateBag, existingState);
|
|
595
|
-
}
|
|
596
|
-
else {
|
|
597
|
-
const existingState = {
|
|
598
|
-
activePath: evt.detail.path,
|
|
599
|
-
activeHash: evt.detail.nodeHashId,
|
|
600
|
-
activeLanguage: language,
|
|
601
|
-
activeNode: result,
|
|
602
|
-
rootHash: this.rolodexRootHash,
|
|
603
|
-
rootPath: this.rolodexRootPath
|
|
604
|
-
};
|
|
605
|
-
this.rolodexStateBag?.set(RolodexStateBag, existingState);
|
|
606
|
-
}
|
|
607
|
-
this.editor.switchLanguage(language);
|
|
608
|
-
let line = 1;
|
|
609
|
-
let col = 0;
|
|
610
|
-
if (evt.detail.line) {
|
|
611
|
-
line = evt.detail.line;
|
|
612
|
-
}
|
|
613
|
-
if (evt.detail.column) {
|
|
614
|
-
col = evt.detail.column;
|
|
615
|
-
}
|
|
616
|
-
this.editor.editor?.setPosition({ lineNumber: line, column: col });
|
|
617
|
-
this.editor.editor?.revealLineInCenter(line, col);
|
|
618
|
-
//this.lintSpec(result.instance);
|
|
619
|
-
if (evt.detail.path) {
|
|
620
|
-
this.rolodexTree.openNodeByPath(evt.detail.path);
|
|
621
|
-
}
|
|
622
|
-
return language;
|
|
623
|
-
};
|
|
624
|
-
ModelService.queryRolodex(evt.detail.nodeHashId, evt.detail.path).then((result) => {
|
|
625
|
-
this.editor.showBreadcrumb = true;
|
|
626
|
-
// clear all references
|
|
627
|
-
this.referenceMapBag?.reset();
|
|
628
|
-
handleRolodexResponse(result.rolodexRoot);
|
|
629
|
-
if (evt.detail.path) {
|
|
630
|
-
if (fileBag && !fileBag.files[evt.detail.path]) {
|
|
631
|
-
fileBag.files[evt.detail.path] = result.rolodexRoot;
|
|
632
|
-
this.rolodexFilesBag?.set(RolodexFilesBag, fileBag);
|
|
633
|
-
}
|
|
634
|
-
if (!fileBag) {
|
|
635
|
-
const rf = {
|
|
636
|
-
files: { [evt.detail.path]: result.rolodexRoot }
|
|
637
|
-
};
|
|
638
|
-
this.rolodexFilesBag?.set(RolodexFilesBag, rf);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
});
|
|
642
|
-
}
|
|
643
|
-
rolodexRootFileSelected(evt) {
|
|
644
|
-
this.rolodexActivePath = evt.detail.path;
|
|
645
|
-
this.rolodexActiveHash = evt.detail.nodeHashId;
|
|
646
|
-
this.rolodexRootPath = evt.detail.path;
|
|
647
|
-
this.importDisabled = true;
|
|
648
|
-
const existingState = this.rolodexStateBag?.get(RolodexStateBag);
|
|
649
|
-
if (existingState) {
|
|
650
|
-
existingState.activePath = evt.detail.path;
|
|
651
|
-
existingState.activeHash = evt.detail.nodeHashId;
|
|
652
|
-
existingState.rootPath = evt.detail.path;
|
|
653
|
-
existingState.rootHash = evt.detail.nodeHashId;
|
|
654
|
-
this.rolodexStateBag?.set(RolodexStateBag, existingState);
|
|
655
|
-
}
|
|
656
|
-
else {
|
|
657
|
-
const existingState = {
|
|
658
|
-
activePath: evt.detail.path,
|
|
659
|
-
activeHash: evt.detail.nodeHashId,
|
|
660
|
-
rootPath: evt.detail.path,
|
|
661
|
-
rootHash: evt.detail.nodeHashId
|
|
662
|
-
};
|
|
663
|
-
this.rolodexStateBag?.set(RolodexStateBag, existingState);
|
|
664
|
-
}
|
|
665
|
-
if (evt.detail.nodeHashId) {
|
|
666
|
-
this.rolodexRootHash = evt.detail.nodeHashId;
|
|
667
|
-
}
|
|
668
|
-
if (evt.detail.content) {
|
|
669
|
-
this.rolodexNeedsReset = true;
|
|
670
|
-
this.editor.setValue(evt.detail.content, true);
|
|
671
|
-
this.lintSpec(evt.detail.content);
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
modelTreeNodeClicked(evt) {
|
|
675
|
-
let node = this.nodeIdMap.get(evt.detail.nodeId);
|
|
676
|
-
if (!node) {
|
|
677
|
-
node = this.nodeIdHashMap.get(evt.detail.nodeId);
|
|
678
|
-
}
|
|
679
|
-
if (node) {
|
|
680
|
-
if (node.origin && node.origin != this.rolodexActivePath && (node.origin != '/root.yaml' && node.origin != 'root.yaml')) {
|
|
681
|
-
// extract the rolodex id using the path
|
|
682
|
-
let hashId = '';
|
|
683
|
-
const fb = this.rolodexFilesBag?.get(RolodexFilesBag);
|
|
684
|
-
if (fb) {
|
|
685
|
-
if (fb.files[node.origin]) {
|
|
686
|
-
hashId = fb.files[node.origin].idHash;
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
// we need to fire a rolodex tree node change event.
|
|
690
|
-
this.rolodexTreeNodeClicked(new CustomEvent(RolodexTreeNodeClicked, {
|
|
691
|
-
detail: {
|
|
692
|
-
nodeHashId: hashId,
|
|
693
|
-
path: node.origin
|
|
694
|
-
}
|
|
695
|
-
}));
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
// don't jump to the root in the editor if the root is selected
|
|
699
|
-
if (node.idHash !== 'root') {
|
|
700
|
-
this.editor.editor?.setPosition({ lineNumber: node.keyLine, column: 0 });
|
|
701
|
-
this.editor.editor?.revealLineInCenter(node.keyLine);
|
|
702
|
-
}
|
|
703
|
-
if (this.explorerVisible) {
|
|
704
|
-
this.explorer.moveToNode(node, evt.detail.first);
|
|
705
|
-
}
|
|
706
|
-
this.activeNode = node;
|
|
707
|
-
// add changes to active node.
|
|
708
|
-
if (evt.detail.changes) {
|
|
709
|
-
node.timeline = evt.detail.changes;
|
|
710
|
-
}
|
|
711
|
-
this.explorer.activeNode = node;
|
|
712
|
-
this.explorer.equalizer.activeNode = node;
|
|
713
|
-
const renderedNode = structuredClone(this.renderedNodeMap.get(node.id));
|
|
714
|
-
if (renderedNode) {
|
|
715
|
-
if (evt.detail.changes) {
|
|
716
|
-
renderedNode.timeline = evt.detail.changes;
|
|
717
|
-
}
|
|
718
|
-
this.renderedNode.node = renderedNode;
|
|
719
|
-
}
|
|
720
|
-
else {
|
|
721
|
-
alert('no id found');
|
|
722
|
-
}
|
|
723
|
-
if (!evt.detail.noState) {
|
|
724
|
-
this.addClickTrack(node);
|
|
725
|
-
evt.detail.noState = true;
|
|
726
|
-
}
|
|
727
|
-
this.explorerNodeClicked(evt, false);
|
|
728
|
-
if (this._firstRun) {
|
|
729
|
-
this._firstRun = false;
|
|
730
|
-
}
|
|
731
|
-
else {
|
|
732
|
-
this.viewerPanel.click();
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
else {
|
|
736
|
-
this.sendToast({
|
|
737
|
-
id: crypto.randomUUID(),
|
|
738
|
-
title: 'Unable to load change model',
|
|
739
|
-
type: ToastType.WARNING,
|
|
740
|
-
body: 'There is no-longer a model with the path `' + evt.detail.nodeId + '` in the document',
|
|
741
|
-
});
|
|
742
|
-
console.error('cannot navigate to node, path not found', evt.detail.nodeId);
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
explorerNodeClicked(evt, replaceRenderedNode = true) {
|
|
746
|
-
let found = false;
|
|
747
|
-
let foundRenderedNode;
|
|
748
|
-
this.explorer.nodeComponents.forEach((node) => {
|
|
749
|
-
if (node.id === evt.detail.nodeId) {
|
|
750
|
-
let renderedNode;
|
|
751
|
-
if (replaceRenderedNode) {
|
|
752
|
-
renderedNode = this.renderedNodeMap.get(node.id);
|
|
753
|
-
if (renderedNode && !this._firstRun) {
|
|
754
|
-
this.renderedNode.node = renderedNode;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
this.selectedNodeHashId = node.body.node.idHash;
|
|
758
|
-
node.body.active = true;
|
|
759
|
-
this.activeNode = node.body.node;
|
|
760
|
-
this.explorer.activeNode = node.body.node;
|
|
761
|
-
found = true;
|
|
762
|
-
if (replaceRenderedNode) {
|
|
763
|
-
foundRenderedNode = renderedNode;
|
|
764
|
-
}
|
|
765
|
-
if (!evt.detail.noState) {
|
|
766
|
-
this.addClickTrack(node.body.node);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
else {
|
|
770
|
-
node.body.active = false;
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
if (!found) {
|
|
774
|
-
// might be filtered, check the filtered nodes
|
|
775
|
-
const node = this.nodeIdMap.get(evt.detail.nodeId);
|
|
776
|
-
if (node) {
|
|
777
|
-
this.selectedNodeHashId = node.idHash;
|
|
778
|
-
this.activeNode = node;
|
|
779
|
-
this.explorer.activeNode = node;
|
|
780
|
-
this.explorer.equalizer.activeNode = node;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
if (foundRenderedNode) {
|
|
784
|
-
// when jumping back to the spec view, we need to set the line
|
|
785
|
-
this.pendingLine = foundRenderedNode.keyLine;
|
|
786
|
-
}
|
|
787
|
-
this.modelTree.explorerClicked(evt.detail.nodeId);
|
|
788
|
-
if (!this._firstRun) {
|
|
789
|
-
this.viewerPanel.click();
|
|
790
|
-
}
|
|
791
|
-
this.explorer.requestUpdate();
|
|
792
|
-
}
|
|
793
350
|
exportRuleset() {
|
|
794
351
|
this.exportRulesetDialog.show();
|
|
795
352
|
}
|
|
@@ -799,452 +356,6 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
799
356
|
sendToast(toast) {
|
|
800
357
|
this.toastManager.addToastManually(toast);
|
|
801
358
|
}
|
|
802
|
-
ruleGroupClicked(event) {
|
|
803
|
-
this.problemsPanel.focus();
|
|
804
|
-
const simEvent = new CustomEvent(ProblemRuleFilterChangedManual, {
|
|
805
|
-
bubbles: true,
|
|
806
|
-
composed: true,
|
|
807
|
-
detail: {
|
|
808
|
-
rule: event.detail.rule
|
|
809
|
-
}
|
|
810
|
-
});
|
|
811
|
-
this.problemsPanel.focus();
|
|
812
|
-
this.problemList.dispatchEvent(simEvent);
|
|
813
|
-
history.pushState({ rule: event.detail.rule }, "", `/${ActiveView.Problems}?rule=${event.detail.rule}`);
|
|
814
|
-
this.controlTabGroup.show(ActiveView.Problems);
|
|
815
|
-
}
|
|
816
|
-
ruleDocsClicked(event) {
|
|
817
|
-
const ruleId = event.detail.rule;
|
|
818
|
-
if (ruleId) {
|
|
819
|
-
switch (event.detail.type) {
|
|
820
|
-
case ProblemDrawerEventType.RULE_DOCS:
|
|
821
|
-
const ruleDoc = this.ruleDocsBag?.get(ruleId);
|
|
822
|
-
if (ruleDoc) {
|
|
823
|
-
event.detail.body = ruleDoc.body;
|
|
824
|
-
this.detailsDrawer.open(event.detail);
|
|
825
|
-
}
|
|
826
|
-
else {
|
|
827
|
-
this.sendToast({
|
|
828
|
-
id: crypto.randomUUID(),
|
|
829
|
-
type: ToastType.INFO,
|
|
830
|
-
title: "Rule documentation unavailable",
|
|
831
|
-
body: `Documentation for '${ruleId}' not available`
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
break;
|
|
835
|
-
case ProblemDrawerEventType.HOW_TO_FIX:
|
|
836
|
-
const howToFix = this.howToFixBag?.get(ruleId);
|
|
837
|
-
if (howToFix) {
|
|
838
|
-
event.detail.body = howToFix.howToFix;
|
|
839
|
-
this.detailsDrawer.open(event.detail);
|
|
840
|
-
}
|
|
841
|
-
else {
|
|
842
|
-
this.sendToast({
|
|
843
|
-
id: crypto.randomUUID(),
|
|
844
|
-
type: ToastType.INFO,
|
|
845
|
-
title: "How to fix unavailable",
|
|
846
|
-
body: `Information on how to fix '${ruleId}' not available`
|
|
847
|
-
});
|
|
848
|
-
}
|
|
849
|
-
break;
|
|
850
|
-
case ProblemDrawerEventType.FUNCTION_DOCS:
|
|
851
|
-
const funcDocs = this.functionDocsBag?.get(ruleId);
|
|
852
|
-
if (funcDocs) {
|
|
853
|
-
event.detail.body = funcDocs.body;
|
|
854
|
-
this.detailsDrawer.open(event.detail);
|
|
855
|
-
}
|
|
856
|
-
else {
|
|
857
|
-
this.sendToast({
|
|
858
|
-
id: crypto.randomUUID(),
|
|
859
|
-
type: ToastType.INFO,
|
|
860
|
-
title: "Function documentation unavailable",
|
|
861
|
-
body: `Documentation for '${ruleId}' not available`
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
|
-
break;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
else {
|
|
868
|
-
switch (event.detail.type) {
|
|
869
|
-
case ProblemDrawerEventType.RENDERED_EXAMPLE:
|
|
870
|
-
case ProblemDrawerEventType.MARKDOWN:
|
|
871
|
-
this.detailsDrawer.open(event.detail);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
rulesetSaved(evt) {
|
|
876
|
-
// lint spec
|
|
877
|
-
if (this.docBag) {
|
|
878
|
-
const doc = this.docBag.get(DefaultDocument);
|
|
879
|
-
const config = this.ruleConfigBag?.get(RuleConfigurationBag);
|
|
880
|
-
if (evt.detail.rules) {
|
|
881
|
-
this.customRulesetBag?.set(CustomRulesetBag, evt.detail.rules);
|
|
882
|
-
// get ruleset config and disable everything,
|
|
883
|
-
// then enable the custom rules.
|
|
884
|
-
if (config) {
|
|
885
|
-
// extract config from the event
|
|
886
|
-
const newConfig = evt.detail.config;
|
|
887
|
-
if (newConfig && this.ruleConfigBag) {
|
|
888
|
-
newConfig.returnedRuleset = evt.detail.returnedRules;
|
|
889
|
-
this.ruleConfigBag?.set(RuleConfigurationBag, newConfig);
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
RulesetService.getSessionRulesetAsYAML().then((yaml) => {
|
|
893
|
-
if (this.selectedEditorTab == "spec") {
|
|
894
|
-
this.rulesetPulse = true;
|
|
895
|
-
}
|
|
896
|
-
this.rulesetEditor.setValue(yaml, true);
|
|
897
|
-
this.fetchRulesetMap();
|
|
898
|
-
});
|
|
899
|
-
// lint the spec
|
|
900
|
-
this.lintSpec(doc, '');
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
buildRolodexResultMap(results) {
|
|
905
|
-
// TODO: optimize this, it's a bit slow.
|
|
906
|
-
this.rolodexProblemMap.clear();
|
|
907
|
-
results.forEach((problem) => {
|
|
908
|
-
// check if the source location is '/root.yaml'
|
|
909
|
-
if (problem.sourceLocation === '/root.yaml' || problem.sourceLocation === 'root.yaml') {
|
|
910
|
-
problem.sourceLocation = "root";
|
|
911
|
-
}
|
|
912
|
-
if (this.rolodexProblemMap.has(problem.sourceLocation)) {
|
|
913
|
-
const problems = this.rolodexProblemMap.get(problem.sourceLocation);
|
|
914
|
-
if (problems) {
|
|
915
|
-
problems.push(problem);
|
|
916
|
-
if (problem.sourceLocation) {
|
|
917
|
-
this.rolodexProblemMap.set(problem.sourceLocation, problems);
|
|
918
|
-
}
|
|
919
|
-
else {
|
|
920
|
-
if (!this.rolodexRootPath) {
|
|
921
|
-
this.rolodexProblemMap.set("root", problems);
|
|
922
|
-
}
|
|
923
|
-
else {
|
|
924
|
-
this.rolodexProblemMap.set(this.rolodexRootPath, problems);
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
else {
|
|
930
|
-
if (problem.sourceLocation) {
|
|
931
|
-
this.rolodexProblemMap.set(problem.sourceLocation, [problem]);
|
|
932
|
-
}
|
|
933
|
-
else {
|
|
934
|
-
if (!this.rolodexRootPath) {
|
|
935
|
-
const currProblems = this.rolodexProblemMap.get("root");
|
|
936
|
-
if (currProblems) {
|
|
937
|
-
currProblems.push(problem);
|
|
938
|
-
this.rolodexProblemMap.set("root", currProblems);
|
|
939
|
-
}
|
|
940
|
-
else {
|
|
941
|
-
this.rolodexProblemMap.set("root", [problem]);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
else {
|
|
945
|
-
const currProblems = this.rolodexProblemMap.get(this.rolodexRootPath);
|
|
946
|
-
if (currProblems) {
|
|
947
|
-
currProblems.push(problem);
|
|
948
|
-
this.rolodexProblemMap.set(this.rolodexRootPath, currProblems);
|
|
949
|
-
}
|
|
950
|
-
else {
|
|
951
|
-
this.rolodexProblemMap.set(this.rolodexRootPath, [problem]);
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
});
|
|
957
|
-
return this.rolodexProblemMap;
|
|
958
|
-
}
|
|
959
|
-
fetchRefMap(currentPath = '') {
|
|
960
|
-
ModelService.fetchReferenceMap().then((result) => {
|
|
961
|
-
this.editor.clearDecorations();
|
|
962
|
-
this.references = result;
|
|
963
|
-
this.editor.links = result;
|
|
964
|
-
this.editor.applyLinkDecorations();
|
|
965
|
-
// add references to our stateful bag
|
|
966
|
-
this.updateRefmapBag(currentPath, result);
|
|
967
|
-
}).catch(() => {
|
|
968
|
-
this.editor.clearDecorations();
|
|
969
|
-
this.editor.clearAllMarkers();
|
|
970
|
-
this.toastManager.addToastManually({
|
|
971
|
-
id: crypto.randomUUID(),
|
|
972
|
-
type: ToastType.INFO,
|
|
973
|
-
title: "File not analyzed",
|
|
974
|
-
body: "This file is not a JSON or YAML file, it has not been analyzed."
|
|
975
|
-
});
|
|
976
|
-
});
|
|
977
|
-
}
|
|
978
|
-
/* LINT SPEC <---------------------------------------------------------------------------------------------
|
|
979
|
-
*
|
|
980
|
-
* This is our main function, man we need to clean this all up, it's bloated to fuck
|
|
981
|
-
*
|
|
982
|
-
* <--------------------------------------------------------------------------------------------------------
|
|
983
|
-
*/
|
|
984
|
-
lintSpec(value, url) {
|
|
985
|
-
this.activitySpinner.show();
|
|
986
|
-
this.editor.breadcumb.isInvalid = false;
|
|
987
|
-
if (url) {
|
|
988
|
-
if (url === 'root') {
|
|
989
|
-
url = '';
|
|
990
|
-
}
|
|
991
|
-
else {
|
|
992
|
-
this.urlProblem.style.display = 'none';
|
|
993
|
-
this.urlOverlay.style.display = "block";
|
|
994
|
-
this.urlSpinner.style.display = "block";
|
|
995
|
-
this.referenceMapBag?.reset(); // wipe out refs.
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
else {
|
|
999
|
-
this.urlProblem.style.display = 'none';
|
|
1000
|
-
this.urlOverlay.style.display = "none";
|
|
1001
|
-
this.urlSpinner.style.display = "none";
|
|
1002
|
-
}
|
|
1003
|
-
let replaceResults = false;
|
|
1004
|
-
let currentPath = this.rolodexActivePath;
|
|
1005
|
-
if (this.rolodexActivePath === this.rolodexRootPath || this.rolodexActivePath === 'root') {
|
|
1006
|
-
replaceResults = true;
|
|
1007
|
-
currentPath = '';
|
|
1008
|
-
this.editor.showBreadcrumb = false;
|
|
1009
|
-
}
|
|
1010
|
-
if (url && url != '') {
|
|
1011
|
-
try {
|
|
1012
|
-
const parsedUrl = new URL(url);
|
|
1013
|
-
if (parsedUrl) {
|
|
1014
|
-
currentPath = parsedUrl.pathname;
|
|
1015
|
-
this.rolodexActivePath = currentPath;
|
|
1016
|
-
this.rolodexRootPath = currentPath;
|
|
1017
|
-
replaceResults = true;
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
catch (e) {
|
|
1021
|
-
// do nothing for now.
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
let revive = true;
|
|
1025
|
-
LintingService.lintFile(value, this.brokerConnectionId, url, currentPath, this.skipTimeline).then((result) => {
|
|
1026
|
-
//if (replaceResults) {
|
|
1027
|
-
this.activitySpinner.hide();
|
|
1028
|
-
const map = this.buildRolodexResultMap(result);
|
|
1029
|
-
if (url) {
|
|
1030
|
-
this.urlOverlay.style.display = "none";
|
|
1031
|
-
this.urlSpinner.style.display = "none";
|
|
1032
|
-
this.urlProblem.style.display = 'none';
|
|
1033
|
-
}
|
|
1034
|
-
// extract empty location problems as we are replacing the root results
|
|
1035
|
-
let rootProblems = this.rolodexProblemMap.get("root");
|
|
1036
|
-
if (!this.rolodexRoot) {
|
|
1037
|
-
rootProblems = [];
|
|
1038
|
-
}
|
|
1039
|
-
if (result && !Array.isArray(result)) {
|
|
1040
|
-
const r = [result];
|
|
1041
|
-
if (this.rolodexProblemMap.size > 0 && this.rolodexProblemMap.has(this.rolodexActivePath)) {
|
|
1042
|
-
const probs = this.rolodexProblemMap.get(this.rolodexActivePath);
|
|
1043
|
-
if (probs) {
|
|
1044
|
-
if (rootProblems) {
|
|
1045
|
-
probs.push(...rootProblems);
|
|
1046
|
-
}
|
|
1047
|
-
this.editor.setMarkers(probs);
|
|
1048
|
-
}
|
|
1049
|
-
else {
|
|
1050
|
-
if (rootProblems) {
|
|
1051
|
-
r.push(...rootProblems);
|
|
1052
|
-
}
|
|
1053
|
-
this.editor.setMarkers(r);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
else {
|
|
1057
|
-
if (rootProblems) {
|
|
1058
|
-
r.push(...rootProblems);
|
|
1059
|
-
}
|
|
1060
|
-
this.editor.setMarkers(r);
|
|
1061
|
-
}
|
|
1062
|
-
this.problemBag?.set(DocumentProblems, r);
|
|
1063
|
-
this.problemList.problems = r;
|
|
1064
|
-
this.problems = r;
|
|
1065
|
-
this.problemsOverview.problems = this.problemList.problemItems;
|
|
1066
|
-
}
|
|
1067
|
-
if (result && Array.isArray(result)) {
|
|
1068
|
-
if (result.length == 0) {
|
|
1069
|
-
this.editor.clearAllMarkers();
|
|
1070
|
-
this.editor.breadcumb.isInvalid = false;
|
|
1071
|
-
this.editor.showBreadcrumb = false;
|
|
1072
|
-
revive = true;
|
|
1073
|
-
this.problemList.isInvalid = false;
|
|
1074
|
-
}
|
|
1075
|
-
// check if this problem is 'unable to parse'
|
|
1076
|
-
if (result.length == 1 && result[0].message.startsWith('unable to parse')) {
|
|
1077
|
-
// short circuit, we are dead.
|
|
1078
|
-
this.editor.clearDecorations();
|
|
1079
|
-
this.editor.clearAllMarkers();
|
|
1080
|
-
this.editor.setMarkers(result);
|
|
1081
|
-
this.editor.breadcumb.isInvalid = true;
|
|
1082
|
-
this.editor.showBreadcrumb = true;
|
|
1083
|
-
this.editor.dead();
|
|
1084
|
-
this.problemList.isInvalid = true;
|
|
1085
|
-
revive = false;
|
|
1086
|
-
}
|
|
1087
|
-
// extract empty location problems as we are replacing the root results
|
|
1088
|
-
if (revive && this.rolodexProblemMap.size > 0 && this.rolodexProblemMap.has(this.rolodexActivePath)) {
|
|
1089
|
-
const probs = this.rolodexProblemMap.get(this.rolodexActivePath);
|
|
1090
|
-
if (probs) {
|
|
1091
|
-
if (rootProblems) {
|
|
1092
|
-
probs.push(...rootProblems);
|
|
1093
|
-
}
|
|
1094
|
-
this.editor.setMarkers(probs);
|
|
1095
|
-
}
|
|
1096
|
-
else {
|
|
1097
|
-
if (rootProblems) {
|
|
1098
|
-
result.push(...rootProblems);
|
|
1099
|
-
}
|
|
1100
|
-
this.editor.setMarkers(result);
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
else {
|
|
1104
|
-
if (replaceResults) {
|
|
1105
|
-
this.editor.setMarkers(result);
|
|
1106
|
-
}
|
|
1107
|
-
else {
|
|
1108
|
-
this.fetchRefMap(currentPath);
|
|
1109
|
-
return;
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
this.problemBag?.set(DocumentProblems, result);
|
|
1113
|
-
this.problemList.problems = result;
|
|
1114
|
-
this.problems = result;
|
|
1115
|
-
this.problemsOverview.problems = this.problemList.problemItems;
|
|
1116
|
-
if (this.problemsOverview.statistics) {
|
|
1117
|
-
if (result.length == 1) {
|
|
1118
|
-
this.problemsOverview.statistics.statistics.totalErrors = 1;
|
|
1119
|
-
this.problemsOverview.statistics.statistics.overallScore = 0;
|
|
1120
|
-
this.problemsOverview.statistics.evaluation = 'Useless';
|
|
1121
|
-
this.problemsOverview.statistics.diagnosis = '<strong>Specification cannot be used</strong>: <br/><br/>' + result[0].message;
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
// enable pb33f theme.
|
|
1126
|
-
if (revive) {
|
|
1127
|
-
this.editor.revive();
|
|
1128
|
-
}
|
|
1129
|
-
else {
|
|
1130
|
-
return;
|
|
1131
|
-
}
|
|
1132
|
-
// fetch graph
|
|
1133
|
-
if ((this.rolodexRootPath == this.rolodexActivePath || this.rolodexActivePath == 'root') || url) {
|
|
1134
|
-
ModelService.fetchLatestGraph().then((result) => {
|
|
1135
|
-
this.extractGraph(result);
|
|
1136
|
-
});
|
|
1137
|
-
}
|
|
1138
|
-
// TODO: rolodex query should happen elsewhere too!
|
|
1139
|
-
if (this.rolodexNeedsReset) {
|
|
1140
|
-
ModelService.queryRolodex().then((result) => {
|
|
1141
|
-
this.fetchRefMap(currentPath);
|
|
1142
|
-
this.importDisabled = true;
|
|
1143
|
-
this.editor.showBreadcrumb = true;
|
|
1144
|
-
this.rolodexNeedsReset = false;
|
|
1145
|
-
result.rolodexRoot.treeExpanded = true;
|
|
1146
|
-
this.rolodexTree.isRolodex = true;
|
|
1147
|
-
this.rolodexTree.node = result.rolodexRoot;
|
|
1148
|
-
this.rolodexRoot = result.rolodexRoot;
|
|
1149
|
-
if (this.rolodexActiveHash) {
|
|
1150
|
-
this.rolodexTree.pendingNavigationHash = this.rolodexActiveHash;
|
|
1151
|
-
}
|
|
1152
|
-
if (this.rolodexActivePath) {
|
|
1153
|
-
this.rolodexTree.pendingNavigationPath = this.rolodexActivePath;
|
|
1154
|
-
}
|
|
1155
|
-
this.rolodexResponseBag?.set(RolodexResponseBag, result);
|
|
1156
|
-
const existingState = this.rolodexStateBag?.get(RolodexStateBag);
|
|
1157
|
-
if (!existingState) {
|
|
1158
|
-
const existingState = {
|
|
1159
|
-
activePath: this.rolodexActivePath,
|
|
1160
|
-
rootPath: this.rolodexRootPath,
|
|
1161
|
-
};
|
|
1162
|
-
this.rolodexStateBag?.set(RolodexStateBag, existingState);
|
|
1163
|
-
}
|
|
1164
|
-
this.requestUpdate();
|
|
1165
|
-
});
|
|
1166
|
-
}
|
|
1167
|
-
else {
|
|
1168
|
-
this.fetchRefMap(currentPath);
|
|
1169
|
-
this.timeVortex.tardisControl.fetchHistory();
|
|
1170
|
-
}
|
|
1171
|
-
// update the overview statistics
|
|
1172
|
-
LintingService.fetchStatistics().then((result) => {
|
|
1173
|
-
let oldScore = 0;
|
|
1174
|
-
if (this.problemsOverview.statistics) {
|
|
1175
|
-
oldScore = this.problemsOverview.statistics.statistics.overallScore;
|
|
1176
|
-
}
|
|
1177
|
-
this.diagnosticBag?.set(DiagnosticBag, result);
|
|
1178
|
-
this.activitySpinner.hide();
|
|
1179
|
-
if (result?.remainingCredit <= 10) {
|
|
1180
|
-
this.statusBar.callsRemaining = result.remainingCredit;
|
|
1181
|
-
this.statusBar.visible = true;
|
|
1182
|
-
console.warn("You are running low on credit, you will need to authenticate soon. " +
|
|
1183
|
-
"" + result.remainingCredit + " credits remaining.");
|
|
1184
|
-
}
|
|
1185
|
-
// determine if the score went up or down and toast it!
|
|
1186
|
-
this.problemsOverview.statistics = result;
|
|
1187
|
-
this.tickRandomly(); // tick randomly to refresh docs iframe.
|
|
1188
|
-
// TODO: re-evaluate these toasts, they get annoying, fucking fast.
|
|
1189
|
-
// if (this.problemsOverview.statistics) {
|
|
1190
|
-
// const newScore = result.statistics.overallScore;
|
|
1191
|
-
// if (oldScore > newScore) {
|
|
1192
|
-
// this.sendToast({
|
|
1193
|
-
// id: crypto.randomUUID(),
|
|
1194
|
-
// type: ToastType.SCOREDOWN,
|
|
1195
|
-
// body: "Your score has decreased. It is now " + newScore + "%",
|
|
1196
|
-
// title: "Score went down by " + (oldScore - newScore) + "%"
|
|
1197
|
-
// });
|
|
1198
|
-
// }
|
|
1199
|
-
// if (oldScore < newScore) {
|
|
1200
|
-
// this.sendToast({
|
|
1201
|
-
// id: crypto.randomUUID(),
|
|
1202
|
-
// type: ToastType.SCOREUP,
|
|
1203
|
-
// body: "Your score has increased to " + newScore + "%",
|
|
1204
|
-
// title: "Score went up by " + (newScore - oldScore) + "%"
|
|
1205
|
-
// });
|
|
1206
|
-
// }
|
|
1207
|
-
// }
|
|
1208
|
-
}).catch((e) => {
|
|
1209
|
-
console.error("statistics service is down", e);
|
|
1210
|
-
this.platformUnavailable(e);
|
|
1211
|
-
});
|
|
1212
|
-
if (!this.explorerBooted) {
|
|
1213
|
-
this.explorer.equalizer.initializeEqualizer();
|
|
1214
|
-
this.explorerBooted = true;
|
|
1215
|
-
}
|
|
1216
|
-
}).catch((e) => {
|
|
1217
|
-
this.activitySpinner.hide();
|
|
1218
|
-
if (!url) {
|
|
1219
|
-
//this.platformUnavailable(e);
|
|
1220
|
-
console.error("so sorry, the doctor cannot see you right now, the clinic is closed.");
|
|
1221
|
-
if (e) {
|
|
1222
|
-
console.error(e.detail);
|
|
1223
|
-
if (e.instance === 'https://pb33f.io/errors/no-credit-remaining') {
|
|
1224
|
-
this.statusBar.callsRemaining = 0;
|
|
1225
|
-
this.statusBar.visible = true;
|
|
1226
|
-
this.sendToast({
|
|
1227
|
-
id: crypto.randomUUID(),
|
|
1228
|
-
type: ToastType.ERROR,
|
|
1229
|
-
body: "Run out of credit, please authenticate for more or wait 24 hours.",
|
|
1230
|
-
title: "Credit exhausted!",
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
else {
|
|
1234
|
-
this.sendToast({
|
|
1235
|
-
id: crypto.randomUUID(),
|
|
1236
|
-
type: ToastType.ERROR,
|
|
1237
|
-
body: e.detail,
|
|
1238
|
-
title: "Platform Error",
|
|
1239
|
-
});
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
else {
|
|
1244
|
-
this.showUrlError(e);
|
|
1245
|
-
}
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
359
|
updateInspectorDivider() {
|
|
1249
360
|
const panelState = this.panelStateBag?.get(PanelStateBag);
|
|
1250
361
|
if (panelState) {
|
|
@@ -1289,15 +400,18 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
1289
400
|
}
|
|
1290
401
|
this.referenceMapBag?.set(ReferenceMapBag, refMap);
|
|
1291
402
|
}
|
|
403
|
+
creditEmpty(e) {
|
|
404
|
+
this.platformUnavailable(e.detail.error);
|
|
405
|
+
}
|
|
1292
406
|
platformUnavailable(error) {
|
|
1293
407
|
if (!this.unavailable) {
|
|
1294
|
-
this.loadingOverlay
|
|
1295
|
-
this.activitySpinner
|
|
408
|
+
this.loadingOverlay?.hide();
|
|
409
|
+
this.activitySpinner?.hide();
|
|
1296
410
|
this.errorBanner.errorTitle = "The doctor is out.";
|
|
1297
|
-
if (!error) {
|
|
411
|
+
if (!error || !error.detail) {
|
|
1298
412
|
this.errorBanner.errorMessage = "The clinic is <strong>closed!</strong> " +
|
|
1299
413
|
"The doctor is currently unavailable" +
|
|
1300
|
-
" because there is no response from the platform.";
|
|
414
|
+
" because there is no response (when asked) from the pb33f platform.";
|
|
1301
415
|
}
|
|
1302
416
|
else {
|
|
1303
417
|
this.errorBanner.errorMessage = "The clinic is <strong>closed!</strong> " +
|
|
@@ -1309,716 +423,12 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
1309
423
|
this.controlTabGroup.show(ActiveView.Overview);
|
|
1310
424
|
}
|
|
1311
425
|
}
|
|
1312
|
-
specClicked(event) {
|
|
1313
|
-
this.detailsDrawer.close();
|
|
1314
|
-
if (this.selectedEditorTab == "spec") {
|
|
1315
|
-
let problemFound = false;
|
|
1316
|
-
for (let i = 0; i < this.problems?.length; i++) {
|
|
1317
|
-
if (this.problems[i].startLineNumber === event.detail.line) {
|
|
1318
|
-
this.problemList.lineClicked(event.detail.line, true);
|
|
1319
|
-
this.controlTabGroup.show(ActiveView.Problems);
|
|
1320
|
-
if (this.sidebarClosed) {
|
|
1321
|
-
this.toggleSidebar();
|
|
1322
|
-
}
|
|
1323
|
-
problemFound = true;
|
|
1324
|
-
break;
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
// use the graph lookup to find the node, use the graphResponse, if available if not, pull from bag
|
|
1328
|
-
const graph = this.graphBag?.get(GraphBag);
|
|
1329
|
-
if (graph) {
|
|
1330
|
-
if (graph.graphMap && event.detail.line) {
|
|
1331
|
-
const nodeHash = graph.graphMap[event.detail.line];
|
|
1332
|
-
if (nodeHash) {
|
|
1333
|
-
this.modelTree.explorerClicked(nodeHash);
|
|
1334
|
-
const rendered = this.renderedNodeMap.get(nodeHash);
|
|
1335
|
-
if (rendered) {
|
|
1336
|
-
this.renderedNode.node = rendered;
|
|
1337
|
-
}
|
|
1338
|
-
if (!problemFound) {
|
|
1339
|
-
this.viewerPanel.click();
|
|
1340
|
-
}
|
|
1341
|
-
const n = this.nodeIdHashMap.get(nodeHash);
|
|
1342
|
-
if (n) {
|
|
1343
|
-
this.explorer.activeNode = n;
|
|
1344
|
-
this.explorer.equalizer.activeNode = n;
|
|
1345
|
-
}
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
if (this.selectedEditorTab == ActiveView.Ruleset) {
|
|
1351
|
-
// check ruleset map for the line number
|
|
1352
|
-
const rulesetMap = this.sessionRulesetMapBag?.get(SessionRulesetMapBag);
|
|
1353
|
-
if (rulesetMap?.rulesMap) {
|
|
1354
|
-
for (let i = 0; i < rulesetMap.rulesMap.length; i++) {
|
|
1355
|
-
if (rulesetMap.rulesMap[i].line === event.detail.line) {
|
|
1356
|
-
this.controlTabGroup.show(ActiveView.Ruleset);
|
|
1357
|
-
if (this.sidebarClosed) {
|
|
1358
|
-
this.toggleSidebar();
|
|
1359
|
-
}
|
|
1360
|
-
break;
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
}
|
|
1366
|
-
problemClicked(event) {
|
|
1367
|
-
if (this.selectedEditorTab != "spec") {
|
|
1368
|
-
this.editorTabGroup.show("spec");
|
|
1369
|
-
this.selectedEditorTab = "spec";
|
|
1370
|
-
}
|
|
1371
|
-
let sourceLocation = event.detail.problem.problemObject.sourceLocation;
|
|
1372
|
-
// no source? use root
|
|
1373
|
-
if (sourceLocation == '' || sourceLocation == undefined || sourceLocation == 'root') {
|
|
1374
|
-
sourceLocation = this.rolodexRootPath;
|
|
1375
|
-
}
|
|
1376
|
-
// locate the node in rolodex root
|
|
1377
|
-
const node = SearchNodeTreeForPath(this.rolodexRoot, sourceLocation);
|
|
1378
|
-
if (node) {
|
|
1379
|
-
// trigger a rolodex load
|
|
1380
|
-
this.rolodexTreeNodeClicked(new CustomEvent(RolodexTreeNodeClicked, {
|
|
1381
|
-
detail: {
|
|
1382
|
-
nodeHashId: node.idHash,
|
|
1383
|
-
path: sourceLocation,
|
|
1384
|
-
line: event.detail.problem.problemObject.startLineNumber,
|
|
1385
|
-
column: event.detail.problem.problemObject.startColumn
|
|
1386
|
-
}
|
|
1387
|
-
}));
|
|
1388
|
-
this.detailsDrawer.close();
|
|
1389
|
-
// make sure we select the file in the rolodex
|
|
1390
|
-
this.rolodexTree.openNodeByPath(sourceLocation);
|
|
1391
|
-
return;
|
|
1392
|
-
}
|
|
1393
|
-
this.controlTabGroup.show(ActiveView.Problems);
|
|
1394
|
-
this.editor.editor?.revealLineInCenter(event.detail.problem.line);
|
|
1395
|
-
this.editor.editor?.setPosition({
|
|
1396
|
-
lineNumber: event.detail.problem.line,
|
|
1397
|
-
column: event.detail.problem.column
|
|
1398
|
-
});
|
|
1399
|
-
this.detailsDrawer.close();
|
|
1400
|
-
if (!event.detail.launchedFromProblems) {
|
|
1401
|
-
this.problemList.lineClicked(event.detail.problem.problemObject.startLineNumber);
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
loadState() {
|
|
1405
|
-
this.graphBag = this.bagManager.getBag(GraphBag);
|
|
1406
|
-
this.docBag = this.bagManager.getBag(DoctorDocumentBag);
|
|
1407
|
-
this.rolodexResponseBag = this.bagManager.getBag(RolodexResponseBag);
|
|
1408
|
-
this.rolodexFilesBag = this.bagManager.getBag(RolodexFilesBag);
|
|
1409
|
-
this.rolodexStateBag = this.bagManager.getBag(RolodexStateBag);
|
|
1410
|
-
this.referenceMapBag = this.bagManager.getBag(ReferenceMapBag);
|
|
1411
|
-
this.docExpirationBag = this.bagManager.getBag(DocumentationExpirationBag);
|
|
1412
|
-
this.panelStateBag = this.bagManager.getBag(PanelStateBag);
|
|
1413
|
-
this.settingsBag = this.bagManager.getBag(SettingsBag);
|
|
1414
|
-
// register a handler for settings bag changes.
|
|
1415
|
-
this.settingsBag?.onAllChanges(this.settingsChanged.bind(this));
|
|
1416
|
-
this.settingsComponent.settingsBag = this.settingsBag;
|
|
1417
|
-
if (this.settingsBag) {
|
|
1418
|
-
this.settingsChanged('', this.settingsBag.get(SettingsBag));
|
|
1419
|
-
}
|
|
1420
|
-
this.settingsComponent.bootstrap();
|
|
1421
|
-
// load the rolodex
|
|
1422
|
-
if (this.rolodexResponseBag) {
|
|
1423
|
-
const response = this.rolodexResponseBag.get(RolodexResponseBag);
|
|
1424
|
-
if (response) {
|
|
1425
|
-
this.rolodexRoot = response.rolodexRoot;
|
|
1426
|
-
this.rolodexTree.isRolodex = true;
|
|
1427
|
-
this.rolodexTree.node = response.rolodexRoot;
|
|
1428
|
-
response.rolodexRoot.treeExpanded = true;
|
|
1429
|
-
this.requestUpdate();
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
let skipDocBag = false;
|
|
1433
|
-
const checkRefMap = (key) => {
|
|
1434
|
-
let refMap = this.referenceMapBag?.get(ReferenceMapBag);
|
|
1435
|
-
if (refMap) {
|
|
1436
|
-
// TODO: replace with scehduled task to refresh the reference map
|
|
1437
|
-
setTimeout(() => {
|
|
1438
|
-
let refs = refMap?.references[key];
|
|
1439
|
-
if (!refs) {
|
|
1440
|
-
refs = refMap?.references[""]; // single file
|
|
1441
|
-
}
|
|
1442
|
-
if (refs) {
|
|
1443
|
-
this.references = refs;
|
|
1444
|
-
this.editor.links = refs;
|
|
1445
|
-
this.editor.applyLinkDecorations();
|
|
1446
|
-
}
|
|
1447
|
-
}, 5); // editor has not loaded yet, give it a second to breathe.
|
|
1448
|
-
}
|
|
1449
|
-
else {
|
|
1450
|
-
ModelService.fetchReferenceMap().then((result) => {
|
|
1451
|
-
this.references = result;
|
|
1452
|
-
this.editor.links = result;
|
|
1453
|
-
this.editor.applyLinkDecorations();
|
|
1454
|
-
}).catch(() => {
|
|
1455
|
-
this.editor.clearDecorations();
|
|
1456
|
-
this.editor.clearAllMarkers();
|
|
1457
|
-
});
|
|
1458
|
-
}
|
|
1459
|
-
};
|
|
1460
|
-
if (this.rolodexStateBag) {
|
|
1461
|
-
const state = this.rolodexStateBag.get(RolodexStateBag);
|
|
1462
|
-
if (state) {
|
|
1463
|
-
this.rolodexActivePath = state.activePath;
|
|
1464
|
-
this.rolodexActiveHash = state.activeHash;
|
|
1465
|
-
// load the root.
|
|
1466
|
-
if (state.rootHash) {
|
|
1467
|
-
this.rolodexTree.pendingNavigationHash = state.rootHash;
|
|
1468
|
-
}
|
|
1469
|
-
if (state.rootPath) {
|
|
1470
|
-
this.rolodexRootPath = state.rootPath;
|
|
1471
|
-
if (state.activePath) {
|
|
1472
|
-
checkRefMap(state.activePath);
|
|
1473
|
-
}
|
|
1474
|
-
// ensure the session has a root selected
|
|
1475
|
-
ModelService.selectRootPath(state.rootPath).then(() => {
|
|
1476
|
-
// nothing to do.
|
|
1477
|
-
}).catch((e) => {
|
|
1478
|
-
console.error('could not select the root path on boot bro', e);
|
|
1479
|
-
});
|
|
1480
|
-
}
|
|
1481
|
-
if (state.rootHash)
|
|
1482
|
-
this.rolodexRootHash = state.rootHash;
|
|
1483
|
-
if (state.activePath) {
|
|
1484
|
-
this.rolodexTree.pendingNavigationPath = state.activePath;
|
|
1485
|
-
this.rolodexTree.requestUpdate();
|
|
1486
|
-
}
|
|
1487
|
-
if (state.activeNode) {
|
|
1488
|
-
// load the content of the active node into the editor
|
|
1489
|
-
if (state.activeLanguage) {
|
|
1490
|
-
this.editor.switchLanguage(state.activeLanguage);
|
|
1491
|
-
}
|
|
1492
|
-
this.editor.setValue(state.activeNode.instance, true);
|
|
1493
|
-
skipDocBag = true;
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
else {
|
|
1497
|
-
this.rolodexActivePath = "root";
|
|
1498
|
-
// refresh the refmap.
|
|
1499
|
-
checkRefMap(this.rolodexActivePath);
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
if (this.docBag && !skipDocBag) {
|
|
1503
|
-
const doc = this.docBag.get(DefaultDocument);
|
|
1504
|
-
if (doc) {
|
|
1505
|
-
this.editor.setValue(doc, true);
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
this.problemBag = this.bagManager.getBag(DocumentProblems);
|
|
1509
|
-
if (this.problemBag) {
|
|
1510
|
-
const markers = this.problemBag.get(DocumentProblems);
|
|
1511
|
-
if (markers) {
|
|
1512
|
-
this.problems = markers;
|
|
1513
|
-
for (let i = 0; i < markers.length; i++) {
|
|
1514
|
-
markers[i] = Problem.reconstruct(markers[i]);
|
|
1515
|
-
}
|
|
1516
|
-
this.buildRolodexResultMap(markers);
|
|
1517
|
-
if (this.rolodexProblemMap.size > 0 && this.rolodexProblemMap.has(this.rolodexActivePath)) {
|
|
1518
|
-
const probs = this.rolodexProblemMap.get(this.rolodexActivePath);
|
|
1519
|
-
if (probs) {
|
|
1520
|
-
this.editor.setMarkers(probs);
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
this.problemList.problems = markers;
|
|
1524
|
-
this.problemsOverview.problems = this.problemList.problemItems;
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
this.howToFixBag = this.bagManager.getBag(HowToFixBag);
|
|
1528
|
-
this.diagnosticBag = this.bagManager.getBag(DiagnosticBag);
|
|
1529
|
-
if (this.diagnosticBag) {
|
|
1530
|
-
const stats = this.diagnosticBag.get(DiagnosticBag);
|
|
1531
|
-
if (stats) {
|
|
1532
|
-
this.problemsOverview.statistics = stats;
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
// extract graph
|
|
1536
|
-
if (this.graphBag) {
|
|
1537
|
-
const graph = this.graphBag.get(GraphBag);
|
|
1538
|
-
if (graph) {
|
|
1539
|
-
this.extractGraph(graph);
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
// extract panel state
|
|
1543
|
-
if (this.panelStateBag) {
|
|
1544
|
-
const panelState = this.panelStateBag.get(PanelStateBag);
|
|
1545
|
-
if (panelState && panelState.explorerPanel) {
|
|
1546
|
-
this.splitPanelExplorer.position = panelState.explorerPanel;
|
|
1547
|
-
}
|
|
1548
|
-
if (panelState && panelState.rolodexPanel) {
|
|
1549
|
-
if (this.splitPanelRolodex) {
|
|
1550
|
-
this.splitPanelRolodex.position = panelState.rolodexPanel;
|
|
1551
|
-
}
|
|
1552
|
-
this.rolodexDividerPosition = panelState.rolodexPanel;
|
|
1553
|
-
}
|
|
1554
|
-
if (panelState && panelState.inspectorPanel) {
|
|
1555
|
-
this.splitPanelInspector.position = panelState.inspectorPanel;
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
if (!this.rolodexRoot) {
|
|
1559
|
-
this.importDisabled = false;
|
|
1560
|
-
}
|
|
1561
|
-
else {
|
|
1562
|
-
this.importDisabled = true;
|
|
1563
|
-
}
|
|
1564
|
-
// extract rulesets from bags
|
|
1565
|
-
const promises = [];
|
|
1566
|
-
this.defaultRulesetBag = this.bagManager.getBag(DefaultRulesetBag);
|
|
1567
|
-
if (this.defaultRulesetBag) {
|
|
1568
|
-
const ruleset = this.defaultRulesetBag.get(DefaultRulesetBag);
|
|
1569
|
-
if (ruleset) {
|
|
1570
|
-
this.defaultRuleset = ruleset;
|
|
1571
|
-
}
|
|
1572
|
-
else {
|
|
1573
|
-
promises.push(this.fetchDefaultRuleset());
|
|
1574
|
-
}
|
|
1575
|
-
}
|
|
1576
|
-
// OWASP ruleset
|
|
1577
|
-
this.OWASPRulesetBag = this.bagManager.getBag(OWASPRulesetBag);
|
|
1578
|
-
if (this.OWASPRulesetBag) {
|
|
1579
|
-
const ruleset = this.OWASPRulesetBag.get(OWASPRulesetBag);
|
|
1580
|
-
if (ruleset) {
|
|
1581
|
-
this.OWASPRuleset = ruleset;
|
|
1582
|
-
}
|
|
1583
|
-
else {
|
|
1584
|
-
promises.push(this.fetchOWASPRuleset());
|
|
1585
|
-
}
|
|
1586
|
-
}
|
|
1587
|
-
// All ruleset
|
|
1588
|
-
this.allRulesetBag = this.bagManager.getBag(AllRulesetBag);
|
|
1589
|
-
if (this.allRulesetBag) {
|
|
1590
|
-
const ruleset = this.allRulesetBag.get(AllRulesetBag);
|
|
1591
|
-
if (ruleset) {
|
|
1592
|
-
this.allRuleset = ruleset;
|
|
1593
|
-
}
|
|
1594
|
-
else {
|
|
1595
|
-
promises.push(this.fetchAllRuleset());
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
// functions
|
|
1599
|
-
this.functionsBag = this.bagManager.getBag(FunctionsBag);
|
|
1600
|
-
this.functionSchemaBag = this.bagManager.getBag(FunctionsSchemaBag);
|
|
1601
|
-
if (this.functionsBag) {
|
|
1602
|
-
const functions = this.functionsBag.get(FunctionsBag);
|
|
1603
|
-
if (functions) {
|
|
1604
|
-
this.functions = functions;
|
|
1605
|
-
}
|
|
1606
|
-
else {
|
|
1607
|
-
promises.push(this.fetchFunctions());
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
// custom ruleset
|
|
1611
|
-
this.customRulesetBag = this.bagManager.getBag(CustomRulesetBag);
|
|
1612
|
-
if (this.customRulesetBag) {
|
|
1613
|
-
const ruleset = this.customRulesetBag.get(CustomRulesetBag);
|
|
1614
|
-
if (ruleset) {
|
|
1615
|
-
this.customRuleset = ruleset;
|
|
1616
|
-
}
|
|
1617
|
-
}
|
|
1618
|
-
// create rule configuration bag
|
|
1619
|
-
this.ruleConfigBag = this.bagManager.getBag(RuleConfigurationBag);
|
|
1620
|
-
// create rule configuration bag
|
|
1621
|
-
this.sessionRulesetMapBag = this.bagManager.getBag(SessionRulesetMapBag);
|
|
1622
|
-
// fire off all network requests, then configure the ruleset management.
|
|
1623
|
-
Promise.all(promises).then(() => {
|
|
1624
|
-
// configure rule management
|
|
1625
|
-
this.manageRuleset.defaultRuleset = this.defaultRuleset;
|
|
1626
|
-
this.manageRuleset.owaspRuleset = this.OWASPRuleset;
|
|
1627
|
-
this.manageRuleset.allRuleset = this.allRuleset;
|
|
1628
|
-
this.manageRuleset.functions = this.functions;
|
|
1629
|
-
const config = this.ruleConfigBag?.get(RuleConfigurationBag);
|
|
1630
|
-
if (config) {
|
|
1631
|
-
this.manageRuleset.rulesetConfig = config;
|
|
1632
|
-
}
|
|
1633
|
-
else {
|
|
1634
|
-
this.manageRuleset.rulesetConfig = { ruleMapping: new Map(), allRulesSwitch: true };
|
|
1635
|
-
}
|
|
1636
|
-
setTimeout(() => {
|
|
1637
|
-
this.manageRuleset.buildRulesets();
|
|
1638
|
-
if (this.customRuleset && this.customRuleset.rules.size > 0) {
|
|
1639
|
-
this.manageRuleset.customRuleset = this.customRuleset;
|
|
1640
|
-
}
|
|
1641
|
-
this.fetchSessionRulesetAsYaml().then((result) => {
|
|
1642
|
-
this.rulesetEditor?.setValue(result, true);
|
|
1643
|
-
this.fetchRulesetMap();
|
|
1644
|
-
}).catch((e) => {
|
|
1645
|
-
this.platformUnavailable(e);
|
|
1646
|
-
});
|
|
1647
|
-
}, 50);
|
|
1648
|
-
});
|
|
1649
|
-
// refresh state for how to fix.
|
|
1650
|
-
this.fetchDocs();
|
|
1651
|
-
}
|
|
1652
|
-
extractGraph(graph) {
|
|
1653
|
-
// handled stripped nodes
|
|
1654
|
-
if (graph.stripped) {
|
|
1655
|
-
this.explorer.nodeLimitExceeded = true;
|
|
1656
|
-
this.modelTree.nodeLimitExceeded = true;
|
|
1657
|
-
if (graph.strippedCount) {
|
|
1658
|
-
this.explorer.nodeLimit = graph.strippedCount;
|
|
1659
|
-
this.modelTree.nodeLimit = graph.strippedCount;
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
else {
|
|
1663
|
-
this.explorer.nodeLimitExceeded = false;
|
|
1664
|
-
this.modelTree.nodeLimitExceeded = false;
|
|
1665
|
-
}
|
|
1666
|
-
this.explorer.renderedNodeMap.clear();
|
|
1667
|
-
this.nodeMap.clear();
|
|
1668
|
-
this.nodeIdMap.clear();
|
|
1669
|
-
this.nodeIdHashMap.clear();
|
|
1670
|
-
const renderedNodes = new Map();
|
|
1671
|
-
graph?.nodesRendered?.forEach((node) => {
|
|
1672
|
-
this.explorer.renderedNodeMap.set(node.id, node);
|
|
1673
|
-
renderedNodes.set(node.id, node);
|
|
1674
|
-
});
|
|
1675
|
-
for (let i = 0; i < graph?.nodesRendered?.length; i++) {
|
|
1676
|
-
this.renderedNodeMap.set(graph.nodesRendered[i].id, graph.nodesRendered[i]);
|
|
1677
|
-
}
|
|
1678
|
-
graph?.nodes?.forEach((node) => {
|
|
1679
|
-
this.nodeMap.set(node.id, node);
|
|
1680
|
-
if (node.idHash.includes('root')) {
|
|
1681
|
-
this.nodeIdMap.set('root', node);
|
|
1682
|
-
this.nodeIdHashMap.set(node.id, node);
|
|
1683
|
-
}
|
|
1684
|
-
else {
|
|
1685
|
-
this.nodeIdMap.set(node.id, node);
|
|
1686
|
-
this.nodeIdHashMap.set(node.idHash, node);
|
|
1687
|
-
}
|
|
1688
|
-
if (node.filtered) {
|
|
1689
|
-
this.filteredNodes.set(node.id, node);
|
|
1690
|
-
}
|
|
1691
|
-
const renderedNode = this.renderedNodeMap.get(node.id);
|
|
1692
|
-
if (this.activeNode?.id === node.id && this.renderedNodeMap.get(node.id)) {
|
|
1693
|
-
if (this.renderedNode && renderedNode) {
|
|
1694
|
-
this.renderedNode.node = renderedNode;
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
});
|
|
1698
|
-
this.graphBag?.set(GraphBag, graph);
|
|
1699
|
-
this.explorer.updateGraphResponse(graph);
|
|
1700
|
-
if (graph && graph.nodes) {
|
|
1701
|
-
this.modelTree.node = graph?.nodesRendered[0]; // update tree
|
|
1702
|
-
}
|
|
1703
|
-
if (!this.explorer.equalizer.isInitialized()) {
|
|
1704
|
-
this.explorer.equalizer.initializeEqualizer();
|
|
1705
|
-
}
|
|
1706
|
-
else {
|
|
1707
|
-
this.explorer.equalizer.runEQ(true);
|
|
1708
|
-
}
|
|
1709
|
-
// sync timeline
|
|
1710
|
-
this.timeVortex.checkHistory();
|
|
1711
|
-
}
|
|
1712
|
-
customRulesetEnabled(event) {
|
|
1713
|
-
const customRS = { rules: new Map() };
|
|
1714
|
-
customRS.id = crypto.randomUUID();
|
|
1715
|
-
customRS.owner = this.authController.session.sessionId;
|
|
1716
|
-
event.detail.rules.forEach((rule) => {
|
|
1717
|
-
if (rule.rule.id != rule.ruleId) {
|
|
1718
|
-
rule.rule.id = rule.ruleId;
|
|
1719
|
-
}
|
|
1720
|
-
customRS.rules.set(rule.ruleId, rule.rule);
|
|
1721
|
-
});
|
|
1722
|
-
// write state
|
|
1723
|
-
this.customRulesetBag?.set(CustomRulesetBag, customRS);
|
|
1724
|
-
if (event.detail.ruleConfig) {
|
|
1725
|
-
this.ruleConfigBag?.set(RuleConfigurationBag, event.detail.ruleConfig);
|
|
1726
|
-
}
|
|
1727
|
-
else {
|
|
1728
|
-
this.ruleConfigBag?.reset();
|
|
1729
|
-
// reset session ruleset
|
|
1730
|
-
RulesetService.resetSessionRuleset(event.detail.rulesetReset).then(() => {
|
|
1731
|
-
this.sendToast({
|
|
1732
|
-
id: crypto.randomUUID(),
|
|
1733
|
-
type: ToastType.INFO,
|
|
1734
|
-
body: "Ruleset has been reset to the default",
|
|
1735
|
-
title: "Ruleset reset",
|
|
1736
|
-
});
|
|
1737
|
-
if (this.docBag) {
|
|
1738
|
-
const doc = this.docBag.get(DefaultDocument);
|
|
1739
|
-
let path = this.rolodexActivePath;
|
|
1740
|
-
if (path == 'root') {
|
|
1741
|
-
path = "";
|
|
1742
|
-
}
|
|
1743
|
-
this.lintSpec(doc, this.rolodexActivePath);
|
|
1744
|
-
}
|
|
1745
|
-
this.fetchSessionRulesetAsYaml().then((result) => {
|
|
1746
|
-
this.rulesetEditor?.setValue(result, true);
|
|
1747
|
-
});
|
|
1748
|
-
}).catch((e) => {
|
|
1749
|
-
this.sendToast({
|
|
1750
|
-
id: crypto.randomUUID(),
|
|
1751
|
-
type: ToastType.ERROR,
|
|
1752
|
-
body: e.detail,
|
|
1753
|
-
title: "Cannot reset ruleset",
|
|
1754
|
-
});
|
|
1755
|
-
});
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
async fetchSessionRulesetAsYaml() {
|
|
1759
|
-
return new Promise(async (resolve, reject) => {
|
|
1760
|
-
RulesetService.getSessionRulesetAsYAML().then((result) => {
|
|
1761
|
-
resolve(result);
|
|
1762
|
-
}).catch((e) => {
|
|
1763
|
-
console.error("cannot fetch session ruleset: ", e.title);
|
|
1764
|
-
reject(e);
|
|
1765
|
-
});
|
|
1766
|
-
});
|
|
1767
|
-
}
|
|
1768
|
-
async fetchFunctions() {
|
|
1769
|
-
return new Promise(async (resolve) => {
|
|
1770
|
-
RulesetService.getFunctions().then((result) => {
|
|
1771
|
-
this.functions = result;
|
|
1772
|
-
this.functionsBag?.set(FunctionsBag, result);
|
|
1773
|
-
// extract schemas for each function
|
|
1774
|
-
const promises = [];
|
|
1775
|
-
result.forEach((functionId) => {
|
|
1776
|
-
promises.push(this.fetchFunctionSchema(functionId));
|
|
1777
|
-
});
|
|
1778
|
-
Promise.all(promises).then(() => {
|
|
1779
|
-
resolve(result);
|
|
1780
|
-
});
|
|
1781
|
-
});
|
|
1782
|
-
});
|
|
1783
|
-
}
|
|
1784
|
-
async fetchFunctionSchema(functionId) {
|
|
1785
|
-
return new Promise(async (resolve) => {
|
|
1786
|
-
RulesetService.getFunctionSchema(functionId).then((result) => {
|
|
1787
|
-
let m = this.functionSchemaBag?.get(FunctionsSchemaBag);
|
|
1788
|
-
if (!m) {
|
|
1789
|
-
m = new Map();
|
|
1790
|
-
}
|
|
1791
|
-
m.set(functionId, result);
|
|
1792
|
-
this.functionSchemaBag?.set(FunctionsSchemaBag, m);
|
|
1793
|
-
resolve(result);
|
|
1794
|
-
});
|
|
1795
|
-
});
|
|
1796
|
-
}
|
|
1797
|
-
async fetchDefaultRuleset() {
|
|
1798
|
-
return new Promise(async (resolve) => {
|
|
1799
|
-
RulesetService.getDefaultRuleset().then((result) => {
|
|
1800
|
-
this.defaultRuleset = result;
|
|
1801
|
-
this.defaultRulesetBag?.set(DefaultRulesetBag, result);
|
|
1802
|
-
resolve(result);
|
|
1803
|
-
});
|
|
1804
|
-
});
|
|
1805
|
-
}
|
|
1806
|
-
async fetchOWASPRuleset() {
|
|
1807
|
-
return new Promise(async (resolve) => {
|
|
1808
|
-
RulesetService.getOWASPRuleset().then((result) => {
|
|
1809
|
-
this.OWASPRuleset = result;
|
|
1810
|
-
this.OWASPRulesetBag?.set(OWASPRulesetBag, result);
|
|
1811
|
-
resolve(result);
|
|
1812
|
-
});
|
|
1813
|
-
});
|
|
1814
|
-
}
|
|
1815
|
-
async fetchAllRuleset() {
|
|
1816
|
-
return new Promise(async (resolve) => {
|
|
1817
|
-
RulesetService.getAllRuleset().then((result) => {
|
|
1818
|
-
this.allRuleset = result;
|
|
1819
|
-
this.allRulesetBag?.set(AllRulesetBag, result);
|
|
1820
|
-
resolve(result);
|
|
1821
|
-
});
|
|
1822
|
-
});
|
|
1823
|
-
}
|
|
1824
|
-
fetchDocs() {
|
|
1825
|
-
this.activitySpinner.show();
|
|
1826
|
-
const url = new URL(window.location.href);
|
|
1827
|
-
const urlParam = url.searchParams.get('url');
|
|
1828
|
-
if (urlParam) {
|
|
1829
|
-
//this.urlInput.value = urlParam;
|
|
1830
|
-
this.activeURL = urlParam;
|
|
1831
|
-
this.lintSpec('', urlParam);
|
|
1832
|
-
}
|
|
1833
|
-
LintingService.fetchAllHowToFix().then((result) => {
|
|
1834
|
-
if (result) {
|
|
1835
|
-
result.forEach((howToFix) => {
|
|
1836
|
-
this.howToFixBag?.set(howToFix.ruleId, howToFix);
|
|
1837
|
-
});
|
|
1838
|
-
}
|
|
1839
|
-
}).catch((e) => {
|
|
1840
|
-
this.platformUnavailable(e);
|
|
1841
|
-
console.error("documentation service is down");
|
|
1842
|
-
});
|
|
1843
|
-
this.ruleDocsBag = this.bagManager.getBag(RuleDocumentationBag);
|
|
1844
|
-
this.functionDocsBag = this.bagManager.getBag(FunctionDocumentationBag);
|
|
1845
|
-
// populate docs via worker.
|
|
1846
|
-
this.ruleDocsWorker.addEventListener("message", (event) => {
|
|
1847
|
-
const data = event.data;
|
|
1848
|
-
if (data) {
|
|
1849
|
-
data.forEach((doc) => {
|
|
1850
|
-
if (doc.ruleId) {
|
|
1851
|
-
this.ruleDocsBag?.set(doc.ruleId, doc);
|
|
1852
|
-
}
|
|
1853
|
-
if (doc.functionId) {
|
|
1854
|
-
this.functionDocsBag?.set(doc.functionId, doc);
|
|
1855
|
-
}
|
|
1856
|
-
});
|
|
1857
|
-
this.activitySpinner.hide();
|
|
1858
|
-
}
|
|
1859
|
-
});
|
|
1860
|
-
// let ruleDocs: string[] = [];
|
|
1861
|
-
// let functionDocs: string[] = [];
|
|
1862
|
-
// if (this.ruleDocsBag) {
|
|
1863
|
-
// ruleDocs = Array.from(this.ruleDocsBag.export().keys());
|
|
1864
|
-
// }
|
|
1865
|
-
// if (this.functionDocsBag) {
|
|
1866
|
-
// functionDocs = Array.from(this.functionDocsBag.export().keys());
|
|
1867
|
-
// }
|
|
1868
|
-
const fetchDocs = () => {
|
|
1869
|
-
this.ruleDocsWorker.postMessage({
|
|
1870
|
-
start: true,
|
|
1871
|
-
endpoint: this.doctorEndpoint,
|
|
1872
|
-
existingRules: [],
|
|
1873
|
-
existingFunctions: []
|
|
1874
|
-
});
|
|
1875
|
-
};
|
|
1876
|
-
// check expiration
|
|
1877
|
-
if (this.docExpirationBag) {
|
|
1878
|
-
const expiration = this.docExpirationBag.get(DocumentationExpirationBag);
|
|
1879
|
-
// if the docs are older than 15 days, refresh them.
|
|
1880
|
-
if (expiration) {
|
|
1881
|
-
const now = new Date().getTime();
|
|
1882
|
-
const then = new Date(expiration).getTime();
|
|
1883
|
-
// if (now - then > 1296000000) {
|
|
1884
|
-
// fetchDocs();
|
|
1885
|
-
// } else {
|
|
1886
|
-
// this.activitySpinner.hide();
|
|
1887
|
-
// }
|
|
1888
|
-
fetchDocs(); // always fetch for now.
|
|
1889
|
-
}
|
|
1890
|
-
else {
|
|
1891
|
-
fetchDocs();
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
else {
|
|
1895
|
-
fetchDocs();
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
fetchRulesetMap() {
|
|
1899
|
-
RulesetService.getSessionRulesetMap().then((result) => {
|
|
1900
|
-
this.sessionRulesetMapBag?.set(SessionRulesetMapBag, result);
|
|
1901
|
-
}).catch(() => {
|
|
1902
|
-
console.warn("map is empty, or unavailable, Did you submit an empty ruleset?");
|
|
1903
|
-
this.sendToast({
|
|
1904
|
-
id: crypto.randomUUID(),
|
|
1905
|
-
type: ToastType.WARNING,
|
|
1906
|
-
body: "map is empty, or unavailable, Did you submit an empty ruleset?",
|
|
1907
|
-
title: "Issue fetching ruleset map"
|
|
1908
|
-
});
|
|
1909
|
-
});
|
|
1910
|
-
}
|
|
1911
|
-
ruleClicked(evt) {
|
|
1912
|
-
// get rule map from bag
|
|
1913
|
-
const map = this.sessionRulesetMapBag?.get(SessionRulesetMapBag);
|
|
1914
|
-
if (map) {
|
|
1915
|
-
const rule = map.rulesMap.find((r) => r.ruleId === evt.detail.ruleId);
|
|
1916
|
-
if (rule) {
|
|
1917
|
-
this.selectedEditorTab = "ruleset";
|
|
1918
|
-
this.editorTabGroup.show(ActiveView.Ruleset);
|
|
1919
|
-
this.rulesetEditor.editor?.setPosition({ lineNumber: rule.line, column: rule.start });
|
|
1920
|
-
this.rulesetEditor.editor?.revealLineInCenter(rule.line);
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
1923
|
-
}
|
|
1924
426
|
builtInRulesetSelected() {
|
|
1925
427
|
// todo
|
|
1926
428
|
}
|
|
1927
|
-
rulesetManuallyChanged() {
|
|
1928
|
-
clearTimeout(this.bounceId);
|
|
1929
|
-
this.bounceId = window.setTimeout(() => {
|
|
1930
|
-
const ruleset = this.rulesetEditor.editor?.getValue();
|
|
1931
|
-
RulesetService.validateRuleset(ruleset).then((result) => {
|
|
1932
|
-
// clear any problems
|
|
1933
|
-
this.manageRuleset.clearRuleProblems();
|
|
1934
|
-
// create a new custom ruleset with a map of rules
|
|
1935
|
-
let customRS = { rules: new Map() };
|
|
1936
|
-
customRS.id = crypto.randomUUID();
|
|
1937
|
-
customRS.owner = this.authController.session.sessionId;
|
|
1938
|
-
customRS.rules = new Map(Object.entries(result.rules));
|
|
1939
|
-
customRS.rules.forEach((rule, id) => {
|
|
1940
|
-
rule.id = id; // set the id to the key
|
|
1941
|
-
});
|
|
1942
|
-
// write state
|
|
1943
|
-
this.customRulesetBag?.set(CustomRulesetBag, customRS);
|
|
1944
|
-
this.customRuleset = customRS;
|
|
1945
|
-
if (customRS.rules.size > 0) {
|
|
1946
|
-
// rebuild the ruleset management
|
|
1947
|
-
this.manageRuleset.customRulesetManual = customRS;
|
|
1948
|
-
}
|
|
1949
|
-
this.selectedEditorTab = ActiveView.Ruleset;
|
|
1950
|
-
this.controlTabGroup.show(ActiveView.Ruleset);
|
|
1951
|
-
this.rulesetEditor.setMarkers([]);
|
|
1952
|
-
this.fetchRulesetMap();
|
|
1953
|
-
}).catch((e) => {
|
|
1954
|
-
this.sendToast({
|
|
1955
|
-
id: crypto.randomUUID(),
|
|
1956
|
-
type: ToastType.ERROR,
|
|
1957
|
-
body: e.detail,
|
|
1958
|
-
title: e.title
|
|
1959
|
-
});
|
|
1960
|
-
console.error('unable to validate ruleset', e);
|
|
1961
|
-
// process bad rules
|
|
1962
|
-
const ruleErrors = e.body;
|
|
1963
|
-
const markers = [];
|
|
1964
|
-
ruleErrors?.forEach((err) => {
|
|
1965
|
-
markers.push({
|
|
1966
|
-
severity: MarkerSeverity.Error,
|
|
1967
|
-
message: err.ruleError,
|
|
1968
|
-
startLineNumber: err.line,
|
|
1969
|
-
startColumn: err.startCol,
|
|
1970
|
-
endLineNumber: err.line,
|
|
1971
|
-
endColumn: err.endCol
|
|
1972
|
-
});
|
|
1973
|
-
});
|
|
1974
|
-
// convert to JSON
|
|
1975
|
-
RulesetService.convertToJSON(ruleset).then((json) => {
|
|
1976
|
-
// create a new custom ruleset with a map of rules
|
|
1977
|
-
let customRS = { rules: new Map() };
|
|
1978
|
-
customRS.id = crypto.randomUUID();
|
|
1979
|
-
customRS.owner = this.authController.session.sessionId;
|
|
1980
|
-
customRS.rules = new Map(Object.entries(json.rules));
|
|
1981
|
-
customRS.rules.forEach((rule, id) => {
|
|
1982
|
-
if (rule.id != id)
|
|
1983
|
-
rule.id = id; // set the id to the key
|
|
1984
|
-
});
|
|
1985
|
-
this.customRuleset = customRS;
|
|
1986
|
-
if (customRS.rules.size > 0) {
|
|
1987
|
-
// rebuild the ruleset management
|
|
1988
|
-
this.manageRuleset.customRulesetManual = customRS;
|
|
1989
|
-
}
|
|
1990
|
-
this.rulesetEditor.setMarkers([]);
|
|
1991
|
-
// clear any problems
|
|
1992
|
-
this.manageRuleset.clearRuleProblems();
|
|
1993
|
-
// set problems.
|
|
1994
|
-
this.rulesetEditor.setMarkers(markers);
|
|
1995
|
-
this.manageRuleset.processBadRules(ruleErrors);
|
|
1996
|
-
this.controlTabGroup.show(ActiveView.Ruleset);
|
|
1997
|
-
}).catch((e) => {
|
|
1998
|
-
console.error("unable to convert ruleset to JSON", e);
|
|
1999
|
-
});
|
|
2000
|
-
});
|
|
2001
|
-
}, this.debounceTimeRuleset);
|
|
2002
|
-
}
|
|
2003
|
-
specChanged(event) {
|
|
2004
|
-
const editor = this.editorMap.get(event.detail.id);
|
|
2005
|
-
if (editor && event.detail.id === 'ruleset-editor') {
|
|
2006
|
-
this.rulesetManuallyChanged();
|
|
2007
|
-
return;
|
|
2008
|
-
}
|
|
2009
|
-
if (this.docBag) {
|
|
2010
|
-
this.docBag.set(DefaultDocument, event.detail.content);
|
|
2011
|
-
}
|
|
2012
|
-
if (this.autoDiagnose) {
|
|
2013
|
-
clearTimeout(this.bounceId);
|
|
2014
|
-
this.bounceId = window.setTimeout(() => {
|
|
2015
|
-
this.lintSpec(event.detail.content);
|
|
2016
|
-
}, this.debounceTime);
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
429
|
runDiagnostics() {
|
|
2020
430
|
if (!this.autoDiagnose) {
|
|
2021
|
-
this.lintSpec(this.editor.getValue());
|
|
431
|
+
this.diagnosticController.lintSpec(this.editor.getValue());
|
|
2022
432
|
}
|
|
2023
433
|
}
|
|
2024
434
|
boostrap() {
|
|
@@ -2028,20 +438,21 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
2028
438
|
if (urlParam) {
|
|
2029
439
|
//this.urlInput.value = urlParam;
|
|
2030
440
|
this.activeURL = urlParam;
|
|
2031
|
-
this.lintSpec('', urlParam);
|
|
441
|
+
this.diagnosticController.lintSpec('', urlParam);
|
|
2032
442
|
return;
|
|
2033
443
|
}
|
|
444
|
+
// todo: this needs work man. I want to see all these settimeouts gone brother.
|
|
2034
445
|
setTimeout(() => {
|
|
2035
|
-
this.loadingOverlay.hide();
|
|
2036
446
|
// check for a history
|
|
2037
447
|
this.timeVortex.doctor = this;
|
|
2038
448
|
this.timeVortex.checkHistory();
|
|
2039
449
|
const editorValue = this.docBag?.get(DefaultDocument);
|
|
2040
450
|
if (!editorValue) {
|
|
2041
451
|
LintingService.bootstrapEditor().then((result) => {
|
|
452
|
+
this.loadingOverlay.hide();
|
|
2042
453
|
this.editor.setValue(result, true);
|
|
2043
454
|
this.rolodexActivePath = "";
|
|
2044
|
-
this.specChanged(new CustomEvent(EditorUpdated, {
|
|
455
|
+
this.specController.specChanged(new CustomEvent(EditorUpdated, {
|
|
2045
456
|
detail: {
|
|
2046
457
|
content: result,
|
|
2047
458
|
id: "spec"
|
|
@@ -2049,40 +460,31 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
2049
460
|
}));
|
|
2050
461
|
});
|
|
2051
462
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
463
|
+
else {
|
|
464
|
+
ModelService.getCurrentSpec().then((result) => {
|
|
465
|
+
this.loadingOverlay.hide();
|
|
466
|
+
this.rolodexController.queryRolodex();
|
|
467
|
+
if (result != editorValue) {
|
|
468
|
+
this.editor.setValue(result, true);
|
|
469
|
+
this.rolodexActivePath = "";
|
|
470
|
+
this.specController.specChanged(new CustomEvent(EditorUpdated, {
|
|
471
|
+
detail: {
|
|
472
|
+
content: result,
|
|
473
|
+
id: "spec"
|
|
474
|
+
}
|
|
475
|
+
}));
|
|
476
|
+
}
|
|
477
|
+
});
|
|
2060
478
|
}
|
|
2061
|
-
}
|
|
2062
|
-
if (jsonRS) {
|
|
2063
|
-
let reportData = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(jsonRS, null, 2));
|
|
2064
|
-
this.downloadRulesetLink.download = "ruleset.json";
|
|
2065
|
-
this.downloadRulesetLink.href = reportData;
|
|
2066
|
-
this.downloadRulesetLink.click();
|
|
2067
|
-
this.exportRulesetDialog.hide();
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
exportYAML() {
|
|
2071
|
-
RulesetService.getSessionRulesetAsYAML().then((yaml) => {
|
|
2072
|
-
let reportData = "data:text/yaml;charset=utf-8," + encodeURIComponent(yaml);
|
|
2073
|
-
this.downloadRulesetLink.download = "ruleset.yaml";
|
|
2074
|
-
this.downloadRulesetLink.href = reportData;
|
|
2075
|
-
this.downloadRulesetLink.click();
|
|
2076
|
-
this.exportRulesetDialog.hide();
|
|
2077
|
-
});
|
|
479
|
+
}, 50);
|
|
2078
480
|
}
|
|
2079
481
|
confirmExport() {
|
|
2080
482
|
switch (this.exportSelection.value) {
|
|
2081
483
|
case "json":
|
|
2082
|
-
this.exportJSON();
|
|
484
|
+
this.ruleController.exportJSON();
|
|
2083
485
|
break;
|
|
2084
486
|
case "yaml":
|
|
2085
|
-
this.exportYAML();
|
|
487
|
+
this.ruleController.exportYAML();
|
|
2086
488
|
break;
|
|
2087
489
|
}
|
|
2088
490
|
}
|
|
@@ -2276,6 +678,30 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
2276
678
|
</sl-tab-group>
|
|
2277
679
|
`;
|
|
2278
680
|
}
|
|
681
|
+
const controls = html `
|
|
682
|
+
<div class="controls">
|
|
683
|
+
<sl-tooltip content="Upload zip file or tar.gz (tarball)" placement="top">
|
|
684
|
+
<sl-button ?disabled=${this.importDisabled} class="import-button" variant="text"
|
|
685
|
+
size="small" @click="${() => {
|
|
686
|
+
this.uploadArchive.show();
|
|
687
|
+
}}">
|
|
688
|
+
Import
|
|
689
|
+
</sl-button>
|
|
690
|
+
</sl-tooltip>
|
|
691
|
+
<sl-tooltip content="Nuke / reset workspace" placement="top">
|
|
692
|
+
<sl-icon-button class="nuke-session-button" name="radioactive" @click="${() => {
|
|
693
|
+
this.nukeWorkspace.show();
|
|
694
|
+
}}">
|
|
695
|
+
</sl-icon-button>
|
|
696
|
+
</sl-tooltip>
|
|
697
|
+
</div>`;
|
|
698
|
+
let navigatorView = html `
|
|
699
|
+
${controls}
|
|
700
|
+
${modelTree}
|
|
701
|
+
`;
|
|
702
|
+
if (this.authController.state && this.authController.state.authenticated) {
|
|
703
|
+
this.statusBar.authenticated = true;
|
|
704
|
+
}
|
|
2279
705
|
return html `
|
|
2280
706
|
${this.uploadArchive}
|
|
2281
707
|
${this.nukeWorkspace}
|
|
@@ -2308,30 +734,11 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
2308
734
|
${this.activitySpinner}
|
|
2309
735
|
${this.errorBanner}
|
|
2310
736
|
${overlay}
|
|
2311
|
-
|
|
2312
737
|
<sl-split-panel id="explorer-split-panel" class="split-panel-explorer" position="12"
|
|
2313
738
|
@sl-reposition="${this.updateExplorerDivider}">
|
|
2314
739
|
<sl-icon id="split-divider-tree" slot="divider" name="grip-vertical" class="divider-vert"></sl-icon>
|
|
2315
740
|
<div slot="start" class="model-tree">
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
<sl-tooltip content="Upload zip file or tar.gz (tarball)" placement="top">
|
|
2319
|
-
<sl-button ?disabled=${this.importDisabled} class="import-button" variant="text"
|
|
2320
|
-
size="small" @click="${() => {
|
|
2321
|
-
this.uploadArchive.show();
|
|
2322
|
-
}}">
|
|
2323
|
-
Import
|
|
2324
|
-
</sl-button>
|
|
2325
|
-
</sl-tooltip>
|
|
2326
|
-
<sl-tooltip content="Nuke / reset workspace" placement="top">
|
|
2327
|
-
<sl-icon-button class="nuke-session-button" name="radioactive" @click="${() => {
|
|
2328
|
-
this.nukeWorkspace.show();
|
|
2329
|
-
}}">
|
|
2330
|
-
</sl-icon-button>
|
|
2331
|
-
</sl-tooltip>
|
|
2332
|
-
|
|
2333
|
-
</div>
|
|
2334
|
-
${modelTree}
|
|
741
|
+
${navigatorView}
|
|
2335
742
|
${this.creditTicker}
|
|
2336
743
|
</div>
|
|
2337
744
|
<div slot="end">
|
|
@@ -2462,15 +869,17 @@ let TheDoctor = class TheDoctor extends LitElement {
|
|
|
2462
869
|
</sl-split-panel>
|
|
2463
870
|
</div>
|
|
2464
871
|
</sl-split-panel>
|
|
2465
|
-
|
|
2466
872
|
</div>`;
|
|
2467
873
|
}
|
|
874
|
+
randomTicker() {
|
|
875
|
+
return crypto.randomUUID().toString();
|
|
876
|
+
}
|
|
2468
877
|
// <iframe src="${this.doctorEndpoint}/model/scalar-template?z=${this.randomTicker}" width="100%" height="100%" style="border: none"></iframe>
|
|
2469
878
|
fetchUrl(event) {
|
|
2470
879
|
this.activeURL = event.detail.url;
|
|
2471
880
|
this.rolodexNeedsReset = true;
|
|
2472
881
|
this.rolodexActivePath = "/";
|
|
2473
|
-
this.lintSpec('', event.detail.url);
|
|
882
|
+
this.diagnosticController.lintSpec('', event.detail.url);
|
|
2474
883
|
}
|
|
2475
884
|
hideUrlError() {
|
|
2476
885
|
this.urlProblem.style.display = 'none';
|
|
@@ -2574,9 +983,6 @@ __decorate([
|
|
|
2574
983
|
__decorate([
|
|
2575
984
|
query('#inspector-split-panel')
|
|
2576
985
|
], TheDoctor.prototype, "splitPanelInspector", void 0);
|
|
2577
|
-
__decorate([
|
|
2578
|
-
state()
|
|
2579
|
-
], TheDoctor.prototype, "randomTicker", void 0);
|
|
2580
986
|
__decorate([
|
|
2581
987
|
state()
|
|
2582
988
|
], TheDoctor.prototype, "rulesetPulse", void 0);
|