hadinicknam commited on
Commit
528f558
·
1 Parent(s): 30a2a5d

Add Advanced Feature option (make it more clear)

Browse files
frontend/src/CustomNode.css CHANGED
@@ -33,7 +33,7 @@
33
  .custom-node-input-row {
34
  display: flex;
35
  flex-direction: column;
36
- margin-bottom: 10px;
37
  }
38
 
39
  .custom-node-input-row:last-child {
@@ -42,7 +42,7 @@
42
 
43
  .custom-node-input-row label {
44
  font-size: 12px;
45
- margin-bottom: 4px;
46
  font-weight: bold;
47
  color: #555;
48
  }
@@ -52,7 +52,7 @@
52
  .custom-node-input-row textarea,
53
  .custom-node-input-row select {
54
  width: 100%;
55
- padding: 6px;
56
  border: 1px solid #ccc;
57
  border-radius: 4px;
58
  box-sizing: border-box;
@@ -76,3 +76,55 @@
76
  margin-bottom: 0;
77
  font-weight: normal;
78
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  .custom-node-input-row {
34
  display: flex;
35
  flex-direction: column;
36
+ margin-bottom: 12px;
37
  }
38
 
39
  .custom-node-input-row:last-child {
 
42
 
43
  .custom-node-input-row label {
44
  font-size: 12px;
45
+ margin-bottom: 5px;
46
  font-weight: bold;
47
  color: #555;
48
  }
 
52
  .custom-node-input-row textarea,
53
  .custom-node-input-row select {
54
  width: 100%;
55
+ padding: 8px;
56
  border: 1px solid #ccc;
57
  border-radius: 4px;
58
  box-sizing: border-box;
 
76
  margin-bottom: 0;
77
  font-weight: normal;
78
  }
79
+
80
+ .file-input-wrapper {
81
+ display: flex;
82
+ align-items: center;
83
+ }
84
+
85
+ .file-input-wrapper input[type="file"] {
86
+ flex-grow: 1;
87
+ font-size: 11px;
88
+ }
89
+
90
+ .file-input-wrapper button {
91
+ padding: 6px 10px;
92
+ font-size: 12px;
93
+ background-color: #007bff;
94
+ color: white;
95
+ border: none;
96
+ border-radius: 4px;
97
+ cursor: pointer;
98
+ margin-left: 8px;
99
+ }
100
+
101
+ .file-input-wrapper button:hover {
102
+ background-color: #0056b3;
103
+ }
104
+
105
+ .advanced-settings {
106
+ margin-top: 15px;
107
+ border-top: 1px solid #eee;
108
+ padding-top: 10px;
109
+ }
110
+
111
+ .advanced-settings-toggle {
112
+ background: none;
113
+ border: none;
114
+ cursor: pointer;
115
+ font-size: 12px;
116
+ font-weight: bold;
117
+ color: #007bff;
118
+ padding: 0;
119
+ margin-bottom: 10px;
120
+ }
121
+
122
+ .advanced-settings-toggle:hover {
123
+ text-decoration: underline;
124
+ }
125
+
126
+ .advanced-settings-content {
127
+ padding: 10px;
128
+ background-color: #f0f0f0;
129
+ border-radius: 4px;
130
+ }
frontend/src/CustomNode.js CHANGED
@@ -1,7 +1,26 @@
1
- import React from 'react';
2
  import { Handle, Position } from 'reactflow';
3
  import './CustomNode.css';
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  const renderInput = (input) => {
6
  const { type, label, props = {} } = input;
7
  const id = `input-${input.id}`;
@@ -11,7 +30,7 @@ const renderInput = (input) => {
11
  return (
12
  <div key={id} className="custom-node-input-row">
13
  <label htmlFor={id}>{label}</label>
14
- <textarea id={id} rows={2} defaultValue={props.value || ''} />
15
  </div>
16
  );
17
  case 'number':
@@ -22,18 +41,8 @@ const renderInput = (input) => {
22
  </div>
23
  );
24
  case 'slider':
25
- return (
26
- <div key={id} className="custom-node-input-row">
27
- <label htmlFor={id}>{label} ({props.value || props.minimum})</label>
28
- <input
29
- id={id}
30
- type="range"
31
- min={props.minimum || 0}
32
- max={props.maximum || 100}
33
- defaultValue={props.value || props.minimum}
34
- />
35
- </div>
36
- );
37
  case 'checkbox':
38
  return (
39
  <div key={id} className="custom-node-input-row checkbox">
@@ -61,7 +70,10 @@ const renderInput = (input) => {
61
  return (
62
  <div key={id} className="custom-node-input-row">
63
  <label htmlFor={id}>{label} ({type})</label>
64
- <input id={id} type="file" />
 
 
 
65
  </div>
66
  );
67
  default:
@@ -75,6 +87,12 @@ const renderInput = (input) => {
75
  };
76
 
77
  const CustomNode = ({ data }) => {
 
 
 
 
 
 
78
  return (
79
  <div className="custom-node">
80
  <Handle type="target" position={Position.Top} />
@@ -83,7 +101,23 @@ const CustomNode = ({ data }) => {
83
  <p>/{data.apiName}</p>
84
  </div>
85
  <div className="custom-node-content">
86
- {data.inputs?.map(renderInput)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  </div>
88
  <Handle type="source" position={Position.Bottom} />
89
  </div>
 
1
+ import React, { useState } from 'react';
2
  import { Handle, Position } from 'reactflow';
3
  import './CustomNode.css';
4
 
5
+ // A dedicated component for the slider to manage its own state
6
+ const SliderInput = ({ id, label, props }) => {
7
+ const [value, setValue] = useState(props.value || props.minimum);
8
+
9
+ return (
10
+ <div className="custom-node-input-row">
11
+ <label htmlFor={id}>{label} ({value})</label>
12
+ <input
13
+ id={id}
14
+ type="range"
15
+ min={props.minimum || 0}
16
+ max={props.maximum || 100}
17
+ value={value}
18
+ onChange={(e) => setValue(e.target.value)}
19
+ />
20
+ </div>
21
+ );
22
+ };
23
+
24
  const renderInput = (input) => {
25
  const { type, label, props = {} } = input;
26
  const id = `input-${input.id}`;
 
30
  return (
31
  <div key={id} className="custom-node-input-row">
32
  <label htmlFor={id}>{label}</label>
33
+ <textarea id={id} rows={3} defaultValue={props.value || ''} />
34
  </div>
35
  );
36
  case 'number':
 
41
  </div>
42
  );
43
  case 'slider':
44
+ // Use the new stateful component for sliders
45
+ return <SliderInput key={id} id={id} label={label} props={props} />;
 
 
 
 
 
 
 
 
 
 
46
  case 'checkbox':
47
  return (
48
  <div key={id} className="custom-node-input-row checkbox">
 
70
  return (
71
  <div key={id} className="custom-node-input-row">
72
  <label htmlFor={id}>{label} ({type})</label>
73
+ <div className="file-input-wrapper">
74
+ <input id={id} type="file" />
75
+ <button>Upload</button>
76
+ </div>
77
  </div>
78
  );
79
  default:
 
87
  };
88
 
89
  const CustomNode = ({ data }) => {
90
+ const [isAdvancedVisible, setAdvancedVisible] = useState(false);
91
+
92
+ const primaryTypes = ['textbox', 'image', 'audio', 'video', 'file'];
93
+ const primaryInputs = data.inputs?.filter(input => primaryTypes.includes(input.type));
94
+ const advancedInputs = data.inputs?.filter(input => !primaryTypes.includes(input.type));
95
+
96
  return (
97
  <div className="custom-node">
98
  <Handle type="target" position={Position.Top} />
 
101
  <p>/{data.apiName}</p>
102
  </div>
103
  <div className="custom-node-content">
104
+ {primaryInputs?.map(renderInput)}
105
+
106
+ {advancedInputs && advancedInputs.length > 0 && (
107
+ <div className="advanced-settings">
108
+ <button
109
+ className="advanced-settings-toggle"
110
+ onClick={() => setAdvancedVisible(!isAdvancedVisible)}
111
+ >
112
+ {isAdvancedVisible ? '▼' : '►'} Advanced Settings
113
+ </button>
114
+ {isAdvancedVisible && (
115
+ <div className="advanced-settings-content">
116
+ {advancedInputs.map(renderInput)}
117
+ </div>
118
+ )}
119
+ </div>
120
+ )}
121
  </div>
122
  <Handle type="source" position={Position.Bottom} />
123
  </div>