diff --git a/packages/noodl-editor/src/editor/src/utils/forge/template/providers/noodl-docs-template-provider.ts b/packages/noodl-editor/src/editor/src/utils/forge/template/providers/noodl-docs-template-provider.ts
index e9c06ed..c65eaec 100644
--- a/packages/noodl-editor/src/editor/src/utils/forge/template/providers/noodl-docs-template-provider.ts
+++ b/packages/noodl-editor/src/editor/src/utils/forge/template/providers/noodl-docs-template-provider.ts
@@ -6,7 +6,7 @@ import { ITemplateProvider, ProgressCallback, TemplateItem, TemplateListFilter }
*/
export class NoodlDocsTemplateProvider implements ITemplateProvider {
get name(): string {
- return 'https://docs.noodl.net';
+ return this.getDocsEndpoint() || 'https://docs.fluxscape.io';
}
constructor(private readonly getDocsEndpoint: () => string) {}
diff --git a/packages/noodl-editor/src/editor/src/views/panels/search-panel/search-panel.tsx b/packages/noodl-editor/src/editor/src/views/panels/search-panel/search-panel.tsx
index 303c75d..e9d3298 100644
--- a/packages/noodl-editor/src/editor/src/views/panels/search-panel/search-panel.tsx
+++ b/packages/noodl-editor/src/editor/src/views/panels/search-panel/search-panel.tsx
@@ -5,6 +5,8 @@ import { useSidePanelKeyboardCommands } from '@noodl-hooks/useKeyboardCommands';
import classNames from 'classnames';
import React, { useEffect, useRef, useState } from 'react';
+import { ComponentModel } from '@noodl-models/componentmodel';
+import { NodeGraphNode } from '@noodl-models/nodegraphmodel';
import { KeyCode, KeyMod } from '@noodl-utils/keyboard/KeyCode';
import { performSearch } from '@noodl-utils/universal-search';
@@ -54,7 +56,7 @@ export function SearchPanel() {
}
}, [debouncedSearchTerm]);
- function onSearchItemClicked(searchResult) {
+ function onSearchItemClicked(searchResult: SearchResultItem) {
if (searchResult.type === 'Component') {
NodeGraphContextTmp.switchToComponent(searchResult.componentTarget, {
breadcrumbs: false,
@@ -85,29 +87,7 @@ export function SearchPanel() {
{searchResults.map((component) => (
-
1 ? 's' : ''
- })`}
- key={component.componentId}
- variant={SectionVariant.Panel}
- >
- {component.results.map((result, index) => (
- onSearchItemClicked(result)}
- >
-
- {result.label}
-
- ))}
-
+
))}
{searchResults.length === 0 && debouncedSearchTerm.length > 0 && (
@@ -118,3 +98,51 @@ export function SearchPanel() {
);
}
+
+type SearchResultItem = {
+ componentTarget: ComponentModel;
+ label: string;
+ nodeTarget: NodeGraphNode;
+ type: string;
+ userLabel: string;
+};
+
+type SearchItemProps = {
+ component: {
+ componentName: string;
+ componentId: string;
+ results: SearchResultItem[];
+ };
+ onSearchItemClicked: (item: SearchResultItem) => void;
+};
+
+function SearchItem({ component, onSearchItemClicked }: SearchItemProps) {
+ const resultCountText = `${component.results.length} result${component.results.length > 1 ? 's' : ''}`;
+ let titleText = `${component.componentName} (${resultCountText})`;
+
+ // We expect there to always be at least one result, to get the full component name.
+ const isInCloudFunctions = component.results[0].componentTarget.name.startsWith('/#__cloud__/');
+ if (isInCloudFunctions) {
+ titleText += ' (Cloud Function)';
+ }
+
+ return (
+
+ {component.results.map((result, index) => (
+ onSearchItemClicked(result)}
+ >
+
+ {result.label}
+
+ ))}
+
+ );
+}
diff --git a/packages/noodl-runtime/src/api/records.js b/packages/noodl-runtime/src/api/records.js
index 7cc72cb..bd4d69c 100644
--- a/packages/noodl-runtime/src/api/records.js
+++ b/packages/noodl-runtime/src/api/records.js
@@ -12,6 +12,7 @@ function createRecordsAPI(modelScope) {
return {
async query(className, query, options) {
+ if (typeof className === "undefined") throw new Error("'className' is undefined");
return new Promise((resolve, reject) => {
cloudstore().query({
collection: className,
@@ -39,6 +40,7 @@ function createRecordsAPI(modelScope) {
},
async count(className, query) {
+ if (typeof className === "undefined") throw new Error("'className' is undefined");
return new Promise((resolve, reject) => {
cloudstore().count({
collection: className,
@@ -60,6 +62,7 @@ function createRecordsAPI(modelScope) {
},
async distinct(className, property, query) {
+ if (typeof className === "undefined") throw new Error("'className' is undefined");
return new Promise((resolve, reject) => {
cloudstore().distinct({
collection: className,
@@ -82,6 +85,7 @@ function createRecordsAPI(modelScope) {
},
async aggregate(className, group, query) {
+ if (typeof className === "undefined") throw new Error("'className' is undefined");
return new Promise((resolve, reject) => {
cloudstore().aggregate({
collection: className,
@@ -104,6 +108,7 @@ function createRecordsAPI(modelScope) {
},
async fetch(objectOrId, options) {
+ if (typeof objectOrId === 'undefined') return Promise.reject(new Error("'objectOrId' is undefined."));
if (typeof objectOrId !== 'string') objectOrId = objectOrId.getId();
const className = (options ? options.className : undefined) || (modelScope || Model).get(objectOrId)._class;
@@ -126,6 +131,7 @@ function createRecordsAPI(modelScope) {
},
async increment(objectOrId, properties, options) {
+ if (typeof objectOrId === 'undefined') return Promise.reject(new Error("'objectOrId' is undefined."));
if (typeof objectOrId !== 'string') objectOrId = objectOrId.getId();
const className = (options ? options.className : undefined) || (modelScope || Model).get(objectOrId)._class;
@@ -149,6 +155,7 @@ function createRecordsAPI(modelScope) {
},
async save(objectOrId, properties, options) {
+ if (typeof objectOrId === 'undefined') return Promise.reject(new Error("'objectOrId' is undefined."));
if (typeof objectOrId !== 'string') objectOrId = objectOrId.getId();
const className = (options ? options.className : undefined) || (modelScope || Model).get(objectOrId)._class;
@@ -179,6 +186,7 @@ function createRecordsAPI(modelScope) {
},
async create(className, properties, options) {
+ if (typeof className === "undefined") throw new Error("'className' is undefined");
return new Promise((resolve, reject) => {
cloudstore().create({
collection: className,
@@ -197,6 +205,7 @@ function createRecordsAPI(modelScope) {
},
async delete(objectOrId, options) {
+ if (typeof objectOrId === 'undefined') return Promise.reject(new Error("'objectOrId' is undefined."));
if (typeof objectOrId !== 'string') objectOrId = objectOrId.getId();
const className = (options ? options.className : undefined) || (modelScope || Model).get(objectOrId)._class;
@@ -265,7 +274,7 @@ function createRecordsAPI(modelScope) {
resolve();
},
error: (err) => {
- reject(Error(rr || 'Failed to add relation.'));
+ reject(Error(err || 'Failed to add relation.'));
}
});
});
diff --git a/packages/noodl-viewer-react/src/nodes/navigation/navigate.js b/packages/noodl-viewer-react/src/nodes/navigation/navigate.js
index 0fb202a..8090044 100644
--- a/packages/noodl-viewer-react/src/nodes/navigation/navigate.js
+++ b/packages/noodl-viewer-react/src/nodes/navigation/navigate.js
@@ -72,8 +72,10 @@ const Navigate = {
backCallback: (action, results) => {
this._internal.backResults = results;
- for (var key in results) {
- if (this.hasOutput('backResult-' + key)) this.flagOutputDirty('backResult-' + key);
+ for (const key in results) {
+ if (this.hasOutput('backResult-' + key)) {
+ this.flagOutputDirty('backResult-' + key);
+ }
}
if (action !== undefined) this.sendSignalOnOutput(action);
@@ -114,22 +116,23 @@ const Navigate = {
return;
}
- if (name === 'target')
+ if (name === 'target') {
return this.registerInput(name, {
set: this.setTargetPageId.bind(this)
});
- else if (name === 'transition')
+ } else if (name === 'transition') {
return this.registerInput(name, {
set: this.setTransition.bind(this)
});
- else if (name.startsWith('tr-'))
+ } else if (name.startsWith('tr-')) {
return this.registerInput(name, {
set: this.setTransitionParam.bind(this, name.substring('tr-'.length))
});
- else if (name.startsWith('pm-'))
+ } else if (name.startsWith('pm-')) {
return this.registerInput(name, {
set: this.setPageParam.bind(this, name.substring('pm-'.length))
});
+ }
},
registerOutputIfNeeded: function (name) {
if (this.hasOutput(name)) {
@@ -174,18 +177,24 @@ function setup(context, graphModel) {
if (Transitions[transition]) ports = ports.concat(Transitions[transition].ports(node.parameters));
}
- // if(node.parameters['stack'] !== undefined) {
- var pageStacks = graphModel.getNodesWithType('Page Stack');
- var pageStack = pageStacks.find(
+ const pageStacks = graphModel.getNodesWithType('Page Stack');
+ const pageStack = pageStacks.find(
(ps) => (ps.parameters['name'] || 'Main') === (node.parameters['stack'] || 'Main')
);
if (pageStack !== undefined) {
- var pages = pageStack.parameters['pages'];
+ const pages = pageStack.parameters['pages'];
if (pages !== undefined && pages.length > 0) {
ports.push({
plug: 'input',
- type: { name: 'enum', enums: pages.map((p) => ({ label: p.label, value: p.id })), allowEditOnly: true },
+ type: {
+ name: 'enum',
+ enums: pages.map((p) => ({
+ label: p.label,
+ value: p.id
+ })),
+ allowEditOnly: true
+ },
group: 'General',
displayName: 'Target Page',
name: 'target',
@@ -193,14 +202,14 @@ function setup(context, graphModel) {
});
// See if there is a target page with component
- var targetPageId = node.parameters['target'] || pages[0].id;
- var targetComponentName = pageStack.parameters['pageComp-' + targetPageId];
+ const targetPageId = node.parameters['target'] || pages[0].id;
+ const targetComponentName = pageStack.parameters['pageComp-' + targetPageId];
if (targetComponentName !== undefined) {
const component = graphModel.components[targetComponentName];
if (component !== undefined) {
// Make all inputs of the component to inputs of this navigation node
- for (var inputName in component.inputPorts) {
+ for (const inputName in component.inputPorts) {
ports.push({
name: 'pm-' + inputName,
displayName: inputName,
@@ -245,7 +254,6 @@ function setup(context, graphModel) {
}
}
}
- // }
context.editorConnection.sendDynamicPorts(node.id, ports);
}