mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Merge pull request #12894 from ToolJet/appbuilder/sprint-12
Appbuilder/sprint 12
This commit is contained in:
commit
cb7eb39334
47 changed files with 2208 additions and 689 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 280578f99c45224428f78ee16285b62f4c3631fd
|
Subproject commit 1b77a556709211daed8924821383db9dccc95eb5
|
||||||
|
|
@ -58,6 +58,7 @@
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"draft-js": "^0.11.7",
|
"draft-js": "^0.11.7",
|
||||||
"draft-js-export-html": "^1.4.1",
|
"draft-js-export-html": "^1.4.1",
|
||||||
|
"draft-js-import-html": "^1.4.1",
|
||||||
"driver.js": "^0.9.8",
|
"driver.js": "^0.9.8",
|
||||||
"emoji-mart": "^5.5.2",
|
"emoji-mart": "^5.5.2",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,7 @@ export const getAllChildComponents = (allComponents, parentId) => {
|
||||||
const childTabId = componentParentId.split('-').at(-1);
|
const childTabId = componentParentId.split('-').at(-1);
|
||||||
if (componentParentId === `${parentId}-${childTabId}`) {
|
if (componentParentId === `${parentId}-${childTabId}`) {
|
||||||
childComponent.isParentTabORCalendar = true;
|
childComponent.isParentTabORCalendar = true;
|
||||||
|
childComponent.events = useStore.getState().eventsSlice.getEventsByComponentsId(componentId);
|
||||||
childComponents.push(childComponent);
|
childComponents.push(childComponent);
|
||||||
// Recursively find children of the current child component
|
// Recursively find children of the current child component
|
||||||
const childrenOfChild = getAllChildComponents(allComponents, componentId);
|
const childrenOfChild = getAllChildComponents(allComponents, componentId);
|
||||||
|
|
@ -242,6 +243,7 @@ export const getAllChildComponents = (allComponents, parentId) => {
|
||||||
if (componentParentId === parentId) {
|
if (componentParentId === parentId) {
|
||||||
let childComponent = deepClone(allComponents[componentId]);
|
let childComponent = deepClone(allComponents[componentId]);
|
||||||
childComponent.id = componentId;
|
childComponent.id = componentId;
|
||||||
|
childComponent.events = useStore.getState().eventsSlice.getEventsByComponentsId(componentId);
|
||||||
childComponents.push(childComponent);
|
childComponents.push(childComponent);
|
||||||
|
|
||||||
// Recursively find children of the current child component
|
// Recursively find children of the current child component
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* eslint-disable import/no-unresolved */
|
||||||
|
import React from 'react';
|
||||||
|
import { openSearchPanel } from '@codemirror/search';
|
||||||
|
import './SearchBox.scss';
|
||||||
|
import { Button as ButtonComponent } from '@/components/ui/Button/Button.jsx';
|
||||||
|
|
||||||
|
export const CodeHinterBtns = ({ view, isPanelOpen, renderCopilot }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="d-flex tw-flex-col align-items-end tw-gap-[2.5px] w-100 position-absolute tw-pt-[4px] tw-pr-[4px]"
|
||||||
|
style={{ top: isPanelOpen ? '44px' : 0 }}
|
||||||
|
>
|
||||||
|
{!isPanelOpen && (
|
||||||
|
<ButtonComponent
|
||||||
|
iconOnly
|
||||||
|
trailingIcon="search01"
|
||||||
|
size="small"
|
||||||
|
variant="outline"
|
||||||
|
ariaLabel="Open search panel"
|
||||||
|
className="codehinter-search-btn"
|
||||||
|
onClick={() => openSearchPanel(view)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{renderCopilot && renderCopilot()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -20,10 +20,12 @@ import { PreviewBox } from './PreviewBox';
|
||||||
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
|
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
|
||||||
import useStore from '@/AppBuilder/_stores/store';
|
import useStore from '@/AppBuilder/_stores/store';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
import { syntaxTree } from '@codemirror/language';
|
||||||
import { search, searchKeymap, searchPanelOpen } from '@codemirror/search';
|
import { search, searchKeymap, searchPanelOpen } from '@codemirror/search';
|
||||||
import { handleSearchPanel, SearchBtn } from './SearchBox';
|
import { handleSearchPanel } from './SearchBox';
|
||||||
import { useQueryPanelKeyHooks } from './useQueryPanelKeyHooks';
|
import { useQueryPanelKeyHooks } from './useQueryPanelKeyHooks';
|
||||||
import { isInsideParent } from './utils';
|
import { isInsideParent } from './utils';
|
||||||
|
import { CodeHinterBtns } from './CodehinterOverlayTriggers';
|
||||||
|
|
||||||
const langSupport = Object.freeze({
|
const langSupport = Object.freeze({
|
||||||
javascript: javascript(),
|
javascript: javascript(),
|
||||||
|
|
@ -66,7 +68,7 @@ const MultiLineCodeEditor = (props) => {
|
||||||
|
|
||||||
const context = useContext(CodeHinterContext);
|
const context = useContext(CodeHinterContext);
|
||||||
|
|
||||||
const { suggestionList } = createReferencesLookup(context, true);
|
const { suggestionList: paramList } = createReferencesLookup(context, true);
|
||||||
|
|
||||||
const currentValueRef = useRef(initialValue);
|
const currentValueRef = useRef(initialValue);
|
||||||
|
|
||||||
|
|
@ -74,6 +76,7 @@ const MultiLineCodeEditor = (props) => {
|
||||||
|
|
||||||
const [editorView, setEditorView] = React.useState(null);
|
const [editorView, setEditorView] = React.useState(null);
|
||||||
|
|
||||||
|
const [isSearchPanelOpen, setIsSearchPanelOpen] = React.useState(false);
|
||||||
const { queryPanelKeybindings } = useQueryPanelKeyHooks(onChange, currentValueRef, 'multiline');
|
const { queryPanelKeybindings } = useQueryPanelKeyHooks(onChange, currentValueRef, 'multiline');
|
||||||
|
|
||||||
const handleOnBlur = () => {
|
const handleOnBlur = () => {
|
||||||
|
|
@ -146,8 +149,29 @@ const MultiLineCodeEditor = (props) => {
|
||||||
return suggestion.hint.includes(nearestSubstring);
|
return suggestion.hint.includes(nearestSubstring);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const localVariables = new Set();
|
||||||
|
|
||||||
|
// Traverse the syntax tree to extract variable declarations
|
||||||
|
syntaxTree(context.state).iterate({
|
||||||
|
enter: (node) => {
|
||||||
|
// JavaScript: Detect variable declarations (var, let, const)
|
||||||
|
if (node.name === 'VariableDefinition') {
|
||||||
|
const varName = context.state.sliceDoc(node.from, node.to);
|
||||||
|
if (varName && varName.startsWith(nearestSubstring)) localVariables.add(varName);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Convert Set to an array of completion suggestions
|
||||||
|
const localVariableSuggestions = [...localVariables].map((varName) => ({
|
||||||
|
hint: varName,
|
||||||
|
type: 'variable',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const suggestionList = paramList.filter((paramSuggestion) => paramSuggestion.hint.includes(nearestSubstring));
|
||||||
|
|
||||||
const suggestions = generateHints(
|
const suggestions = generateHints(
|
||||||
[...JSLangHints, ...autoSuggestionList, ...suggestionList],
|
[...localVariableSuggestions, ...JSLangHints, ...autoSuggestionList, ...suggestionList],
|
||||||
null,
|
null,
|
||||||
nearestSubstring
|
nearestSubstring
|
||||||
).map((hint) => {
|
).map((hint) => {
|
||||||
|
|
@ -204,6 +228,7 @@ const MultiLineCodeEditor = (props) => {
|
||||||
return {
|
return {
|
||||||
from: context.pos,
|
from: context.pos,
|
||||||
options: [...suggestions],
|
options: [...suggestions],
|
||||||
|
filter: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,7 +262,7 @@ const MultiLineCodeEditor = (props) => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const overRideFunction = React.useCallback((context) => autoCompleteExtensionConfig(context), []);
|
const overRideFunction = React.useCallback((context) => autoCompleteExtensionConfig(context), [paramList]);
|
||||||
const { handleTogglePopupExapand, isOpen, setIsOpen, forceUpdate } = portalProps;
|
const { handleTogglePopupExapand, isOpen, setIsOpen, forceUpdate } = portalProps;
|
||||||
let cyLabel = paramLabel ? paramLabel.toLowerCase().trim().replace(/\s+/g, '-') : props.cyLabel;
|
let cyLabel = paramLabel ? paramLabel.toLowerCase().trim().replace(/\s+/g, '-') : props.cyLabel;
|
||||||
|
|
||||||
|
|
@ -258,7 +283,7 @@ const MultiLineCodeEditor = (props) => {
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
>
|
>
|
||||||
<div className={`${className} ${darkMode && 'cm-codehinter-dark-themed'}`}>
|
<div className={`${className} ${darkMode && 'cm-codehinter-dark-themed'}`}>
|
||||||
<SearchBtn view={editorView} />
|
<CodeHinterBtns view={editorView} isPanelOpen={isSearchPanelOpen} renderCopilot={renderCopilot} />
|
||||||
<CodeHinter.PopupIcon
|
<CodeHinter.PopupIcon
|
||||||
callback={handleTogglePopupExapand}
|
callback={handleTogglePopupExapand}
|
||||||
icon="portal-open"
|
icon="portal-open"
|
||||||
|
|
@ -266,7 +291,6 @@ const MultiLineCodeEditor = (props) => {
|
||||||
isMultiEditor={true}
|
isMultiEditor={true}
|
||||||
isQueryManager={isInsideQueryPane}
|
isQueryManager={isInsideQueryPane}
|
||||||
/>
|
/>
|
||||||
{renderCopilot && renderCopilot()}
|
|
||||||
|
|
||||||
<CodeHinter.Portal
|
<CodeHinter.Portal
|
||||||
isCopilotEnabled={false}
|
isCopilotEnabled={false}
|
||||||
|
|
@ -326,12 +350,7 @@ const MultiLineCodeEditor = (props) => {
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
editable={editable} //for transformations in query manager
|
editable={editable} //for transformations in query manager
|
||||||
onCreateEditor={(view) => setEditorView(view)}
|
onCreateEditor={(view) => setEditorView(view)}
|
||||||
onUpdate={(view) => {
|
onUpdate={(view) => setIsSearchPanelOpen(searchPanelOpen(view.state))}
|
||||||
const icon = document.querySelector('.codehinter-search-btn');
|
|
||||||
if (searchPanelOpen(view.state)) {
|
|
||||||
icon.style.display = 'none';
|
|
||||||
} else icon.style.display = 'block';
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{showPreview && (
|
{showPreview && (
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import {
|
||||||
findPrevious,
|
findPrevious,
|
||||||
replaceNext,
|
replaceNext,
|
||||||
replaceAll,
|
replaceAll,
|
||||||
openSearchPanel,
|
|
||||||
} from '@codemirror/search';
|
} from '@codemirror/search';
|
||||||
import './SearchBox.scss';
|
import './SearchBox.scss';
|
||||||
import InputComponent from '@/components/ui/Input/Index.jsx';
|
import InputComponent from '@/components/ui/Input/Index.jsx';
|
||||||
|
|
@ -162,22 +161,3 @@ function SearchPanel({ view }) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SearchBtn = ({ view }) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="d-flex justify-content-end w-100 position-absolute tw-pt-[3px] tw-pr-[4px] codehinter-search-btn-wrapper"
|
|
||||||
style={{ top: 0 }}
|
|
||||||
>
|
|
||||||
<ButtonComponent
|
|
||||||
iconOnly
|
|
||||||
trailingIcon="search01"
|
|
||||||
size="small"
|
|
||||||
variant="outline"
|
|
||||||
ariaLabel="Open search panel"
|
|
||||||
className="codehinter-search-btn"
|
|
||||||
onClick={() => openSearchPanel(view)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,5 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-hinter-wrapper .codehinter-search-btn {
|
.code-hinter-wrapper .codehinter-search-btn {
|
||||||
display: block;
|
z-index: 1000;
|
||||||
padding-top: 1px;
|
|
||||||
z-index: 10000;
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
/* eslint-disable import/no-unresolved */
|
/* eslint-disable import/no-unresolved */
|
||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useEffect, useMemo, useRef, useState, useContext } from 'react';
|
||||||
import { PreviewBox } from './PreviewBox';
|
import { PreviewBox } from './PreviewBox';
|
||||||
import { ToolTip } from '@/Editor/Inspector/Elements/Components/ToolTip';
|
import { ToolTip } from '@/Editor/Inspector/Elements/Components/ToolTip';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { camelCase, isEmpty, noop, get } from 'lodash';
|
import { camelCase, isEmpty, noop, get } from 'lodash';
|
||||||
import CodeMirror from '@uiw/react-codemirror';
|
import CodeMirror from '@uiw/react-codemirror';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
import { autocompletion, completionKeymap, completionStatus, acceptCompletion } from '@codemirror/autocomplete';
|
import {
|
||||||
|
autocompletion,
|
||||||
|
completionKeymap,
|
||||||
|
completionStatus,
|
||||||
|
acceptCompletion,
|
||||||
|
startCompletion,
|
||||||
|
} from '@codemirror/autocomplete';
|
||||||
import { defaultKeymap } from '@codemirror/commands';
|
import { defaultKeymap } from '@codemirror/commands';
|
||||||
import { keymap } from '@codemirror/view';
|
import { keymap } from '@codemirror/view';
|
||||||
import FxButton from '../CodeBuilder/Elements/FxButton';
|
import FxButton from '../CodeBuilder/Elements/FxButton';
|
||||||
|
|
@ -22,6 +28,8 @@ import CodeHinter from './CodeHinter';
|
||||||
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
|
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
|
||||||
import useStore from '@/AppBuilder/_stores/store';
|
import useStore from '@/AppBuilder/_stores/store';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
import { CodeHinterContext } from '../CodeBuilder/CodeHinterContext';
|
||||||
|
import { createReferencesLookup } from '@/_stores/utils';
|
||||||
import { useQueryPanelKeyHooks } from './useQueryPanelKeyHooks';
|
import { useQueryPanelKeyHooks } from './useQueryPanelKeyHooks';
|
||||||
|
|
||||||
const SingleLineCodeEditor = ({ componentName, fieldMeta = {}, componentId, ...restProps }) => {
|
const SingleLineCodeEditor = ({ componentName, fieldMeta = {}, componentId, ...restProps }) => {
|
||||||
|
|
@ -73,6 +81,7 @@ const SingleLineCodeEditor = ({ componentName, fieldMeta = {}, componentId, ...r
|
||||||
if (typeof initialValue === 'string' && (initialValue?.includes('components') || initialValue?.includes('queries'))) {
|
if (typeof initialValue === 'string' && (initialValue?.includes('components') || initialValue?.includes('queries'))) {
|
||||||
newInitialValue = replaceIdsWithName(initialValue);
|
newInitialValue = replaceIdsWithName(initialValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Re render the component when the componentName changes as the initialValue is not updated
|
//! Re render the component when the componentName changes as the initialValue is not updated
|
||||||
|
|
||||||
// const { variablesExposedForPreview } = useContext(EditorContext) || {};
|
// const { variablesExposedForPreview } = useContext(EditorContext) || {};
|
||||||
|
|
@ -199,9 +208,14 @@ const EditorInput = ({
|
||||||
wrapperRef,
|
wrapperRef,
|
||||||
showSuggestions,
|
showSuggestions,
|
||||||
}) => {
|
}) => {
|
||||||
const getServerSideGlobalSuggestions = useStore((state) => state.getServerSideGlobalSuggestions, shallow);
|
const codeHinterContext = useContext(CodeHinterContext);
|
||||||
|
const { suggestionList: paramHints } = createReferencesLookup(codeHinterContext, true);
|
||||||
|
|
||||||
const getSuggestions = useStore((state) => state.getSuggestions, shallow);
|
const getSuggestions = useStore((state) => state.getSuggestions, shallow);
|
||||||
|
const [codeMirrorView, setCodeMirrorView] = useState(undefined);
|
||||||
|
|
||||||
|
const getServerSideGlobalSuggestions = useStore((state) => state.getServerSideGlobalSuggestions, shallow);
|
||||||
|
|
||||||
const { queryPanelKeybindings } = useQueryPanelKeyHooks(onBlurUpdate, currentValue, 'singleline');
|
const { queryPanelKeybindings } = useQueryPanelKeyHooks(onBlurUpdate, currentValue, 'singleline');
|
||||||
|
|
||||||
const isInsideQueryManager = useMemo(
|
const isInsideQueryManager = useMemo(
|
||||||
|
|
@ -209,16 +223,16 @@ const EditorInput = ({
|
||||||
[wrapperRef.current]
|
[wrapperRef.current]
|
||||||
);
|
);
|
||||||
function autoCompleteExtensionConfig(context) {
|
function autoCompleteExtensionConfig(context) {
|
||||||
const hints = getSuggestions();
|
const hintsWithoutParamHints = getSuggestions();
|
||||||
const serverHints = getServerSideGlobalSuggestions(isInsideQueryManager);
|
const serverHints = getServerSideGlobalSuggestions(isInsideQueryManager);
|
||||||
|
|
||||||
const allHints = {
|
|
||||||
...hints,
|
|
||||||
appHints: [...hints.appHints, ...serverHints],
|
|
||||||
};
|
|
||||||
|
|
||||||
let word = context.matchBefore(/\w*/);
|
let word = context.matchBefore(/\w*/);
|
||||||
|
|
||||||
|
const hints = {
|
||||||
|
...hintsWithoutParamHints,
|
||||||
|
appHints: [...hintsWithoutParamHints.appHints, ...serverHints, ...paramHints],
|
||||||
|
};
|
||||||
|
|
||||||
const totalReferences = (context.state.doc.toString().match(/{{/g) || []).length;
|
const totalReferences = (context.state.doc.toString().match(/{{/g) || []).length;
|
||||||
|
|
||||||
let queryInput = context.state.doc.toString();
|
let queryInput = context.state.doc.toString();
|
||||||
|
|
@ -247,17 +261,18 @@ const EditorInput = ({
|
||||||
queryInput = '{{' + currentWord + '}}';
|
queryInput = '{{' + currentWord + '}}';
|
||||||
}
|
}
|
||||||
|
|
||||||
let completions = getAutocompletion(queryInput, validationType, allHints, totalReferences, originalQueryInput);
|
let completions = getAutocompletion(queryInput, validationType, hints, totalReferences, originalQueryInput);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
from: word.from,
|
from: word.from,
|
||||||
options: completions,
|
options: completions,
|
||||||
validFor: /^\{\{.*\}\}$/,
|
validFor: /^\{\{.*\}\}$/,
|
||||||
|
filter: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const overRideFunction = React.useCallback((context) => autoCompleteExtensionConfig(context), [isInsideQueryManager]);
|
const overRideFunction = React.useCallback((context) => autoCompleteExtensionConfig(context), [isInsideQueryManager, paramHints]);
|
||||||
|
|
||||||
const autoCompleteConfig = autocompletion({
|
const autoCompleteConfig = autocompletion({
|
||||||
override: [overRideFunction],
|
override: [overRideFunction],
|
||||||
|
|
@ -424,6 +439,9 @@ const EditorInput = ({
|
||||||
ref={previewRef}
|
ref={previewRef}
|
||||||
>
|
>
|
||||||
<CodeMirror
|
<CodeMirror
|
||||||
|
onCreateEditor={(view) => {
|
||||||
|
setCodeMirrorView(view);
|
||||||
|
}}
|
||||||
value={currentValue}
|
value={currentValue}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
height={isInsideQueryPane ? '100%' : showLineNumbers ? '400px' : '100%'}
|
height={isInsideQueryPane ? '100%' : showLineNumbers ? '400px' : '100%'}
|
||||||
|
|
@ -460,11 +478,16 @@ const EditorInput = ({
|
||||||
theme={theme}
|
theme={theme}
|
||||||
indentWithTab={false}
|
indentWithTab={false}
|
||||||
readOnly={disabled}
|
readOnly={disabled}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (event.key === 'Backspace') {
|
||||||
|
startCompletion(codeMirrorView);
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary >
|
||||||
</CodeHinter.Portal>
|
</CodeHinter.Portal >
|
||||||
</div>
|
</div >
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,8 @@ export const getAutocompletion = (input, fieldType, hints, totalReferences = 1,
|
||||||
originalQueryInput,
|
originalQueryInput,
|
||||||
searchInput
|
searchInput
|
||||||
);
|
);
|
||||||
return orderSuggestions(suggestions, fieldType);
|
|
||||||
|
return suggestions;
|
||||||
};
|
};
|
||||||
|
|
||||||
function orderSuggestions(suggestions, validationType) {
|
function orderSuggestions(suggestions, validationType) {
|
||||||
|
|
@ -90,10 +91,18 @@ export const generateHints = (hints, totalReferences = 1, input, searchText) =>
|
||||||
const hasDepth = currentWord.includes('.');
|
const hasDepth = currentWord.includes('.');
|
||||||
const lastDepth = getLastSubstring(currentWord);
|
const lastDepth = getLastSubstring(currentWord);
|
||||||
|
|
||||||
const displayLabel = getLastDepth(displayedHint);
|
let displayLabel = getLastDepth(displayedHint);
|
||||||
|
|
||||||
|
if (type != 'js_method') {
|
||||||
|
const currentWordDepth = currentWord.split('.').length;
|
||||||
|
displayLabel = hint
|
||||||
|
.split('.')
|
||||||
|
.slice(currentWordDepth - 1)
|
||||||
|
.join('.');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
displayLabel: lastDepth === '' ? displayedHint : displayLabel,
|
displayLabel,
|
||||||
label: displayedHint,
|
label: displayedHint,
|
||||||
info: displayedHint,
|
info: displayedHint,
|
||||||
type: type === 'js_method' ? 'js_methods' : type?.toLowerCase(),
|
type: type === 'js_method' ? 'js_methods' : type?.toLowerCase(),
|
||||||
|
|
@ -154,40 +163,24 @@ export const generateHints = (hints, totalReferences = 1, input, searchText) =>
|
||||||
};
|
};
|
||||||
|
|
||||||
function filterHintsByDepth(input, hints) {
|
function filterHintsByDepth(input, hints) {
|
||||||
if (input === '') return hints;
|
const inputParts = input.split('.');
|
||||||
|
const inputDepth = inputParts.length + 1;
|
||||||
|
|
||||||
const inputDepth = input.includes('.') ? input.split('.').length : 0;
|
const hintsWithDepth = hints.map((hint) => {
|
||||||
|
const hintParts = hint.hint.split('.');
|
||||||
const filteredHints = hints.filter((cm) => {
|
return {
|
||||||
const hintParts = cm.hint.split('.');
|
...hint,
|
||||||
|
depth: hintParts.length,
|
||||||
let shouldInclude =
|
};
|
||||||
(cm.hint.startsWith(input) && hintParts.length === inputDepth + 1) ||
|
|
||||||
(cm.hint.startsWith(input) && hintParts.length === inputDepth);
|
|
||||||
|
|
||||||
const shouldFuzzyMatch = !shouldInclude ? hintParts.length > inputDepth : false;
|
|
||||||
|
|
||||||
if (shouldFuzzyMatch) {
|
|
||||||
// fuzzy match
|
|
||||||
let matchedDepth = -1;
|
|
||||||
for (let i = 0; i < hintParts.length; i++) {
|
|
||||||
if (hintParts[i].includes(input)) {
|
|
||||||
matchedDepth = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchedDepth !== -1) {
|
|
||||||
shouldInclude = hintParts.length === matchedDepth + 1;
|
|
||||||
}
|
|
||||||
} else if (input.endsWith('.')) {
|
|
||||||
shouldInclude = cm.hint.startsWith(input) && hintParts.length === inputDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shouldInclude;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return filteredHints;
|
const filteredHints = hintsWithDepth.filter((hint) => {
|
||||||
|
return hint.depth <= inputDepth;
|
||||||
|
});
|
||||||
|
|
||||||
|
const sortedHints = filteredHints.sort((hint1, hint2) => hint1.depth - hint2.depth);
|
||||||
|
|
||||||
|
return sortedHints;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findNearestSubstring(inputStr, currentCurosorPos) {
|
export function findNearestSubstring(inputStr, currentCurosorPos) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,20 @@
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import Select from '@/_ui/Select';
|
import Select from '@/_ui/Select';
|
||||||
import { decodeEntities } from '@/_helpers/utils';
|
import { decodeEntities } from '@/_helpers/utils';
|
||||||
|
import usePopoverObserver from '@/AppBuilder/_hooks/usePopoverObserver';
|
||||||
|
|
||||||
export const ChangeDataSource = ({ dataSources, onChange, value, isVersionReleased }) => {
|
export const ChangeDataSource = ({ dataSources, onChange, value, isVersionReleased }) => {
|
||||||
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
usePopoverObserver(
|
||||||
|
document.getElementsByClassName('query-details')[0],
|
||||||
|
document.querySelector('.change-data-source-select.react-select__control'),
|
||||||
|
document.querySelector('.change-data-source-select.react-select__menu'),
|
||||||
|
isMenuOpen,
|
||||||
|
() => (document.querySelector('.change-data-source-select.react-select__menu').style.display = 'block'),
|
||||||
|
() => (document.querySelector('.change-data-source-select.react-select__menu').style.display = 'none')
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
className="w-100"
|
className="w-100"
|
||||||
|
|
@ -14,6 +26,13 @@ export const ChangeDataSource = ({ dataSources, onChange, value, isVersionReleas
|
||||||
}}
|
}}
|
||||||
useMenuPortal={true}
|
useMenuPortal={true}
|
||||||
isDisabled={isVersionReleased}
|
isDisabled={isVersionReleased}
|
||||||
|
customClassPrefix="change-data-source-select"
|
||||||
|
onMenuOpen={() => {
|
||||||
|
setIsMenuOpen(true);
|
||||||
|
}}
|
||||||
|
onMenuClose={() => {
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ class Restapi extends React.Component {
|
||||||
codeHinterHeight: 32, // Default height
|
codeHinterHeight: 32, // Default height
|
||||||
};
|
};
|
||||||
this.codeHinterRef = React.createRef();
|
this.codeHinterRef = React.createRef();
|
||||||
|
this.isMenuOpenRef = React.createRef();
|
||||||
|
this.prevIsMenuOpenRef = React.createRef(false);
|
||||||
|
this.intersectionObserver = null;
|
||||||
this.resizeObserver = null;
|
this.resizeObserver = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,6 +50,9 @@ class Restapi extends React.Component {
|
||||||
if (this.codeHinterRef.current && !this.resizeObserver) {
|
if (this.codeHinterRef.current && !this.resizeObserver) {
|
||||||
this.setupResizeObserver();
|
this.setupResizeObserver();
|
||||||
}
|
}
|
||||||
|
if (!this.intersectionObserver) {
|
||||||
|
this.setupIntersectionObserver();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
@ -75,6 +81,7 @@ class Restapi extends React.Component {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
this.setupResizeObserver();
|
this.setupResizeObserver();
|
||||||
|
this.setupIntersectionObserver();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|
@ -84,6 +91,9 @@ class Restapi extends React.Component {
|
||||||
if (this.resizeObserver) {
|
if (this.resizeObserver) {
|
||||||
this.resizeObserver.disconnect();
|
this.resizeObserver.disconnect();
|
||||||
}
|
}
|
||||||
|
if (this.intersectionObserver) {
|
||||||
|
this.intersectionObserver.disconnect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupResizeObserver() {
|
setupResizeObserver() {
|
||||||
|
|
@ -132,6 +142,33 @@ class Restapi extends React.Component {
|
||||||
this.resizeObserver.observe(element);
|
this.resizeObserver.observe(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupIntersectionObserver() {
|
||||||
|
const container = document.getElementsByClassName('query-details')[0];
|
||||||
|
const trigger = document.querySelector('.restapi-method-select.react-select__control');
|
||||||
|
|
||||||
|
if (this.intersectionObserver) {
|
||||||
|
this.intersectionObserver.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.intersectionObserver = new IntersectionObserver(
|
||||||
|
([entry]) => {
|
||||||
|
const popover = document.querySelector('.restapi-method-select.react-select__menu');
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
if (this.prevIsMenuOpenRef.current) {
|
||||||
|
popover.style.display = 'block';
|
||||||
|
this.prevIsMenuOpenRef.current = false;
|
||||||
|
}
|
||||||
|
} else if (this.isMenuOpenRef.current) {
|
||||||
|
popover.style.display = 'none';
|
||||||
|
this.prevIsMenuOpenRef.current = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ root: container, threshold: [0.5] }
|
||||||
|
);
|
||||||
|
|
||||||
|
this.intersectionObserver.observe(trigger);
|
||||||
|
}
|
||||||
|
|
||||||
initizalizeRetryNetworkErrorsToggle = () => {
|
initizalizeRetryNetworkErrorsToggle = () => {
|
||||||
const isRetryNetworkErrorToggleUnused = this.props.options.retry_network_errors === null;
|
const isRetryNetworkErrorToggleUnused = this.props.options.retry_network_errors === null;
|
||||||
if (isRetryNetworkErrorToggleUnused) {
|
if (isRetryNetworkErrorToggleUnused) {
|
||||||
|
|
@ -287,6 +324,13 @@ class Restapi extends React.Component {
|
||||||
height={32}
|
height={32}
|
||||||
styles={this.customSelectStyles(this.props.darkMode, 91)}
|
styles={this.customSelectStyles(this.props.darkMode, 91)}
|
||||||
useCustomStyles={true}
|
useCustomStyles={true}
|
||||||
|
customClassPrefix="restapi-method-select"
|
||||||
|
onMenuOpen={() => {
|
||||||
|
this.isMenuOpenRef.current = true;
|
||||||
|
}}
|
||||||
|
onMenuClose={() => {
|
||||||
|
this.isMenuOpenRef.current = false;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,25 @@ import CodeHinter from '@/AppBuilder/CodeEditor';
|
||||||
import './workflows-query.scss';
|
import './workflows-query.scss';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import useStore from '@/AppBuilder/_stores/store';
|
import useStore from '@/AppBuilder/_stores/store';
|
||||||
|
import usePopoverObserver from '@/AppBuilder/_hooks/usePopoverObserver';
|
||||||
|
|
||||||
export function Workflows({ options, optionsChanged, currentState }) {
|
export function Workflows({ options, optionsChanged, currentState }) {
|
||||||
const [workflowOptions, setWorkflowOptions] = useState([]);
|
const [workflowOptions, setWorkflowOptions] = useState([]);
|
||||||
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
const [_selectedWorkflowId, setSelectedWorkflowId] = useState(undefined);
|
const [_selectedWorkflowId, setSelectedWorkflowId] = useState(undefined);
|
||||||
const [params, setParams] = useState([...(options.params ?? [{ key: '', value: '' }])]);
|
const [params, setParams] = useState([...(options.params ?? [{ key: '', value: '' }])]);
|
||||||
|
|
||||||
const appId = useStore((state) => state.app.appId);
|
const appId = useStore((state) => state.app.appId);
|
||||||
|
|
||||||
|
usePopoverObserver(
|
||||||
|
document.getElementsByClassName('query-details')[0],
|
||||||
|
document.querySelector('.workflow-select.react-select__control'),
|
||||||
|
document.querySelector('.workflow-select.react-select__menu'),
|
||||||
|
isMenuOpen,
|
||||||
|
() => (document.querySelector('.workflow-select.react-select__menu').style.display = 'block'),
|
||||||
|
() => (document.querySelector('.workflow-select.react-select__menu').style.display = 'none')
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
appsService.getWorkflows(appId).then(({ workflows }) => {
|
appsService.getWorkflows(appId).then(({ workflows }) => {
|
||||||
setWorkflowOptions(
|
setWorkflowOptions(
|
||||||
|
|
@ -50,6 +61,13 @@ export function Workflows({ options, optionsChanged, currentState }) {
|
||||||
customWrap={true}
|
customWrap={true}
|
||||||
width="300px"
|
width="300px"
|
||||||
menuPlacement="bottom"
|
menuPlacement="bottom"
|
||||||
|
customClassPrefix="workflow-select"
|
||||||
|
onMenuOpen={() => {
|
||||||
|
setIsMenuOpen(true);
|
||||||
|
}}
|
||||||
|
onMenuClose={() => {
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<label className="my-2">Params</label>
|
<label className="my-2">Params</label>
|
||||||
<div className="grid"></div>
|
<div className="grid"></div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,538 @@
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import Accordion from '@/_ui/Accordion';
|
||||||
|
import { EventManager } from '../EventManager';
|
||||||
|
import { renderElement } from '../Utils';
|
||||||
|
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
|
||||||
|
import Popover from 'react-bootstrap/Popover';
|
||||||
|
import List from '@/ToolJetUI/List/List';
|
||||||
|
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
|
||||||
|
import useStore from '@/AppBuilder/_stores/store';
|
||||||
|
import CodeHinter from '@/AppBuilder/CodeEditor';
|
||||||
|
import AddNewButton from '@/ToolJetUI/Buttons/AddNewButton/AddNewButton';
|
||||||
|
import ListGroup from 'react-bootstrap/ListGroup';
|
||||||
|
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
|
||||||
|
import SortableList from '@/_components/SortableList';
|
||||||
|
import Trash from '@/_ui/Icon/solidIcons/Trash';
|
||||||
|
import { shallow } from 'zustand/shallow';
|
||||||
|
import Switch from '@/Editor/CodeBuilder/Elements/Switch';
|
||||||
|
import { usePrevious } from '@dnd-kit/utilities';
|
||||||
|
|
||||||
|
export function Steps({ componentMeta, darkMode, ...restProps }) {
|
||||||
|
const {
|
||||||
|
layoutPropertyChanged,
|
||||||
|
component,
|
||||||
|
dataQueries,
|
||||||
|
paramUpdated,
|
||||||
|
currentState,
|
||||||
|
eventsChanged,
|
||||||
|
apps,
|
||||||
|
allComponents,
|
||||||
|
pages,
|
||||||
|
} = restProps;
|
||||||
|
const getResolvedValue = useStore((state) => state.getResolvedValue, shallow);
|
||||||
|
|
||||||
|
const isDynamicOptionsEnabled = getResolvedValue(component?.component?.definition?.properties?.advanced?.value);
|
||||||
|
const variant = component?.component?.definition?.properties?.variant?.value;
|
||||||
|
const prevVariant = usePrevious(variant)
|
||||||
|
console.log("variant", component?.component?.definition);
|
||||||
|
|
||||||
|
|
||||||
|
const [options, setOptions] = useState([]);
|
||||||
|
const [hoveredOptionIndex, setHoveredOptionIndex] = useState(null);
|
||||||
|
let properties = [];
|
||||||
|
let additionalActions = [];
|
||||||
|
let optionsProperties = [];
|
||||||
|
|
||||||
|
for (const [key] of Object.entries(componentMeta?.properties)) {
|
||||||
|
if (componentMeta?.properties[key]?.section === 'additionalActions') {
|
||||||
|
additionalActions.push(key);
|
||||||
|
} else if (componentMeta?.properties[key]?.accordian === 'Options') {
|
||||||
|
optionsProperties.push(key);
|
||||||
|
} else {
|
||||||
|
properties.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the default style of "number" & "titles" type are different for completed label
|
||||||
|
// TODO: Need to revisit this logic when text custom themes are implemented
|
||||||
|
useEffect(() => {
|
||||||
|
const completedLabelColor = component?.component?.definition?.styles?.completedLabel?.value;
|
||||||
|
if (variant !== prevVariant) {
|
||||||
|
if (variant === "numbers" && completedLabelColor === "#1B1F24") {
|
||||||
|
paramUpdated({ name: 'completedLabel' }, 'value', "#FFFFFF", 'styles', false, {});
|
||||||
|
} else if (variant === "titles" && completedLabelColor === "#FFFFFF") {
|
||||||
|
paramUpdated({ name: 'completedLabel' }, 'value', "#1B1F24", 'styles', false, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [variant])
|
||||||
|
|
||||||
|
const getItemStyle = (isDragging, draggableStyle) => ({
|
||||||
|
userSelect: 'none',
|
||||||
|
...draggableStyle,
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateAllOptionsParams = (options, props) => {
|
||||||
|
paramUpdated({ name: 'steps' }, 'value', options, 'properties', false, props);
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateNewOptions = () => {
|
||||||
|
let found = false;
|
||||||
|
let label = '';
|
||||||
|
let currentNumber = options.length + 1;
|
||||||
|
while (!found) {
|
||||||
|
label = `step ${currentNumber}`;
|
||||||
|
if (options.find((option) => option.name === label) === undefined) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
currentNumber += 1;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: label,
|
||||||
|
id: currentNumber - 1,
|
||||||
|
tooltip: label,
|
||||||
|
visible: { value: '{{true}}' },
|
||||||
|
disabled: { value: '{{false}}' },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddOption = () => {
|
||||||
|
let _option = generateNewOptions();
|
||||||
|
const _items = [...options, _option];
|
||||||
|
setOptions(_items);
|
||||||
|
updateAllOptionsParams(_items);
|
||||||
|
};
|
||||||
|
const handleDeleteOption = (index) => {
|
||||||
|
const _items = options.filter((option, i) => i !== index);
|
||||||
|
setOptions(_items);
|
||||||
|
updateAllOptionsParams(_items, { isParamFromDropdownOptions: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLabelChange = (propertyName, value, index) => {
|
||||||
|
const _options = options.map((option, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
[propertyName]: value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
setOptions(_options);
|
||||||
|
updateAllOptionsParams(_options);
|
||||||
|
};
|
||||||
|
|
||||||
|
const reorderOptions = async (startIndex, endIndex) => {
|
||||||
|
const result = [...options];
|
||||||
|
const [removed] = result.splice(startIndex, 1);
|
||||||
|
result.splice(endIndex, 0, removed);
|
||||||
|
setOptions(result);
|
||||||
|
updateAllOptionsParams(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDragEnd = ({ source, destination }) => {
|
||||||
|
if (!destination || source?.index === destination?.index) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reorderOptions(source.index, destination.index);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnFxPress = (active, index, key) => {
|
||||||
|
const _options = options.map((option, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
[key]: {
|
||||||
|
...option[key],
|
||||||
|
fxActive: active,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
setOptions(_options);
|
||||||
|
updateAllOptionsParams(_options);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _renderOverlay = (item, index) => {
|
||||||
|
return (
|
||||||
|
<Popover className={`${darkMode && 'dark-theme theme-dark'}`} style={{ minWidth: '248px' }}>
|
||||||
|
<Popover.Body>
|
||||||
|
<div className="field mb-3" data-cy={`input-and-label-column-name`}>
|
||||||
|
<label data-cy={`label-column-name`} className="font-weight-500 mb-1 font-size-12">
|
||||||
|
{'Id'}
|
||||||
|
</label>
|
||||||
|
<CodeHinter
|
||||||
|
type={'basic'}
|
||||||
|
initialValue={item?.id + ''}
|
||||||
|
theme={darkMode ? 'monokai' : 'default'}
|
||||||
|
mode="javascript"
|
||||||
|
lineNumbers={false}
|
||||||
|
placeholder={'Option label'}
|
||||||
|
onChange={(value) => handleLabelChange('id', value, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="field mb-3" data-cy={`input-and-label-column-name`}>
|
||||||
|
<label data-cy={`label-column-name`} className="font-weight-500 mb-1 font-size-12">
|
||||||
|
{'Label'}
|
||||||
|
</label>
|
||||||
|
<CodeHinter
|
||||||
|
type={'basic'}
|
||||||
|
initialValue={item?.name}
|
||||||
|
theme={darkMode ? 'monokai' : 'default'}
|
||||||
|
mode="javascript"
|
||||||
|
lineNumbers={false}
|
||||||
|
placeholder={'Option label'}
|
||||||
|
onChange={(value) => handleLabelChange('name', value, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="field mb-3" data-cy={`input-and-label-column-name`}>
|
||||||
|
<label data-cy={`label-column-name`} className="font-weight-500 mb-1 font-size-12">
|
||||||
|
{'Tooltip'}
|
||||||
|
</label>
|
||||||
|
<CodeHinter
|
||||||
|
type={'basic'}
|
||||||
|
initialValue={item?.tooltip + ''}
|
||||||
|
theme={darkMode ? 'monokai' : 'default'}
|
||||||
|
mode="javascript"
|
||||||
|
lineNumbers={false}
|
||||||
|
placeholder={'Tooltip'}
|
||||||
|
onChange={(value) => handleLabelChange('tooltip', value, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="field mb-2" data-cy={`input-and-label-column-name`}>
|
||||||
|
<CodeHinter
|
||||||
|
initialValue={item?.visible?.value}
|
||||||
|
theme={darkMode ? 'monokai' : 'default'}
|
||||||
|
mode="javascript"
|
||||||
|
lineNumbers={false}
|
||||||
|
component={component}
|
||||||
|
type={'fxEditor'}
|
||||||
|
paramLabel={'Visibility'}
|
||||||
|
onChange={(value) =>
|
||||||
|
handleLabelChange(
|
||||||
|
'visible',
|
||||||
|
{
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
paramName={'visible'}
|
||||||
|
onFxPress={(active) => handleOnFxPress(active, index, 'visible')}
|
||||||
|
fxActive={item?.visible?.fxActive}
|
||||||
|
fieldMeta={{
|
||||||
|
type: 'toggle',
|
||||||
|
displayName: 'Make editable',
|
||||||
|
}}
|
||||||
|
paramType={'toggle'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="field" data-cy={`input-and-label-column-name`}>
|
||||||
|
<CodeHinter
|
||||||
|
initialValue={item?.disabled?.value}
|
||||||
|
theme={darkMode ? 'monokai' : 'default'}
|
||||||
|
mode="javascript"
|
||||||
|
lineNumbers={false}
|
||||||
|
component={component}
|
||||||
|
type={'fxEditor'}
|
||||||
|
paramLabel={'Disable'}
|
||||||
|
paramName={'disable'}
|
||||||
|
onChange={(value) => handleLabelChange('disabled', { value }, index)}
|
||||||
|
onFxPress={(active) => handleOnFxPress(active, index, 'disabled')}
|
||||||
|
fxActive={item?.disabled?.fxActive}
|
||||||
|
fieldMeta={{
|
||||||
|
type: 'toggle',
|
||||||
|
displayName: 'Make editable',
|
||||||
|
}}
|
||||||
|
paramType={'toggle'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Popover.Body>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const _renderOptions = () => {
|
||||||
|
return (
|
||||||
|
<List style={{ marginBottom: '20px' }}>
|
||||||
|
<DragDropContext
|
||||||
|
onDragEnd={(result) => {
|
||||||
|
onDragEnd(result);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Droppable droppableId="droppable">
|
||||||
|
{({ innerRef, droppableProps, placeholder }) => (
|
||||||
|
<div className="w-100" {...droppableProps} ref={innerRef}>
|
||||||
|
{options?.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Draggable key={item.name} draggableId={item.name} index={index}>
|
||||||
|
{(provided, snapshot) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)}
|
||||||
|
>
|
||||||
|
<OverlayTrigger
|
||||||
|
trigger="click"
|
||||||
|
placement="left"
|
||||||
|
rootClose
|
||||||
|
overlay={_renderOverlay(item, index)}
|
||||||
|
>
|
||||||
|
<div key={item.name + item.id}>
|
||||||
|
<ListGroup.Item
|
||||||
|
style={{ marginBottom: '8px', backgroundColor: 'var(--slate3)' }}
|
||||||
|
onMouseEnter={() => setHoveredOptionIndex(index)}
|
||||||
|
onMouseLeave={() => setHoveredOptionIndex(null)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-auto d-flex align-items-center">
|
||||||
|
<SortableList.DragHandle show />
|
||||||
|
</div>
|
||||||
|
<div className="col text-truncate cursor-pointer" style={{ padding: '0px' }}>
|
||||||
|
{getResolvedValue(item.name)}
|
||||||
|
</div>
|
||||||
|
<div className="col-auto">
|
||||||
|
{index === hoveredOptionIndex && (
|
||||||
|
<ButtonSolid
|
||||||
|
variant="danger"
|
||||||
|
size="xs"
|
||||||
|
className={'delete-icon-btn'}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleDeleteOption(index);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="d-flex">
|
||||||
|
<Trash fill={'var(--tomato9)'} width={12} />
|
||||||
|
</span>
|
||||||
|
</ButtonSolid>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ListGroup.Item>
|
||||||
|
</div>
|
||||||
|
</OverlayTrigger>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{placeholder}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</DragDropContext>
|
||||||
|
<AddNewButton onClick={handleAddOption} dataCy="add-new-dropdown-option" className="mt-0">
|
||||||
|
Add new option
|
||||||
|
</AddNewButton>
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isDynamicStepsEnabled = getResolvedValue(component?.component?.definition?.properties?.advanced?.value);
|
||||||
|
useEffect(() => {
|
||||||
|
setOptions(constructSteps());
|
||||||
|
}, [component?.id, isDynamicStepsEnabled]);
|
||||||
|
|
||||||
|
const constructSteps = () => {
|
||||||
|
try {
|
||||||
|
let optionsValue = isDynamicOptionsEnabled
|
||||||
|
? component?.component?.definition?.properties?.schema?.value
|
||||||
|
: component?.component?.definition?.properties?.steps?.value;
|
||||||
|
let options = [];
|
||||||
|
|
||||||
|
if (isDynamicOptionsEnabled || typeof optionsValue === 'string') {
|
||||||
|
options = getResolvedValue(optionsValue);
|
||||||
|
} else {
|
||||||
|
options = optionsValue?.map((option) => option);
|
||||||
|
}
|
||||||
|
return options.map((option) => {
|
||||||
|
const newOption = { ...option };
|
||||||
|
|
||||||
|
Object.keys(option).forEach((key) => {
|
||||||
|
if (typeof option[key]?.value === 'boolean') {
|
||||||
|
newOption[key]['value'] = `{{${option[key]?.value}}}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!('visible' in newOption)) {
|
||||||
|
newOption['visible'] = { value: '{{true}}' };
|
||||||
|
}
|
||||||
|
return newOption;
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let items = [];
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
title: 'Steps',
|
||||||
|
isOpen: true,
|
||||||
|
children: (
|
||||||
|
<>
|
||||||
|
{properties
|
||||||
|
.filter((property) => !optionsProperties.includes(property))
|
||||||
|
?.map((property) => {
|
||||||
|
if (property === 'steps') {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{renderElement(
|
||||||
|
component,
|
||||||
|
componentMeta,
|
||||||
|
paramUpdated,
|
||||||
|
dataQueries,
|
||||||
|
'advanced',
|
||||||
|
'properties',
|
||||||
|
currentState,
|
||||||
|
allComponents
|
||||||
|
)}
|
||||||
|
{isDynamicStepsEnabled
|
||||||
|
? renderElement(
|
||||||
|
component,
|
||||||
|
componentMeta,
|
||||||
|
paramUpdated,
|
||||||
|
dataQueries,
|
||||||
|
'schema',
|
||||||
|
'properties',
|
||||||
|
currentState,
|
||||||
|
allComponents
|
||||||
|
)
|
||||||
|
: _renderOptions()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// else if (property === 'variant') {
|
||||||
|
// return renderTest(
|
||||||
|
// component,
|
||||||
|
// componentMeta,
|
||||||
|
// paramUpdated,
|
||||||
|
// dataQueries,
|
||||||
|
// 'variant',
|
||||||
|
// 'properties',
|
||||||
|
// currentState,
|
||||||
|
// allComponents,
|
||||||
|
// handleLabelChange
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
return renderElement(
|
||||||
|
component,
|
||||||
|
componentMeta,
|
||||||
|
paramUpdated,
|
||||||
|
dataQueries,
|
||||||
|
property,
|
||||||
|
'properties',
|
||||||
|
currentState,
|
||||||
|
allComponents,
|
||||||
|
darkMode
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
title: 'Events',
|
||||||
|
isOpen: true,
|
||||||
|
children: (
|
||||||
|
<EventManager
|
||||||
|
sourceId={component?.id}
|
||||||
|
eventSourceType="component"
|
||||||
|
eventMetaDefinition={componentMeta}
|
||||||
|
dataQueries={dataQueries}
|
||||||
|
components={allComponents}
|
||||||
|
eventsChanged={eventsChanged}
|
||||||
|
apps={apps}
|
||||||
|
darkMode={darkMode}
|
||||||
|
pages={pages}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
items.push({
|
||||||
|
title: `Additional Actions`,
|
||||||
|
isOpen: true,
|
||||||
|
children: additionalActions.map((property) => {
|
||||||
|
return renderElement(
|
||||||
|
component,
|
||||||
|
componentMeta,
|
||||||
|
paramUpdated,
|
||||||
|
dataQueries,
|
||||||
|
property,
|
||||||
|
'properties',
|
||||||
|
currentState,
|
||||||
|
allComponents,
|
||||||
|
darkMode,
|
||||||
|
componentMeta.properties?.[property]?.placeholder
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
title: 'Devices',
|
||||||
|
isOpen: true,
|
||||||
|
children: (
|
||||||
|
<>
|
||||||
|
{renderElement(
|
||||||
|
component,
|
||||||
|
componentMeta,
|
||||||
|
layoutPropertyChanged,
|
||||||
|
dataQueries,
|
||||||
|
'showOnDesktop',
|
||||||
|
'others',
|
||||||
|
currentState,
|
||||||
|
allComponents
|
||||||
|
)}
|
||||||
|
{renderElement(
|
||||||
|
component,
|
||||||
|
componentMeta,
|
||||||
|
layoutPropertyChanged,
|
||||||
|
dataQueries,
|
||||||
|
'showOnMobile',
|
||||||
|
'others',
|
||||||
|
currentState,
|
||||||
|
allComponents
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
return <Accordion items={items} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTest(...props) {
|
||||||
|
const [
|
||||||
|
component,
|
||||||
|
componentMeta,
|
||||||
|
paramUpdated,
|
||||||
|
dataQueries,
|
||||||
|
param,
|
||||||
|
paramType,
|
||||||
|
currentState,
|
||||||
|
components = {},
|
||||||
|
darkMode = false,
|
||||||
|
placeholder = '',
|
||||||
|
validationFn,
|
||||||
|
] = props;
|
||||||
|
const value = componentMeta?.definition?.properties?.variant?.value;
|
||||||
|
return (
|
||||||
|
<div style={{ marginBottom: 8 }}>
|
||||||
|
<Switch
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => {
|
||||||
|
paramUpdated({ name: 'variant' }, 'value', e, 'properties', false, props);
|
||||||
|
}}
|
||||||
|
meta={{
|
||||||
|
...componentMeta.properties[param],
|
||||||
|
fullWidth: true,
|
||||||
|
}}
|
||||||
|
paramName={param}
|
||||||
|
isIcon={false}
|
||||||
|
component={component.component.definition.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -255,7 +255,7 @@ export const PropertiesTabElements = ({
|
||||||
paramType="properties"
|
paramType="properties"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{resolveReferences(column?.isEditable) && (
|
{(column?.fxActiveFields?.includes('isEditable') || resolveReferences(column?.isEditable)) && (
|
||||||
<ValidationProperties
|
<ValidationProperties
|
||||||
column={column}
|
column={column}
|
||||||
index={index}
|
index={index}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect, useContext } from 'react';
|
import React, { useState, useEffect, useContext, useRef } from 'react';
|
||||||
|
|
||||||
import { ActionTypes } from '@/Editor/ActionTypes';
|
import { ActionTypes } from '@/Editor/ActionTypes';
|
||||||
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
|
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
|
||||||
|
|
@ -32,6 +32,9 @@ import useStore from '@/AppBuilder/_stores/store';
|
||||||
import { useEventActions, useEvents } from '@/AppBuilder/_stores/slices/eventsSlice';
|
import { useEventActions, useEvents } from '@/AppBuilder/_stores/slices/eventsSlice';
|
||||||
import ToggleGroup from '@/ToolJetUI/SwitchGroup/ToggleGroup';
|
import ToggleGroup from '@/ToolJetUI/SwitchGroup/ToggleGroup';
|
||||||
import ToggleGroupItem from '@/ToolJetUI/SwitchGroup/ToggleGroupItem';
|
import ToggleGroupItem from '@/ToolJetUI/SwitchGroup/ToggleGroupItem';
|
||||||
|
import usePopoverObserver from '@/AppBuilder/_hooks/usePopoverObserver';
|
||||||
|
import SolidIcon from '@/_ui/Icon/SolidIcons';
|
||||||
|
import { components as selectComponents } from 'react-select';
|
||||||
|
|
||||||
export const EventManager = ({
|
export const EventManager = ({
|
||||||
sourceId,
|
sourceId,
|
||||||
|
|
@ -82,6 +85,8 @@ export const EventManager = ({
|
||||||
|
|
||||||
const [events, setEvents] = useState([]);
|
const [events, setEvents] = useState([]);
|
||||||
const [focusedEventIndex, setFocusedEventIndex] = useState(null);
|
const [focusedEventIndex, setFocusedEventIndex] = useState(null);
|
||||||
|
const lastFocusedEventIndex = useRef(null);
|
||||||
|
const shouldSkipOnToggle = useRef(null);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|
@ -101,8 +106,23 @@ export const EventManager = ({
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [JSON.stringify(currentEvents)]);
|
}, [JSON.stringify(currentEvents)]);
|
||||||
|
|
||||||
let actionOptions = ActionTypes.map((action) => {
|
let groupedOptions = ActionTypes.reduce((acc, action) => {
|
||||||
return { name: action.name, value: action.id };
|
const groupName = action.group;
|
||||||
|
|
||||||
|
if (!acc[groupName]) {
|
||||||
|
acc[groupName] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
acc[groupName].push({
|
||||||
|
label: action.name,
|
||||||
|
value: action.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
let actionOptions = Object.keys(groupedOptions).map((groupName) => {
|
||||||
|
return { label: groupName, options: groupedOptions[groupName] };
|
||||||
});
|
});
|
||||||
|
|
||||||
let checkIfClicksAreInsideOf = document.querySelector('.cm-completionListIncompleteBottom');
|
let checkIfClicksAreInsideOf = document.querySelector('.cm-completionListIncompleteBottom');
|
||||||
|
|
@ -124,6 +144,46 @@ export const EventManager = ({
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const actionStyles = {
|
||||||
|
...styles,
|
||||||
|
menuList: (base) => ({
|
||||||
|
...base,
|
||||||
|
padding: '8px 0 8px 8px',
|
||||||
|
'&::-webkit-scrollbar': {
|
||||||
|
width: '10px',
|
||||||
|
},
|
||||||
|
'&::-webkit-scrollbar-track': {
|
||||||
|
background: 'transparent',
|
||||||
|
},
|
||||||
|
'&::-webkit-scrollbar-thumb': {
|
||||||
|
background: '#E4E7EB',
|
||||||
|
border: '1px solid transparent',
|
||||||
|
backgroundClip: 'content-box',
|
||||||
|
},
|
||||||
|
'&::-webkit-scrollbar-thumb:hover': {
|
||||||
|
background: '#E4E7EB !important',
|
||||||
|
border: '1px solid transparent !important',
|
||||||
|
backgroundClip: 'content-box !important',
|
||||||
|
},
|
||||||
|
'&:hover': {
|
||||||
|
'&::-webkit-scrollbar-thumb': {
|
||||||
|
background: '#E4E7EB !important',
|
||||||
|
border: '1px solid transparent !important',
|
||||||
|
backgroundClip: 'content-box !important',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
group: (base) => ({
|
||||||
|
...base,
|
||||||
|
padding: 0,
|
||||||
|
}),
|
||||||
|
groupHeading: (base) => ({
|
||||||
|
...base,
|
||||||
|
margin: 0,
|
||||||
|
padding: '0',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
const actionLookup = Object.fromEntries(ActionTypes.map((actionType) => [actionType.id, actionType]));
|
const actionLookup = Object.fromEntries(ActionTypes.map((actionType) => [actionType.id, actionType]));
|
||||||
|
|
||||||
let alertTypes = [
|
let alertTypes = [
|
||||||
|
|
@ -394,6 +454,29 @@ export const EventManager = ({
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatGroupLabel = (data) => {
|
||||||
|
if (data.label === 'run-action') return;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="tw-border-x-0 tw-border-t-0 tw-border-b-[0.5px] tw-border-solid tw-my-[4px]"
|
||||||
|
style={{ borderColor: 'var(--border-weak)' }}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomOption = (props) => {
|
||||||
|
return (
|
||||||
|
<selectComponents.Option {...props}>
|
||||||
|
<div className="d-flex align-items-center">
|
||||||
|
<div style={{ width: '16px', marginRight: '6px' }}>
|
||||||
|
{props.isSelected && <SolidIcon name="tickv3" width="16px" height="16px" />}
|
||||||
|
</div>
|
||||||
|
<span>{props.label}</span>
|
||||||
|
</div>
|
||||||
|
</selectComponents.Option>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
function eventPopover(event, index) {
|
function eventPopover(event, index) {
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
|
|
@ -433,13 +516,17 @@ export const EventManager = ({
|
||||||
<Select
|
<Select
|
||||||
className={`${darkMode ? 'select-search-dark' : 'select-search'} w-100`}
|
className={`${darkMode ? 'select-search-dark' : 'select-search'} w-100`}
|
||||||
options={actionOptions}
|
options={actionOptions}
|
||||||
value={event.actionId}
|
value={actionOptions
|
||||||
|
.flatMap((group) => group.options)
|
||||||
|
.find((option) => option.value === event.actionId)}
|
||||||
|
components={{ Option: CustomOption }}
|
||||||
search={false}
|
search={false}
|
||||||
onChange={(value) => handlerChanged(index, 'actionId', value)}
|
onChange={(value) => handlerChanged(index, 'actionId', value)}
|
||||||
placeholder={t('globals.select', 'Select') + '...'}
|
placeholder={t('globals.select', 'Select') + '...'}
|
||||||
styles={styles}
|
styles={actionStyles}
|
||||||
useMenuPortal={false}
|
useMenuPortal={false}
|
||||||
useCustomStyles={true}
|
useCustomStyles={true}
|
||||||
|
formatGroupLabel={formatGroupLabel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1006,10 +1093,21 @@ export const EventManager = ({
|
||||||
placement={popoverPlacement || 'left'}
|
placement={popoverPlacement || 'left'}
|
||||||
rootClose={true}
|
rootClose={true}
|
||||||
overlay={eventPopover(event.event, index)}
|
overlay={eventPopover(event.event, index)}
|
||||||
onHide={() => setFocusedEventIndex(null)}
|
|
||||||
onToggle={(showing) => {
|
onToggle={(showing) => {
|
||||||
|
// If the toggle action should be skipped (e.g., due to a previous state change), reset the flag and exit early.
|
||||||
|
if (shouldSkipOnToggle.current) {
|
||||||
|
shouldSkipOnToggle.current = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is already a focused event, set the skip flag to prevent unnecessary state updates.
|
||||||
|
if (focusedEventIndex !== null && showing) {
|
||||||
|
shouldSkipOnToggle.current = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (showing) {
|
if (showing) {
|
||||||
setFocusedEventIndex(index);
|
setFocusedEventIndex(index);
|
||||||
|
lastFocusedEventIndex.current = index;
|
||||||
} else {
|
} else {
|
||||||
setFocusedEventIndex(null);
|
setFocusedEventIndex(null);
|
||||||
}
|
}
|
||||||
|
|
@ -1018,6 +1116,7 @@ export const EventManager = ({
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
|
id={`${sourceId}-${index}`}
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
{...provided.draggableProps}
|
{...provided.draggableProps}
|
||||||
{...provided.dragHandleProps}
|
{...provided.dragHandleProps}
|
||||||
|
|
@ -1061,6 +1160,17 @@ export const EventManager = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const shouldUsePopoverObserver = events.length !== 0 && eventSourceType === 'data_query';
|
||||||
|
|
||||||
|
usePopoverObserver(
|
||||||
|
shouldUsePopoverObserver ? document.getElementsByClassName('query-details')[0] : null,
|
||||||
|
document.getElementById(`${sourceId}-${lastFocusedEventIndex.current}`),
|
||||||
|
document.getElementById('popover-basic'),
|
||||||
|
focusedEventIndex !== null,
|
||||||
|
() => (document.getElementById('popover-basic').style.display = 'block'),
|
||||||
|
() => (document.getElementById('popover-basic').style.display = 'none')
|
||||||
|
);
|
||||||
|
|
||||||
if (events.length === 0) {
|
if (events.length === 0) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import Inspect from '@/_ui/Icon/solidIcons/Inspect';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { EMPTY_ARRAY } from '@/_stores/editorStore';
|
import { EMPTY_ARRAY } from '@/_stores/editorStore';
|
||||||
import { Select } from './Components/Select';
|
import { Select } from './Components/Select';
|
||||||
|
import { Steps } from './Components/Steps.jsx';
|
||||||
import { deepClone } from '@/_helpers/utilities/utils.helpers';
|
import { deepClone } from '@/_helpers/utilities/utils.helpers';
|
||||||
import useStore from '@/AppBuilder/_stores/store';
|
import useStore from '@/AppBuilder/_stores/store';
|
||||||
// import { componentTypes } from '@/Editor/WidgetManager/components';
|
// import { componentTypes } from '@/Editor/WidgetManager/components';
|
||||||
|
|
@ -90,6 +91,7 @@ const NEW_REVAMPED_COMPONENTS = [
|
||||||
'VerticalDivider',
|
'VerticalDivider',
|
||||||
'ModalV2',
|
'ModalV2',
|
||||||
'Link',
|
'Link',
|
||||||
|
'Steps',
|
||||||
];
|
];
|
||||||
|
|
||||||
export const Inspector = ({ componentDefinitionChanged, darkMode, pages, selectedComponentId }) => {
|
export const Inspector = ({ componentDefinitionChanged, darkMode, pages, selectedComponentId }) => {
|
||||||
|
|
@ -539,8 +541,8 @@ export const Inspector = ({ componentDefinitionChanged, darkMode, pages, selecte
|
||||||
componentMeta.displayName === 'Toggle Switch (Legacy)'
|
componentMeta.displayName === 'Toggle Switch (Legacy)'
|
||||||
? 'Toggle (Legacy)'
|
? 'Toggle (Legacy)'
|
||||||
: componentMeta.displayName === 'Toggle Switch'
|
: componentMeta.displayName === 'Toggle Switch'
|
||||||
? 'Toggle Switch'
|
? 'Toggle Switch'
|
||||||
: componentMeta.component,
|
: componentMeta.component,
|
||||||
})}
|
})}
|
||||||
</small>
|
</small>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -740,6 +742,8 @@ const GetAccordion = React.memo(
|
||||||
case 'DatePickerV2':
|
case 'DatePickerV2':
|
||||||
case 'TimePicker':
|
case 'TimePicker':
|
||||||
return <DatetimePickerV2 {...restProps} componentName={componentName} />;
|
return <DatetimePickerV2 {...restProps} componentName={componentName} />;
|
||||||
|
case 'Steps':
|
||||||
|
return <Steps {...restProps} />;
|
||||||
case 'PhoneInput':
|
case 'PhoneInput':
|
||||||
return <PhoneInput {...restProps} />;
|
return <PhoneInput {...restProps} />;
|
||||||
case 'CurrencyInput':
|
case 'CurrencyInput':
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@ const NEW_WIDGETS = [
|
||||||
'TimePicker',
|
'TimePicker',
|
||||||
'ModalV2',
|
'ModalV2',
|
||||||
'TextArea',
|
'TextArea',
|
||||||
|
'EmailInput',
|
||||||
|
'PhoneInput',
|
||||||
|
'CurrencyInput',
|
||||||
];
|
];
|
||||||
|
|
||||||
export const WidgetBox = ({ component, darkMode }) => {
|
export const WidgetBox = ({ component, darkMode }) => {
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ export const Viewer = ({ id: appId, darkMode, moduleId = 'canvas', switchDarkMod
|
||||||
showViewerNavigation={!isPagesSidebarHidden}
|
showViewerNavigation={!isPagesSidebarHidden}
|
||||||
handleAppEnvironmentChanged={handleAppEnvironmentChanged}
|
handleAppEnvironmentChanged={handleAppEnvironmentChanged}
|
||||||
changeToDarkMode={changeToDarkMode}
|
changeToDarkMode={changeToDarkMode}
|
||||||
|
switchPage={switchPage}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="sub-section">
|
<div className="sub-section">
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ export const containerConfig = {
|
||||||
displayName: 'Container',
|
displayName: 'Container',
|
||||||
description: 'Group components',
|
description: 'Group components',
|
||||||
defaultSize: {
|
defaultSize: {
|
||||||
width: 10,
|
width: 13,
|
||||||
height: 200,
|
height: 480,
|
||||||
},
|
},
|
||||||
component: 'Container',
|
component: 'Container',
|
||||||
others: {
|
others: {
|
||||||
|
|
|
||||||
|
|
@ -4,25 +4,38 @@ export const stepsConfig = {
|
||||||
description: 'Step-by-step navigation aid',
|
description: 'Step-by-step navigation aid',
|
||||||
component: 'Steps',
|
component: 'Steps',
|
||||||
properties: {
|
properties: {
|
||||||
|
variant: {
|
||||||
|
type: 'switch',
|
||||||
|
displayName: 'Variant',
|
||||||
|
validation: { schema: { type: 'string' }, defaultValue: 'titles' },
|
||||||
|
options: [
|
||||||
|
{ displayName: 'Label', value: 'titles' },
|
||||||
|
{ displayName: 'Number', value: 'numbers' },
|
||||||
|
{ displayName: 'Plain', value: 'plain' },
|
||||||
|
],
|
||||||
|
accordian: 'label',
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
type: 'code',
|
||||||
|
displayName: 'Schema',
|
||||||
|
conditionallyRender: {
|
||||||
|
key: 'advanced',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
accordian: 'Options',
|
||||||
|
},
|
||||||
steps: {
|
steps: {
|
||||||
type: 'code',
|
type: 'code',
|
||||||
displayName: 'Steps',
|
displayName: '',
|
||||||
|
showLabel: false,
|
||||||
validation: {
|
validation: {
|
||||||
schema: {
|
schema: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
element: { type: 'object', object: { id: { type: 'number' } } },
|
element: { type: 'object' },
|
||||||
},
|
},
|
||||||
defaultValue: `[{ name: 'step 1'}, {name: 'step 2'}]`,
|
defaultValue: `[{ name: 'step 1'}, {name: 'step 2'}]`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
currentStep: {
|
|
||||||
type: 'code',
|
|
||||||
displayName: 'Current step',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'number' },
|
|
||||||
defaultValue: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
stepsSelectable: {
|
stepsSelectable: {
|
||||||
type: 'toggle',
|
type: 'toggle',
|
||||||
displayName: 'Steps selectable',
|
displayName: 'Steps selectable',
|
||||||
|
|
@ -30,7 +43,38 @@ export const stepsConfig = {
|
||||||
schema: { type: 'boolean' },
|
schema: { type: 'boolean' },
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
},
|
},
|
||||||
|
section: 'additionalActions',
|
||||||
},
|
},
|
||||||
|
disabledState: {
|
||||||
|
type: 'toggle',
|
||||||
|
displayName: 'Disable',
|
||||||
|
validation: { schema: { type: 'boolean' } },
|
||||||
|
section: 'additionalActions',
|
||||||
|
},
|
||||||
|
visibility: {
|
||||||
|
type: 'toggle',
|
||||||
|
displayName: 'Visibility',
|
||||||
|
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||||
|
section: 'additionalActions',
|
||||||
|
},
|
||||||
|
advanced: {
|
||||||
|
type: 'toggle',
|
||||||
|
displayName: 'Dynamic options',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'boolean' },
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
|
accordian: 'Options',
|
||||||
|
},
|
||||||
|
currentStep: {
|
||||||
|
type: 'code',
|
||||||
|
displayName: 'Current step',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'number' },
|
||||||
|
defaultValue: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
defaultSize: {
|
defaultSize: {
|
||||||
width: 22,
|
width: 22,
|
||||||
|
|
@ -40,46 +84,126 @@ export const stepsConfig = {
|
||||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||||
},
|
},
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
handle: 'setStep',
|
||||||
|
displayName: 'Set step',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
handle: 'option',
|
||||||
|
displayName: 'Option',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'setVisibility',
|
||||||
|
displayName: 'Set visibility',
|
||||||
|
params: [{ handle: 'visible', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'setDisabled',
|
||||||
|
displayName: 'Set disabled',
|
||||||
|
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{true}}', type: 'toggle' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'resetSteps',
|
||||||
|
displayName: 'Reset steps',
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'setStepVisible',
|
||||||
|
displayName: 'Set step visible',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
handle: 'id',
|
||||||
|
displayName: 'Step id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'visibility',
|
||||||
|
displayName: 'visibility',
|
||||||
|
defaultValue: '{{false}}',
|
||||||
|
type: 'toggle',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'setStepDisable',
|
||||||
|
displayName: 'Set step disable',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
handle: 'id',
|
||||||
|
displayName: 'Step id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'disabled',
|
||||||
|
displayName: 'disabled',
|
||||||
|
defaultValue: '{{true}}',
|
||||||
|
type: 'toggle',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
events: {
|
events: {
|
||||||
onSelect: { displayName: 'On select' },
|
onSelect: { displayName: 'On select' },
|
||||||
},
|
},
|
||||||
styles: {
|
styles: {
|
||||||
color: {
|
incompletedAccent: {
|
||||||
type: 'colorSwatches',
|
type: 'colorSwatches',
|
||||||
displayName: 'colorSwatches',
|
displayName: 'Incompleted accent',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'string' },
|
||||||
|
defaultValue: '#CCD1D5',
|
||||||
|
},
|
||||||
|
accordian: 'steps',
|
||||||
|
},
|
||||||
|
incompletedLabel: {
|
||||||
|
type: 'colorSwatches',
|
||||||
|
displayName: 'Incompleted label',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'string' },
|
||||||
|
defaultValue: '#1B1F24',
|
||||||
|
},
|
||||||
|
accordian: 'steps',
|
||||||
|
},
|
||||||
|
completedAccent: {
|
||||||
|
type: 'colorSwatches',
|
||||||
|
displayName: 'Completed accent',
|
||||||
validation: {
|
validation: {
|
||||||
schema: { type: 'string' },
|
schema: { type: 'string' },
|
||||||
defaultValue: 'var(--primary-brand)',
|
defaultValue: 'var(--primary-brand)',
|
||||||
},
|
},
|
||||||
|
accordian: 'steps',
|
||||||
},
|
},
|
||||||
textColor: {
|
completedLabel: {
|
||||||
type: 'colorSwatches',
|
type: 'colorSwatches',
|
||||||
displayName: 'Text color',
|
displayName: 'Completed label',
|
||||||
validation: {
|
validation: {
|
||||||
schema: { type: 'string' },
|
schema: { type: 'string' },
|
||||||
defaultValue: '#000000',
|
defaultValue: '#1B1F24',
|
||||||
},
|
},
|
||||||
|
accordian: 'steps',
|
||||||
},
|
},
|
||||||
theme: {
|
currentStepLabel: {
|
||||||
type: 'select',
|
type: 'colorSwatches',
|
||||||
displayName: 'Theme',
|
displayName: 'Current step label',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'string' },
|
||||||
|
defaultValue: '#1B1F24',
|
||||||
|
},
|
||||||
|
accordian: 'steps',
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
type: 'switch',
|
||||||
|
displayName: 'Padding',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||||
|
defaultValue: 'default',
|
||||||
|
},
|
||||||
options: [
|
options: [
|
||||||
{ name: 'titles', value: 'titles' },
|
{ displayName: 'Default', value: 'default' },
|
||||||
{ name: 'numbers', value: 'numbers' },
|
{ displayName: 'None', value: 'none' },
|
||||||
{ name: 'plain', value: 'plain' },
|
|
||||||
],
|
],
|
||||||
validation: {
|
accordian: 'container',
|
||||||
schema: { type: 'string' },
|
|
||||||
defaultValue: 'titles',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
visibility: {
|
|
||||||
type: 'toggle',
|
|
||||||
displayName: 'Visibility',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'boolean' },
|
|
||||||
defaultValue: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
exposedVariables: {
|
exposedVariables: {
|
||||||
|
|
@ -92,17 +216,35 @@ export const stepsConfig = {
|
||||||
},
|
},
|
||||||
properties: {
|
properties: {
|
||||||
steps: {
|
steps: {
|
||||||
value: `{{ [{ name: 'step 1', tooltip: 'some tooltip', id: 1},{ name: 'step 2', tooltip: 'some tooltip', id: 2},{ name: 'step 3', tooltip: 'some tooltip', id: 3},{ name: 'step 4', tooltip: 'some tooltip', id: 4},{ name: 'step 5', tooltip: 'some tooltip', id: 5}]}}`,
|
value: [
|
||||||
|
{ name: 'step 1', tooltip: '', id: 1, visible: { value: true }, disabled: { value: false } },
|
||||||
|
{ name: 'step 2', tooltip: '', id: 2, visible: { value: true }, disabled: { value: false } },
|
||||||
|
{ name: 'step 3', tooltip: '', id: 3, visible: { value: true }, disabled: { value: false } },
|
||||||
|
{ name: 'step 4', tooltip: '', id: 4, visible: { value: true }, disabled: { value: false } },
|
||||||
|
{ name: 'step 5', tooltip: '', id: 5, visible: { value: true }, disabled: { value: false } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
schema: {
|
||||||
|
value: `{{ [{ name: 'step 1', tooltip: '', id: 1,visible: true, disabled: false},{ name: 'step 2', tooltip: '', id: 2,visible: true, disabled: false},{ name: 'step 3', tooltip: '', id: 3,visible: true, disabled: false},{ name: 'step 4', tooltip: '', id: 4,visible: true, disabled: false},{ name: 'step 5', tooltip: '', id: 5,visible: true, disabled: false}]}}`,
|
||||||
|
},
|
||||||
|
disabledState: { value: '{{false}}' },
|
||||||
|
variant: { value: 'titles' },
|
||||||
currentStep: { value: '{{3}}' },
|
currentStep: { value: '{{3}}' },
|
||||||
stepsSelectable: { value: true },
|
stepsSelectable: { value: true },
|
||||||
|
advanced: { value: `{{false}}` },
|
||||||
|
visibility: { value: '{{true}}' },
|
||||||
},
|
},
|
||||||
events: [],
|
events: [],
|
||||||
styles: {
|
styles: {
|
||||||
visibility: { value: '{{true}}' },
|
visibility: { value: '{{true}}' },
|
||||||
theme: { value: 'titles' },
|
// color: { value: '' },
|
||||||
color: { value: 'var(--primary-brand)' },
|
// textColor: { value: '' },
|
||||||
textColor: { value: '' },
|
padding: { value: 'default' },
|
||||||
|
incompletedAccent: { value: '#E4E7EB' },
|
||||||
|
incompletedLabel: { value: '#1B1F24' },
|
||||||
|
completedAccent: { value: 'var(--primary-brand)' },
|
||||||
|
completedLabel: { value: '#1B1F24' },
|
||||||
|
currentStepLabel: { value: '#1B1F24' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ function usePopoverObserver(containerRef, triggerRef, popoverRef, show, onShow,
|
||||||
const prevShow = useRef(false);
|
const prevShow = useRef(false);
|
||||||
|
|
||||||
// Check if it is a ref or a DOM element
|
// Check if it is a ref or a DOM element
|
||||||
const container = containerRef?.current ? containerRef.current : containerRef;
|
const container = containerRef?.current !== undefined ? containerRef.current : containerRef;
|
||||||
const trigger = triggerRef?.current ? triggerRef.current : triggerRef;
|
const trigger = triggerRef?.current !== undefined ? triggerRef.current : triggerRef;
|
||||||
const popover = popoverRef?.current ? popoverRef.current : popoverRef;
|
const popover = popoverRef?.current !== undefined ? popoverRef.current : popoverRef;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!container || !trigger) return;
|
if (!container || !trigger) return;
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,11 @@ export const createDataQuerySlice = (set, get) => ({
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.dataQuery.creatingQueryInProcessId = null;
|
state.dataQuery.creatingQueryInProcessId = null;
|
||||||
state.dataQuery.queries.modules[moduleId] = [
|
state.dataQuery.queries.modules[moduleId] = [
|
||||||
{ ...data, data_source_id: queryToClone.data_source_id },
|
{
|
||||||
|
...data,
|
||||||
|
data_source_id: queryToClone.data_source_id,
|
||||||
|
plugin: { iconFile: queryToClone.plugin?.iconFile, icon_file: queryToClone.plugin?.icon_file },
|
||||||
|
},
|
||||||
...state.dataQuery.queries.modules[moduleId],
|
...state.dataQuery.queries.modules[moduleId],
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ export const createResolvedSlice = (set, get) => ({
|
||||||
'setVariables'
|
'setVariables'
|
||||||
);
|
);
|
||||||
get().updateDependencyValues(`variables.${key}`);
|
get().updateDependencyValues(`variables.${key}`);
|
||||||
|
get().checkAndSetTrueBuildSuggestionsFlag();
|
||||||
},
|
},
|
||||||
|
|
||||||
getVariable: (key, moduleId = 'canvas') => {
|
getVariable: (key, moduleId = 'canvas') => {
|
||||||
|
|
@ -165,6 +166,7 @@ export const createResolvedSlice = (set, get) => ({
|
||||||
'setPageVariable'
|
'setPageVariable'
|
||||||
);
|
);
|
||||||
get().updateDependencyValues(`page.variables.${key}`);
|
get().updateDependencyValues(`page.variables.${key}`);
|
||||||
|
get().checkAndSetTrueBuildSuggestionsFlag();
|
||||||
},
|
},
|
||||||
|
|
||||||
getPageVariable: (key, moduleId = 'canvas') => {
|
getPageVariable: (key, moduleId = 'canvas') => {
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,36 @@
|
||||||
export const ActionTypes = [
|
export const ActionTypes = [
|
||||||
|
{
|
||||||
|
name: 'Run query',
|
||||||
|
id: 'run-query',
|
||||||
|
options: [{ queryId: '' }],
|
||||||
|
group: 'run-action',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Show Alert',
|
name: 'Show Alert',
|
||||||
id: 'show-alert',
|
id: 'show-alert',
|
||||||
options: [{ name: 'message', type: 'text', default: 'Message !' }],
|
options: [{ name: 'message', type: 'text', default: 'Message !' }],
|
||||||
|
group: 'run-action',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Logout',
|
name: 'Control component',
|
||||||
id: 'logout',
|
id: 'control-component',
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Run Query',
|
|
||||||
id: 'run-query',
|
|
||||||
options: [{ queryId: '' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Open Webpage',
|
|
||||||
id: 'open-webpage',
|
|
||||||
options: [{ name: 'url', type: 'text', default: 'https://example.com' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Go to app',
|
|
||||||
id: 'go-to-app',
|
|
||||||
options: [
|
options: [
|
||||||
{ name: 'app', type: 'text', default: '' },
|
{ name: 'component', type: 'text', default: '' },
|
||||||
{ name: 'queryParams', type: 'code', default: '[]' },
|
{ name: 'action', type: 'text', default: '' },
|
||||||
],
|
],
|
||||||
|
group: 'control-component',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Show Modal',
|
name: 'Show modal',
|
||||||
id: 'show-modal',
|
id: 'show-modal',
|
||||||
options: [{ name: 'modal', type: 'text', default: '' }],
|
options: [{ name: 'modal', type: 'text', default: '' }],
|
||||||
|
group: 'control-component',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Close Modal',
|
name: 'Close modal',
|
||||||
id: 'close-modal',
|
id: 'close-modal',
|
||||||
options: [{ name: 'modal', type: 'text', default: '' }],
|
options: [{ name: 'modal', type: 'text', default: '' }],
|
||||||
},
|
group: 'control-component',
|
||||||
{
|
|
||||||
name: 'Copy to clipboard',
|
|
||||||
id: 'copy-to-clipboard',
|
|
||||||
options: [{ name: 'copy-to-clipboard', type: 'text', default: '' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Set local storage',
|
|
||||||
id: 'set-localstorage-value',
|
|
||||||
options: [
|
|
||||||
{ name: 'key', type: 'code', default: '' },
|
|
||||||
{ name: 'value', type: 'code', default: '' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Generate file',
|
|
||||||
id: 'generate-file',
|
|
||||||
options: [
|
|
||||||
{ name: 'fileType', type: 'text', default: '' },
|
|
||||||
{ name: 'fileName', type: 'text', default: '' },
|
|
||||||
{ name: 'data', type: 'code', default: '{{[]}}' },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Set table page',
|
name: 'Set table page',
|
||||||
|
|
@ -69,28 +43,28 @@ export const ActionTypes = [
|
||||||
},
|
},
|
||||||
{ name: 'pageIndex', type: 'text', default: '{{1}}' },
|
{ name: 'pageIndex', type: 'text', default: '{{1}}' },
|
||||||
],
|
],
|
||||||
},
|
group: 'control-component',
|
||||||
{
|
|
||||||
name: 'Set variable',
|
|
||||||
id: 'set-custom-variable',
|
|
||||||
options: [
|
|
||||||
{ name: 'key', type: 'code', default: '' },
|
|
||||||
{ name: 'value', type: 'code', default: '' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Unset all variables',
|
|
||||||
id: 'unset-all-custom-variables',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Unset variable',
|
|
||||||
id: 'unset-custom-variable',
|
|
||||||
options: [{ name: 'key', type: 'code', default: '' }],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Switch page',
|
name: 'Switch page',
|
||||||
id: 'switch-page',
|
id: 'switch-page',
|
||||||
options: [{ name: 'page', type: 'text', default: '' }],
|
options: [{ name: 'page', type: 'text', default: '' }],
|
||||||
|
group: 'navigation',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Go to app',
|
||||||
|
id: 'go-to-app',
|
||||||
|
options: [
|
||||||
|
{ name: 'app', type: 'text', default: '' },
|
||||||
|
{ name: 'queryParams', type: 'code', default: '[]' },
|
||||||
|
],
|
||||||
|
group: 'navigation',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Open webpage',
|
||||||
|
id: 'open-webpage',
|
||||||
|
options: [{ name: 'url', type: 'text', default: 'https://example.com' }],
|
||||||
|
group: 'navigation',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Set page variable',
|
name: 'Set page variable',
|
||||||
|
|
@ -99,10 +73,7 @@ export const ActionTypes = [
|
||||||
{ name: 'key', type: 'code', default: '' },
|
{ name: 'key', type: 'code', default: '' },
|
||||||
{ name: 'value', type: 'code', default: '' },
|
{ name: 'value', type: 'code', default: '' },
|
||||||
],
|
],
|
||||||
},
|
group: 'variable',
|
||||||
{
|
|
||||||
name: 'Unset all page variables',
|
|
||||||
id: 'unset-all-page-variables',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Unset page variable',
|
name: 'Unset page variable',
|
||||||
|
|
@ -111,14 +82,61 @@ export const ActionTypes = [
|
||||||
{ name: 'key', type: 'code', default: '' },
|
{ name: 'key', type: 'code', default: '' },
|
||||||
{ name: 'value', type: 'code', default: '' },
|
{ name: 'value', type: 'code', default: '' },
|
||||||
],
|
],
|
||||||
|
group: 'variable',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: 'Control component',
|
name: 'Unset all page variables',
|
||||||
id: 'control-component',
|
id: 'unset-all-page-variables',
|
||||||
|
group: 'variable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Set variable',
|
||||||
|
id: 'set-custom-variable',
|
||||||
options: [
|
options: [
|
||||||
{ name: 'component', type: 'text', default: '' },
|
{ name: 'key', type: 'code', default: '' },
|
||||||
{ name: 'action', type: 'text', default: '' },
|
{ name: 'value', type: 'code', default: '' },
|
||||||
],
|
],
|
||||||
|
group: 'variable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Unset variable',
|
||||||
|
id: 'unset-custom-variable',
|
||||||
|
options: [{ name: 'key', type: 'code', default: '' }],
|
||||||
|
group: 'variable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Unset all variables',
|
||||||
|
id: 'unset-all-custom-variables',
|
||||||
|
group: 'variable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Logout',
|
||||||
|
id: 'logout',
|
||||||
|
group: 'other',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Generate file',
|
||||||
|
id: 'generate-file',
|
||||||
|
options: [
|
||||||
|
{ name: 'fileType', type: 'text', default: '' },
|
||||||
|
{ name: 'fileName', type: 'text', default: '' },
|
||||||
|
{ name: 'data', type: 'code', default: '{{[]}}' },
|
||||||
|
],
|
||||||
|
group: 'other',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Set local storage',
|
||||||
|
id: 'set-localstorage-value',
|
||||||
|
options: [
|
||||||
|
{ name: 'key', type: 'code', default: '' },
|
||||||
|
{ name: 'value', type: 'code', default: '' },
|
||||||
|
],
|
||||||
|
group: 'other',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Copy to clipboard',
|
||||||
|
id: 'copy-to-clipboard',
|
||||||
|
options: [{ name: 'copy-to-clipboard', type: 'text', default: '' }],
|
||||||
|
group: 'other',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
/* eslint-disable react/no-string-refs */
|
/* eslint-disable react/no-string-refs */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Editor, EditorState, RichUtils, getDefaultKeyBinding, ContentState, convertFromHTML } from 'draft-js';
|
import { Editor, EditorState, RichUtils, getDefaultKeyBinding } from 'draft-js';
|
||||||
import 'draft-js/dist/Draft.css';
|
import 'draft-js/dist/Draft.css';
|
||||||
|
import { stateFromHTML } from 'draft-js-import-html';
|
||||||
import { stateToHTML } from 'draft-js-export-html';
|
import { stateToHTML } from 'draft-js-export-html';
|
||||||
import Loader from '@/ToolJetUI/Loader/Loader';
|
import Loader from '@/ToolJetUI/Loader/Loader';
|
||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
|
|
@ -150,11 +151,8 @@ const InlineStyleControls = (props) => {
|
||||||
class DraftEditor extends React.Component {
|
class DraftEditor extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
const blocksFromHTML = convertFromHTML(DOMPurify.sanitize(this.props.defaultValue));
|
|
||||||
this.state = {
|
this.state = {
|
||||||
editorState: EditorState.createWithContent(
|
editorState: EditorState.createWithContent(stateFromHTML(DOMPurify.sanitize(this.props.defaultValue))),
|
||||||
ContentState.createFromBlockArray(blocksFromHTML.contentBlocks, blocksFromHTML.entityMap)
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.editorContainerRef = React.createRef();
|
this.editorContainerRef = React.createRef();
|
||||||
|
|
@ -173,6 +171,18 @@ class DraftEditor extends React.Component {
|
||||||
this.toggleInlineStyle = this._toggleInlineStyle.bind(this);
|
this.toggleInlineStyle = this._toggleInlineStyle.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps.defaultValue !== this.props.defaultValue) {
|
||||||
|
const newContentState = stateFromHTML(DOMPurify.sanitize(this.props.defaultValue));
|
||||||
|
const newEditorState = EditorState.createWithContent(newContentState);
|
||||||
|
const html = stateToHTML(newContentState);
|
||||||
|
|
||||||
|
this.props.handleChange(html);
|
||||||
|
|
||||||
|
this.setState({ editorState: newEditorState });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
//For resizing the editor container based on the height of rich text editor controls
|
//For resizing the editor container based on the height of rich text editor controls
|
||||||
this.resizeObserver = new ResizeObserver(() => {
|
this.resizeObserver = new ResizeObserver(() => {
|
||||||
|
|
@ -193,11 +203,7 @@ class DraftEditor extends React.Component {
|
||||||
isVisible: this.props.isVisible,
|
isVisible: this.props.isVisible,
|
||||||
isLoading: this.props.isLoading,
|
isLoading: this.props.isLoading,
|
||||||
setValue: async (text) => {
|
setValue: async (text) => {
|
||||||
const blocksFromHTML = convertFromHTML(DOMPurify.sanitize(text));
|
const newContentState = stateFromHTML(DOMPurify.sanitize(text));
|
||||||
const newContentState = ContentState.createFromBlockArray(
|
|
||||||
blocksFromHTML.contentBlocks,
|
|
||||||
blocksFromHTML.entityMap
|
|
||||||
);
|
|
||||||
const newEditorState = EditorState.createWithContent(newContentState);
|
const newEditorState = EditorState.createWithContent(newContentState);
|
||||||
const html = stateToHTML(newContentState);
|
const html = stateToHTML(newContentState);
|
||||||
this.props.handleChange(html);
|
this.props.handleChange(html);
|
||||||
|
|
@ -226,19 +232,6 @@ class DraftEditor extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
if (prevProps.defaultValue !== this.props.defaultValue) {
|
|
||||||
const blocksFromHTML = convertFromHTML(DOMPurify.sanitize(this.props.defaultValue));
|
|
||||||
const newContentState = ContentState.createFromBlockArray(blocksFromHTML.contentBlocks, blocksFromHTML.entityMap);
|
|
||||||
const newEditorState = EditorState.createWithContent(newContentState);
|
|
||||||
const html = stateToHTML(newContentState);
|
|
||||||
|
|
||||||
this.props.handleChange(html);
|
|
||||||
|
|
||||||
this.setState({ editorState: newEditorState });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleKeyCommand(command, editorState) {
|
_handleKeyCommand(command, editorState) {
|
||||||
const newState = RichUtils.handleKeyCommand(editorState, command);
|
const newState = RichUtils.handleKeyCommand(editorState, command);
|
||||||
if (newState) {
|
if (newState) {
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ export const RadioButtonV2 = ({
|
||||||
data-cy={`label-${String(componentName).toLowerCase()} `}
|
data-cy={`label-${String(componentName).toLowerCase()} `}
|
||||||
data-disabled={isDisabled}
|
data-disabled={isDisabled}
|
||||||
id={String(componentName)}
|
id={String(componentName)}
|
||||||
className={cx('radio-button,', 'd-flex', {
|
className={cx('radio-button', 'd-flex', {
|
||||||
[alignment === 'top' &&
|
[alignment === 'top' &&
|
||||||
((labelWidth != 0 && label?.length != 0) ||
|
((labelWidth != 0 && label?.length != 0) ||
|
||||||
(labelAutoWidth && labelWidth == 0 && label && label?.length != 0))
|
(labelAutoWidth && labelWidth == 0 && label && label?.length != 0))
|
||||||
|
|
@ -279,7 +279,7 @@ export const RadioButtonV2 = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${isValid ? '' : visibility ? 'd-flex' : 'none'}`}
|
className={`${isValid ? 'd-none' : visibility ? 'd-flex' : 'd-none'}`}
|
||||||
style={{
|
style={{
|
||||||
color: 'var(--status-error-strong)',
|
color: 'var(--status-error-strong)',
|
||||||
justifyContent: direction === 'right' ? 'flex-start' : 'flex-end',
|
justifyContent: direction === 'right' ? 'flex-start' : 'flex-end',
|
||||||
|
|
|
||||||
|
|
@ -1,53 +1,226 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
import { isExpectedDataType } from '@/_helpers/utils';
|
import { isExpectedDataType } from '@/_helpers/utils';
|
||||||
|
import { ToolTip } from '@/_components/ToolTip';
|
||||||
|
import './Steps.scss';
|
||||||
|
|
||||||
export const Steps = function Button({ properties, styles, fireEvent, setExposedVariable, height, darkMode, dataCy }) {
|
export const Steps = function Steps({ properties, styles, fireEvent, setExposedVariable, height, darkMode, dataCy }) {
|
||||||
const { stepsSelectable } = properties;
|
const { stepsSelectable, disabledState } = properties;
|
||||||
const currentStep = isExpectedDataType(properties.currentStep, 'number');
|
const visibility = isExpectedDataType(properties.visibility, 'boolean');
|
||||||
const steps = isExpectedDataType(properties.steps, 'array');
|
const currentStepId = isExpectedDataType(properties.currentStep, 'number');
|
||||||
const { color, theme, visibility, boxShadow } = styles;
|
const isDynamicStepsEnabled = isExpectedDataType(properties.advanced, 'boolean');
|
||||||
|
const steps = isDynamicStepsEnabled ? properties.schema : properties.steps;
|
||||||
|
const { color, boxShadow } = styles;
|
||||||
const textColor = darkMode && styles.textColor === '#000' ? '#fff' : styles.textColor;
|
const textColor = darkMode && styles.textColor === '#000' ? '#fff' : styles.textColor;
|
||||||
const [activeStep, setActiveStep] = useState(null);
|
const { completedAccent, incompletedAccent, incompletedLabel, completedLabel, currentStepLabel } = styles;
|
||||||
|
const [stepsArr, setStepsArr] = useState(steps);
|
||||||
|
const [isVisible, setIsVisible] = useState(visibility);
|
||||||
|
const [isDisabled, setIsDisabled] = useState(disabledState);
|
||||||
|
const [activeStepId, setActiveStepId] = useState(currentStepId);
|
||||||
|
const theme = properties.variant;
|
||||||
|
const [progressBarWidth, setProgressBarWidth] = useState(0);
|
||||||
|
const [containerPadding, setContainerPadding] = useState(0);
|
||||||
|
const [containerWidth, setContainerWidth] = useState(0);
|
||||||
|
const [filteredSteps, setFilteredSteps] = useState([]);
|
||||||
|
const firstLabelRef = useRef(null);
|
||||||
|
const lastLabelRef = useRef(null);
|
||||||
|
const containerRef = useRef(null);
|
||||||
|
|
||||||
|
const currentStepIndex = filteredSteps.findIndex((step) => step.id == activeStepId);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const sanitizedSteps = JSON.parse(JSON.stringify(steps || [])).map((step) => ({
|
||||||
|
...step,
|
||||||
|
visible: 'visible' in step ? step.visible : true,
|
||||||
|
disabled: 'disabled' in step ? step.disabled : false,
|
||||||
|
}));
|
||||||
|
const newFilteredSteps = (sanitizedSteps || []).filter((step) => step.visible);
|
||||||
|
setFilteredSteps(newFilteredSteps);
|
||||||
|
setStepsArr(sanitizedSteps);
|
||||||
|
}, [JSON.stringify(steps)]);
|
||||||
|
|
||||||
|
// Common function to calculate progress bar width and label padding
|
||||||
|
const calculateProgressBarWidth = () => {
|
||||||
|
if (!containerRef.current || theme !== 'titles') return;
|
||||||
|
|
||||||
|
const containerWidth = containerRef.current.offsetWidth;
|
||||||
|
setContainerWidth(containerWidth);
|
||||||
|
|
||||||
|
const stepWidth = 20; // width of dot + padding
|
||||||
|
const totalStepsWidth = filteredSteps.length * stepWidth;
|
||||||
|
const totalProgressBars = filteredSteps.length - 1;
|
||||||
|
|
||||||
|
if (filteredSteps.length === 1) {
|
||||||
|
setProgressBarWidth(containerWidth);
|
||||||
|
setContainerPadding(0); // No padding needed for single step
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate progress bar width
|
||||||
|
const progressBarWidth = (containerWidth - totalStepsWidth) / totalProgressBars;
|
||||||
|
setProgressBarWidth(Math.min(progressBarWidth, (containerWidth - totalStepsWidth) / filteredSteps.length));
|
||||||
|
|
||||||
|
// Calculate container padding
|
||||||
|
if (firstLabelRef.current && lastLabelRef.current) {
|
||||||
|
const labelWidth = (containerWidth - (filteredSteps.length - 1) - 4) / filteredSteps.length;
|
||||||
|
|
||||||
|
const firstLabelWidth = firstLabelRef.current.offsetWidth;
|
||||||
|
const lastLabelWidth = lastLabelRef.current.offsetWidth;
|
||||||
|
const maxLabelWidth = Math.max(firstLabelWidth, lastLabelWidth);
|
||||||
|
|
||||||
|
const calculatedPadding = (maxLabelWidth / 2) - 1;
|
||||||
|
setContainerPadding(Math.max(2, calculatedPadding)); // Ensure minimum padding of 2px
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add resize observer to track container width and calculate progress bar width
|
||||||
|
useEffect(() => {
|
||||||
|
calculateProgressBarWidth();
|
||||||
|
if (theme !== 'titles') return;
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
calculateProgressBarWidth();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (containerRef.current) {
|
||||||
|
resizeObserver.observe(containerRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => resizeObserver.disconnect();
|
||||||
|
}, [theme, JSON.stringify(steps), filteredSteps]);
|
||||||
|
// Dynamic styles for theming
|
||||||
const dynamicStyle = {
|
const dynamicStyle = {
|
||||||
'--bgColor': styles.color,
|
'--bgColor': styles.color,
|
||||||
'--textColor': textColor,
|
'--textColor': textColor,
|
||||||
};
|
'--completedAccent': completedAccent === '#4368E3' ? 'var(--primary-brand)' : completedAccent,
|
||||||
const activeStepHandler = (id) => {
|
'--incompletedAccent': incompletedAccent === '#E4E7EB' ? 'var(--surfaces-surface-03)' : incompletedAccent,
|
||||||
const active = steps.filter((item) => item.id == id);
|
'--incompletedLabel': incompletedLabel === '#1B1F24' ? 'var(--text-primary)' : incompletedLabel,
|
||||||
setExposedVariable('currentStepId', active[0].id);
|
'--completedLabel': completedLabel === '#1B1F24' ? 'var(--text-primary)' : completedLabel,
|
||||||
fireEvent('onSelect');
|
'--currentStepLabel': currentStepLabel === '#1B1F24' ? 'var(--text-primary)' : currentStepLabel,
|
||||||
setActiveStep(active[0].id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Step click handler
|
||||||
|
const handleStepClick = (id) => {
|
||||||
|
const step = filteredSteps.find((item) => item.id == id);
|
||||||
|
if (step && !step.disabled && !isDisabled) {
|
||||||
|
setActiveStepId(step.id);
|
||||||
|
fireEvent('onSelect');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expose variables and methods
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setActiveStep(currentStep);
|
setExposedVariable('isVisible', isVisible);
|
||||||
setExposedVariable('currentStepId', currentStep);
|
setExposedVariable('isDisabled', isDisabled);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
setExposedVariable('currentStepId', activeStepId);
|
||||||
}, [currentStep]);
|
setExposedVariable('steps', stepsArr);
|
||||||
|
|
||||||
|
setExposedVariable('setStepVisible', (stepId, visibility) => {
|
||||||
|
setStepsArr((prev) => {
|
||||||
|
const updatedSteps = prev.map((item) =>
|
||||||
|
item.id == stepId ? { ...item, visible: visibility } : item
|
||||||
|
);
|
||||||
|
setExposedVariable('steps', updatedSteps);
|
||||||
|
return updatedSteps;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setExposedVariable('setStepDisable', (stepId, disabled) => {
|
||||||
|
setStepsArr((prev) => {
|
||||||
|
const updatedSteps = prev.map((item) =>
|
||||||
|
item.id == stepId ? { ...item, disabled: disabled } : item
|
||||||
|
);
|
||||||
|
setExposedVariable('steps', updatedSteps);
|
||||||
|
return updatedSteps;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setExposedVariable('resetSteps', () => {
|
||||||
|
setActiveStepId(stepsArr.filter((step) => step.visible)?.[0]?.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
setExposedVariable('setStep', (stepId) => {
|
||||||
|
if (!disabledState) setActiveStepId(stepId);
|
||||||
|
});
|
||||||
|
setExposedVariable('setVisibility', (visibility) => setIsVisible(visibility));
|
||||||
|
setExposedVariable('setDisable', (disabled) => setIsDisabled(disabled));
|
||||||
|
}, [isVisible, isDisabled, activeStepId, stepsArr, disabledState]);
|
||||||
|
|
||||||
|
// Update state from props
|
||||||
|
useEffect(() => setIsVisible(visibility), [visibility]);
|
||||||
|
useEffect(() => setIsDisabled(disabledState), [disabledState]);
|
||||||
|
useEffect(() => setActiveStepId(currentStepId), [currentStepId]);
|
||||||
|
|
||||||
|
if (!isVisible) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
visibility && (
|
<div
|
||||||
<div
|
ref={containerRef}
|
||||||
className={`steps ${theme == 'numbers' && 'steps-counter '}`}
|
className={`steps-container ${isDisabled ? 'disabled' : ''} ${filteredSteps.length === 1 ? 'single-step' : ''}`}
|
||||||
style={{ color: textColor, height, boxShadow }}
|
style={{
|
||||||
data-cy={dataCy}
|
height,
|
||||||
>
|
boxShadow,
|
||||||
{steps?.map((item) => (
|
padding: theme === 'titles' ? `0 ${containerPadding}px` : 2,
|
||||||
<a
|
paddingTop: theme === 'plain' ? `3px` : theme === 'numbers' ? `2px` : 0,
|
||||||
key={item.id}
|
...dynamicStyle
|
||||||
className={`step-item ${item.id == activeStep && 'active'} ${!stepsSelectable && 'step-item-disabled'} ${
|
}}
|
||||||
color && `step-${color}`
|
data-cy={dataCy}
|
||||||
}`}
|
>
|
||||||
data-bs-toggle="tooltip"
|
<div className={`progress-line-container ${filteredSteps.length === 1 ? 'single-step' : ''}`}>
|
||||||
title={item?.tooltip}
|
{filteredSteps.map((step, index) => {
|
||||||
onClick={() => stepsSelectable && activeStepHandler(item.id)}
|
const isStepDisabled = step.disabled;
|
||||||
style={dynamicStyle}
|
const isCompleted = index < currentStepIndex;
|
||||||
>
|
const isActive = index === currentStepIndex;
|
||||||
{theme == 'titles' && item.name}
|
const isUpcoming = index > currentStepIndex;
|
||||||
</a>
|
const isFirstStep = index === 0;
|
||||||
))}
|
const isLastStep = index === filteredSteps.length - 1;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment key={index}> {/* using index as key to avoid issues due to duplicate step ids */}
|
||||||
|
<ToolTip
|
||||||
|
show={!step.disabled && !isDisabled && step.tooltip}
|
||||||
|
message={step.tooltip || ''}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
onClick={() => stepsSelectable && handleStepClick(step.id)}
|
||||||
|
className={`milestone ${theme === 'numbers' ? 'numbers' : ''} ${isDisabled || isStepDisabled ? 'disabled' : ''
|
||||||
|
} ${isCompleted ? 'completed' : isActive ? 'active' : 'incomplete'}`}
|
||||||
|
>
|
||||||
|
{theme === 'numbers' ? (
|
||||||
|
index + 1
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={`dot ${isCompleted ? 'completed' : isActive ? 'active' : 'incomplete'}`}
|
||||||
|
style={{
|
||||||
|
border: `2px solid ${isCompleted ? completedAccent : isActive ? completedAccent : incompletedAccent}`,
|
||||||
|
backgroundColor: isActive ? 'transparent' : (isCompleted ? completedAccent : incompletedAccent)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{theme === 'titles' && (
|
||||||
|
<div
|
||||||
|
ref={isFirstStep ? firstLabelRef : isLastStep ? lastLabelRef : null}
|
||||||
|
className={`label ${isCompleted ? 'completed' : isActive ? 'active' : 'incomplete'}`}
|
||||||
|
style={{ maxWidth: `${progressBarWidth}px` }}
|
||||||
|
>
|
||||||
|
{step.name}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ToolTip>
|
||||||
|
|
||||||
|
{index < filteredSteps.length - 1 && (
|
||||||
|
<div
|
||||||
|
className={`step-connector ${isCompleted ? 'completed' : 'incomplete'}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
132
frontend/src/Editor/Components/Steps.scss
Normal file
132
frontend/src/Editor/Components/Steps.scss
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
.steps-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.single-step {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-line-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
|
&.single-step {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.milestone {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.numbers {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
box-sizing: content-box;
|
||||||
|
|
||||||
|
&.completed {
|
||||||
|
background-color: var(--completedAccent);
|
||||||
|
color: var(--completedLabel);
|
||||||
|
border: 2px solid var(--completedAccent);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: var(--currentStepLabel);
|
||||||
|
border: 2px solid var(--completedAccent);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.incomplete {
|
||||||
|
background-color: var(--incompletedAccent);
|
||||||
|
color: var(--incompletedLabel);
|
||||||
|
border: 2px solid var(--incompletedAccent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
width: 0.5rem;
|
||||||
|
height: 0.5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-sizing: content-box;
|
||||||
|
|
||||||
|
&.completed {
|
||||||
|
background-color: var(--completedAccent);
|
||||||
|
border: 2px solid var(--completedAccent);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: white;
|
||||||
|
border: 2px solid var(--primary-brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.incomplete {
|
||||||
|
background-color: var(--incompletedAccent);
|
||||||
|
border: 2px solid var(--incompletedAccent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 2px;
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: max-content;
|
||||||
|
|
||||||
|
&.completed {
|
||||||
|
color: var(--completedLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: var(--completedLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.incomplete {
|
||||||
|
color: var(--incompletedLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-connector {
|
||||||
|
flex-grow: 1;
|
||||||
|
height: 2px;
|
||||||
|
align-self: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&.completed {
|
||||||
|
background-color: var(--completedAccent);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.incomplete {
|
||||||
|
background-color: var(--incompletedAccent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,8 +3,8 @@ export const containerConfig = {
|
||||||
displayName: 'Container',
|
displayName: 'Container',
|
||||||
description: 'Group components',
|
description: 'Group components',
|
||||||
defaultSize: {
|
defaultSize: {
|
||||||
width: 10,
|
width: 13,
|
||||||
height: 200,
|
height: 480,
|
||||||
},
|
},
|
||||||
component: 'Container',
|
component: 'Container',
|
||||||
others: {
|
others: {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ import { verticalDividerConfig } from './verticalDivider';
|
||||||
import { customComponentConfig } from './customComponent';
|
import { customComponentConfig } from './customComponent';
|
||||||
import { buttonGroupConfig } from './buttonGroup';
|
import { buttonGroupConfig } from './buttonGroup';
|
||||||
import { pdfConfig } from './pdf';
|
import { pdfConfig } from './pdf';
|
||||||
import { stepsConfig } from './steps';
|
// import { stepsConfig } from './steps';
|
||||||
import { kanbanConfig } from './kanban';
|
import { kanbanConfig } from './kanban';
|
||||||
import { colorPickerConfig } from './colorPicker';
|
import { colorPickerConfig } from './colorPicker';
|
||||||
import { treeSelectConfig } from './treeSelect';
|
import { treeSelectConfig } from './treeSelect';
|
||||||
|
|
@ -106,7 +106,7 @@ export {
|
||||||
customComponentConfig,
|
customComponentConfig,
|
||||||
buttonGroupConfig,
|
buttonGroupConfig,
|
||||||
pdfConfig,
|
pdfConfig,
|
||||||
stepsConfig,
|
// stepsConfig,
|
||||||
kanbanConfig,
|
kanbanConfig,
|
||||||
kanbanBoardConfig, //!Depreciated
|
kanbanBoardConfig, //!Depreciated
|
||||||
colorPickerConfig,
|
colorPickerConfig,
|
||||||
|
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
export const stepsConfig = {
|
|
||||||
name: 'Steps',
|
|
||||||
displayName: 'Steps',
|
|
||||||
description: 'Step-by-step navigation aid',
|
|
||||||
component: 'Steps',
|
|
||||||
properties: {
|
|
||||||
steps: {
|
|
||||||
type: 'code',
|
|
||||||
displayName: 'Steps',
|
|
||||||
validation: {
|
|
||||||
schema: {
|
|
||||||
type: 'array',
|
|
||||||
element: { type: 'object', object: { id: { type: 'number' } } },
|
|
||||||
},
|
|
||||||
defaultValue: `[{ name: 'step 1'}, {name: 'step 2'}]`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
currentStep: {
|
|
||||||
type: 'code',
|
|
||||||
displayName: 'Current step',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'number' },
|
|
||||||
defaultValue: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
stepsSelectable: {
|
|
||||||
type: 'toggle',
|
|
||||||
displayName: 'Steps selectable',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'boolean' },
|
|
||||||
defaultValue: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultSize: {
|
|
||||||
width: 22,
|
|
||||||
height: 38,
|
|
||||||
},
|
|
||||||
others: {
|
|
||||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
|
||||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
|
||||||
},
|
|
||||||
events: {
|
|
||||||
onSelect: { displayName: 'On select' },
|
|
||||||
},
|
|
||||||
styles: {
|
|
||||||
color: {
|
|
||||||
type: 'color',
|
|
||||||
displayName: 'Color',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'string' },
|
|
||||||
defaultValue: '#000000',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
textColor: {
|
|
||||||
type: 'color',
|
|
||||||
displayName: 'Text color',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'string' },
|
|
||||||
defaultValue: '#000000',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
theme: {
|
|
||||||
type: 'select',
|
|
||||||
displayName: 'Theme',
|
|
||||||
options: [
|
|
||||||
{ name: 'titles', value: 'titles' },
|
|
||||||
{ name: 'numbers', value: 'numbers' },
|
|
||||||
{ name: 'plain', value: 'plain' },
|
|
||||||
],
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'string' },
|
|
||||||
defaultValue: 'titles',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
visibility: {
|
|
||||||
type: 'toggle',
|
|
||||||
displayName: 'Visibility',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'boolean' },
|
|
||||||
defaultValue: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
exposedVariables: {
|
|
||||||
currentStepId: '3',
|
|
||||||
},
|
|
||||||
definition: {
|
|
||||||
others: {
|
|
||||||
showOnDesktop: { value: '{{true}}' },
|
|
||||||
showOnMobile: { value: '{{false}}' },
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
steps: {
|
|
||||||
value: `{{ [{ name: 'step 1', tooltip: 'some tooltip', id: 1},{ name: 'step 2', tooltip: 'some tooltip', id: 2},{ name: 'step 3', tooltip: 'some tooltip', id: 3},{ name: 'step 4', tooltip: 'some tooltip', id: 4},{ name: 'step 5', tooltip: 'some tooltip', id: 5}]}}`,
|
|
||||||
},
|
|
||||||
currentStep: { value: '{{3}}' },
|
|
||||||
stepsSelectable: { value: true },
|
|
||||||
},
|
|
||||||
events: [],
|
|
||||||
styles: {
|
|
||||||
visibility: { value: '{{true}}' },
|
|
||||||
theme: { value: 'titles' },
|
|
||||||
color: { value: '' },
|
|
||||||
textColor: { value: '' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
@ -7675,29 +7675,33 @@ fieldset:disabled .btn {
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded {
|
.rounded {
|
||||||
border-radius: 4px ;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-0 {
|
.rounded-0 {
|
||||||
border-radius: 0 !important
|
border-radius: 0 !important
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-top-left{
|
.rounded-top-left {
|
||||||
border-top-left-radius: 4px;
|
border-top-left-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-top-left-0{
|
.rounded-top-left-0 {
|
||||||
border-top-left-radius: 0 !important;
|
border-top-left-radius: 0 !important;
|
||||||
}
|
}
|
||||||
.rounded-top-right-0{
|
|
||||||
|
.rounded-top-right-0 {
|
||||||
border-top-right-radius: 0 !important;
|
border-top-right-radius: 0 !important;
|
||||||
}
|
}
|
||||||
.rounded-bottom-left-0{
|
|
||||||
|
.rounded-bottom-left-0 {
|
||||||
border-bottom-left-radius: 0 !important;
|
border-bottom-left-radius: 0 !important;
|
||||||
}
|
}
|
||||||
.rounded-bottom-right-0{
|
|
||||||
|
.rounded-bottom-right-0 {
|
||||||
border-bottom-right-radius: 0 !important;
|
border-bottom-right-radius: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-1 {
|
.rounded-1 {
|
||||||
border-radius: 2px !important
|
border-radius: 2px !important
|
||||||
}
|
}
|
||||||
|
|
@ -17484,8 +17488,8 @@ a.step-item:hover {
|
||||||
|
|
||||||
.step-item:not(:first-child):after {
|
.step-item:not(:first-child):after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -50%;
|
left: calc(-50% + 8px);
|
||||||
width: 100%;
|
width: calc(100% - 16px);
|
||||||
content: "";
|
content: "";
|
||||||
transform: translateY(-50%)
|
transform: translateY(-50%)
|
||||||
}
|
}
|
||||||
|
|
@ -17498,13 +17502,25 @@ a.step-item:hover {
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
display: block;
|
display: block;
|
||||||
content: "";
|
content: "";
|
||||||
border: 2px solid #fff;
|
border: 2px solid transparent;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
transform: translateX(-50%)
|
transform: translateX(-50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-item.active {
|
.steps.steps-counter {
|
||||||
font-weight: 600
|
.step-item:not(:first-child):after {
|
||||||
|
left: calc(-50% + 16px) !important;
|
||||||
|
width: calc(100% - 32px) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.steps-counter .step-item:before {
|
||||||
|
color:var(--completedLabel) !important;
|
||||||
|
}
|
||||||
|
.steps .step-item.active:before{
|
||||||
|
color : var(--currentStepLabel) !important;
|
||||||
|
}
|
||||||
|
.step-item {
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-item.active:before {
|
.step-item.active:before {
|
||||||
|
|
@ -17521,7 +17537,7 @@ a.step-item:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-item.active~.step-item:before {
|
.step-item.active~.step-item:before {
|
||||||
color: #656d77 !important
|
color: var(--incompletedLabel) !important
|
||||||
}
|
}
|
||||||
|
|
||||||
.steps-counter {
|
.steps-counter {
|
||||||
|
|
@ -17549,7 +17565,8 @@ a.step-item:hover {
|
||||||
.steps-counter .step-item:before {
|
.steps-counter .step-item:before {
|
||||||
font-size: .75rem;
|
font-size: .75rem;
|
||||||
line-height: 1.5rem;
|
line-height: 1.5rem;
|
||||||
content: counter(steps)
|
content: counter(steps);
|
||||||
|
font-weight: 500 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.steps-counter .step-item.active~.step-item:before {
|
.steps-counter .step-item.active~.step-item:before {
|
||||||
|
|
|
||||||
|
|
@ -4761,14 +4761,17 @@ input[type="text"] {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: #888 transparent;
|
scrollbar-color: #888 transparent;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: block;
|
display: block;
|
||||||
width: 5px;
|
width: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background-color: #888;
|
background-color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
&::-webkit-scrollbar-track {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
@ -6518,6 +6521,7 @@ div#driver-page-overlay {
|
||||||
// steps-widget
|
// steps-widget
|
||||||
a.step-item-disabled {
|
a.step-item-disabled {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.steps {
|
.steps {
|
||||||
|
|
@ -6527,34 +6531,45 @@ a.step-item-disabled {
|
||||||
|
|
||||||
.step-item.active~.step-item:after,
|
.step-item.active~.step-item:after,
|
||||||
.step-item.active~.step-item:before {
|
.step-item.active~.step-item:before {
|
||||||
background: #f3f5f5 !important;
|
background: var(--incompletedAccent) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-item.active:before {
|
.step-item.active:before {
|
||||||
background: #ffffff !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.steps .step-item.active:before {
|
.steps .step-item.active:before {
|
||||||
border-color: #b4b2b2 !important;
|
border-color: var(--completedAccent) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.steps-item {
|
.steps-item {
|
||||||
color: var(--textColor) !important;
|
color: var(--textColor) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.step-item {
|
||||||
|
&.completed-label {
|
||||||
|
color: var(--completedLabel) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.incompleted-label {
|
||||||
|
color: var(--incompletedLabel) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active-label {
|
||||||
|
color: var(--currentStepLabel) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.step-item:before {
|
.step-item:before {
|
||||||
background: var(--bgColor) !important;
|
background-color: var(--completedAccent) !important;
|
||||||
// remaining code
|
// remaining code
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-item:after {
|
.step-item:after {
|
||||||
background: var(--bgColor) !important;
|
background: var(--completedAccent) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-item.active~.step-item {
|
|
||||||
color: var(--textColor) !important;
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notification-center-badge {
|
.notification-center-badge {
|
||||||
|
|
||||||
|
|
@ -9872,25 +9887,30 @@ tbody {
|
||||||
.workspace-settings-table-wrap {
|
.workspace-settings-table-wrap {
|
||||||
max-width: 880px;
|
max-width: 880px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
.tj-user-table-wrapper{
|
|
||||||
|
.tj-user-table-wrapper {
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
}
|
}
|
||||||
&:hover{
|
|
||||||
.tj-user-table-wrapper{
|
&:hover {
|
||||||
padding-right: 0px;
|
.tj-user-table-wrapper {
|
||||||
}
|
padding-right: 0px;
|
||||||
::-webkit-scrollbar{
|
}
|
||||||
display: block;
|
|
||||||
width: 4px;
|
::-webkit-scrollbar {
|
||||||
}
|
display: block;
|
||||||
::-webkit-scrollbar-track{
|
width: 4px;
|
||||||
background: var(--base);
|
}
|
||||||
}
|
|
||||||
::-webkit-scrollbar-thumb{
|
::-webkit-scrollbar-track {
|
||||||
background: var(--slate7);
|
background: var(--base);
|
||||||
border-radius: 6px;
|
}
|
||||||
}
|
|
||||||
}
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--slate7);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -10695,6 +10715,10 @@ tbody {
|
||||||
width: 660px;
|
width: 660px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.org-users-page-animation-fade {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.org-users-page {
|
.org-users-page {
|
||||||
.nav-tabs .nav-link.active {
|
.nav-tabs .nav-link.active {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
|
|
@ -10861,6 +10885,25 @@ tbody {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.default-group-wrap-small {
|
||||||
|
gap: 4px;
|
||||||
|
width: 121px;
|
||||||
|
height: 28px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--indigo3);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-weight: 500 !important;
|
||||||
|
line-height: 18px !important;
|
||||||
|
color: var(--indigo9);
|
||||||
|
font-family: 'IBM Plex Sans', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.sso-icon-wrapper {
|
.sso-icon-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
@ -12056,8 +12099,10 @@ tbody {
|
||||||
letter-spacing: -0.02em;
|
letter-spacing: -0.02em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-list-wrap.sidebar-list-wrap-with-banner.isAdmin {
|
.sidebar-list-wrap.sidebar-list-wrap-with-banner.isAdmin {
|
||||||
height: calc(100vh - 371px);
|
height: calc(100vh - 371px);
|
||||||
|
|
||||||
&.resource-limit-reached {
|
&.resource-limit-reached {
|
||||||
height: calc(100vh - 371px);
|
height: calc(100vh - 371px);
|
||||||
}
|
}
|
||||||
|
|
@ -15801,6 +15846,7 @@ textarea.tj-text-input-widget{
|
||||||
|
|
||||||
.rest-api-options-codehinter {
|
.rest-api-options-codehinter {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.cm-content>.cm-line {
|
.cm-content>.cm-line {
|
||||||
// max-width: 357px !important;
|
// max-width: 357px !important;
|
||||||
}
|
}
|
||||||
|
|
@ -16232,19 +16278,20 @@ fieldset:disabled {
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker-validation-half {
|
.datepicker-validation-half {
|
||||||
flex:1 1 calc(50% - 8px);
|
flex: 1 1 calc(50% - 8px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.date-validation-wrapper {
|
.date-validation-wrapper {
|
||||||
|
|
||||||
.field {
|
.field {
|
||||||
height:24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-flex-wrapper {
|
.code-flex-wrapper {
|
||||||
flex-wrap:wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -16253,55 +16300,58 @@ fieldset:disabled {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.react-datepicker__day--disabled {
|
.react-datepicker__day--disabled {
|
||||||
|
color: #ccc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__time-list {
|
||||||
|
li.react-datepicker__time-list-item--disabled.react-datepicker__time-list-item {
|
||||||
color: #ccc !important;
|
color: #ccc !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.react-datepicker__time-list{
|
.inspector-validation-date-picker {
|
||||||
li.react-datepicker__time-list-item--disabled.react-datepicker__time-list-item {
|
.react-datepicker-wrapper {
|
||||||
color: #ccc !important;
|
input {
|
||||||
}
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inspector-validation-date-picker {
|
|
||||||
.react-datepicker-wrapper{
|
|
||||||
input {
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
input.dark-theme {
|
|
||||||
background-color: var(--slate3);
|
|
||||||
color: var(--slate12);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
input.dark-theme {
|
||||||
|
background-color: var(--slate3);
|
||||||
|
color: var(--slate12);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.datetimepicker-component, #component-portal, .custom-inspector-validation-time-picker {
|
|
||||||
|
.datetimepicker-component,
|
||||||
|
#component-portal,
|
||||||
|
.custom-inspector-validation-time-picker {
|
||||||
|
|
||||||
.datepicker-component {
|
.datepicker-component {
|
||||||
.react-datepicker {
|
.react-datepicker {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||||
height:auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.react-datepicker-time-component {
|
.react-datepicker-time-component {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width:auto;
|
width: auto;
|
||||||
|
|
||||||
.custom-time-input{
|
.custom-time-input {
|
||||||
border-left:none;
|
border-left: none;
|
||||||
border-radius:10px;
|
border-radius: 10px;
|
||||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-input-body {
|
.time-input-body {
|
||||||
padding-bottom:0px;
|
padding-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-col {
|
.time-col {
|
||||||
|
|
@ -16313,27 +16363,31 @@ fieldset:disabled {
|
||||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker-time__input-container{
|
.react-datepicker-time__input-container {
|
||||||
border-radius:10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.dark-theme {
|
.dark-theme {
|
||||||
.react-datepicker__year-text, .react-datepicker__month-text {
|
|
||||||
|
.react-datepicker__year-text,
|
||||||
|
.react-datepicker__month-text {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text:hover, .react-datepicker__month-text:hover {
|
.react-datepicker__year-text:hover,
|
||||||
background-color: #9ba1a6 ;
|
.react-datepicker__month-text:hover {
|
||||||
|
background-color: #9ba1a6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tj-datepicker-widget-year-selector:hover, .tj-datepicker-widget-month-selector:hover {
|
.tj-datepicker-widget-year-selector:hover,
|
||||||
padding:1px 6px;
|
.tj-datepicker-widget-month-selector:hover {
|
||||||
|
padding: 1px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker{
|
.react-datepicker {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
border-top-right-radius: 0rem;
|
border-top-right-radius: 0rem;
|
||||||
|
|
@ -16346,48 +16400,49 @@ fieldset:disabled {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-wrapper {
|
.react-datepicker__year-wrapper {
|
||||||
display:grid;
|
display: grid;
|
||||||
grid-template-columns:repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
max-width: unset;
|
max-width: unset;
|
||||||
gap:10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker {
|
.react-datepicker {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__header--custom{
|
.react-datepicker__header--custom {
|
||||||
height: 34px;
|
height: 34px;
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year--container{
|
.react-datepicker__year--container {
|
||||||
height:208px;
|
height: 208px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text--selected {
|
.react-datepicker__year-text--selected {
|
||||||
background-color: #4368E3 !important;
|
background-color: #4368E3 !important;
|
||||||
height:24px;
|
height: 24px;
|
||||||
width:61.33px;
|
width: 61.33px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: #fff ;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text{
|
.react-datepicker__year-text {
|
||||||
font-family:'IBM Plex Sans' ;
|
font-family: 'IBM Plex Sans';
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
height:24px;
|
height: 24px;
|
||||||
width:61.33px;
|
width: 61.33px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display:flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -16402,42 +16457,42 @@ fieldset:disabled {
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-container {
|
.react-datepicker__month-container {
|
||||||
height:208px;
|
height: 208px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__monthPicker {
|
.react-datepicker__monthPicker {
|
||||||
display:flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap:10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-text--selected {
|
.react-datepicker__month-text--selected {
|
||||||
background-color: #4368E3 !important;
|
background-color: #4368E3 !important;
|
||||||
height:24px;
|
height: 24px;
|
||||||
width:61.33px;
|
width: 61.33px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: #fff ;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-wrapper {
|
.react-datepicker__month-wrapper {
|
||||||
display:flex;
|
display: flex;
|
||||||
gap:24px;
|
gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-text {
|
.react-datepicker__month-text {
|
||||||
font-family:'IBM Plex Sans' ;
|
font-family: 'IBM Plex Sans';
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
height:24px;
|
height: 24px;
|
||||||
width:61.33px;
|
width: 61.33px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display:flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -16447,7 +16502,7 @@ fieldset:disabled {
|
||||||
|
|
||||||
.react-datepicker__month-container {
|
.react-datepicker__month-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
width:250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__input-time-container {
|
.react-datepicker__input-time-container {
|
||||||
|
|
@ -16467,7 +16522,7 @@ fieldset:disabled {
|
||||||
margin-left: 0px !important;
|
margin-left: 0px !important;
|
||||||
|
|
||||||
.dark-time-input {
|
.dark-time-input {
|
||||||
color:#f4f6fa !important;
|
color: #f4f6fa !important;
|
||||||
background-color: var(--surfaces-surface-01) !important;
|
background-color: var(--surfaces-surface-01) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -16477,7 +16532,7 @@ fieldset:disabled {
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker-time__caption {
|
.react-datepicker-time__caption {
|
||||||
display:none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-time-input {
|
.custom-time-input {
|
||||||
|
|
@ -16497,7 +16552,7 @@ fieldset:disabled {
|
||||||
border-bottom: 1px solid #CCD1D5;
|
border-bottom: 1px solid #CCD1D5;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-family: 'IBM Plex Sans';
|
font-family: 'IBM Plex Sans';
|
||||||
color:#ACB2B9;
|
color: #ACB2B9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-input-body {
|
.time-input-body {
|
||||||
|
|
@ -16516,12 +16571,12 @@ fieldset:disabled {
|
||||||
.selected-time {
|
.selected-time {
|
||||||
background-color: #4368E3 !important;
|
background-color: #4368E3 !important;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
color:#fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-item {
|
.time-item {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height:22px;
|
height: 22px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -16861,16 +16916,17 @@ section.ai-message-prompt-input-wrapper {
|
||||||
|
|
||||||
|
|
||||||
.tj-inspector-timepicker.dark-theme {
|
.tj-inspector-timepicker.dark-theme {
|
||||||
.react-datepicker {
|
.react-datepicker {
|
||||||
color:#f4f6fa !important;
|
color: #f4f6fa !important;
|
||||||
background-color: var(--surfaces-surface-01) !important;
|
background-color: var(--surfaces-surface-01) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker, .react-datepicker__header {
|
.react-datepicker,
|
||||||
|
.react-datepicker__header {
|
||||||
border: 1px solid var(--borders-default);
|
border: 1px solid var(--borders-default);
|
||||||
background-color: #1f2936;
|
background-color: #1f2936;
|
||||||
|
|
||||||
.react-datepicker-time__header{
|
.react-datepicker-time__header {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -16878,25 +16934,27 @@ section.ai-message-prompt-input-wrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
.tj-inspector-timepicker {
|
.tj-inspector-timepicker {
|
||||||
padding:0px !important;
|
padding: 0px !important;
|
||||||
|
|
||||||
.react-datepicker__time-list {
|
.react-datepicker__time-list {
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__triangle {
|
.react-datepicker__triangle {
|
||||||
display:none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-inspector-validation-date-picker, .custom-inspector-validation-time-picker {
|
.custom-inspector-validation-date-picker,
|
||||||
|
.custom-inspector-validation-time-picker {
|
||||||
flex-basis: 100% !important;
|
flex-basis: 100% !important;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
height:32px;
|
height: 32px;
|
||||||
|
|
||||||
.react-datepicker-wrapper {
|
.react-datepicker-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid var(--slate7);
|
border: 1px solid var(--slate7);
|
||||||
|
|
@ -16904,7 +16962,7 @@ section.ai-message-prompt-input-wrapper {
|
||||||
background-color: var(--base);
|
background-color: var(--base);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: rgb(0, 92, 197);
|
color: rgb(0, 92, 197);
|
||||||
height:32px;
|
height: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.dark-theme {
|
input.dark-theme {
|
||||||
|
|
@ -16919,8 +16977,8 @@ section.ai-message-prompt-input-wrapper {
|
||||||
|
|
||||||
.custom-inspector-validation-time-picker {
|
.custom-inspector-validation-time-picker {
|
||||||
.custom-time-input {
|
.custom-time-input {
|
||||||
border-left:none;
|
border-left: none;
|
||||||
border-radius:10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-col {
|
.time-col {
|
||||||
|
|
@ -16928,7 +16986,7 @@ section.ai-message-prompt-input-wrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__input-time-container {
|
.react-datepicker__input-time-container {
|
||||||
border-radius:10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -16936,11 +16994,13 @@ section.ai-message-prompt-input-wrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-inspector-validation-time-picker-popper {
|
.custom-inspector-validation-time-picker-popper {
|
||||||
border-radius:10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-date-display-format, .input-date-time-format {
|
.input-date-display-format,
|
||||||
|
.input-date-time-format {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
|
|
||||||
.hide-fx {
|
.hide-fx {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.3s ease;
|
transition: opacity 0.3s ease;
|
||||||
|
|
@ -16959,8 +17019,9 @@ section.ai-message-prompt-input-wrapper {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__day:hover, .react-datepicker__day--selecting-range-end {
|
.react-datepicker__day:hover,
|
||||||
background-color: var(--interactive-overlays-fill-hover) !important ;
|
.react-datepicker__day--selecting-range-end {
|
||||||
|
background-color: var(--interactive-overlays-fill-hover) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__day--keyboard-selected {
|
.react-datepicker__day--keyboard-selected {
|
||||||
|
|
@ -16983,15 +17044,17 @@ section.ai-message-prompt-input-wrapper {
|
||||||
|
|
||||||
.tj-daterange-widget {
|
.tj-daterange-widget {
|
||||||
|
|
||||||
border-radius:10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
||||||
font-family: 'IBM Plex Sans';
|
font-family: 'IBM Plex Sans';
|
||||||
|
|
||||||
.react-datepicker__day--in-selecting-range, .react-datepicker__day--in-range {
|
.react-datepicker__day--in-selecting-range,
|
||||||
border-radius:0px;
|
.react-datepicker__day--in-range {
|
||||||
|
border-radius: 0px;
|
||||||
background-color: #4368E31A !important;
|
background-color: #4368E31A !important;
|
||||||
}
|
}
|
||||||
.react-datepicker__header{
|
|
||||||
|
.react-datepicker__header {
|
||||||
background-color: var(--surfaces-surface-01);
|
background-color: var(--surfaces-surface-01);
|
||||||
padding: 6px 0px;
|
padding: 6px 0px;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
@ -17002,13 +17065,16 @@ section.ai-message-prompt-input-wrapper {
|
||||||
background-color: #ededee !important;
|
background-color: #ededee !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__day--selecting-range-start, .react-datepicker__day--selected, .react-datepicker__day--range-end {
|
.react-datepicker__day--selecting-range-start,
|
||||||
border-radius:8px !important;
|
.react-datepicker__day--selected,
|
||||||
|
.react-datepicker__day--range-end {
|
||||||
|
border-radius: 8px !important;
|
||||||
background-color: #4368E3 !important;
|
background-color: #4368E3 !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__day--in-range:has(+ .react-datepicker__day--range-end), .react-datepicker__day--in-selecting-range:has(+ .react-datepicker__day--selecting-range-end) {
|
.react-datepicker__day--in-range:has(+ .react-datepicker__day--range-end),
|
||||||
|
.react-datepicker__day--in-selecting-range:has(+ .react-datepicker__day--selecting-range-end) {
|
||||||
border-top-right-radius: 8px;
|
border-top-right-radius: 8px;
|
||||||
border-bottom-right-radius: 8px;
|
border-bottom-right-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -17017,12 +17083,13 @@ section.ai-message-prompt-input-wrapper {
|
||||||
box-shadow: 10px 0 0 0px #4368E31A;
|
box-shadow: 10px 0 0 0px #4368E31A;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__day--range-start + .react-datepicker__day--in-range, .react-datepicker__day--selecting-range-start + .react-datepicker__day--in-selecting-range{
|
.react-datepicker__day--range-start+.react-datepicker__day--in-range,
|
||||||
|
.react-datepicker__day--selecting-range-start+.react-datepicker__day--in-selecting-range {
|
||||||
border-top-left-radius: 8px;
|
border-top-left-radius: 8px;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__day--range-start + .react-datepicker__day--in-range {
|
.react-datepicker__day--range-start+.react-datepicker__day--in-range {
|
||||||
box-shadow: -10px 0 0 0px #4368E31A;
|
box-shadow: -10px 0 0 0px #4368E31A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17030,8 +17097,8 @@ section.ai-message-prompt-input-wrapper {
|
||||||
|
|
||||||
.react-datepicker__day--in-range:first-of-type,
|
.react-datepicker__day--in-range:first-of-type,
|
||||||
.react-datepicker__day--in-selecting-range:first-of-type,
|
.react-datepicker__day--in-selecting-range:first-of-type,
|
||||||
.react-datepicker__day--outside-month + .react-datepicker__day--in-range,
|
.react-datepicker__day--outside-month+.react-datepicker__day--in-range,
|
||||||
.react-datepicker__day--outside-month + .react-datepicker__day--in-selecting-range{
|
.react-datepicker__day--outside-month+.react-datepicker__day--in-selecting-range {
|
||||||
border-top-left-radius: 8px;
|
border-top-left-radius: 8px;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -17039,7 +17106,7 @@ section.ai-message-prompt-input-wrapper {
|
||||||
.react-datepicker__day--in-range:last-of-type,
|
.react-datepicker__day--in-range:last-of-type,
|
||||||
.react-datepicker__day--in-selecting-range:last-of-type,
|
.react-datepicker__day--in-selecting-range:last-of-type,
|
||||||
.react-datepicker__day--in-range:has(+ .react-datepicker__day--outside-month),
|
.react-datepicker__day--in-range:has(+ .react-datepicker__day--outside-month),
|
||||||
.react-datepicker__day--in-selecting-range:has(+ .react-datepicker__day--outside-month){
|
.react-datepicker__day--in-selecting-range:has(+ .react-datepicker__day--outside-month) {
|
||||||
border-top-right-radius: 8px;
|
border-top-right-radius: 8px;
|
||||||
border-bottom-right-radius: 8px;
|
border-bottom-right-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -17057,8 +17124,8 @@ section.ai-message-prompt-input-wrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
.tj-datepicker-widget-right {
|
.tj-datepicker-widget-right {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tj-datepicker-widget-left {
|
.tj-datepicker-widget-left {
|
||||||
|
|
@ -17081,41 +17148,42 @@ section.ai-message-prompt-input-wrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker {
|
.react-datepicker {
|
||||||
border-radius:10px !important;
|
border-radius: 10px !important;
|
||||||
border:none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tj-daterangepicker-widget-month-selector, .tj-daterangepicker-widget-year-selector {
|
.tj-daterangepicker-widget-month-selector,
|
||||||
appearance: none;
|
.tj-daterangepicker-widget-year-selector {
|
||||||
-moz-appearance: none;
|
appearance: none;
|
||||||
-webkit-appearance: none;
|
-moz-appearance: none;
|
||||||
padding-right: 4px;
|
-webkit-appearance: none;
|
||||||
/* Add some padding on the right to create space for custom arrow */
|
padding-right: 4px;
|
||||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23424242" width="18px" height="18px"><path d="M7 10l5 5 5-5z" /></svg>');
|
/* Add some padding on the right to create space for custom arrow */
|
||||||
/* Add a custom arrow (you can use your own SVG) */
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23424242" width="18px" height="18px"><path d="M7 10l5 5 5-5z" /></svg>');
|
||||||
background-repeat: no-repeat;
|
/* Add a custom arrow (you can use your own SVG) */
|
||||||
background-position: right center;
|
background-repeat: no-repeat;
|
||||||
border: none;
|
background-position: right center;
|
||||||
/* Remove the default border */
|
border: none;
|
||||||
padding: 8px;
|
/* Remove the default border */
|
||||||
/* Adjust padding as needed */
|
padding: 8px;
|
||||||
cursor: pointer;
|
/* Adjust padding as needed */
|
||||||
/* Add pointer cursor for better usability */
|
cursor: pointer;
|
||||||
background: none;
|
/* Add pointer cursor for better usability */
|
||||||
padding: 0px;
|
background: none;
|
||||||
height: 24px;
|
padding: 0px;
|
||||||
text-align: center;
|
height: 24px;
|
||||||
color: var(--text-primary);
|
text-align: center;
|
||||||
font-weight: 500;
|
color: var(--text-primary);
|
||||||
width:auto;
|
font-weight: 500;
|
||||||
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.datepicker-widget {
|
.datepicker-widget {
|
||||||
.react-datepicker-wrapper{
|
.react-datepicker-wrapper {
|
||||||
width:100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17129,26 +17197,29 @@ section.ai-message-prompt-input-wrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
.tj-daterange-widget.react-datepicker-month-component {
|
.tj-daterange-widget.react-datepicker-month-component {
|
||||||
border-radius:10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
||||||
font-family: 'IBM Plex Sans';
|
font-family: 'IBM Plex Sans';
|
||||||
|
|
||||||
.react-datepicker__month-container {
|
.react-datepicker__month-container {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.react-datepicker__month-text {
|
.react-datepicker__month-text {
|
||||||
height:26px !important;
|
height: 26px !important;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
width:100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-text--in-selecting-range, .react-datepicker__month-text--in-range {
|
.react-datepicker__month-text--in-selecting-range,
|
||||||
border-radius:0px;
|
.react-datepicker__month-text--in-range {
|
||||||
|
border-radius: 0px;
|
||||||
background-color: #4368E31A !important;
|
background-color: #4368E31A !important;
|
||||||
color:#000;
|
color: #000;
|
||||||
}
|
}
|
||||||
.react-datepicker__header{
|
|
||||||
|
.react-datepicker__header {
|
||||||
background-color: var(--surfaces-surface-01);
|
background-color: var(--surfaces-surface-01);
|
||||||
padding: 6px 0px;
|
padding: 6px 0px;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
@ -17161,13 +17232,16 @@ section.ai-message-prompt-input-wrapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-text--selecting-range-start, .react-datepicker__month-text--selected, .react-datepicker__month-text--range-end {
|
.react-datepicker__month-text--selecting-range-start,
|
||||||
border-radius:8px !important;
|
.react-datepicker__month-text--selected,
|
||||||
|
.react-datepicker__month-text--range-end {
|
||||||
|
border-radius: 8px !important;
|
||||||
background-color: #4368E3 !important;
|
background-color: #4368E3 !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-text--in-range:has(+ .react-datepicker__month-text--range-end), .react-datepicker__month-text--in-selecting-range:has(+ .react-datepicker__month-text--selecting-range-end) {
|
.react-datepicker__month-text--in-range:has(+ .react-datepicker__month-text--range-end),
|
||||||
|
.react-datepicker__month-text--in-selecting-range:has(+ .react-datepicker__month-text--selecting-range-end) {
|
||||||
border-top-right-radius: 8px;
|
border-top-right-radius: 8px;
|
||||||
border-bottom-right-radius: 8px;
|
border-bottom-right-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -17176,22 +17250,23 @@ section.ai-message-prompt-input-wrapper {
|
||||||
box-shadow: 10px 0 0 0px #4368E31A;
|
box-shadow: 10px 0 0 0px #4368E31A;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-text--range-start + .react-datepicker__month-text--in-range, .react-datepicker__month-text--selecting-range-start + .react-datepicker__month-text--in-selecting-range{
|
.react-datepicker__month-text--range-start+.react-datepicker__month-text--in-range,
|
||||||
|
.react-datepicker__month-text--selecting-range-start+.react-datepicker__month-text--in-selecting-range {
|
||||||
border-top-left-radius: 8px;
|
border-top-left-radius: 8px;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-text--range-start + .react-datepicker__month-text--in-range {
|
.react-datepicker__month-text--range-start+.react-datepicker__month-text--in-range {
|
||||||
box-shadow: -10px 0 0 0px #4368E31A;
|
box-shadow: -10px 0 0 0px #4368E31A;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__month-wrapper{
|
.react-datepicker__month-wrapper {
|
||||||
gap:0px !important;
|
gap: 0px !important;
|
||||||
|
|
||||||
.react-datepicker__month-text--in-range:first-of-type,
|
.react-datepicker__month-text--in-range:first-of-type,
|
||||||
.react-datepicker__month-text--in-selecting-range:first-of-type,
|
.react-datepicker__month-text--in-selecting-range:first-of-type,
|
||||||
.react-datepicker__month-text--outside-month-text + .react-datepicker__month-text--in-range,
|
.react-datepicker__month-text--outside-month-text+.react-datepicker__month-text--in-range,
|
||||||
.react-datepicker__month-text--outside-month-text + .react-datepicker__month-text--in-selecting-range{
|
.react-datepicker__month-text--outside-month-text+.react-datepicker__month-text--in-selecting-range {
|
||||||
border-top-left-radius: 8px;
|
border-top-left-radius: 8px;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -17199,7 +17274,7 @@ section.ai-message-prompt-input-wrapper {
|
||||||
.react-datepicker__month-text--in-range:last-of-type,
|
.react-datepicker__month-text--in-range:last-of-type,
|
||||||
.react-datepicker__month-text--in-selecting-range:last-of-type,
|
.react-datepicker__month-text--in-selecting-range:last-of-type,
|
||||||
.react-datepicker__month-text--in-range:has(+ .react-datepicker__month-text--outside-month-text),
|
.react-datepicker__month-text--in-range:has(+ .react-datepicker__month-text--outside-month-text),
|
||||||
.react-datepicker__month-text--in-selecting-range:has(+ .react-datepicker__month-text--outside-month-text){
|
.react-datepicker__month-text--in-selecting-range:has(+ .react-datepicker__month-text--outside-month-text) {
|
||||||
border-top-right-radius: 8px;
|
border-top-right-radius: 8px;
|
||||||
border-bottom-right-radius: 8px;
|
border-bottom-right-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -17219,24 +17294,25 @@ section.ai-message-prompt-input-wrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
.tj-daterange-widget.react-datepicker-year-component {
|
.tj-daterange-widget.react-datepicker-year-component {
|
||||||
border-radius:10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
||||||
font-family: 'IBM Plex Sans';
|
font-family: 'IBM Plex Sans';
|
||||||
|
|
||||||
.react-datepicker__year-container {
|
.react-datepicker__year-container {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-wrapper{
|
.react-datepicker__year-wrapper {
|
||||||
gap:0px !important;
|
gap: 0px !important;
|
||||||
|
|
||||||
.react-datepicker__year-text--in-range:first-of-type,
|
.react-datepicker__year-text--in-range:first-of-type,
|
||||||
.react-datepicker__year-text--in-selecting-range:first-of-type{
|
.react-datepicker__year-text--in-selecting-range:first-of-type {
|
||||||
border-top-left-radius: 8px;
|
border-top-left-radius: 8px;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text--in-range:last-of-type,
|
.react-datepicker__year-text--in-range:last-of-type,
|
||||||
.react-datepicker__year-text--in-selecting-range:last-of-type{
|
.react-datepicker__year-text--in-selecting-range:last-of-type {
|
||||||
border-top-right-radius: 8px;
|
border-top-right-radius: 8px;
|
||||||
border-bottom-right-radius: 8px;
|
border-bottom-right-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -17244,19 +17320,21 @@ section.ai-message-prompt-input-wrapper {
|
||||||
|
|
||||||
|
|
||||||
.react-datepicker__year-text {
|
.react-datepicker__year-text {
|
||||||
height:26px !important;
|
height: 26px !important;
|
||||||
margin-top: 5px !important;
|
margin-top: 5px !important;
|
||||||
margin-bottom:5px !important;
|
margin-bottom: 5px !important;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
width:62px !important;
|
width: 62px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text--in-selecting-range, .react-datepicker__year-text--in-range {
|
.react-datepicker__year-text--in-selecting-range,
|
||||||
border-radius:0px;
|
.react-datepicker__year-text--in-range {
|
||||||
|
border-radius: 0px;
|
||||||
background-color: #4368E31A !important;
|
background-color: #4368E31A !important;
|
||||||
color:#000;
|
color: #000;
|
||||||
}
|
}
|
||||||
.react-datepicker__header{
|
|
||||||
|
.react-datepicker__header {
|
||||||
background-color: var(--surfaces-surface-01);
|
background-color: var(--surfaces-surface-01);
|
||||||
padding: 6px 0px;
|
padding: 6px 0px;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
@ -17269,13 +17347,16 @@ section.ai-message-prompt-input-wrapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text--selecting-range-start, .react-datepicker__year-text--selected, .react-datepicker__year-text--range-end {
|
.react-datepicker__year-text--selecting-range-start,
|
||||||
border-radius:8px !important;
|
.react-datepicker__year-text--selected,
|
||||||
|
.react-datepicker__year-text--range-end {
|
||||||
|
border-radius: 8px !important;
|
||||||
background-color: #4368E3 !important;
|
background-color: #4368E3 !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text--in-range:has(+ .react-datepicker__year-text--range-end), .react-datepicker__year-text--in-selecting-range:has(+ .react-datepicker__year-text--selecting-range-end) {
|
.react-datepicker__year-text--in-range:has(+ .react-datepicker__year-text--range-end),
|
||||||
|
.react-datepicker__year-text--in-selecting-range:has(+ .react-datepicker__year-text--selecting-range-end) {
|
||||||
border-top-right-radius: 8px;
|
border-top-right-radius: 8px;
|
||||||
border-bottom-right-radius: 8px;
|
border-bottom-right-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
@ -17284,12 +17365,13 @@ section.ai-message-prompt-input-wrapper {
|
||||||
box-shadow: 10px 0 0 0px #4368E31A;
|
box-shadow: 10px 0 0 0px #4368E31A;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text--range-start + .react-datepicker__year-text--in-range, .react-datepicker__year-text--selecting-range-start + .react-datepicker__year-text--in-selecting-range{
|
.react-datepicker__year-text--range-start+.react-datepicker__year-text--in-range,
|
||||||
|
.react-datepicker__year-text--selecting-range-start+.react-datepicker__year-text--in-selecting-range {
|
||||||
border-top-left-radius: 8px;
|
border-top-left-radius: 8px;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-datepicker__year-text--range-start + .react-datepicker__year-text--in-range {
|
.react-datepicker__year-text--range-start+.react-datepicker__year-text--in-range {
|
||||||
box-shadow: -10px 0 0 0px #4368E31A;
|
box-shadow: -10px 0 0 0px #4368E31A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -18322,6 +18404,10 @@ section.ai-message-prompt-input-wrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.codehinter-copilot-btn {
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
#copilot-menu {
|
#copilot-menu {
|
||||||
width: 440px;
|
width: 440px;
|
||||||
max-width: 440px;
|
max-width: 440px;
|
||||||
|
|
@ -18783,6 +18869,7 @@ section.ai-message-prompt-input-wrapper {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
|
|
||||||
&.dark {
|
&.dark {
|
||||||
background: #FFFAEB !important;
|
background: #FFFAEB !important;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
frontend/src/_ui/Icon/solidIcons/Moon.jsx
Normal file
23
frontend/src/_ui/Icon/solidIcons/Moon.jsx
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const Moon = ({ fill = '#6A727C', width = '24', className = '', viewBox = '0 0 24 24' }) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={width}
|
||||||
|
height={width}
|
||||||
|
viewBox={viewBox}
|
||||||
|
className={className}
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M16.107 6.64283C15.6139 6.64283 15.2142 6.24309 15.2142 5.74998V5.21426H14.6785C14.1854 5.21426 13.7856 4.81452 13.7856 4.32141C13.7856 3.8283 14.1854 3.42856 14.6785 3.42856H15.2142V2.89285C15.2142 2.39974 15.6139 2 16.107 2C16.6002 2 16.9999 2.39974 16.9999 2.89285V3.42856H17.5356C18.0288 3.42856 18.4285 3.8283 18.4285 4.32141C18.4285 4.81452 18.0288 5.21426 17.5356 5.21426H16.9999V5.74998C16.9999 6.24309 16.6002 6.64283 16.107 6.64283ZM18.7856 11.4642C18.7856 11.9573 19.1853 12.3571 19.6785 12.3571C20.1716 12.3571 20.5713 11.9573 20.5713 11.4642V10.9285H21.107C21.6002 10.9285 21.9999 10.5288 21.9999 10.0357C21.9999 9.54255 21.6002 9.14281 21.107 9.14281H20.5713V8.6071C20.5713 8.11399 20.1716 7.71425 19.6785 7.71425C19.1853 7.71425 18.7856 8.11399 18.7856 8.6071V9.14281H18.2499C17.7568 9.14281 17.357 9.54255 17.357 10.0357C17.357 10.5288 17.7568 10.9285 18.2499 10.9285H18.7856V11.4642ZM6.07263 6.07373C7.96356 4.98201 10.1187 4.74735 12.1075 5.23996C12.7387 5.39633 12.9939 5.95217 12.9996 6.40209C13.0051 6.8352 12.7967 7.33059 12.3328 7.59845C10.4674 8.67541 9.82636 11.1468 10.9769 13.1396C12.1274 15.1324 14.5883 15.8129 16.4536 14.736C16.9176 14.4681 17.4508 14.5354 17.8232 14.7567C18.2099 14.9866 18.5637 15.4855 18.3835 16.1103C17.8158 18.0789 16.5349 19.828 14.644 20.9197C10.6598 23.2201 5.53735 21.7172 3.18302 17.6395C0.828705 13.5616 2.08841 8.37403 6.07263 6.07373Z"
|
||||||
|
fill={fill}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Moon;
|
||||||
|
|
@ -234,6 +234,7 @@ import NewTabSmall from './NewTabSmall.jsx';
|
||||||
import Code from './Code.jsx';
|
import Code from './Code.jsx';
|
||||||
import WorkflowV3 from './WorkflowV3.jsx';
|
import WorkflowV3 from './WorkflowV3.jsx';
|
||||||
import WorkspaceV3 from './WorkspaceV3.jsx';
|
import WorkspaceV3 from './WorkspaceV3.jsx';
|
||||||
|
import Moon from './Moon.jsx';
|
||||||
|
|
||||||
const Icon = (props) => {
|
const Icon = (props) => {
|
||||||
switch (props.name) {
|
switch (props.name) {
|
||||||
|
|
@ -707,6 +708,8 @@ const Icon = (props) => {
|
||||||
return <AICrown {...props} />;
|
return <AICrown {...props} />;
|
||||||
case 'play01':
|
case 'play01':
|
||||||
return <Play01 {...props} />;
|
return <Play01 {...props} />;
|
||||||
|
case 'moon':
|
||||||
|
return <Moon {...props} />;
|
||||||
default:
|
default:
|
||||||
return <Apps {...props} />;
|
return <Apps {...props} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ export const SelectComponent = ({ options = [], value, onChange, closeMenuOnSele
|
||||||
isDisabled = false,
|
isDisabled = false,
|
||||||
borderRadius,
|
borderRadius,
|
||||||
openMenuOnFocus = false,
|
openMenuOnFocus = false,
|
||||||
|
customClassPrefix = '',
|
||||||
} = restProps;
|
} = restProps;
|
||||||
|
|
||||||
const customStyles = useCustomStyles ? styles : defaultStyles(isDarkMode, width, height, styles, borderRadius);
|
const customStyles = useCustomStyles ? styles : defaultStyles(isDarkMode, width, height, styles, borderRadius);
|
||||||
|
|
@ -74,7 +75,7 @@ export const SelectComponent = ({ options = [], value, onChange, closeMenuOnSele
|
||||||
maxMenuHeight={maxMenuHeight}
|
maxMenuHeight={maxMenuHeight}
|
||||||
menuPortalTarget={useMenuPortal ? document.body : menuPortalTarget}
|
menuPortalTarget={useMenuPortal ? document.body : menuPortalTarget}
|
||||||
closeMenuOnSelect={closeMenuOnSelect ?? true}
|
closeMenuOnSelect={closeMenuOnSelect ?? true}
|
||||||
classNamePrefix={`${isDarkMode && 'dark-theme'} ${'react-select'}`}
|
classNamePrefix={`${customClassPrefix} ${isDarkMode && 'dark-theme'} ${'react-select'}`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { Input } from '../Input';
|
||||||
import { HelperMessage, ValidationMessage } from '../InputUtils/InputUtils';
|
import { HelperMessage, ValidationMessage } from '../InputUtils/InputUtils';
|
||||||
import Tooltip from '../../Tooltip/Tooltip';
|
import Tooltip from '../../Tooltip/Tooltip';
|
||||||
|
|
||||||
const EditableTitleInput = ({ size, disabled, helperText, onChange, ...restProps }) => {
|
const EditableTitleInput = ({ size, disabled, helperText, onChange: change, readOnly, placeholder, ...restProps }) => {
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const [tooltipWidth, setTooltipWidth] = useState('auto');
|
const [tooltipWidth, setTooltipWidth] = useState('auto');
|
||||||
const [isValid, setIsValid] = useState(null);
|
const [isValid, setIsValid] = useState(null);
|
||||||
|
|
@ -17,7 +17,7 @@ const EditableTitleInput = ({ size, disabled, helperText, onChange, ...restProps
|
||||||
setIsValid(validateObj.valid);
|
setIsValid(validateObj.valid);
|
||||||
setMessage(validateObj.message);
|
setMessage(validateObj.message);
|
||||||
}
|
}
|
||||||
onChange(e, validateObj);
|
change(e, validateObj);
|
||||||
};
|
};
|
||||||
|
|
||||||
const inputStyle = `tw-border-transparent hover:tw-border-border-default tw-font-medium tw-pl-[12px] tw-pr-[12px] ${
|
const inputStyle = `tw-border-transparent hover:tw-border-border-default tw-font-medium tw-pl-[12px] tw-pr-[12px] ${
|
||||||
|
|
@ -35,7 +35,14 @@ const EditableTitleInput = ({ size, disabled, helperText, onChange, ...restProps
|
||||||
return (
|
return (
|
||||||
<div className="tw-relative">
|
<div className="tw-relative">
|
||||||
<div className="tw-peer tw-relative" ref={inputRef}>
|
<div className="tw-peer tw-relative" ref={inputRef}>
|
||||||
<Input size={size} disabled={disabled} onChange={handleChange} {...restProps} className={inputStyle} />
|
<Input
|
||||||
|
size={size}
|
||||||
|
disabled={disabled}
|
||||||
|
placeholder={disabled && readOnly ? readOnly : placeholder}
|
||||||
|
onChange={handleChange}
|
||||||
|
{...restProps}
|
||||||
|
className={inputStyle}
|
||||||
|
/>
|
||||||
<SolidIcon
|
<SolidIcon
|
||||||
name="editable"
|
name="editable"
|
||||||
width="16px"
|
width="16px"
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ const Input = React.forwardRef(({ className, size, type, multiline, response, ro
|
||||||
type={isPasswordField && isPasswordVisible ? 'text' : type}
|
type={isPasswordField && isPasswordVisible ? 'text' : type}
|
||||||
className={cn(
|
className={cn(
|
||||||
inputVariants({ size }),
|
inputVariants({ size }),
|
||||||
`tw-relative tw-peer tw-flex tw-text-[12px]/[18px] tw-w-full tw-rounded-[8px] tw-border-[1px] tw-border-solid tw-bg-background-surface-layer-01 tw-py-[7px] tw-text-text-default focus-visible:tw-ring-[1px] focus-visible:tw-ring-offset-[1px] focus-visible:tw-ring-border-accent-strong focus-visible:tw-ring-offset-border-accent-strong focus-visible:tw-border-transparent disabled:tw-cursor-not-allowed ${props.styles}`,
|
`tw-peer tw-flex tw-text-[12px]/[18px] tw-w-full tw-rounded-[8px] tw-border-[1px] tw-border-solid tw-bg-background-surface-layer-01 tw-py-[7px] tw-text-text-default focus-visible:tw-ring-[1px] focus-visible:tw-ring-offset-[1px] focus-visible:tw-ring-border-accent-strong focus-visible:tw-ring-offset-border-accent-strong focus-visible:tw-border-transparent disabled:tw-cursor-not-allowed ${props.styles}`,
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|
|
||||||
81
server/data-migrations/1742369436314-StepsV2Migration.ts
Normal file
81
server/data-migrations/1742369436314-StepsV2Migration.ts
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
import { Component } from '@entities/component.entity';
|
||||||
|
import { EntityManager, MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
import { processDataInBatches } from '@helpers/migration.helper';
|
||||||
|
|
||||||
|
export class StepsV2Migration1742369436314 implements MigrationInterface {
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const componentTypes = ['Steps'];
|
||||||
|
const batchSize = 100;
|
||||||
|
const entityManager = queryRunner.manager;
|
||||||
|
|
||||||
|
for (const componentType of componentTypes) {
|
||||||
|
await processDataInBatches(
|
||||||
|
entityManager,
|
||||||
|
async (entityManager: EntityManager) => {
|
||||||
|
return await entityManager.find(Component, {
|
||||||
|
where: { type: componentType },
|
||||||
|
order: { createdAt: 'ASC' },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async (entityManager: EntityManager, components: Component[]) => {
|
||||||
|
await this.processUpdates(entityManager, components);
|
||||||
|
},
|
||||||
|
batchSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {}
|
||||||
|
|
||||||
|
private async processUpdates(entityManager, components) {
|
||||||
|
for (const component of components) {
|
||||||
|
const properties = component.properties;
|
||||||
|
const styles = component.styles;
|
||||||
|
const general = component.general;
|
||||||
|
const generalStyles = component.generalStyles;
|
||||||
|
const validation = component.validation;
|
||||||
|
|
||||||
|
if (styles.visibility) {
|
||||||
|
properties.visibility = styles.visibility;
|
||||||
|
delete styles.visibility;
|
||||||
|
}
|
||||||
|
if (styles.theme) {
|
||||||
|
properties['variant'] = styles.theme;
|
||||||
|
delete styles.theme;
|
||||||
|
}
|
||||||
|
if (styles.color) {
|
||||||
|
styles['completedAccent'] = styles.color;
|
||||||
|
}
|
||||||
|
delete styles.color;
|
||||||
|
if (styles.textColor) {
|
||||||
|
styles['completedLabel'] = styles.textColor;
|
||||||
|
styles['incompletedLabel'] = styles.textColor;
|
||||||
|
styles['currentStepLabel'] = styles.textColor;
|
||||||
|
}
|
||||||
|
delete styles.textColor;
|
||||||
|
if (properties.steps) {
|
||||||
|
properties['schema'] = properties.steps;
|
||||||
|
delete properties.steps;
|
||||||
|
properties['advanced'] = { value: '{{true}}' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (properties.stepsSelectable) {
|
||||||
|
// properties.disabledState = styles.disabledState;
|
||||||
|
// delete styles.disabledState;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (generalStyles?.boxShadow) {
|
||||||
|
// styles.boxShadow = generalStyles?.boxShadow;
|
||||||
|
// delete generalStyles?.boxShadow;
|
||||||
|
// }
|
||||||
|
|
||||||
|
await entityManager.update(Component, component.id, {
|
||||||
|
properties,
|
||||||
|
styles,
|
||||||
|
general,
|
||||||
|
generalStyles,
|
||||||
|
validation,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 69bdefb1f3f1d35bd6e7231e50799ff10a77a60f
|
Subproject commit 8155e72286b253042ede33cab64a5099d441ff44
|
||||||
|
|
@ -95,7 +95,9 @@ export class ComponentsService implements IComponentsService {
|
||||||
if (componentData.type === 'Table' && _.isArray(objValue)) {
|
if (componentData.type === 'Table' && _.isArray(objValue)) {
|
||||||
return srcValue;
|
return srcValue;
|
||||||
} else if (
|
} else if (
|
||||||
(componentData.type === 'DropdownV2' || componentData.type === 'MultiselectV2') &&
|
(componentData.type === 'DropdownV2' ||
|
||||||
|
componentData.type === 'MultiselectV2' ||
|
||||||
|
componentData.type === 'Steps') &&
|
||||||
_.isArray(objValue)
|
_.isArray(objValue)
|
||||||
) {
|
) {
|
||||||
return _.isArray(srcValue) ? srcValue : Object.values(srcValue);
|
return _.isArray(srcValue) ? srcValue : Object.values(srcValue);
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ export const containerConfig = {
|
||||||
displayName: 'Container',
|
displayName: 'Container',
|
||||||
description: 'Group components',
|
description: 'Group components',
|
||||||
defaultSize: {
|
defaultSize: {
|
||||||
width: 10,
|
width: 13,
|
||||||
height: 200,
|
height: 480,
|
||||||
},
|
},
|
||||||
component: 'Container',
|
component: 'Container',
|
||||||
others: {
|
others: {
|
||||||
|
|
|
||||||
|
|
@ -4,25 +4,38 @@ export const stepsConfig = {
|
||||||
description: 'Step-by-step navigation aid',
|
description: 'Step-by-step navigation aid',
|
||||||
component: 'Steps',
|
component: 'Steps',
|
||||||
properties: {
|
properties: {
|
||||||
|
variant: {
|
||||||
|
type: 'switch',
|
||||||
|
displayName: 'Variant',
|
||||||
|
validation: { schema: { type: 'string' }, defaultValue: 'titles' },
|
||||||
|
options: [
|
||||||
|
{ displayName: 'Label', value: 'titles' },
|
||||||
|
{ displayName: 'Number', value: 'numbers' },
|
||||||
|
{ displayName: 'Plain', value: 'plain' },
|
||||||
|
],
|
||||||
|
accordian: 'label',
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
type: 'code',
|
||||||
|
displayName: 'Schema',
|
||||||
|
conditionallyRender: {
|
||||||
|
key: 'advanced',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
accordian: 'Options',
|
||||||
|
},
|
||||||
steps: {
|
steps: {
|
||||||
type: 'code',
|
type: 'code',
|
||||||
displayName: 'Steps',
|
displayName: '',
|
||||||
|
showLabel: false,
|
||||||
validation: {
|
validation: {
|
||||||
schema: {
|
schema: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
element: { type: 'object', object: { id: { type: 'number' } } },
|
element: { type: 'object' },
|
||||||
},
|
},
|
||||||
defaultValue: `[{ name: 'step 1'}, {name: 'step 2'}]`,
|
defaultValue: `[{ name: 'step 1'}, {name: 'step 2'}]`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
currentStep: {
|
|
||||||
type: 'code',
|
|
||||||
displayName: 'Current step',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'number' },
|
|
||||||
defaultValue: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
stepsSelectable: {
|
stepsSelectable: {
|
||||||
type: 'toggle',
|
type: 'toggle',
|
||||||
displayName: 'Steps selectable',
|
displayName: 'Steps selectable',
|
||||||
|
|
@ -30,6 +43,36 @@ export const stepsConfig = {
|
||||||
schema: { type: 'boolean' },
|
schema: { type: 'boolean' },
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
},
|
},
|
||||||
|
section: 'additionalActions',
|
||||||
|
},
|
||||||
|
disabledState: {
|
||||||
|
type: 'toggle',
|
||||||
|
displayName: 'Disable',
|
||||||
|
validation: { schema: { type: 'boolean' } },
|
||||||
|
section: 'additionalActions',
|
||||||
|
},
|
||||||
|
visibility: {
|
||||||
|
type: 'toggle',
|
||||||
|
displayName: 'Visibility',
|
||||||
|
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||||
|
section: 'additionalActions',
|
||||||
|
},
|
||||||
|
advanced: {
|
||||||
|
type: 'toggle',
|
||||||
|
displayName: 'Dynamic options',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'boolean' },
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
|
accordian: 'Options',
|
||||||
|
},
|
||||||
|
currentStep: {
|
||||||
|
type: 'code',
|
||||||
|
displayName: 'Current step',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'number' },
|
||||||
|
defaultValue: 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultSize: {
|
defaultSize: {
|
||||||
|
|
@ -40,46 +83,126 @@ export const stepsConfig = {
|
||||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||||
},
|
},
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
handle: 'setStep',
|
||||||
|
displayName: 'Set step',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
handle: 'option',
|
||||||
|
displayName: 'Option',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'setVisibility',
|
||||||
|
displayName: 'Set visibility',
|
||||||
|
params: [{ handle: 'visible', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'setDisabled',
|
||||||
|
displayName: 'Set disabled',
|
||||||
|
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{true}}', type: 'toggle' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'resetSteps',
|
||||||
|
displayName: 'Reset steps',
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'setStepVisible',
|
||||||
|
displayName: 'Set step visible',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
handle: 'id',
|
||||||
|
displayName: 'Step id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'visibility',
|
||||||
|
displayName: 'visibility',
|
||||||
|
defaultValue: '{{false}}',
|
||||||
|
type: 'toggle',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'setStepDisable',
|
||||||
|
displayName: 'Set step disable',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
handle: 'id',
|
||||||
|
displayName: 'Step id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
handle: 'disabled',
|
||||||
|
displayName: 'disabled',
|
||||||
|
defaultValue: '{{true}}',
|
||||||
|
type: 'toggle',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
events: {
|
events: {
|
||||||
onSelect: { displayName: 'On select' },
|
onSelect: { displayName: 'On select' },
|
||||||
},
|
},
|
||||||
styles: {
|
styles: {
|
||||||
color: {
|
incompletedAccent: {
|
||||||
type: 'colorSwatches',
|
type: 'colorSwatches',
|
||||||
displayName: 'Color',
|
displayName: 'Incompleted accent',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'string' },
|
||||||
|
defaultValue: '#CCD1D5',
|
||||||
|
},
|
||||||
|
accordian: 'steps',
|
||||||
|
},
|
||||||
|
incompletedLabel: {
|
||||||
|
type: 'colorSwatches',
|
||||||
|
displayName: 'Incompleted label',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'string' },
|
||||||
|
defaultValue: '#1B1F24',
|
||||||
|
},
|
||||||
|
accordian: 'steps',
|
||||||
|
},
|
||||||
|
completedAccent: {
|
||||||
|
type: 'colorSwatches',
|
||||||
|
displayName: 'Completed accent',
|
||||||
validation: {
|
validation: {
|
||||||
schema: { type: 'string' },
|
schema: { type: 'string' },
|
||||||
defaultValue: 'var(--primary-brand)',
|
defaultValue: 'var(--primary-brand)',
|
||||||
},
|
},
|
||||||
|
accordian: 'steps',
|
||||||
},
|
},
|
||||||
textColor: {
|
completedLabel: {
|
||||||
type: 'colorSwatches',
|
type: 'colorSwatches',
|
||||||
displayName: 'Text color',
|
displayName: 'Completed label',
|
||||||
validation: {
|
validation: {
|
||||||
schema: { type: 'string' },
|
schema: { type: 'string' },
|
||||||
defaultValue: '#000000',
|
defaultValue: '#1B1F24',
|
||||||
},
|
},
|
||||||
|
accordian: 'steps',
|
||||||
},
|
},
|
||||||
theme: {
|
currentStepLabel: {
|
||||||
type: 'select',
|
type: 'colorSwatches',
|
||||||
displayName: 'Theme',
|
displayName: 'Current step label',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'string' },
|
||||||
|
defaultValue: '#1B1F24',
|
||||||
|
},
|
||||||
|
accordian: 'steps',
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
type: 'switch',
|
||||||
|
displayName: 'Padding',
|
||||||
|
validation: {
|
||||||
|
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||||
|
defaultValue: 'default',
|
||||||
|
},
|
||||||
options: [
|
options: [
|
||||||
{ name: 'titles', value: 'titles' },
|
{ displayName: 'Default', value: 'default' },
|
||||||
{ name: 'numbers', value: 'numbers' },
|
{ displayName: 'None', value: 'none' },
|
||||||
{ name: 'plain', value: 'plain' },
|
|
||||||
],
|
],
|
||||||
validation: {
|
accordian: 'container',
|
||||||
schema: { type: 'string' },
|
|
||||||
defaultValue: 'titles',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
visibility: {
|
|
||||||
type: 'toggle',
|
|
||||||
displayName: 'Visibility',
|
|
||||||
validation: {
|
|
||||||
schema: { type: 'boolean' },
|
|
||||||
defaultValue: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
exposedVariables: {
|
exposedVariables: {
|
||||||
|
|
@ -92,17 +215,35 @@ export const stepsConfig = {
|
||||||
},
|
},
|
||||||
properties: {
|
properties: {
|
||||||
steps: {
|
steps: {
|
||||||
value: `{{ [{ name: 'step 1', tooltip: 'some tooltip', id: 1},{ name: 'step 2', tooltip: 'some tooltip', id: 2},{ name: 'step 3', tooltip: 'some tooltip', id: 3},{ name: 'step 4', tooltip: 'some tooltip', id: 4},{ name: 'step 5', tooltip: 'some tooltip', id: 5}]}}`,
|
value: [
|
||||||
|
{ name: 'step 1', tooltip: '', id: 1, visible: { value: true }, disabled: { value: false } },
|
||||||
|
{ name: 'step 2', tooltip: '', id: 2, visible: { value: true }, disabled: { value: false } },
|
||||||
|
{ name: 'step 3', tooltip: '', id: 3, visible: { value: true }, disabled: { value: false } },
|
||||||
|
{ name: 'step 4', tooltip: '', id: 4, visible: { value: true }, disabled: { value: false } },
|
||||||
|
{ name: 'step 5', tooltip: '', id: 5, visible: { value: true }, disabled: { value: false } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
schema: {
|
||||||
|
value: `{{ [{ name: 'step 1', tooltip: '', id: 1,visible: true, disabled: false},{ name: 'step 2', tooltip: '', id: 2,visible: true, disabled: false},{ name: 'step 3', tooltip: '', id: 3,visible: true, disabled: false},{ name: 'step 4', tooltip: '', id: 4,visible: true, disabled: false},{ name: 'step 5', tooltip: '', id: 5,visible: true, disabled: false}]}}`,
|
||||||
|
},
|
||||||
|
disabledState: { value: '{{false}}' },
|
||||||
|
variant: { value: 'titles' },
|
||||||
currentStep: { value: '{{3}}' },
|
currentStep: { value: '{{3}}' },
|
||||||
stepsSelectable: { value: true },
|
stepsSelectable: { value: true },
|
||||||
|
advanced: { value: `{{false}}` },
|
||||||
|
visibility: { value: '{{true}}' },
|
||||||
},
|
},
|
||||||
events: [],
|
events: [],
|
||||||
styles: {
|
styles: {
|
||||||
visibility: { value: '{{true}}' },
|
visibility: { value: '{{true}}' },
|
||||||
theme: { value: 'titles' },
|
// color: { value: '' },
|
||||||
color: { value: 'var(--primary-brand)' },
|
// textColor: { value: '' },
|
||||||
textColor: { value: '' },
|
padding: { value: 'default' },
|
||||||
|
incompletedAccent: { value: '#E4E7EB' },
|
||||||
|
incompletedLabel: { value: '#1B1F24' },
|
||||||
|
completedAccent: { value: '#4368E3' },
|
||||||
|
completedLabel: { value: '#1B1F24' },
|
||||||
|
currentStepLabel: { value: '#1B1F24' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -490,7 +490,7 @@ export class AppsUtilService implements IAppsUtilService {
|
||||||
if (['Table'].includes(currentComponentData?.component?.component) && isArray(objValue)) {
|
if (['Table'].includes(currentComponentData?.component?.component) && isArray(objValue)) {
|
||||||
return srcValue;
|
return srcValue;
|
||||||
} else if (
|
} else if (
|
||||||
['DropdownV2', 'MultiselectV2'].includes(currentComponentData?.component?.component) &&
|
['DropdownV2', 'MultiselectV2', 'Steps'].includes(currentComponentData?.component?.component) &&
|
||||||
isArray(objValue)
|
isArray(objValue)
|
||||||
) {
|
) {
|
||||||
return isArray(srcValue) ? srcValue : Object.values(srcValue);
|
return isArray(srcValue) ? srcValue : Object.values(srcValue);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export class DataQueriesService implements IDataQueriesService {
|
||||||
protected readonly dataQueryRepository: DataQueryRepository,
|
protected readonly dataQueryRepository: DataQueryRepository,
|
||||||
protected readonly dataQueryUtilService: DataQueriesUtilService,
|
protected readonly dataQueryUtilService: DataQueriesUtilService,
|
||||||
protected readonly dataSourceRepository: DataSourcesRepository
|
protected readonly dataSourceRepository: DataSourcesRepository
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
async getAll(versionId: string) {
|
async getAll(versionId: string) {
|
||||||
const queries = await this.dataQueryRepository.getAll(versionId);
|
const queries = await this.dataQueryRepository.getAll(versionId);
|
||||||
|
|
@ -30,9 +30,6 @@ export class DataQueriesService implements IDataQueriesService {
|
||||||
|
|
||||||
// serialize
|
// serialize
|
||||||
for (const query of queries) {
|
for (const query of queries) {
|
||||||
if (query.dataSource.type === DataSourceTypes.STATIC) {
|
|
||||||
delete query['dataSourceId'];
|
|
||||||
}
|
|
||||||
delete query['dataSource'];
|
delete query['dataSource'];
|
||||||
|
|
||||||
const decamelizeQuery = decamelizeKeys(query);
|
const decamelizeQuery = decamelizeKeys(query);
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ export const TJDefaultTheme: Definition = {
|
||||||
light: '#1B1F24',
|
light: '#1B1F24',
|
||||||
dark: '#CFD3D8',
|
dark: '#CFD3D8',
|
||||||
},
|
},
|
||||||
secondary: {
|
placeholder: {
|
||||||
light: '#6A727C',
|
light: '#6A727C',
|
||||||
dark: '#858C94',
|
dark: '#858C94',
|
||||||
},
|
},
|
||||||
tertiary: {
|
disabled: {
|
||||||
light: '#ACB2B9',
|
light: '#ACB2B9',
|
||||||
dark: '#545B64',
|
dark: '#545B64',
|
||||||
},
|
},
|
||||||
|
|
@ -48,15 +48,15 @@ export const TJDefaultTheme: Definition = {
|
||||||
large: 0,
|
large: 0,
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
primary: {
|
default: {
|
||||||
light: '#CCD1D5',
|
light: '#CCD1D5',
|
||||||
dark: '#3C434B',
|
dark: '#3C434B',
|
||||||
},
|
},
|
||||||
secondary: {
|
weak: {
|
||||||
light: '#E4E7EB',
|
light: '#E4E7EB',
|
||||||
dark: '#EEF0F1',
|
dark: '#EEF0F1',
|
||||||
},
|
},
|
||||||
tertiary: {
|
disabled: {
|
||||||
light: '#E4E7EB',
|
light: '#E4E7EB',
|
||||||
dark: '#F6F8FA',
|
dark: '#F6F8FA',
|
||||||
},
|
},
|
||||||
|
|
@ -64,15 +64,15 @@ export const TJDefaultTheme: Definition = {
|
||||||
},
|
},
|
||||||
systemStatus: {
|
systemStatus: {
|
||||||
colors: {
|
colors: {
|
||||||
primary: {
|
success: {
|
||||||
light: '#1E823B',
|
light: '#1E823B',
|
||||||
dark: '#318344',
|
dark: '#318344',
|
||||||
},
|
},
|
||||||
secondary: {
|
error: {
|
||||||
light: '#D72D39',
|
light: '#D72D39',
|
||||||
dark: '#D03F43',
|
dark: '#D03F43',
|
||||||
},
|
},
|
||||||
tertiary: {
|
warning: {
|
||||||
light: '#BF4F03',
|
light: '#BF4F03',
|
||||||
dark: '#BA5722',
|
dark: '#BA5722',
|
||||||
},
|
},
|
||||||
|
|
@ -84,6 +84,18 @@ export const TJDefaultTheme: Definition = {
|
||||||
light: '#F6F6F6',
|
light: '#F6F6F6',
|
||||||
dark: '#121518',
|
dark: '#121518',
|
||||||
},
|
},
|
||||||
|
surface1: {
|
||||||
|
light: '#FFFFFF',
|
||||||
|
dark: '#1E2226',
|
||||||
|
},
|
||||||
|
surface2: {
|
||||||
|
light: '#F6F8FA',
|
||||||
|
dark: '#2B3036',
|
||||||
|
},
|
||||||
|
surface3: {
|
||||||
|
light: '#E4E7EB',
|
||||||
|
dark: '#3C434B',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -33,12 +33,12 @@ class TextColors {
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => Color)
|
@Type(() => Color)
|
||||||
secondary?: Color;
|
placeholder?: Color;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => Color)
|
@Type(() => Color)
|
||||||
tertiary?: Color;
|
disabled?: Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Text {
|
class Text {
|
||||||
|
|
@ -64,17 +64,17 @@ class BorderRadius {
|
||||||
class BorderColors {
|
class BorderColors {
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => Color)
|
@Type(() => Color)
|
||||||
primary: Color;
|
default: Color;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => Color)
|
@Type(() => Color)
|
||||||
secondary?: Color;
|
weak?: Color;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => Color)
|
@Type(() => Color)
|
||||||
tertiary?: Color;
|
disabled?: Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Border {
|
class Border {
|
||||||
|
|
@ -90,17 +90,17 @@ class Border {
|
||||||
class SystemStatusColors {
|
class SystemStatusColors {
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => Color)
|
@Type(() => Color)
|
||||||
primary: Color;
|
success: Color;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => Color)
|
@Type(() => Color)
|
||||||
secondary?: Color;
|
error?: Color;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => Color)
|
@Type(() => Color)
|
||||||
tertiary?: Color;
|
warning?: Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SystemStatus {
|
class SystemStatus {
|
||||||
|
|
@ -121,6 +121,18 @@ class SurfaceColors {
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => AppBackgroundColor)
|
@Type(() => AppBackgroundColor)
|
||||||
appBackground: AppBackgroundColor;
|
appBackground: AppBackgroundColor;
|
||||||
|
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Color)
|
||||||
|
surface1: Color;
|
||||||
|
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Color)
|
||||||
|
surface2: Color;
|
||||||
|
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => Color)
|
||||||
|
surface3: Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Surface {
|
class Surface {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue