1 Commits

Author SHA1 Message Date
Axel Wretman
360cdc46f2 Added Contribution markdown file and a section in the readme. 2025-09-09 15:06:23 +02:00
24 changed files with 71269 additions and 17487 deletions

36
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,36 @@
# Contributing to OpenNoodl
Thank you for your interest in contributing! Heres how you can help:
## How to Contribute
1. **Fork the repository** and create your feature branch:
```bash
git checkout -b feature/my-feature
```
2. **Make your changes** and ensure your code follows the existing style and conventions.
3. **Test your changes** locally.
4. **Commit your changes** with a clear message:
```bash
git commit -am 'Add new feature'
```
5. **Push to your branch**:
```bash
git push origin feature/my-feature
```
6. **Open a pull request** on GitHub. Describe your changes and the motivation behind them.
## Guidelines
- The branch name should be descriptive of the feature or fix. Either `feature/<my-feature>` or `fix/<my-fix>` prefixes are recommended. Also including an issue number can be helpful.
- Follow the coding style used in the project.
- Write clear, concise commit messages.
- Add tests for new features or bug fixes when possible.
- Document any new functionality.
## Need Help?
- Join our [community](https://the-low-code-foundation.fibery.io/invite/5NtlTThnCPh2vaAk)
- Open an issue for questions or suggestions.
Thank you for helping improve OpenNoodl!

View File

@@ -1,6 +1,6 @@
# OpenNoodl # OpenNoodl
OpenNoodl is a fork of the original Noodl open source code under GPL-3.0 license. OpenNoodl / Noodl is a front end React app builder with a visual programming interface. OpenNoodl is a fork of the original Noodl open source code under GPL-3.0 license. OpenNoodl / Noodl is a front end React app builder with a visual programming interface.
OpenNoodl will aim to stay entirely in sync with the original repository, including future updates to this repository. A roadmap for updates will be published soon. OpenNoodl will aim to stay entirely in sync with the original repository, including future updates to this repository. A roadmap for updates will be published soon.
@@ -40,6 +40,21 @@ If you prefer self-hosting or a local backend, while still taking advantage of t
See the original Noodl documentation below See the original Noodl documentation below
# Contribution
We welcome contributions to OpenNoodl! To contribute:
1. **Fork the repository** and create your feature branch (`git checkout -b feature/my-feature`).
2. **Make your changes** and follow the existing code style.
3. **Test your changes** locally.
4. **Commit your changes** (`git commit -am 'Add new feature'`).
5. **Push to your branch** (`git push origin feature/my-feature`).
6. **Open a pull request** describing your changes.
See [CONTRIBUTING.md](CONTRIBUTING.md) for details and our code of conduct.
If you have questions, join our [community](https://the-low-code-foundation.fibery.io/invite/5NtlTThnCPh2vaAk) or open an issue.
# Noodl # Noodl
[Noodl](https://noodl.net) is a low-code platform where designers and developers build custom applications and experiences. Designed as a visual programming environment, it aims to expedite your development process. It promotes the swift and efficient creation of applications, requiring minimal coding knowledge. [Noodl](https://noodl.net) is a low-code platform where designers and developers build custom applications and experiences. Designed as a visual programming environment, it aims to expedite your development process. It promotes the swift and efficient creation of applications, requiring minimal coding knowledge.
@@ -88,5 +103,5 @@ Packaged licensed under MIT:
- `noodl-runtime` - `noodl-runtime`
- `noodl-viewer-cloud` - `noodl-viewer-cloud`
- `noodl-viewer-react` - `noodl-viewer-react`
You can find a MIT LICENSE file in each of these packages. The rest of the repository is licensed under GPLv3. You can find a MIT LICENSE file in each of these packages. The rest of the repository is licensed under GPLv3.

88367
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -27,24 +27,24 @@
"test:platform": "lerna exec --scope @noodl/platform-node -- npm test" "test:platform": "lerna exec --scope @noodl/platform-node -- npm test"
}, },
"devDependencies": { "devDependencies": {
"@ianvs/prettier-plugin-sort-imports": "^3.7.2", "@ianvs/prettier-plugin-sort-imports": "^3.7.1",
"@types/keyv": "3.1.4", "@types/keyv": "3.1.4",
"@types/node": "^18.19.123", "@types/node": "^18.8.3",
"@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/eslint-plugin": "^5.49.0",
"@typescript-eslint/parser": "^5.62.0", "@typescript-eslint/parser": "^5.49.0",
"eslint": "^8.57.1", "eslint": "^8.33.0",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.32.2",
"fs-extra": "^10.1.0", "fs-extra": "^10.0.0",
"lerna": "^7.4.2",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.1",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"webpack": "^5.101.3", "webpack": "^5.84.1",
"webpack-cli": "^5.1.4", "webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.2" "webpack-dev-server": "^4.15.0",
"lerna": "^7.4.2"
}, },
"engines": { "engines": {
"npm": ">=6.0.0", "npm": ">=6.0.0",
"node": ">=16.0.0" "node": ">=16.0.0 <=18"
} }
} }

View File

@@ -34,25 +34,37 @@
] ]
}, },
"dependencies": { "dependencies": {
"classnames": "^2.5.1" "classnames": "^2.3.1"
}, },
"peerDependencies": { "peerDependencies": {
"@noodl/platform": "file:../noodl-platform", "@noodl/platform": "file:../noodl-platform",
"react": "19.0.0", "react": "^17.0.2",
"react-dom": "19.0.0" "react-dom": "^17.0.2"
}, },
"devDependencies": { "devDependencies": {
"@storybook/addon-actions": "6.5.12",
"@storybook/addon-essentials": "6.5.9",
"@storybook/addon-interactions": "6.5.12",
"@storybook/addon-links": "6.5.9",
"@storybook/addon-measure": "6.5.9",
"@storybook/addons": "6.5.9",
"@storybook/builder-webpack5": "6.5.12",
"@storybook/manager-webpack5": "6.5.9",
"@storybook/node-logger": "6.5.9",
"@storybook/preset-create-react-app": "^4.1.2",
"@storybook/react": "6.5.9",
"@storybook/testing-library": "^0.0.13",
"@storybook/theming": "6.5.9",
"@types/jest": "^27.5.2", "@types/jest": "^27.5.2",
"@types/node": "^16.11.42", "@types/node": "^16.11.42",
"@types/react": "19.0.0", "@types/react": "^17.0.3",
"@types/react-dom": "19.0.0", "@types/react-dom": "^18.0.0",
"babel-plugin-named-exports-order": "^0.0.2", "babel-plugin-named-exports-order": "^0.0.2",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"sass": "^1.90.0", "sass": "^1.53.0",
"storybook": "^9.1.3", "typescript": "^4.7.4",
"ts-loader": "^9.5.4", "web-vitals": "^3.0.3",
"typescript": "^4.9.5", "webpack": "^5.74.0",
"web-vitals": "^3.5.2", "ts-loader": "^9.3.1"
"webpack": "^5.101.3"
} }
} }

View File

@@ -58,81 +58,81 @@
] ]
}, },
"dependencies": { "dependencies": {
"@electron/remote": "^2.1.3", "@electron/remote": "^2.1.2",
"@jaames/iro": "^5.5.2", "@jaames/iro": "^5.5.2",
"@microlink/react-json-view": "^1.27.0",
"@microsoft/fetch-event-source": "^2.0.1", "@microsoft/fetch-event-source": "^2.0.1",
"@noodl/git": "file:../noodl-git", "@noodl/git": "file:../noodl-git",
"@noodl/noodl-parse-dashboard": "file:../noodl-parse-dashboard", "@noodl/noodl-parse-dashboard": "file:../noodl-parse-dashboard",
"@noodl/platform": "file:../noodl-platform", "@noodl/platform": "file:../noodl-platform",
"@noodl/platform-electron": "file:../noodl-platform-electron", "@noodl/platform-electron": "file:../noodl-platform-electron",
"about-window": "^1.15.2", "about-window": "^1.15.2",
"algoliasearch": "^5.35.0", "algoliasearch": "^4.14.2",
"archiver": "^5.3.2", "archiver": "^5.3.0",
"async": "^3.2.6", "async": "^3.2.4",
"classnames": "^2.5.1", "classnames": "^2.3.2",
"diff3": "0.0.4", "diff3": "0.0.4",
"electron-store": "^8.2.0", "electron-store": "^8.1.0",
"electron-updater": "^6.6.2", "electron-updater": "^6.1.7",
"express": "^4.21.2", "express": "^4.17.3",
"highlight.js": "^11.11.1", "highlight.js": "^11.5.1",
"isbinaryfile": "^5.0.4", "isbinaryfile": "^5.0.0",
"md5": "^2.3.0", "md5": "^2.3.0",
"md5-file": "^5.0.0", "md5-file": "^5.0.0",
"mixpanel-browser": "^2.69.1", "mixpanel-browser": "^2.45.0",
"mkdirp": "0.5.1", "mkdirp": "0.5.1",
"mkdirp-sync": "0.0.2", "mkdirp-sync": "0.0.2",
"monaco-editor": "^0.34.1", "monaco-editor": "^0.34.0",
"react": "19.0.0", "react": "^17.0.2",
"react-dom": "19.0.0", "react-dom": "^17.0.0",
"react-hot-toast": "^2.6.0", "react-hot-toast": "^2.4.0",
"react-instantsearch": "^7.16.2", "react-instantsearch-hooks-web": "^6.38.0",
"react-rnd": "^10.5.2", "react-json-view": "^1.21.3",
"react-rnd": "^10.3.7",
"remarkable": "^2.0.1", "remarkable": "^2.0.1",
"s3": "github:noodlapp/node-s3-client", "s3": "git+https://github.com/noodlapp/node-s3-client.git",
"string.prototype.matchall": "^4.0.12", "string.prototype.matchall": "^4.0.7",
"underscore": "^1.13.7", "underscore": "^1.13.6",
"webpack": "^5.101.3", "webpack": "^5.74.0",
"websocket-stream": "^5.5.2", "websocket-stream": "^5.5.2",
"ws": "^8.18.3" "ws": "^8.9.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.28.3", "@babel/core": "^7.19.1",
"@babel/preset-react": "^7.27.1", "@babel/preset-react": "^7.18.6",
"@svgr/webpack": "^6.5.1", "@svgr/webpack": "^6.4.0",
"@types/checksum": "^0.1.35", "@types/checksum": "^0.1.33",
"@types/jasmine": "^4.6.5", "@types/jasmine": "^4.3.0",
"@types/jquery": "^3.5.33", "@types/jquery": "^3.5.14",
"@types/react": "^19.0.00", "@types/react": "^17.0.50",
"@types/react-dom": "^19.0.0", "@types/react-dom": "^18.0.0",
"@types/remarkable": "^2.0.8", "@types/remarkable": "^2.0.3",
"@types/rimraf": "^3.0.2", "@types/rimraf": "^3.0.2",
"@types/split2": "^3.2.1", "@types/split2": "^3.2.1",
"@types/string.prototype.matchall": "^4.0.4", "@types/string.prototype.matchall": "^4.0.1",
"@types/underscore": "^1.13.0", "@types/underscore": "^1.11.4",
"@types/webpack-env": "^1.18.8", "@types/webpack-env": "^1.18.0",
"babel-loader": "^8.4.1", "babel-loader": "^8.2.4",
"concurrently": "^7.6.0", "concurrently": "^7.4.0",
"css-loader": "^6.11.0", "css-loader": "^6.7.1",
"electron": "31.3.1", "electron": "31.3.1",
"electron-builder": "^24.13.3", "electron-builder": "^24.9.1",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"html-loader": "^3.1.2", "html-loader": "^3.1.0",
"monaco-editor-webpack-plugin": "^7.1.0", "monaco-editor-webpack-plugin": "^7.0.1",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"sass": "^1.90.0", "sass": "^1.55.0",
"sass-loader": "^12.6.0", "sass-loader": "^12.6.0",
"stringify": "^5.2.0", "stringify": "^5.2.0",
"style-loader": "^3.3.4", "style-loader": "^3.3.1",
"ts-loader": "^9.5.4", "ts-loader": "^9.4.1",
"ts-node": "^10.9.2", "ts-node": "^10.7.0",
"typescript": "^4.9.5", "typescript": "^4.8.3",
"url-loader": "^4.1.1", "url-loader": "^4.1.1",
"webpack": "^5.101.3", "webpack": "^5.74.0",
"webpack-cli": "^4.10.0", "webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.15.2", "webpack-dev-server": "^4.11.1",
"webpack-merge": "^5.10.0" "webpack-merge": "^5.8.0"
}, },
"engines": { "engines": {
"npm": ">=6.0.0", "npm": ">=6.0.0",
@@ -141,4 +141,4 @@
"optionalDependencies": { "optionalDependencies": {
"dmg-license": "^1.0.11" "dmg-license": "^1.0.11"
} }
} }

