From c9fb1f31188b9a7df749eb7b55053c2083c37b62 Mon Sep 17 00:00:00 2001 From: Kartik Gupta Date: Wed, 19 Mar 2025 13:45:02 +0530 Subject: [PATCH 01/35] steps v2 component --- .../Inspector/Components/Steps.jsx | 505 +++++++++++++++++ .../RightSideBar/Inspector/Inspector.jsx | 4 + .../AppBuilder/WidgetManager/widgets/steps.js | 191 ++++++- frontend/src/Editor/Components/Steps.jsx | 149 ++++- frontend/src/_styles/tabler.scss | 13 +- frontend/src/_styles/theme.scss | 514 ++++++++++-------- .../1742369436314-StepsV2Migration.ts | 81 +++ .../apps/services/component.service.ts | 4 +- .../apps/services/widget-config/steps.js | 191 ++++++- server/src/modules/apps/util.service.ts | 2 +- 10 files changed, 1339 insertions(+), 315 deletions(-) create mode 100644 frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx create mode 100644 server/data-migrations/1742369436314-StepsV2Migration.ts 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..23636aec50 --- /dev/null +++ b/frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx @@ -0,0 +1,505 @@ +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'; + +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 [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); + } + } + + 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.label === label) === undefined) { + found = true; + } + currentNumber += 1; + } + return { + name: label, + id: Number((Math.random() * 1000).toFixed(0)), + 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('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 ec3aac4309..785ee19f34 100644 --- a/frontend/src/AppBuilder/RightSideBar/Inspector/Inspector.jsx +++ b/frontend/src/AppBuilder/RightSideBar/Inspector/Inspector.jsx @@ -34,6 +34,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 '@/AppBuilder/WidgetManager/componentTypes'; @@ -81,6 +82,7 @@ const NEW_REVAMPED_COMPONENTS = [ 'Container', 'ModalV2', 'Link', + 'Steps', ]; export const Inspector = ({ componentDefinitionChanged, darkMode, pages, selectedComponentId }) => { @@ -731,6 +733,8 @@ const GetAccordion = React.memo( case 'DatePickerV2': case 'TimePicker': return ; + case 'Steps': + return ; default: { return ; diff --git a/frontend/src/AppBuilder/WidgetManager/widgets/steps.js b/frontend/src/AppBuilder/WidgetManager/widgets/steps.js index a39c634919..bb75948fc9 100644 --- a/frontend/src/AppBuilder/WidgetManager/widgets/steps.js +++ b/frontend/src/AppBuilder/WidgetManager/widgets/steps.js @@ -4,9 +4,30 @@ 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: 'Numbers', 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', @@ -15,6 +36,27 @@ export const stepsConfig = { defaultValue: `[{ name: 'step 1'}, {name: 'step 2'}]`, }, }, + visibility: { + type: 'toggle', + displayName: 'Visibility', + validation: { schema: { type: 'boolean' }, defaultValue: true }, + section: 'additionalActions', + }, + // disabledState: { + // type: 'toggle', + // displayName: 'Disable', + // 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', @@ -30,6 +72,7 @@ export const stepsConfig = { schema: { type: 'boolean' }, defaultValue: false, }, + section: 'additionalActions', }, }, defaultSize: { @@ -40,46 +83,122 @@ 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: 'option', + displayName: 'Option', + }, + ], + }, + { + handle: 'resetSteps', + displayName: 'Reset steps', + params: [], + }, + { + handle: 'setStepVisible', + displayName: 'Set step visible', + params: [ + { + handle: 'id', + displayName: 'Step id', + }, + { + handle: 'visibility', + displayName: 'visibility', + }, + ], + }, + { + handle: 'setStepDisable', + displayName: 'Set step disable', + params: [ + { + handle: 'id', + displayName: 'Step id', + }, + { + handle: 'disabled', + displayName: 'disabled', + }, + ], + }, + ], events: { onSelect: { displayName: 'On select' }, }, styles: { - color: { + incompletedAccent: { type: 'color', - displayName: 'Color', + displayName: 'Incompleted accent', validation: { schema: { type: 'string' }, - defaultValue: '#000000', + defaultValue: '#E4E7EB', }, + accordian: 'steps', }, - textColor: { + incompletedLabel: { type: 'color', - displayName: 'Text color', + displayName: 'Incompleted label', validation: { schema: { type: 'string' }, - defaultValue: '#000000', + defaultValue: '#1B1F24', }, + accordian: 'steps', }, - theme: { - type: 'select', - displayName: 'Theme', + completedAccent: { + type: 'color', + displayName: 'Completed accent', + validation: { + schema: { type: 'string' }, + defaultValue: '#4368E3', + }, + accordian: 'steps', + }, + completedLabel: { + type: 'color', + displayName: 'Completed label', + validation: { + schema: { type: 'string' }, + defaultValue: '#FBFCFD', + }, + accordian: 'steps', + }, + currentStepLabel: { + type: 'color', + 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 +211,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: 'some tooltip', id: 1, visible: { value: true }, disabled: { value: false } }, + { name: 'step 2', tooltip: 'some tooltip', id: 2, visible: { value: true }, disabled: { value: false } }, + { name: 'step 3', tooltip: 'some tooltip', id: 3, visible: { value: true }, disabled: { value: false } }, + { name: 'step 4', tooltip: 'some tooltip', id: 4, visible: { value: true }, disabled: { value: false } }, + { name: 'step 5', tooltip: 'some tooltip', id: 5, visible: { value: true }, disabled: { value: false } }, + ], }, + schema: { + value: `{{ [{ name: 'step 1', tooltip: 'some tooltip', id: 1,visible: true, disabled: false},{ name: 'step 2', tooltip: 'some tooltip', id: 2,visible: true, disabled: false},{ name: 'step 3', tooltip: 'some tooltip', id: 3,visible: true, disabled: false},{ name: 'step 4', tooltip: 'some tooltip', id: 4,visible: true, disabled: false},{ name: 'step 5', tooltip: 'some tooltip', id: 5,visible: true, disabled: false}]}}`, + }, + variant: { value: 'titles' }, currentStep: { value: '{{3}}' }, stepsSelectable: { value: true }, + advanced: { value: `{{false}}` }, + // disabledState: { value: '{{false}}' }, + visibility: { value: '{{true}}' }, }, events: [], styles: { visibility: { value: '{{true}}' }, - theme: { value: 'titles' }, 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/frontend/src/Editor/Components/Steps.jsx b/frontend/src/Editor/Components/Steps.jsx index 4a42e9362e..e161e12440 100644 --- a/frontend/src/Editor/Components/Steps.jsx +++ b/frontend/src/Editor/Components/Steps.jsx @@ -1,52 +1,143 @@ import React, { useEffect, useState } from 'react'; import { isExpectedDataType } from '@/_helpers/utils'; +import { ToolTip } from '@/_components/ToolTip'; 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; + 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 filteredSteps = (stepsArr || []).filter((step) => step.visible); + const currentStepIndex = filteredSteps.findIndex((step) => step.id == activeStepId); + + useEffect(() => { + // this is required for legacy support where visible and disabled properties are not present + const sanitizedSteps = JSON.parse(JSON.stringify(steps || [])).map((step) => { + if (!('visible' in step)) step.visible = true; + if (!('disabled' in step)) step.disabled = false; + return step; + }); + setStepsArr(sanitizedSteps); + }, [JSON.stringify(steps)]); const dynamicStyle = { '--bgColor': styles.color, '--textColor': textColor, + '--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, }; + const theme = properties.variant; const activeStepHandler = (id) => { - const active = steps.filter((item) => item.id == id); - setExposedVariable('currentStepId', active[0].id); - fireEvent('onSelect'); - setActiveStep(active[0].id); + const step = filteredSteps.find((item) => item.id == id); + if (step) { + setActiveStepId(step.id); + fireEvent('onSelect'); + } }; useEffect(() => { - setActiveStep(currentStep); - setExposedVariable('currentStepId', currentStep); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [currentStep]); + setExposedVariable('setStep', (stepId) => setActiveStepId(stepId)); + setExposedVariable('setVisibility', (visibility) => setIsVisible(visibility)); + setExposedVariable('setDisabled', (disabled) => setIsDisabled(disabled)); + }, []); + + useEffect(() => { + setExposedVariable('currentStepId', activeStepId); + }, [activeStepId]); + + useEffect(() => { + setExposedVariable('steps', steps); + setExposedVariable('setStepVisible', (stepId, visibility) => { + setStepsArr((prev) => { + const updatedSteps = prev.map((item) => { + if (item.id == stepId) { + return { ...item, visible: visibility }; + } + return item; + }); + setExposedVariable('steps', updatedSteps); + return updatedSteps; + }); + }); + setExposedVariable('setStepDisable', (stepId, disabled) => { + setStepsArr((prev) => { + const updatedSteps = prev.map((item) => { + if (item.id == stepId) { + return { ...item, disabled: disabled }; + } + return item; + }); + setExposedVariable('steps', updatedSteps); + return updatedSteps; + }); + }); + setExposedVariable('resetSteps', () => { + setActiveStepId(stepsArr.filter((step) => step.visible)?.[0]?.id); + }); + }, [JSON.stringify(steps), JSON.stringify(stepsArr)]); + + useEffect(() => { + setExposedVariable('isVisible', isVisible); + }, [isVisible]); + + useEffect(() => { + setIsVisible(visibility); + }, [visibility]); + + useEffect(() => { + setExposedVariable('isDisabled', isDisabled); + }, [isDisabled]); + + useEffect(() => { + setIsDisabled(!disabledState); + }, [disabledState]); return ( - visibility && ( + isVisible && ( ) ); diff --git a/frontend/src/_styles/tabler.scss b/frontend/src/_styles/tabler.scss index 34afb6bd0e..fd12d00b55 100644 --- a/frontend/src/_styles/tabler.scss +++ b/frontend/src/_styles/tabler.scss @@ -17473,8 +17473,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%) } @@ -17487,11 +17487,18 @@ 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%) } +.steps.steps-counter { + .step-item:not(:first-child):after { + left: calc(-50% + 16px) !important; + width: calc(100% - 32px) !important; + } +} + .step-item.active { font-weight: 600 } diff --git a/frontend/src/_styles/theme.scss b/frontend/src/_styles/theme.scss index 4e2d88ba13..f564828821 100644 --- a/frontend/src/_styles/theme.scss +++ b/frontend/src/_styles/theme.scss @@ -4749,15 +4749,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; } @@ -6507,6 +6510,7 @@ div#driver-page-overlay { // steps-widget a.step-item-disabled { text-decoration: none; + opacity: 0.5; } .steps { @@ -6516,7 +6520,7 @@ 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 { @@ -6524,26 +6528,37 @@ a.step-item-disabled { } .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 { @@ -9857,25 +9872,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; + } + } } @@ -12131,8 +12151,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); } @@ -15856,6 +15878,7 @@ tbody { .rest-api-options-codehinter { height: 100%; + .cm-content>.cm-line { // max-width: 357px !important; } @@ -16287,19 +16310,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; } @@ -16308,57 +16332,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; } @@ -16367,28 +16394,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; @@ -16401,48 +16432,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; } } @@ -16457,42 +16489,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; } } @@ -16502,7 +16534,7 @@ fieldset:disabled { .react-datepicker__month-container { width: 100%; - width:250px; + width: 250px; } .react-datepicker__input-time-container { @@ -16517,12 +16549,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; } } @@ -16530,15 +16562,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; } @@ -16552,18 +16584,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; } @@ -16571,12 +16603,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; @@ -16916,16 +16948,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; } @@ -16933,25 +16966,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); @@ -16959,23 +16994,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 { @@ -16983,19 +17018,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; @@ -17014,8 +17051,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 { @@ -17038,15 +17076,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; @@ -17057,44 +17097,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; } @@ -17112,8 +17156,8 @@ section.ai-message-prompt-input-wrapper { } .tj-datepicker-widget-right { - position: absolute; - right: 10px; + position: absolute; + right: 10px; } .tj-datepicker-widget-left { @@ -17136,41 +17180,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; } } @@ -17184,26 +17229,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; @@ -17216,45 +17264,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; } @@ -17274,44 +17326,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; @@ -17324,31 +17379,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 { @@ -18658,6 +18717,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 a39c634919..bb75948fc9 100644 --- a/server/src/modules/apps/services/widget-config/steps.js +++ b/server/src/modules/apps/services/widget-config/steps.js @@ -4,9 +4,30 @@ 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: 'Numbers', 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', @@ -15,6 +36,27 @@ export const stepsConfig = { defaultValue: `[{ name: 'step 1'}, {name: 'step 2'}]`, }, }, + visibility: { + type: 'toggle', + displayName: 'Visibility', + validation: { schema: { type: 'boolean' }, defaultValue: true }, + section: 'additionalActions', + }, + // disabledState: { + // type: 'toggle', + // displayName: 'Disable', + // 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', @@ -30,6 +72,7 @@ export const stepsConfig = { schema: { type: 'boolean' }, defaultValue: false, }, + section: 'additionalActions', }, }, defaultSize: { @@ -40,46 +83,122 @@ 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: 'option', + displayName: 'Option', + }, + ], + }, + { + handle: 'resetSteps', + displayName: 'Reset steps', + params: [], + }, + { + handle: 'setStepVisible', + displayName: 'Set step visible', + params: [ + { + handle: 'id', + displayName: 'Step id', + }, + { + handle: 'visibility', + displayName: 'visibility', + }, + ], + }, + { + handle: 'setStepDisable', + displayName: 'Set step disable', + params: [ + { + handle: 'id', + displayName: 'Step id', + }, + { + handle: 'disabled', + displayName: 'disabled', + }, + ], + }, + ], events: { onSelect: { displayName: 'On select' }, }, styles: { - color: { + incompletedAccent: { type: 'color', - displayName: 'Color', + displayName: 'Incompleted accent', validation: { schema: { type: 'string' }, - defaultValue: '#000000', + defaultValue: '#E4E7EB', }, + accordian: 'steps', }, - textColor: { + incompletedLabel: { type: 'color', - displayName: 'Text color', + displayName: 'Incompleted label', validation: { schema: { type: 'string' }, - defaultValue: '#000000', + defaultValue: '#1B1F24', }, + accordian: 'steps', }, - theme: { - type: 'select', - displayName: 'Theme', + completedAccent: { + type: 'color', + displayName: 'Completed accent', + validation: { + schema: { type: 'string' }, + defaultValue: '#4368E3', + }, + accordian: 'steps', + }, + completedLabel: { + type: 'color', + displayName: 'Completed label', + validation: { + schema: { type: 'string' }, + defaultValue: '#FBFCFD', + }, + accordian: 'steps', + }, + currentStepLabel: { + type: 'color', + 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 +211,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: 'some tooltip', id: 1, visible: { value: true }, disabled: { value: false } }, + { name: 'step 2', tooltip: 'some tooltip', id: 2, visible: { value: true }, disabled: { value: false } }, + { name: 'step 3', tooltip: 'some tooltip', id: 3, visible: { value: true }, disabled: { value: false } }, + { name: 'step 4', tooltip: 'some tooltip', id: 4, visible: { value: true }, disabled: { value: false } }, + { name: 'step 5', tooltip: 'some tooltip', id: 5, visible: { value: true }, disabled: { value: false } }, + ], }, + schema: { + value: `{{ [{ name: 'step 1', tooltip: 'some tooltip', id: 1,visible: true, disabled: false},{ name: 'step 2', tooltip: 'some tooltip', id: 2,visible: true, disabled: false},{ name: 'step 3', tooltip: 'some tooltip', id: 3,visible: true, disabled: false},{ name: 'step 4', tooltip: 'some tooltip', id: 4,visible: true, disabled: false},{ name: 'step 5', tooltip: 'some tooltip', id: 5,visible: true, disabled: false}]}}`, + }, + variant: { value: 'titles' }, currentStep: { value: '{{3}}' }, stepsSelectable: { value: true }, + advanced: { value: `{{false}}` }, + // disabledState: { value: '{{false}}' }, + visibility: { value: '{{true}}' }, }, events: [], styles: { visibility: { value: '{{true}}' }, - theme: { value: 'titles' }, 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 36def10913..7cf95ea067 100644 --- a/server/src/modules/apps/util.service.ts +++ b/server/src/modules/apps/util.service.ts @@ -487,7 +487,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); From 8c2c42701ee39f155f180de12a4a8727c3ed3dce Mon Sep 17 00:00:00 2001 From: Kartik Gupta Date: Fri, 21 Mar 2025 20:32:48 +0530 Subject: [PATCH 02/35] wa feedbacks --- .../Inspector/Components/Steps.jsx | 14 ++ .../AppBuilder/WidgetManager/widgets/steps.js | 14 +- frontend/src/Editor/Components/Steps.jsx | 46 ++-- .../src/Editor/WidgetManager/configs/steps.js | 201 +++++++++++++++--- server/ee | 2 +- .../apps/services/widget-config/steps.js | 14 +- 6 files changed, 232 insertions(+), 59 deletions(-) diff --git a/frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx b/frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx index 23636aec50..6956236919 100644 --- a/frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx +++ b/frontend/src/AppBuilder/RightSideBar/Inspector/Components/Steps.jsx @@ -139,6 +139,20 @@ export function Steps({ componentMeta, darkMode, ...restProps }) { return ( +
+ + handleLabelChange('id', value, index)} + /> +