mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
Merge pull request #12591 from ToolJet/feat/steps-v2-alignment-style-improvement
feat: dynamic steps length based on steps text size
This commit is contained in:
commit
31552242a2
13 changed files with 1650 additions and 468 deletions
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ import Inspect from '@/_ui/Icon/solidIcons/Inspect';
|
|||
import classNames from 'classnames';
|
||||
import { EMPTY_ARRAY } from '@/_stores/editorStore';
|
||||
import { Select } from './Components/Select';
|
||||
import { Steps } from './Components/Steps.jsx';
|
||||
import { deepClone } from '@/_helpers/utilities/utils.helpers';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
// import { componentTypes } from '@/Editor/WidgetManager/components';
|
||||
|
|
@ -90,6 +91,7 @@ const NEW_REVAMPED_COMPONENTS = [
|
|||
'VerticalDivider',
|
||||
'ModalV2',
|
||||
'Link',
|
||||
'Steps',
|
||||
];
|
||||
|
||||
export const Inspector = ({ componentDefinitionChanged, darkMode, pages, selectedComponentId }) => {
|
||||
|
|
@ -539,8 +541,8 @@ export const Inspector = ({ componentDefinitionChanged, darkMode, pages, selecte
|
|||
componentMeta.displayName === 'Toggle Switch (Legacy)'
|
||||
? 'Toggle (Legacy)'
|
||||
: componentMeta.displayName === 'Toggle Switch'
|
||||
? 'Toggle Switch'
|
||||
: componentMeta.component,
|
||||
? 'Toggle Switch'
|
||||
: componentMeta.component,
|
||||
})}
|
||||
</small>
|
||||
</span>
|
||||
|
|
@ -740,6 +742,8 @@ const GetAccordion = React.memo(
|
|||
case 'DatePickerV2':
|
||||
case 'TimePicker':
|
||||
return <DatetimePickerV2 {...restProps} componentName={componentName} />;
|
||||
case 'Steps':
|
||||
return <Steps {...restProps} />;
|
||||
case 'PhoneInput':
|
||||
return <PhoneInput {...restProps} />;
|
||||
case 'CurrencyInput':
|
||||
|
|
|
|||
|
|
@ -4,25 +4,38 @@ export const stepsConfig = {
|
|||
description: 'Step-by-step navigation aid',
|
||||
component: 'Steps',
|
||||
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: {
|
||||
type: 'code',
|
||||
displayName: 'Steps',
|
||||
displayName: '',
|
||||
showLabel: false,
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'array',
|
||||
element: { type: 'object', object: { id: { type: 'number' } } },
|
||||
element: { type: 'object' },
|
||||
},
|
||||
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',
|
||||
|
|
@ -30,7 +43,38 @@ export const stepsConfig = {
|
|||
schema: { type: 'boolean' },
|
||||
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: {
|
||||
width: 22,
|
||||
|
|
@ -40,46 +84,126 @@ export const stepsConfig = {
|
|||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
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: {
|
||||
onSelect: { displayName: 'On select' },
|
||||
},
|
||||
styles: {
|
||||
color: {
|
||||
incompletedAccent: {
|
||||
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: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'var(--primary-brand)',
|
||||
},
|
||||
accordian: 'steps',
|
||||
},
|
||||
textColor: {
|
||||
completedLabel: {
|
||||
type: 'colorSwatches',
|
||||
displayName: 'Text color',
|
||||
displayName: 'Completed label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000000',
|
||||
defaultValue: '#1B1F24',
|
||||
},
|
||||
accordian: 'steps',
|
||||
},
|
||||
theme: {
|
||||
type: 'select',
|
||||
displayName: 'Theme',
|
||||
currentStepLabel: {
|
||||
type: 'colorSwatches',
|
||||
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: [
|
||||
{ name: 'titles', value: 'titles' },
|
||||
{ name: 'numbers', value: 'numbers' },
|
||||
{ name: 'plain', value: 'plain' },
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'titles',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
accordian: 'container',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
|
|
@ -92,17 +216,35 @@ export const stepsConfig = {
|
|||
},
|
||||
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}]}}`,
|
||||
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}}' },
|
||||
stepsSelectable: { value: true },
|
||||
advanced: { value: `{{false}}` },
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
theme: { value: 'titles' },
|
||||
color: { value: 'var(--primary-brand)' },
|
||||
textColor: { value: '' },
|
||||
// color: { value: '' },
|
||||
// textColor: { value: '' },
|
||||
padding: { value: 'default' },
|
||||
incompletedAccent: { value: '#E4E7EB' },
|
||||
incompletedLabel: { value: '#1B1F24' },
|
||||
completedAccent: { value: 'var(--primary-brand)' },
|
||||
completedLabel: { value: '#1B1F24' },
|
||||
currentStepLabel: { value: '#1B1F24' },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,53 +1,226 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
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 }) {
|
||||
const { stepsSelectable } = properties;
|
||||
const currentStep = isExpectedDataType(properties.currentStep, 'number');
|
||||
const steps = isExpectedDataType(properties.steps, 'array');
|
||||
const { color, theme, visibility, boxShadow } = styles;
|
||||
export const Steps = function Steps({ properties, styles, fireEvent, setExposedVariable, height, darkMode, dataCy }) {
|
||||
const { stepsSelectable, disabledState } = properties;
|
||||
const visibility = isExpectedDataType(properties.visibility, 'boolean');
|
||||
const currentStepId = isExpectedDataType(properties.currentStep, 'number');
|
||||
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 [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 = {
|
||||
'--bgColor': styles.color,
|
||||
'--textColor': textColor,
|
||||
};
|
||||
const activeStepHandler = (id) => {
|
||||
const active = steps.filter((item) => item.id == id);
|
||||
setExposedVariable('currentStepId', active[0].id);
|
||||
fireEvent('onSelect');
|
||||
setActiveStep(active[0].id);
|
||||
'--completedAccent': completedAccent === '#4368E3' ? 'var(--primary-brand)' : completedAccent,
|
||||
'--incompletedAccent': incompletedAccent === '#E4E7EB' ? 'var(--surfaces-surface-03)' : incompletedAccent,
|
||||
'--incompletedLabel': incompletedLabel === '#1B1F24' ? 'var(--text-primary)' : incompletedLabel,
|
||||
'--completedLabel': completedLabel === '#1B1F24' ? 'var(--text-primary)' : completedLabel,
|
||||
'--currentStepLabel': currentStepLabel === '#1B1F24' ? 'var(--text-primary)' : currentStepLabel,
|
||||
};
|
||||
|
||||
// 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(() => {
|
||||
setActiveStep(currentStep);
|
||||
setExposedVariable('currentStepId', currentStep);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentStep]);
|
||||
setExposedVariable('isVisible', isVisible);
|
||||
setExposedVariable('isDisabled', isDisabled);
|
||||
setExposedVariable('currentStepId', activeStepId);
|
||||
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 (
|
||||
visibility && (
|
||||
<div
|
||||
className={`steps ${theme == 'numbers' && 'steps-counter '}`}
|
||||
style={{ color: textColor, height, boxShadow }}
|
||||
data-cy={dataCy}
|
||||
>
|
||||
{steps?.map((item) => (
|
||||
<a
|
||||
key={item.id}
|
||||
className={`step-item ${item.id == activeStep && 'active'} ${!stepsSelectable && 'step-item-disabled'} ${
|
||||
color && `step-${color}`
|
||||
}`}
|
||||
data-bs-toggle="tooltip"
|
||||
title={item?.tooltip}
|
||||
onClick={() => stepsSelectable && activeStepHandler(item.id)}
|
||||
style={dynamicStyle}
|
||||
>
|
||||
{theme == 'titles' && item.name}
|
||||
</a>
|
||||
))}
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={`steps-container ${isDisabled ? 'disabled' : ''} ${filteredSteps.length === 1 ? 'single-step' : ''}`}
|
||||
style={{
|
||||
height,
|
||||
boxShadow,
|
||||
padding: theme === 'titles' ? `0 ${containerPadding}px` : 2,
|
||||
paddingTop: theme === 'plain' ? `3px` : theme === 'numbers' ? `2px` : 0,
|
||||
...dynamicStyle
|
||||
}}
|
||||
data-cy={dataCy}
|
||||
>
|
||||
<div className={`progress-line-container ${filteredSteps.length === 1 ? 'single-step' : ''}`}>
|
||||
{filteredSteps.map((step, index) => {
|
||||
const isStepDisabled = step.disabled;
|
||||
const isCompleted = index < currentStepIndex;
|
||||
const isActive = index === currentStepIndex;
|
||||
const isUpcoming = index > currentStepIndex;
|
||||
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>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ import { verticalDividerConfig } from './verticalDivider';
|
|||
import { customComponentConfig } from './customComponent';
|
||||
import { buttonGroupConfig } from './buttonGroup';
|
||||
import { pdfConfig } from './pdf';
|
||||
import { stepsConfig } from './steps';
|
||||
// import { stepsConfig } from './steps';
|
||||
import { kanbanConfig } from './kanban';
|
||||
import { colorPickerConfig } from './colorPicker';
|
||||
import { treeSelectConfig } from './treeSelect';
|
||||
|
|
@ -106,7 +106,7 @@ export {
|
|||
customComponentConfig,
|
||||
buttonGroupConfig,
|
||||
pdfConfig,
|
||||
stepsConfig,
|
||||
// stepsConfig,
|
||||
kanbanConfig,
|
||||
kanbanBoardConfig, //!Depreciated
|
||||
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 {
|
||||
border-radius: 4px ;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.rounded-0 {
|
||||
border-radius: 0 !important
|
||||
}
|
||||
|
||||
.rounded-top-left{
|
||||
.rounded-top-left {
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
|
||||
.rounded-top-left-0{
|
||||
.rounded-top-left-0 {
|
||||
border-top-left-radius: 0 !important;
|
||||
}
|
||||
.rounded-top-right-0{
|
||||
|
||||
.rounded-top-right-0 {
|
||||
border-top-right-radius: 0 !important;
|
||||
}
|
||||
.rounded-bottom-left-0{
|
||||
|
||||
.rounded-bottom-left-0 {
|
||||
border-bottom-left-radius: 0 !important;
|
||||
}
|
||||
.rounded-bottom-right-0{
|
||||
|
||||
.rounded-bottom-right-0 {
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||
|
||||
.rounded-1 {
|
||||
border-radius: 2px !important
|
||||
}
|
||||
|
|
@ -17484,8 +17488,8 @@ a.step-item:hover {
|
|||
|
||||
.step-item:not(:first-child):after {
|
||||
position: absolute;
|
||||
left: -50%;
|
||||
width: 100%;
|
||||
left: calc(-50% + 8px);
|
||||
width: calc(100% - 16px);
|
||||
content: "";
|
||||
transform: translateY(-50%)
|
||||
}
|
||||
|
|
@ -17498,13 +17502,25 @@ a.step-item:hover {
|
|||
box-sizing: content-box;
|
||||
display: block;
|
||||
content: "";
|
||||
border: 2px solid #fff;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 50%;
|
||||
transform: translateX(-50%)
|
||||
}
|
||||
|
||||
.step-item.active {
|
||||
font-weight: 600
|
||||
.steps.steps-counter {
|
||||
.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 {
|
||||
|
|
@ -17521,7 +17537,7 @@ a.step-item:hover {
|
|||
}
|
||||
|
||||
.step-item.active~.step-item:before {
|
||||
color: #656d77 !important
|
||||
color: var(--incompletedLabel) !important
|
||||
}
|
||||
|
||||
.steps-counter {
|
||||
|
|
@ -17549,7 +17565,8 @@ a.step-item:hover {
|
|||
.steps-counter .step-item:before {
|
||||
font-size: .75rem;
|
||||
line-height: 1.5rem;
|
||||
content: counter(steps)
|
||||
content: counter(steps);
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
.steps-counter .step-item.active~.step-item:before {
|
||||
|
|
@ -19156,4 +19173,4 @@ img {
|
|||
background: #1f2936;
|
||||
border-color: #dadcde
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4760,15 +4760,18 @@ input[type="text"] {
|
|||
.folder-list {
|
||||
overflow-y: scroll;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #888 transparent;
|
||||
scrollbar-color: #888 transparent;
|
||||
|
||||
&:hover {
|
||||
&::-webkit-scrollbar {
|
||||
display: block;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
|
@ -6518,6 +6521,7 @@ div#driver-page-overlay {
|
|||
// steps-widget
|
||||
a.step-item-disabled {
|
||||
text-decoration: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.steps {
|
||||
|
|
@ -6527,34 +6531,45 @@ a.step-item-disabled {
|
|||
|
||||
.step-item.active~.step-item:after,
|
||||
.step-item.active~.step-item:before {
|
||||
background: #f3f5f5 !important;
|
||||
background: var(--incompletedAccent) !important;
|
||||
}
|
||||
|
||||
.step-item.active:before {
|
||||
background: #ffffff !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.steps .step-item.active:before {
|
||||
border-color: #b4b2b2 !important;
|
||||
border-color: var(--completedAccent) !important;
|
||||
}
|
||||
|
||||
.steps-item {
|
||||
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 {
|
||||
background: var(--bgColor) !important;
|
||||
background-color: var(--completedAccent) !important;
|
||||
// remaining code
|
||||
}
|
||||
|
||||
.step-item:after {
|
||||
background: var(--bgColor) !important;
|
||||
background: var(--completedAccent) !important;
|
||||
}
|
||||
|
||||
.step-item.active~.step-item {
|
||||
color: var(--textColor) !important;
|
||||
;
|
||||
}
|
||||
|
||||
.notification-center-badge {
|
||||
|
||||
|
|
@ -9872,25 +9887,30 @@ tbody {
|
|||
.workspace-settings-table-wrap {
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
.tj-user-table-wrapper{
|
||||
|
||||
.tj-user-table-wrapper {
|
||||
padding-right: 4px;
|
||||
}
|
||||
&:hover{
|
||||
.tj-user-table-wrapper{
|
||||
padding-right: 0px;
|
||||
}
|
||||
::-webkit-scrollbar{
|
||||
display: block;
|
||||
width: 4px;
|
||||
}
|
||||
::-webkit-scrollbar-track{
|
||||
background: var(--base);
|
||||
}
|
||||
::-webkit-scrollbar-thumb{
|
||||
background: var(--slate7);
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.tj-user-table-wrapper {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: block;
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--base);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--slate7);
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -12056,8 +12076,10 @@ tbody {
|
|||
letter-spacing: -0.02em;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-list-wrap.sidebar-list-wrap-with-banner.isAdmin {
|
||||
height: calc(100vh - 371px);
|
||||
|
||||
&.resource-limit-reached {
|
||||
height: calc(100vh - 371px);
|
||||
}
|
||||
|
|
@ -15801,6 +15823,7 @@ textarea.tj-text-input-widget{
|
|||
|
||||
.rest-api-options-codehinter {
|
||||
height: 100%;
|
||||
|
||||
.cm-content>.cm-line {
|
||||
// max-width: 357px !important;
|
||||
}
|
||||
|
|
@ -16232,19 +16255,20 @@ fieldset:disabled {
|
|||
}
|
||||
|
||||
.datepicker-validation-half {
|
||||
flex:1 1 calc(50% - 8px);
|
||||
flex: 1 1 calc(50% - 8px);
|
||||
}
|
||||
|
||||
|
||||
.date-validation-wrapper {
|
||||
|
||||
.field {
|
||||
height:24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.code-flex-wrapper {
|
||||
flex-wrap:wrap;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
|
|
@ -16253,57 +16277,60 @@ 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;
|
||||
}
|
||||
|
||||
.react-datepicker__time-list{
|
||||
li.react-datepicker__time-list-item--disabled.react-datepicker__time-list-item {
|
||||
color: #ccc !important;
|
||||
}
|
||||
}
|
||||
|
||||
.inspector-validation-date-picker {
|
||||
.react-datepicker-wrapper{
|
||||
input {
|
||||
background-color: #fff;
|
||||
}
|
||||
input.dark-theme {
|
||||
background-color: var(--slate3);
|
||||
color: var(--slate12);
|
||||
}
|
||||
}
|
||||
|
||||
.inspector-validation-date-picker {
|
||||
.react-datepicker-wrapper {
|
||||
input {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
.react-datepicker {
|
||||
border-radius: 10px;
|
||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||
height:auto;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.react-datepicker-time-component {
|
||||
border-radius: 10px;
|
||||
width:auto;
|
||||
width: auto;
|
||||
|
||||
.custom-time-input{
|
||||
border-left:none;
|
||||
border-radius:10px;
|
||||
.custom-time-input {
|
||||
border-left: none;
|
||||
border-radius: 10px;
|
||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||
}
|
||||
|
||||
.time-input-body {
|
||||
padding-bottom:0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
|
||||
.time-col {
|
||||
height: 200px;
|
||||
}
|
||||
|
|
@ -16312,28 +16339,32 @@ fieldset:disabled {
|
|||
border-radius: 10px;
|
||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||
}
|
||||
|
||||
.react-datepicker-time__input-container{
|
||||
border-radius:10px;
|
||||
|
||||
.react-datepicker-time__input-container {
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.dark-theme {
|
||||
.react-datepicker__year-text, .react-datepicker__month-text {
|
||||
|
||||
.react-datepicker__year-text,
|
||||
.react-datepicker__month-text {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.react-datepicker__year-text:hover, .react-datepicker__month-text:hover {
|
||||
background-color: #9ba1a6 ;
|
||||
.react-datepicker__year-text:hover,
|
||||
.react-datepicker__month-text:hover {
|
||||
background-color: #9ba1a6;
|
||||
}
|
||||
}
|
||||
|
||||
.tj-datepicker-widget-year-selector:hover, .tj-datepicker-widget-month-selector:hover {
|
||||
padding:1px 6px;
|
||||
.tj-datepicker-widget-year-selector:hover,
|
||||
.tj-datepicker-widget-month-selector:hover {
|
||||
padding: 1px 6px;
|
||||
}
|
||||
|
||||
.react-datepicker{
|
||||
.react-datepicker {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
border-top-right-radius: 0rem;
|
||||
|
|
@ -16346,48 +16377,49 @@ fieldset:disabled {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.react-datepicker__year-wrapper {
|
||||
display:grid;
|
||||
grid-template-columns:repeat(3, 1fr);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
max-width: unset;
|
||||
gap:10px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.react-datepicker {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.react-datepicker__header--custom{
|
||||
.react-datepicker__header--custom {
|
||||
height: 34px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.react-datepicker__year--container{
|
||||
height:208px;
|
||||
.react-datepicker__year--container {
|
||||
height: 208px;
|
||||
width: 250px;
|
||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.react-datepicker__year-text--selected {
|
||||
background-color: #4368E3 !important;
|
||||
height:24px;
|
||||
width:61.33px;
|
||||
border-radius: 8px;
|
||||
color: #fff ;
|
||||
background-color: #4368E3 !important;
|
||||
height: 24px;
|
||||
width: 61.33px;
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.react-datepicker__year-text{
|
||||
font-family:'IBM Plex Sans' ;
|
||||
.react-datepicker__year-text {
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
height:24px;
|
||||
width:61.33px;
|
||||
height: 24px;
|
||||
width: 61.33px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display:flex;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -16402,42 +16434,42 @@ fieldset:disabled {
|
|||
}
|
||||
|
||||
.react-datepicker__month-container {
|
||||
height:208px;
|
||||
height: 208px;
|
||||
width: 250px;
|
||||
box-shadow: 8px 8px 16px 0px #3032331A;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.react-datepicker__monthPicker {
|
||||
display:flex;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap:10px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.react-datepicker__month-text--selected {
|
||||
background-color: #4368E3 !important;
|
||||
height:24px;
|
||||
width:61.33px;
|
||||
height: 24px;
|
||||
width: 61.33px;
|
||||
border-radius: 8px;
|
||||
color: #fff ;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.react-datepicker__month-wrapper {
|
||||
display:flex;
|
||||
gap:24px;
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.react-datepicker__month-text {
|
||||
font-family:'IBM Plex Sans' ;
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
height:24px;
|
||||
width:61.33px;
|
||||
height: 24px;
|
||||
width: 61.33px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display:flex;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -16447,7 +16479,7 @@ fieldset:disabled {
|
|||
|
||||
.react-datepicker__month-container {
|
||||
width: 100%;
|
||||
width:250px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.react-datepicker__input-time-container {
|
||||
|
|
@ -16462,12 +16494,12 @@ fieldset:disabled {
|
|||
color: #ccc !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker-time__input {
|
||||
margin-left: 0px !important;
|
||||
|
||||
.dark-time-input {
|
||||
color:#f4f6fa !important;
|
||||
color: #f4f6fa !important;
|
||||
background-color: var(--surfaces-surface-01) !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -16475,15 +16507,15 @@ fieldset:disabled {
|
|||
.react-datepicker-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker-time__caption {
|
||||
display:none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.custom-time-input {
|
||||
background-color: #fff;
|
||||
border-left: 1px solid #CCD1D5;
|
||||
border-top-right-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
}
|
||||
|
||||
|
|
@ -16497,18 +16529,18 @@ fieldset:disabled {
|
|||
border-bottom: 1px solid #CCD1D5;
|
||||
font-weight: 500;
|
||||
font-family: 'IBM Plex Sans';
|
||||
color:#ACB2B9;
|
||||
color: #ACB2B9;
|
||||
}
|
||||
|
||||
|
||||
.time-input-body {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.time-col {
|
||||
margin-top: 5px;
|
||||
overflow-y: auto;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: none;
|
||||
scrollbar-width: none;
|
||||
height: 265px;
|
||||
width: 62px;
|
||||
}
|
||||
|
|
@ -16516,12 +16548,12 @@ fieldset:disabled {
|
|||
.selected-time {
|
||||
background-color: #4368E3 !important;
|
||||
border-radius: 6px;
|
||||
color:#fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.time-item {
|
||||
width: 50px;
|
||||
height:22px;
|
||||
width: 50px;
|
||||
height: 22px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
|
@ -16861,16 +16893,17 @@ section.ai-message-prompt-input-wrapper {
|
|||
|
||||
|
||||
.tj-inspector-timepicker.dark-theme {
|
||||
.react-datepicker {
|
||||
color:#f4f6fa !important;
|
||||
.react-datepicker {
|
||||
color: #f4f6fa !important;
|
||||
background-color: var(--surfaces-surface-01) !important;
|
||||
}
|
||||
|
||||
.react-datepicker, .react-datepicker__header {
|
||||
.react-datepicker,
|
||||
.react-datepicker__header {
|
||||
border: 1px solid var(--borders-default);
|
||||
background-color: #1f2936;
|
||||
|
||||
.react-datepicker-time__header{
|
||||
.react-datepicker-time__header {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
|
|
@ -16878,25 +16911,27 @@ section.ai-message-prompt-input-wrapper {
|
|||
}
|
||||
|
||||
.tj-inspector-timepicker {
|
||||
padding:0px !important;
|
||||
padding: 0px !important;
|
||||
|
||||
.react-datepicker__time-list {
|
||||
scrollbar-width: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.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;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
height:32px;
|
||||
|
||||
height: 32px;
|
||||
|
||||
.react-datepicker-wrapper {
|
||||
width: 100%;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
border: 1px solid var(--slate7);
|
||||
|
|
@ -16904,23 +16939,23 @@ section.ai-message-prompt-input-wrapper {
|
|||
background-color: var(--base);
|
||||
background-color: #fff;
|
||||
color: rgb(0, 92, 197);
|
||||
height:32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
input.dark-theme {
|
||||
background-color: #272822;
|
||||
color: rgb(174, 129, 255);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.custom-inspector-validation-time-picker {
|
||||
.custom-time-input {
|
||||
border-left:none;
|
||||
border-radius:10px;
|
||||
border-left: none;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.time-col {
|
||||
|
|
@ -16928,19 +16963,21 @@ section.ai-message-prompt-input-wrapper {
|
|||
}
|
||||
|
||||
.react-datepicker__input-time-container {
|
||||
border-radius:10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.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;
|
||||
|
||||
.hide-fx {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
|
|
@ -16959,8 +16996,9 @@ section.ai-message-prompt-input-wrapper {
|
|||
color: white;
|
||||
}
|
||||
|
||||
.react-datepicker__day:hover, .react-datepicker__day--selecting-range-end {
|
||||
background-color: var(--interactive-overlays-fill-hover) !important ;
|
||||
.react-datepicker__day:hover,
|
||||
.react-datepicker__day--selecting-range-end {
|
||||
background-color: var(--interactive-overlays-fill-hover) !important;
|
||||
}
|
||||
|
||||
.react-datepicker__day--keyboard-selected {
|
||||
|
|
@ -16983,15 +17021,17 @@ section.ai-message-prompt-input-wrapper {
|
|||
|
||||
.tj-daterange-widget {
|
||||
|
||||
border-radius:10px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
||||
font-family: 'IBM Plex Sans';
|
||||
|
||||
.react-datepicker__day--in-selecting-range, .react-datepicker__day--in-range {
|
||||
border-radius:0px;
|
||||
.react-datepicker__day--in-selecting-range,
|
||||
.react-datepicker__day--in-range {
|
||||
border-radius: 0px;
|
||||
background-color: #4368E31A !important;
|
||||
}
|
||||
.react-datepicker__header{
|
||||
|
||||
.react-datepicker__header {
|
||||
background-color: var(--surfaces-surface-01);
|
||||
padding: 6px 0px;
|
||||
border: none;
|
||||
|
|
@ -17002,44 +17042,48 @@ section.ai-message-prompt-input-wrapper {
|
|||
background-color: #ededee !important;
|
||||
}
|
||||
|
||||
.react-datepicker__day--selecting-range-start, .react-datepicker__day--selected, .react-datepicker__day--range-end {
|
||||
border-radius:8px !important;
|
||||
.react-datepicker__day--selecting-range-start,
|
||||
.react-datepicker__day--selected,
|
||||
.react-datepicker__day--range-end {
|
||||
border-radius: 8px !important;
|
||||
background-color: #4368E3 !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-bottom-right-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__day--in-range:has(+ .react-datepicker__day--range-end) {
|
||||
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-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;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__week {
|
||||
|
||||
.react-datepicker__day--in-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-selecting-range{
|
||||
.react-datepicker__day--in-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-selecting-range {
|
||||
border-top-left-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
.react-datepicker__day--in-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-selecting-range:has(+ .react-datepicker__day--outside-month){
|
||||
.react-datepicker__day--in-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-selecting-range:has(+ .react-datepicker__day--outside-month) {
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
}
|
||||
|
|
@ -17057,8 +17101,8 @@ section.ai-message-prompt-input-wrapper {
|
|||
}
|
||||
|
||||
.tj-datepicker-widget-right {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.tj-datepicker-widget-left {
|
||||
|
|
@ -17081,41 +17125,42 @@ section.ai-message-prompt-input-wrapper {
|
|||
}
|
||||
|
||||
.react-datepicker {
|
||||
border-radius:10px !important;
|
||||
border:none;
|
||||
border-radius: 10px !important;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.tj-daterangepicker-widget-month-selector, .tj-daterangepicker-widget-year-selector {
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
padding-right: 4px;
|
||||
/* Add some padding on the right to create space for custom arrow */
|
||||
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 a custom arrow (you can use your own SVG) */
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
border: none;
|
||||
/* Remove the default border */
|
||||
padding: 8px;
|
||||
/* Adjust padding as needed */
|
||||
cursor: pointer;
|
||||
/* Add pointer cursor for better usability */
|
||||
background: none;
|
||||
padding: 0px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
color: var(--text-primary);
|
||||
font-weight: 500;
|
||||
width:auto;
|
||||
.tj-daterangepicker-widget-month-selector,
|
||||
.tj-daterangepicker-widget-year-selector {
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
padding-right: 4px;
|
||||
/* Add some padding on the right to create space for custom arrow */
|
||||
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 a custom arrow (you can use your own SVG) */
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
border: none;
|
||||
/* Remove the default border */
|
||||
padding: 8px;
|
||||
/* Adjust padding as needed */
|
||||
cursor: pointer;
|
||||
/* Add pointer cursor for better usability */
|
||||
background: none;
|
||||
padding: 0px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
color: var(--text-primary);
|
||||
font-weight: 500;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
|
||||
.datepicker-widget {
|
||||
.react-datepicker-wrapper{
|
||||
width:100% !important;
|
||||
.react-datepicker-wrapper {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -17129,26 +17174,29 @@ section.ai-message-prompt-input-wrapper {
|
|||
}
|
||||
|
||||
.tj-daterange-widget.react-datepicker-month-component {
|
||||
border-radius:10px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
||||
font-family: 'IBM Plex Sans';
|
||||
|
||||
.react-datepicker__month-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.react-datepicker__month-text {
|
||||
height:26px !important;
|
||||
height: 26px !important;
|
||||
margin: 0px;
|
||||
width:100% !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.react-datepicker__month-text--in-selecting-range, .react-datepicker__month-text--in-range {
|
||||
border-radius:0px;
|
||||
.react-datepicker__month-text--in-selecting-range,
|
||||
.react-datepicker__month-text--in-range {
|
||||
border-radius: 0px;
|
||||
background-color: #4368E31A !important;
|
||||
color:#000;
|
||||
color: #000;
|
||||
}
|
||||
.react-datepicker__header{
|
||||
|
||||
.react-datepicker__header {
|
||||
background-color: var(--surfaces-surface-01);
|
||||
padding: 6px 0px;
|
||||
border: none;
|
||||
|
|
@ -17161,45 +17209,49 @@ section.ai-message-prompt-input-wrapper {
|
|||
|
||||
}
|
||||
|
||||
.react-datepicker__month-text--selecting-range-start, .react-datepicker__month-text--selected, .react-datepicker__month-text--range-end {
|
||||
border-radius:8px !important;
|
||||
.react-datepicker__month-text--selecting-range-start,
|
||||
.react-datepicker__month-text--selected,
|
||||
.react-datepicker__month-text--range-end {
|
||||
border-radius: 8px !important;
|
||||
background-color: #4368E3 !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-bottom-right-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__month-text--in-range:has(+ .react-datepicker__month-text--range-end) {
|
||||
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-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;
|
||||
}
|
||||
|
||||
.react-datepicker__month-wrapper{
|
||||
gap:0px !important;
|
||||
|
||||
.react-datepicker__month-text--in-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-selecting-range{
|
||||
.react-datepicker__month-wrapper {
|
||||
gap: 0px !important;
|
||||
|
||||
.react-datepicker__month-text--in-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-selecting-range {
|
||||
border-top-left-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
.react-datepicker__month-text--in-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-selecting-range:has(+ .react-datepicker__month-text--outside-month-text){
|
||||
.react-datepicker__month-text--in-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-selecting-range:has(+ .react-datepicker__month-text--outside-month-text) {
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
}
|
||||
|
|
@ -17219,44 +17271,47 @@ section.ai-message-prompt-input-wrapper {
|
|||
}
|
||||
|
||||
.tj-daterange-widget.react-datepicker-year-component {
|
||||
border-radius:10px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 8px 16px 0px #3032331A !important;
|
||||
font-family: 'IBM Plex Sans';
|
||||
|
||||
.react-datepicker__year-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.react-datepicker__year-wrapper{
|
||||
gap:0px !important;
|
||||
.react-datepicker__year-wrapper {
|
||||
gap: 0px !important;
|
||||
|
||||
.react-datepicker__year-text--in-range:first-of-type,
|
||||
.react-datepicker__year-text--in-selecting-range:first-of-type{
|
||||
.react-datepicker__year-text--in-range:first-of-type,
|
||||
.react-datepicker__year-text--in-selecting-range:first-of-type {
|
||||
border-top-left-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
.react-datepicker__year-text--in-range:last-of-type,
|
||||
.react-datepicker__year-text--in-selecting-range:last-of-type{
|
||||
.react-datepicker__year-text--in-range:last-of-type,
|
||||
.react-datepicker__year-text--in-selecting-range:last-of-type {
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.react-datepicker__year-text {
|
||||
height:26px !important;
|
||||
height: 26px !important;
|
||||
margin-top: 5px !important;
|
||||
margin-bottom:5px !important;
|
||||
margin-bottom: 5px !important;
|
||||
margin: 0px;
|
||||
width:62px !important;
|
||||
width: 62px !important;
|
||||
}
|
||||
|
||||
.react-datepicker__year-text--in-selecting-range, .react-datepicker__year-text--in-range {
|
||||
border-radius:0px;
|
||||
.react-datepicker__year-text--in-selecting-range,
|
||||
.react-datepicker__year-text--in-range {
|
||||
border-radius: 0px;
|
||||
background-color: #4368E31A !important;
|
||||
color:#000;
|
||||
color: #000;
|
||||
}
|
||||
.react-datepicker__header{
|
||||
|
||||
.react-datepicker__header {
|
||||
background-color: var(--surfaces-surface-01);
|
||||
padding: 6px 0px;
|
||||
border: none;
|
||||
|
|
@ -17269,31 +17324,35 @@ section.ai-message-prompt-input-wrapper {
|
|||
|
||||
}
|
||||
|
||||
.react-datepicker__year-text--selecting-range-start, .react-datepicker__year-text--selected, .react-datepicker__year-text--range-end {
|
||||
border-radius:8px !important;
|
||||
.react-datepicker__year-text--selecting-range-start,
|
||||
.react-datepicker__year-text--selected,
|
||||
.react-datepicker__year-text--range-end {
|
||||
border-radius: 8px !important;
|
||||
background-color: #4368E3 !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-bottom-right-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__year-text--in-range:has(+ .react-datepicker__year-text--range-end) {
|
||||
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-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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.dark-theme {
|
||||
|
|
@ -18783,6 +18842,7 @@ section.ai-message-prompt-input-wrapper {
|
|||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
|
||||
&.dark {
|
||||
background: #FFFAEB !important;
|
||||
}
|
||||
|
|
|
|||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +95,9 @@ export class ComponentsService implements IComponentsService {
|
|||
if (componentData.type === 'Table' && _.isArray(objValue)) {
|
||||
return srcValue;
|
||||
} else if (
|
||||
(componentData.type === 'DropdownV2' || componentData.type === 'MultiselectV2') &&
|
||||
(componentData.type === 'DropdownV2' ||
|
||||
componentData.type === 'MultiselectV2' ||
|
||||
componentData.type === 'Steps') &&
|
||||
_.isArray(objValue)
|
||||
) {
|
||||
return _.isArray(srcValue) ? srcValue : Object.values(srcValue);
|
||||
|
|
|
|||
|
|
@ -4,25 +4,38 @@ export const stepsConfig = {
|
|||
description: 'Step-by-step navigation aid',
|
||||
component: 'Steps',
|
||||
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: {
|
||||
type: 'code',
|
||||
displayName: 'Steps',
|
||||
displayName: '',
|
||||
showLabel: false,
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'array',
|
||||
element: { type: 'object', object: { id: { type: 'number' } } },
|
||||
element: { type: 'object' },
|
||||
},
|
||||
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',
|
||||
|
|
@ -30,6 +43,36 @@ export const stepsConfig = {
|
|||
schema: { type: 'boolean' },
|
||||
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: {
|
||||
|
|
@ -40,46 +83,126 @@ export const stepsConfig = {
|
|||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
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: {
|
||||
onSelect: { displayName: 'On select' },
|
||||
},
|
||||
styles: {
|
||||
color: {
|
||||
incompletedAccent: {
|
||||
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: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'var(--primary-brand)',
|
||||
},
|
||||
accordian: 'steps',
|
||||
},
|
||||
textColor: {
|
||||
completedLabel: {
|
||||
type: 'colorSwatches',
|
||||
displayName: 'Text color',
|
||||
displayName: 'Completed label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000000',
|
||||
defaultValue: '#1B1F24',
|
||||
},
|
||||
accordian: 'steps',
|
||||
},
|
||||
theme: {
|
||||
type: 'select',
|
||||
displayName: 'Theme',
|
||||
currentStepLabel: {
|
||||
type: 'colorSwatches',
|
||||
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: [
|
||||
{ name: 'titles', value: 'titles' },
|
||||
{ name: 'numbers', value: 'numbers' },
|
||||
{ name: 'plain', value: 'plain' },
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'titles',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
accordian: 'container',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
|
|
@ -92,17 +215,35 @@ export const stepsConfig = {
|
|||
},
|
||||
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}]}}`,
|
||||
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}}' },
|
||||
stepsSelectable: { value: true },
|
||||
advanced: { value: `{{false}}` },
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
theme: { value: 'titles' },
|
||||
color: { value: 'var(--primary-brand)' },
|
||||
textColor: { value: '' },
|
||||
// color: { 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)) {
|
||||
return srcValue;
|
||||
} else if (
|
||||
['DropdownV2', 'MultiselectV2'].includes(currentComponentData?.component?.component) &&
|
||||
['DropdownV2', 'MultiselectV2', 'Steps'].includes(currentComponentData?.component?.component) &&
|
||||
isArray(objValue)
|
||||
) {
|
||||
return isArray(srcValue) ? srcValue : Object.values(srcValue);
|
||||
|
|
|
|||
Loading…
Reference in a new issue