View File

@@ -1,7 +1,7 @@
import * as remote from '@electron/remote'; import * as remote from '@electron/remote';
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import React from 'react'; import React from 'react';
import { createRoot } from 'react-dom/client'; import ReactDOM from 'react-dom';
import './process-setup'; import './process-setup';
@@ -83,5 +83,5 @@ window.addEventListener('DOMContentLoaded', () => {
// Create the main element // Create the main element
const rootElement = document.getElementById('root'); const rootElement = document.getElementById('root');
createRoot(rootElement).render(React.createElement(Router, { uri: remote.process.env.noodlURI })); ReactDOM.render(React.createElement(Router, { uri: remote.process.env.noodlURI }), rootElement);
}); });

View File

@@ -3,7 +3,7 @@ import { useEffect, useRef } from 'react';
type IntervalCallback = () => Promise<void>; type IntervalCallback = () => Promise<void>;
export function useInterval(callback: IntervalCallback, delay: number) { export function useInterval(callback: IntervalCallback, delay: number) {
const savedCallback = useRef<IntervalCallback>(callback); const savedCallback = useRef<IntervalCallback>();
// Remember the latest callback. // Remember the latest callback.
useEffect(() => { useEffect(() => {

View File

@@ -1,6 +1,6 @@
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import React from 'react'; import React from 'react';
import { createRoot } from 'react-dom/client'; import ReactDOM from 'react-dom';
import { EventDispatcher } from '../../shared/utils/EventDispatcher'; import { EventDispatcher } from '../../shared/utils/EventDispatcher';
import LessonTemplatesModel from './models/lessontemplatesmodel'; import LessonTemplatesModel from './models/lessontemplatesmodel';
@@ -24,11 +24,11 @@ function createToastLayer() {
toastLayer.classList.add('toast-layer'); toastLayer.classList.add('toast-layer');
$('body').append(toastLayer); $('body').append(toastLayer);
createRoot(toastLayer).render(React.createElement(ToastLayerContainer)); ReactDOM.render(React.createElement(ToastLayerContainer), toastLayer);
if (import.meta.webpackHot) { if (import.meta.webpackHot) {
import.meta.webpackHot.accept('./views/ToastLayer', () => { import.meta.webpackHot.accept('./views/ToastLayer', () => {
createRoot(toastLayer).render(React.createElement(ToastLayerContainer)); ReactDOM.render(React.createElement(ToastLayerContainer), toastLayer);
}); });
} }
} }
@@ -47,11 +47,11 @@ function createDialogLayer() {
dialogLayer.classList.add('dialog-layer'); dialogLayer.classList.add('dialog-layer');
$('body').append(dialogLayer); $('body').append(dialogLayer);
createRoot(dialogLayer).render(React.createElement(DialogLayerContainer)); ReactDOM.render(React.createElement(DialogLayerContainer), dialogLayer);
if (import.meta.webpackHot) { if (import.meta.webpackHot) {
import.meta.webpackHot.accept('./views/DialogLayer', () => { import.meta.webpackHot.accept('./views/DialogLayer', () => {
createRoot(dialogLayer).render(React.createElement(DialogLayerContainer)); ReactDOM.render(React.createElement(DialogLayerContainer), dialogLayer);
}); });
} }
} }

View File

@@ -51,7 +51,7 @@ export default function Clippy() {
const firstInputRef = useRef(null); const firstInputRef = useRef(null);
const secondInputRef = useRef(null); const secondInputRef = useRef(null);
const secondTextAreaRef = useRef(null); const secondTextAreaRef = useRef(null);
const ref = useRef<HTMLDivElement>(undefined); const ref = useRef<HTMLDivElement>();
const [hasApiKey, setHasApiKey] = useState(false); const [hasApiKey, setHasApiKey] = useState(false);
const aiAssistantModel = useModernModel(AiAssistantModel.instance); const aiAssistantModel = useModernModel(AiAssistantModel.instance);
const nodeGraphContext = useNodeGraphContext(); const nodeGraphContext = useNodeGraphContext();

View File

@@ -1,6 +1,6 @@
import algoliasearch from 'algoliasearch/lite'; import algoliasearch from 'algoliasearch/lite';
import React, { useRef, useState } from 'react'; import React, { useRef, useState } from 'react';
import { InstantSearch, Hits, Highlight, useSearchBox, Configure } from 'react-instantsearch'; import { InstantSearch, Hits, Highlight, useSearchBox, Configure } from 'react-instantsearch-hooks-web';
import { platform } from '@noodl/platform'; import { platform } from '@noodl/platform';
import { IconName, IconSize } from '@noodl-core-ui/components/common/Icon'; import { IconName, IconSize } from '@noodl-core-ui/components/common/Icon';

View File

@@ -1,6 +1,6 @@
import { getCurrentWindow, screen } from '@electron/remote'; import { getCurrentWindow, screen } from '@electron/remote';
import React from 'react'; import React from 'react';
import { createRoot } from 'react-dom/client'; import ReactDOM from 'react-dom';
import { DialogRenderDirection } from '@noodl-core-ui/components/layout/BaseDialog'; import { DialogRenderDirection } from '@noodl-core-ui/components/layout/BaseDialog';
import { MenuDialog, MenuDialogItem, MenuDialogWidth } from '@noodl-core-ui/components/popups/MenuDialog'; import { MenuDialog, MenuDialogItem, MenuDialogWidth } from '@noodl-core-ui/components/popups/MenuDialog';
@@ -23,7 +23,6 @@ export function showContextMenuInPopup({
const container = document.createElement('div'); const container = document.createElement('div');
const screenPoint = screen.getCursorScreenPoint(); const screenPoint = screen.getCursorScreenPoint();
const [winX, winY] = getCurrentWindow().getPosition(); const [winX, winY] = getCurrentWindow().getPosition();
const root = createRoot(container)
const popout = PopupLayer.instance.showPopout({ const popout = PopupLayer.instance.showPopout({
content: { el: $(container) }, content: { el: $(container) },
@@ -34,11 +33,11 @@ export function showContextMenuInPopup({
}, },
position: 'top', position: 'top',
onClose: () => { onClose: () => {
root.unmount(); ReactDOM.unmountComponentAtNode(container);
} }
}); });
root.render( ReactDOM.render(
<MenuDialog <MenuDialog
title={title} title={title}
width={width || MenuDialogWidth.Large} width={width || MenuDialogWidth.Large}
@@ -49,5 +48,7 @@ export function showContextMenuInPopup({
PopupLayer.instance.hidePopout(popout); PopupLayer.instance.hidePopout(popout);
}} }}
items={items} items={items}
/>); />,
container
);
} }

View File

@@ -1,6 +1,6 @@
import _ from 'underscore'; import _ from 'underscore';
import React from 'react'; import React from 'react';
import { createRoot, Root } from 'react-dom/client'; import ReactDOM from 'react-dom';
import { Comment, CommentsModel } from '@noodl-models/commentsmodel'; import { Comment, CommentsModel } from '@noodl-models/commentsmodel';
import KeyboardHandler from '@noodl-utils/keyboardhandler'; import KeyboardHandler from '@noodl-utils/keyboardhandler';
@@ -36,8 +36,6 @@ export default class CommentLayer {
backgroundDiv: HTMLDivElement; backgroundDiv: HTMLDivElement;
activeCommentId: string; activeCommentId: string;
foregroundDiv: HTMLDivElement; foregroundDiv: HTMLDivElement;
backgroundRoot: Root;
foregroundRoot: Root;
constructor(nodegraphEditor) { constructor(nodegraphEditor) {
this.nodegraphEditor = nodegraphEditor; this.nodegraphEditor = nodegraphEditor;
@@ -142,16 +140,14 @@ export default class CommentLayer {
return; return;
} }
this.backgroundRoot = createRoot(this.backgroundDiv); ReactDOM.render(React.createElement(CommentLayerView.Background, this.props), this.backgroundDiv);
this.backgroundRoot.render(React.createElement(CommentLayerView.Background, this.props)); ReactDOM.render(React.createElement(CommentLayerView.Foreground, this.props), this.foregroundDiv);
this.foregroundRoot = createRoot(this.foregroundDiv);
this.foregroundRoot.render(React.createElement(CommentLayerView.Foreground, this.props));
} }
renderTo(backgroundDiv, foregroundDiv) { renderTo(backgroundDiv, foregroundDiv) {
if (this.backgroundDiv) { if (this.backgroundDiv) {
this.backgroundRoot.unmount(); ReactDOM.unmountComponentAtNode(this.backgroundDiv);
this.foregroundRoot.unmount(); ReactDOM.unmountComponentAtNode(this.foregroundDiv);
} }
this.backgroundDiv = backgroundDiv; this.backgroundDiv = backgroundDiv;
@@ -301,8 +297,8 @@ export default class CommentLayer {
} }
dispose() { dispose() {
this.foregroundRoot.unmount(); ReactDOM.unmountComponentAtNode(this.foregroundDiv);
this.backgroundRoot.unmount(); ReactDOM.unmountComponentAtNode(this.backgroundDiv);
//hack to remove all event listeners without having to keep track of them //hack to remove all event listeners without having to keep track of them
const newForegroundDiv = this.foregroundDiv.cloneNode(true); const newForegroundDiv = this.foregroundDiv.cloneNode(true);

View File

@@ -1,7 +1,7 @@
import { clipboard, ipcRenderer } from 'electron'; import { clipboard, ipcRenderer } from 'electron';
import _ from 'underscore'; import _ from 'underscore';
import React from 'react'; import React from 'react';
import { createRoot, Root } from 'react-dom/client'; import ReactDOM from 'react-dom';
import { NodeGraphColors } from '@noodl-constants/NodeGraphColors'; import { NodeGraphColors } from '@noodl-constants/NodeGraphColors';
import { AiAssistantEvent, AiAssistantModel } from '@noodl-models/AiAssistant/AiAssistantModel'; import { AiAssistantEvent, AiAssistantModel } from '@noodl-models/AiAssistant/AiAssistantModel';
@@ -227,8 +227,6 @@ export class NodeGraphEditor extends View {
nodesIdsAnimating: string[]; nodesIdsAnimating: string[];
isPlayingNodeAnimations: boolean; isPlayingNodeAnimations: boolean;
toolbarRoots: Root[];
constructor(args) { constructor(args) {
super(); super();
@@ -1420,8 +1418,8 @@ export class NodeGraphEditor extends View {
} }
updateTitle() { updateTitle() {
const rootElem = this.el[0].querySelector('.nodegraph-component-trail-root'); const root = this.el[0].querySelector('.nodegraph-component-trail-root');
const root = createRoot(rootElem);
if (this.activeComponent) { if (this.activeComponent) {
const fullName = this.activeComponent.fullName; const fullName = this.activeComponent.fullName;
const nameParts = fullName.split('/'); const nameParts = fullName.split('/');
@@ -1466,9 +1464,9 @@ export class NodeGraphEditor extends View {
canNavigateForward: this.navigationHistory.canNavigateForward canNavigateForward: this.navigationHistory.canNavigateForward
}; };
root.render(React.createElement(NodeGraphComponentTrail, props)); ReactDOM.render(React.createElement(NodeGraphComponentTrail, props), root);
} else { } else {
root.unmount(); ReactDOM.unmountComponentAtNode(root);
} }
} }
@@ -1763,10 +1761,10 @@ export class NodeGraphEditor extends View {
// @ts-expect-error // @ts-expect-error
toProps.sourcePort = fromPort; toProps.sourcePort = fromPort;
toProps.disabled = false; toProps.disabled = false;
createRoot(toDiv).render(React.createElement(ConnectionPopup, toProps)); ReactDOM.render(React.createElement(ConnectionPopup, toProps), toDiv);
fromProps.disabled = true; fromProps.disabled = true;
createRoot(fromDiv).render(React.createElement(ConnectionPopup, fromProps)); ReactDOM.render(React.createElement(ConnectionPopup, fromProps), fromDiv);
fromNode.borderHighlighted = false; fromNode.borderHighlighted = false;
toNode.borderHighlighted = true; toNode.borderHighlighted = true;
@@ -1774,8 +1772,7 @@ export class NodeGraphEditor extends View {
} }
}; };
const fromDiv = document.createElement('div'); const fromDiv = document.createElement('div');
const root = createRoot(fromDiv); ReactDOM.render(React.createElement(ConnectionPopup, fromProps), fromDiv);
root.render(React.createElement(ConnectionPopup, fromProps));
const fromPosition = toNode.global.x > fromNodeXPos ? 'left' : 'right'; const fromPosition = toNode.global.x > fromNodeXPos ? 'left' : 'right';
@@ -1793,7 +1790,7 @@ export class NodeGraphEditor extends View {
y: (fromNode.global.y + panAndScale.y) * panAndScale.scale + tl[1] + 20 * panAndScale.scale y: (fromNode.global.y + panAndScale.y) * panAndScale.scale + tl[1] + 20 * panAndScale.scale
}, },
onClose: () => { onClose: () => {
root.unmount(); ReactDOM.unmountComponentAtNode(fromDiv);
ipcRenderer.send('viewer-show'); ipcRenderer.send('viewer-show');
} }
}); });
@@ -1827,10 +1824,10 @@ export class NodeGraphEditor extends View {
// @ts-expect-error // @ts-expect-error
toProps.sourcePort = undefined; toProps.sourcePort = undefined;
toProps.disabled = true; toProps.disabled = true;
createRoot(toDiv).render(React.createElement(ConnectionPopup, toProps)); ReactDOM.render(React.createElement(ConnectionPopup, toProps), toDiv);
fromProps.disabled = false; fromProps.disabled = false;
createRoot(fromDiv).render(React.createElement(ConnectionPopup, fromProps)); ReactDOM.render(React.createElement(ConnectionPopup, fromProps), fromDiv);
fromNode.borderHighlighted = true; fromNode.borderHighlighted = true;
toNode.borderHighlighted = false; toNode.borderHighlighted = false;
@@ -1839,7 +1836,7 @@ export class NodeGraphEditor extends View {
} }
}; };
const toDiv = document.createElement('div'); const toDiv = document.createElement('div');
createRoot(toDiv).render(React.createElement(ConnectionPopup, toProps)); ReactDOM.render(React.createElement(ConnectionPopup, toProps), toDiv);
const toPosition = fromNodeXPos >= toNode.global.x ? 'left' : 'right'; const toPosition = fromNodeXPos >= toNode.global.x ? 'left' : 'right';
const toPopout = PopupLayer.instance.showPopout({ const toPopout = PopupLayer.instance.showPopout({
@@ -1854,7 +1851,7 @@ export class NodeGraphEditor extends View {
y: (toNode.global.y + panAndScale.y) * panAndScale.scale + tl[1] + 20 * panAndScale.scale y: (toNode.global.y + panAndScale.y) * panAndScale.scale + tl[1] + 20 * panAndScale.scale
}, },
onClose: () => { onClose: () => {
root.unmount(); ReactDOM.unmountComponentAtNode(toDiv);
this.clearSelection(); this.clearSelection();
this.repaint(); this.repaint();
} }
@@ -2206,23 +2203,20 @@ export class NodeGraphEditor extends View {
div.style.position = 'absolute'; div.style.position = 'absolute';
div.style.left = pos.x + 'px'; div.style.left = pos.x + 'px';
div.style.top = pos.y + 'px'; div.style.top = pos.y + 'px';
const root = createRoot(div);
this.toolbarRoots.push(root); ReactDOM.render(
root.render(
React.createElement(PopupToolbar, { React.createElement(PopupToolbar, {
menuItems, menuItems,
contextMenuItems: this.getContextMenuActions() contextMenuItems: this.getContextMenuActions()
} as PopupToolbarProps) } as PopupToolbarProps),
div
); );
} }
hideNodeToolbar() { hideNodeToolbar() {
for (const root of this.toolbarRoots) {
root.unmount();
}
this.toolbarRoots = [];
const toolbars = this.domElementContainer.querySelectorAll('.nodegraph-node-toolbar'); const toolbars = this.domElementContainer.querySelectorAll('.nodegraph-node-toolbar');
for (const toolbar of toolbars) { for (const toolbar of toolbars) {
ReactDOM.unmountComponentAtNode(toolbar);
this.domElementContainer.removeChild(toolbar); this.domElementContainer.removeChild(toolbar);
} }
} }

View File

@@ -1,6 +1,6 @@
import classNames from 'classnames'; import classNames from 'classnames';
import React from 'react'; import React from 'react';
import ReactJson from '@microlink/react-json-view'; import ReactJson from 'react-json-view';
import { ProjectModel } from '@noodl-models/projectmodel'; import { ProjectModel } from '@noodl-models/projectmodel';

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { createRoot } from 'react-dom/client'; import ReactDOM from 'react-dom';
import { Git } from '@noodl/git'; import { Git } from '@noodl/git';
import { platform } from '@noodl/platform'; import { platform } from '@noodl/platform';
@@ -126,8 +126,8 @@ function BaseVersionControlPanel() {
function openGitSettingsPopout() { function openGitSettingsPopout() {
const popoutDiv = document.createElement('div'); const popoutDiv = document.createElement('div');
const root = createRoot(popoutDiv);
root.render(React.createElement(GitProviderPopout, { git })); ReactDOM.render(React.createElement(GitProviderPopout, { git }), popoutDiv);
//the timeout is needed to solve a bug when the popout us opened from the git status button //the timeout is needed to solve a bug when the popout us opened from the git status button
//it causes timing issues between native events and react where the popout is instantly closed //it causes timing issues between native events and react where the popout is instantly closed
@@ -138,7 +138,7 @@ function BaseVersionControlPanel() {
position: 'right', position: 'right',
disableDynamicPositioning: true, disableDynamicPositioning: true,
onClose: () => { onClose: () => {
root.unmount(); ReactDOM.unmountComponentAtNode(popoutDiv);
fetch.fetchRemote(); fetch.fetchRemote();
} }
}); });

View File

@@ -1,7 +1,7 @@
import { useModernModel } from '@noodl-hooks/useModel'; import { useModernModel } from '@noodl-hooks/useModel';
import { OpenAiStore } from '@noodl-store/AiAssistantStore'; import { OpenAiStore } from '@noodl-store/AiAssistantStore';
import React, { useEffect, useMemo, useRef, useState } from 'react'; import React, { useEffect, useMemo, useRef, useState } from 'react';
import { createRoot } from 'react-dom/client'; import ReactDOM from 'react-dom';
import { AiAssistantModel } from '@noodl-models/AiAssistant/AiAssistantModel'; import { AiAssistantModel } from '@noodl-models/AiAssistant/AiAssistantModel';
import { AiCopilotContext } from '@noodl-models/AiAssistant/AiCopilotContext'; import { AiCopilotContext } from '@noodl-models/AiAssistant/AiCopilotContext';
@@ -332,8 +332,7 @@ function AiMessageFunctionNodeAffix({ context, onUpdated }: AiMessageFunctionNod
}; };
const popoutDiv = document.createElement('div'); const popoutDiv = document.createElement('div');
const root = createRoot(popoutDiv); ReactDOM.render(React.createElement(CodeEditor, props), popoutDiv);
root.render(React.createElement(CodeEditor, props));
const popout = PopupLayer.instance.showPopout({ const popout = PopupLayer.instance.showPopout({
content: { el: [popoutDiv] }, content: { el: [popoutDiv] },

View File

@@ -1,12 +1,11 @@
import { ipcRenderer } from 'electron';
import React from 'react'; import React from 'react';
import { createRoot } from 'react-dom/client'; import ReactDOM from 'react-dom';
import { ipcRenderer } from 'electron';
import { LocalStorageKey } from '@noodl-constants/LocalStorageKey'; import { LocalStorageKey } from '@noodl-constants/LocalStorageKey';
import getDocsEndpoint from '@noodl-utils/getDocsEndpoint'; import getDocsEndpoint from '@noodl-utils/getDocsEndpoint';
import { NewsModal } from './views/NewsModal';
import PopupLayer from './views/popuplayer'; import PopupLayer from './views/popuplayer';
import { NewsModal } from './views/NewsModal';
/** /**
* Display latest whats-new-post if the user hasn't seen one after it was last published * Display latest whats-new-post if the user hasn't seen one after it was last published
@@ -35,11 +34,12 @@ export async function whatsnewRender() {
modalContainer.classList.add('popup-layer-react-modal'); modalContainer.classList.add('popup-layer-react-modal');
PopupLayer.instance.el.find('.popup-layer-modal').before(modalContainer); PopupLayer.instance.el.find('.popup-layer-modal').before(modalContainer);
createRoot(modalContainer).render( ReactDOM.render(
React.createElement(NewsModal, { React.createElement(NewsModal, {
content: latestChangelogPost.content_html, content: latestChangelogPost.content_html,
onFinished: () => ipcRenderer.send('viewer-show') onFinished: () => ipcRenderer.send('viewer-show')
}) }),
modalContainer
); );
localStorage.setItem(LocalStorageKey.lastSeenChangelogDate, latestChangelogDate.toString()); localStorage.setItem(LocalStorageKey.lastSeenChangelogDate, latestChangelogDate.toString());

View File

@@ -7,8 +7,8 @@
"homepage": "https://noodl.net", "homepage": "https://noodl.net",
"dependencies": { "dependencies": {
"desktop-trampoline": "https://github.com/desktop/desktop-trampoline/archive/refs/tags/v0.9.8.tar.gz", "desktop-trampoline": "https://github.com/desktop/desktop-trampoline/archive/refs/tags/v0.9.8.tar.gz",
"dugite": "^1.106.0",
"double-ended-queue": "^2.1.0-0", "double-ended-queue": "^2.1.0-0",
"dugite": "^1.110.0",
"split2": "^4.1.0" "split2": "^4.1.0"
} }
} }

View File

@@ -5,7 +5,7 @@
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"connect-flash": "0.1.1", "connect-flash": "0.1.1",
"cookie-session": "2.0.0", "cookie-session": "2.0.0",
"express": "^4.21.2", "express": "^4.18.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"otpauth": "^7.1.3", "otpauth": "^7.1.3",
"package-json": "7.0.0", "package-json": "7.0.0",
@@ -30,6 +30,6 @@
], ],
"main": "Parse-Dashboard/app.js", "main": "Parse-Dashboard/app.js",
"devDependencies": { "devDependencies": {
"keyv": "^4.5.4" "keyv": "^4.5.1"
} }
} }

View File

@@ -10,7 +10,7 @@
"@noodl/platform-node": "file:../noodl-platform-node" "@noodl/platform-node": "file:../noodl-platform-node"
}, },
"peerDependencies": { "peerDependencies": {
"@electron/remote": "^2.1.3", "@electron/remote": ">=2.0.8",
"electron": ">=20.1.0" "electron": ">=20.1.0"
} }
} }

View File

@@ -11,14 +11,14 @@
}, },
"dependencies": { "dependencies": {
"@noodl/platform": "file:../noodl-platform", "@noodl/platform": "file:../noodl-platform",
"fs-extra": "^10.1.0", "fs-extra": "^10.0.1",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"mkdirp-sync": "0.0.2", "mkdirp-sync": "0.0.2",
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.0.1", "@types/jest": "^29.0.1",
"jest": "^29.7.0", "ts-jest": "^29.0.0",
"ts-jest": "^29.4.1" "jest": "^29.0.3"
} }
} }

View File

@@ -14,9 +14,9 @@
"@noodl/runtime": "file:../noodl-runtime" "@noodl/runtime": "file:../noodl-runtime"
}, },
"devDependencies": { "devDependencies": {
"copy-webpack-plugin": "^4.6.0",
"generate-json-webpack-plugin": "^2.0.0", "generate-json-webpack-plugin": "^2.0.0",
"ts-loader": "^9.5.4", "ts-loader": "^9.3.1",
"typescript": "^4.9.5" "typescript": "^4.7.4",
"copy-webpack-plugin": "^4.6.0"
} }
} }

View File

@@ -8,42 +8,42 @@
"test": "jest" "test": "jest"
}, },
"dependencies": { "dependencies": {
"@better-scroll/core": "^2.5.1", "@better-scroll/core": "^2.0.0-beta.6",
"@better-scroll/mouse-wheel": "^2.5.1", "@better-scroll/mouse-wheel": "^2.0.0-beta.6",
"@better-scroll/nested-scroll": "^2.5.1", "@better-scroll/nested-scroll": "^2.4.2",
"@better-scroll/scroll-bar": "^2.5.1", "@better-scroll/scroll-bar": "^2.0.0-beta.6",
"@noodl/runtime": "file:../noodl-runtime", "@noodl/runtime": "file:../noodl-runtime",
"bezier-easing": "^1.1.1", "bezier-easing": "^1.1.1",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"core-js": "^3.45.1", "core-js": "^3.12.1",
"events": "^3.3.0", "events": "^3.3.0",
"lodash.difference": "^4.5.0", "lodash.difference": "^4.5.0",
"lodash.isequal": "^4.5.0", "lodash.isequal": "^4.5.0",
"react-draggable": "^4.5.0", "react-draggable": "^4.4.5",
"react-rnd": "^10.5.2", "react-rnd": "^10.3.7",
"stream-browserify": "^3.0.0", "stream-browserify": "^3.0.0",
"timers-browserify": "^2.0.12", "timers-browserify": "^2.0.12",
"webfontloader": "^1.6.28" "webfontloader": "^1.6.28"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.28.3", "@babel/core": "^7.14.0",
"@babel/plugin-proposal-object-rest-spread": "^7.20.7", "@babel/plugin-proposal-object-rest-spread": "^7.18.9",
"@babel/preset-env": "^7.28.3", "@babel/preset-env": "^7.14.1",
"@babel/preset-react": "^7.27.1", "@babel/preset-react": "^7.18.6",
"@types/jest": "^27.5.2", "@types/jest": "^27.5.1",
"babel-loader": "^8.4.1", "babel-loader": "^8.2.2",
"clean-webpack-plugin": "^1.0.1", "clean-webpack-plugin": "^1.0.0",
"copy-webpack-plugin": "^4.6.0", "copy-webpack-plugin": "^4.6.0",
"css-loader": "^5.0.0", "css-loader": "^5.0.0",
"jest": "^28.1.0", "jest": "^28.1.0",
"style-loader": "^2.0.0", "style-loader": "^2.0.0",
"ts-jest": "^28.0.3", "ts-jest": "^28.0.3",
"ts-loader": "^9.5.4", "ts-loader": "^9.4.3",
"typescript": "^5.1.3", "typescript": "^5.1.3",
"webpack": "^5.101.3", "webpack": "^5.74.0",
"webpack-bundle-analyzer": "^4.10.2", "webpack-bundle-analyzer": "^4.4.2",
"webpack-cli": "^4.10.0", "webpack-cli": "^4.10.0",
"webpack-dev-server": "^3.11.2", "webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.10.0" "webpack-merge": "^5.7.3"
} }
} }