diff --git a/frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx b/frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx
new file mode 100644
index 0000000000..314fe8ba89
--- /dev/null
+++ b/frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx
@@ -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 (
+
+
+
+
+ handleLabelChange('id', value, index)}
+ />
+
+
+
+ handleLabelChange('name', value, index)}
+ />
+
+
+
+ handleLabelChange('tooltip', value, index)}
+ />
+
+
+
+ handleLabelChange(
+ 'visible',
+ {
+ value,
+ },
+ index
+ )
+ }
+ paramName={'visible'}
+ onFxPress={(active) => handleOnFxPress(active, index, 'visible')}
+ fxActive={item?.visible?.fxActive}
+ fieldMeta={{
+ type: 'toggle',
+ displayName: 'Make editable',
+ }}
+ paramType={'toggle'}
+ />
+
+
+ handleLabelChange('disabled', { value }, index)}
+ onFxPress={(active) => handleOnFxPress(active, index, 'disabled')}
+ fxActive={item?.disabled?.fxActive}
+ fieldMeta={{
+ type: 'toggle',
+ displayName: 'Make editable',
+ }}
+ paramType={'toggle'}
+ />
+
+
+
+ );
+ };
+ const _renderOptions = () => {
+ return (
+
+ {
+ onDragEnd(result);
+ }}
+ >
+
+ {({ innerRef, droppableProps, placeholder }) => (
+
+ {options?.map((item, index) => {
+ return (
+
+ {(provided, snapshot) => (
+
+
+
+
setHoveredOptionIndex(index)}
+ onMouseLeave={() => setHoveredOptionIndex(null)}
+ {...restProps}
+ >
+
+
+
+
+
+ {getResolvedValue(item.name)}
+
+
+ {index === hoveredOptionIndex && (
+ {
+ e.stopPropagation();
+ handleDeleteOption(index);
+ }}
+ >
+
+
+
+
+ )}
+
+
+
+
+
+
+ )}
+
+ );
+ })}
+ {placeholder}
+
+ )}
+
+
+
+ Add new option
+
+
+ );
+ };
+
+ 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: (
+
+ ),
+ });
+ 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 ;
+}
+
+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 (
+
+ {
+ paramUpdated({ name: 'variant' }, 'value', e, 'properties', false, props);
+ }}
+ meta={{
+ ...componentMeta.properties[param],
+ fullWidth: true,
+ }}
+ paramName={param}
+ isIcon={false}
+ component={component.component.definition.name}
+ />
+
+ );
+}
diff --git a/frontend/src/AppBuilder/RightSideBar/Inspector/Inspector.jsx b/frontend/src/AppBuilder/RightSideBar/Inspector/Inspector.jsx
index e101069fdb..07b53c4454 100644
--- a/frontend/src/AppBuilder/RightSideBar/Inspector/Inspector.jsx
+++ b/frontend/src/AppBuilder/RightSideBar/Inspector/Inspector.jsx
@@ -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,
})}
@@ -740,6 +742,8 @@ const GetAccordion = React.memo(
case 'DatePickerV2':
case 'TimePicker':
return ;
+ case 'Steps':
+ return ;
case 'PhoneInput':
return ;
case 'CurrencyInput':
diff --git a/frontend/src/AppBuilder/WidgetManager/widgets/steps.js b/frontend/src/AppBuilder/WidgetManager/widgets/steps.js
index 0a6a2cd575..9e71a89f90 100644
--- a/frontend/src/AppBuilder/WidgetManager/widgets/steps.js
+++ b/frontend/src/AppBuilder/WidgetManager/widgets/steps.js
@@ -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' },
},
},
};
diff --git a/frontend/src/Editor/Components/Steps.jsx b/frontend/src/Editor/Components/Steps.jsx
index 4a42e9362e..4662c92bc6 100644
--- a/frontend/src/Editor/Components/Steps.jsx
+++ b/frontend/src/Editor/Components/Steps.jsx
@@ -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 && (
-
- {steps?.map((item) => (
-
stepsSelectable && activeStepHandler(item.id)}
- style={dynamicStyle}
- >
- {theme == 'titles' && item.name}
-
- ))}
+
+
+ {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 (
+
{/* using index as key to avoid issues due to duplicate step ids */}
+
+ stepsSelectable && handleStepClick(step.id)}
+ className={`milestone ${theme === 'numbers' ? 'numbers' : ''} ${isDisabled || isStepDisabled ? 'disabled' : ''
+ } ${isCompleted ? 'completed' : isActive ? 'active' : 'incomplete'}`}
+ >
+ {theme === 'numbers' ? (
+ index + 1
+ ) : (
+ <>
+
+ {theme === 'titles' && (
+
+ {step.name}
+
+ )}
+ >
+ )}
+
+
+
+ {index < filteredSteps.length - 1 && (
+
+ )}
+
+ );
+ })}
- )
+
);
};
diff --git a/frontend/src/Editor/Components/Steps.scss b/frontend/src/Editor/Components/Steps.scss
new file mode 100644
index 0000000000..c61f185a73
--- /dev/null
+++ b/frontend/src/Editor/Components/Steps.scss
@@ -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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/Editor/WidgetManager/configs/index.js b/frontend/src/Editor/WidgetManager/configs/index.js
index 93e45fd06c..b26b6c84a2 100644
--- a/frontend/src/Editor/WidgetManager/configs/index.js
+++ b/frontend/src/Editor/WidgetManager/configs/index.js
@@ -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,
diff --git a/frontend/src/Editor/WidgetManager/configs/steps.js b/frontend/src/Editor/WidgetManager/configs/steps.js
deleted file mode 100644
index a39c634919..0000000000
--- a/frontend/src/Editor/WidgetManager/configs/steps.js
+++ /dev/null
@@ -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: '' },
- },
- },
-};
diff --git a/frontend/src/_styles/tabler.scss b/frontend/src/_styles/tabler.scss
index 086712dfa5..6b021cce0d 100644
--- a/frontend/src/_styles/tabler.scss
+++ b/frontend/src/_styles/tabler.scss
@@ -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
}
-}
+}
\ No newline at end of file
diff --git a/frontend/src/_styles/theme.scss b/frontend/src/_styles/theme.scss
index b77c83ba30..86019a158a 100644
--- a/frontend/src/_styles/theme.scss
+++ b/frontend/src/_styles/theme.scss
@@ -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,
');
- /* 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,
');
+ /* 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;
}
diff --git a/server/data-migrations/1742369436314-StepsV2Migration.ts b/server/data-migrations/1742369436314-StepsV2Migration.ts
new file mode 100644
index 0000000000..dcb041db1f
--- /dev/null
+++ b/server/data-migrations/1742369436314-StepsV2Migration.ts
@@ -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
{
+ 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 {}
+
+ 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,
+ });
+ }
+ }
+}
diff --git a/server/src/modules/apps/services/component.service.ts b/server/src/modules/apps/services/component.service.ts
index a7538f5f40..fcc01e52f0 100644
--- a/server/src/modules/apps/services/component.service.ts
+++ b/server/src/modules/apps/services/component.service.ts
@@ -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);
diff --git a/server/src/modules/apps/services/widget-config/steps.js b/server/src/modules/apps/services/widget-config/steps.js
index c8b9753d9a..4400a19137 100644
--- a/server/src/modules/apps/services/widget-config/steps.js
+++ b/server/src/modules/apps/services/widget-config/steps.js
@@ -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' },
},
},
};
diff --git a/server/src/modules/apps/util.service.ts b/server/src/modules/apps/util.service.ts
index f17fa876a7..3db7df4a99 100644
--- a/server/src/modules/apps/util.service.ts
+++ b/server/src/modules/apps/util.service.ts
@@ -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);