ToolJet/frontend/src/Editor/WidgetManager.jsx
Johnson Cherian 3169d38d63
Release: Appbuilder S1 (#10081)
* fix : color for all new columns

* revert

* Fix: selection of copy of selected component for ease (#9818)

* fix: selection of copy of selected component for ease

* add pre selection for clonig as well

* add clone check

* fixes selection of components on empty canvas

* Fix: sizing issues in horizontal divider (#9942)

* fix horizontal divider sizing issues

* fix dark mode color in horizontal divider and remove unused class

* add custom fallback for images when not found (#9943)

* cherry pick error message log changes and fix tjdb error logs in debugger (#9951)

* Fix: mouse release on canvas when properties/styles values selected (#9732)

* fix: mouse release on canvas when properties/styles values selected

* fix: event name

* fix: rest api headers empty state while creating new query (#9729)

* fix: selection issue in table row while editing  (#9944)

* allow selection in table cell

* update classname for selection

* display date picker date as text instead of input in read only mode

* Add new revamped multiselect widget (#9837)

* init textinput revamp

* updated styles panel

* bugfix

* updates

* fix :: accordion

* fix :: styling

* add box shadow , additional property,tooltip

* fix conditional render for styles

* feat :: fixed order of each property and styles

* feat :: styling input

* bugfix

* feat :: add option to add icon

* add option to add icon

* adding option to toggle visibility

* updated password input with new design

* chnaging component location

* bugfix

* style fixes

* fix :: added loader

* updated :: few detailing

* few bugfixes

* fix :: for form widget label

* fixes

* added option to add icon color

* including label field for password input

* fix for label

* fix

* test fix backward compatibility for height

* updates

* revert

* adding key for distinguishing older and newer widgets

* testing

* test

* test

* update

* update

* migration testing

* limit vertical resizing in textinput

* testing

* throw test

* test

* adding check for label length

* fixing edge cases

* removing resize

* backward compatibility height

* backward compatibility

* number input review fixes

* added exposed items

* fixing csa

* ui fixes

* fix height compatibility

* feat :: csa for all inputs and exposed variables

* backward compatibility fixes and validation fixes

* fixes :: textinput positioning of loader and icon

* fix :: password input

* cleanup and fixes

* fixes

* cleanup

* fixes

* review fixes

* review fixes

* typo fix

* fix padding

* review fixes styles component panel

* fix naming

* fix padding

* feat :: toggle switch revamp

* init checkbox

* fixes

* fixes

* switch fixes

* validation fix

* fixes

* cleanup

* height fix

* fix height toggle

* updates

* fix :: icons position

* updates

* cleanup

* updates events , csa

* cleanup

* backward compatibility

* clean

* backward compatibility fix

* label fixed to one line

* feat :: change validation from properties

* ui fixes

* icon name

* removed 'px' text from tooltip

* added onchange event for checkbox

* fixes placeholder

* few updates :: removing label in form

* ui in form

* fire onchange

* update :: number input validation behaviour

* testing fixes

* added side handlers

* removing unwanted fx

* disabling fx for padding field

* ordering change

* fix

* label issue + restricted side handler

* fix :: box shadow bug

* fix

* on change event doesnt propagate exposed vars correctly

* adding debounce for slider value change

* fix :: for modal ooen bug during onfocus event

* test slider

* fix :: bugs regarding state update in checbox , slider , slider bug

* update slider with radix slider

* bugfix

* update tooltip

* fix toggle switch

* fixes : inspector

* fix : checkbox label

* Remove date-fns depedency from table datepicker

* Revert Remove date-fns depedency from table datepicker

* feat : checkbox completed

* update checkbox review changes

* feat : toggle component

* feat : added new toggle component

* fix : colors

* updated review changes

* update name for old and new version

* update

* case change

* update

* update icon

* removed padding from checkbox and toggle

* fix naming

* product review and bugfixes : changes

* fix : checkbox setvalue action

* Update setvalue action in toggle

* fixed: section for legacy and new components

* add new version of dropdown

* Add same styles as other input components

* fix height issues

* Add new revamped multiselect widget

* Fix design review

* fix design issues

* Fix

* Fix merge issues

* Add menu portal target

* resolve code comments

* widget config changes

* add hover for clear icon

* fix

* Fix review comments

* Multiselect changes after dropdown merge

* exposed variables

* Delete unused components

* Multiselect fixes

* Dropdown CSS fixes and multiselect fixes

* Fix merge issues

* fix

* Add highlight text

* Change multiselect UI

* fix error message

* fix multiselect opening closing

* placeholder fix

* fix highlighting in multiselect

* fix : testing bugs

* fix : default value

* Fix merge issues

* Fix Qa bugs

* Fix QA bugs

* Fix codehinter default values

* fix fireEvent on focus

* Fixes

* Provide minwidth to dropdown and multiselect

* Fix search input value not getting updated

---------

Co-authored-by: stepinfwd <stepinfwd@gmail.com>
Co-authored-by: Johnson Cherian <johnsonc.dev@gmail.com>

* Fix: remove mandatory key from password input (#9786)

* Remove date-fns depedency from table datepicker

* Revert Remove date-fns depedency from table datepicker

* remove mandatory key from password input

---------

Co-authored-by: Nakul Nagargade <nakul@tooljet.com>
Co-authored-by: Johnson Cherian <johnsonc.dev@gmail.com>

* feat : Query manager separated to different tabs (#9823)

* change toggle for query manager and revamp preview

* feat : query manger body revamp

* updates

* fix : tranformation switch

* preview integration

* loader safari changes and overflow fix

* fix

* fix : settings tab QM

* revert few changes to fix datasources page

* revert header options change

* zindex fix for query-pane

* fix : events ui

* fix :events widget manager

* code optimised for this file

* QM header fixes

* dark mode changes

* fix : info icon

* open preview drawer on run query

* fix : query manager query section icons update

* update color

* design feedbacks and make preview panel resizable

* update toggle for preview result & increate draggable area

* fix :review changes

* merge fixes

* Merge branch 'appbuilder-1.8' into feature/query-manager-body

* fix : codehinter in disabled state

* ui fix

* code refactor

* cleanup

* fix fontsize in datasource selector popup

* fix border issue in preview container and increase draggable area

* fix : review fixes

* fix: fixed text css formatting for safari support

* Revert "code refactor"

This reverts commit 4763dd11a3.

* typo

* fix : not able to select text in preview

* fix : not able to view add params

* fix selection issue in preview

* fix : add scroll in query  manager when preview is blocking view

---------

Co-authored-by: Kartik Gupta <gupta.kartik18kg@gmail.com>

* Fixes: select all click behaviour on label (#10108)

* fixes: select all click behaviour on label

* fix: legacy component names

* fix: selecto issue (#10107)

* Fix : Prevent component autofill (#10040)

* fix : prevent other component from autofilling data when password is filled from browser suggestions

* optimise

* feat: skip onDragStop execution if drag event is empty (#10118)

* feat: skip onDragStop execution if drag event is empty

* fix: added additonal logs for  error

* display query preview data in preview panel and display transformation failure stacktrace data in previewpanel as well (#10129)

* Fix while adding new rows in table components when ever entered the text and pressed enter it doubles the text (#10112)

* Integration bugfixes appbuilder 1.8 (#10109)

* fix : query maanager duplicate and preview issue

* fix : multiselect breaking on making dynamic options null

* fix : preview and query panel integration bugs

* fix : placeholder

* fix : doc links

* fix : scroll in TJDB filter section

* fix : portal for multiselect

* fixes

* fix : image column table alignment

* fix : doc link for multiselect

* fix : codehinter state being persited across components

* fix :export app qery manager items not coming in correct order

* fix: search icon position

* code refactor

---------

Co-authored-by: Johnson Cherian <johnsonc.dev@gmail.com>

* add z-index to app name info header container (#10116)

* Fix dropdown and multiselect crash on integer labels (#10128)

* cast integer labels to string

* add null check for label and provide default value for empty labels

* empty and null handle for schemas and other values

* revert changes

* Fix: dark mode on preview names (#10136)

* fix: dark mode of preview names

* fix background color of preview

* fix tjdb query import (#10134)

* fix :revert radio button name change (#10153)

* Fix: select issue on multiselect (#10137)

* remove portal from multiselect

* fix: dynamic values for options in dropdown/multiselect

* remove fx from default option

* Fix: delete on options delete in dropdown (#10192)

* fix: delete on options delete

* fix: overlapping of multiselect on parent container

* fix: outside click of multiselect

* hotfix : Table breaking on importing older apps with null value in column (#10185)

* fix : table breaking on importing older apps with null value in column

* fix : table crash , codehinter not saving values upon page change

* remove low priority wrapper from autosave

* remove logs

* added delay to autosave as callback

* fix: dropdown crash on invalid data (#10202)

* revert to previous transformation code , fix darkmode color (#10216)

* fix : doclink for dropdown (#10217)

* fix : Transformations value getting cleared / not getting saved (#10218)

* fix : transformation value not getting saved

* remove dependency

* chore: version update for release

---------

Co-authored-by: stepinfwd <stepinfwd@gmail.com>
Co-authored-by: vjaris42 <vjy239@gmail.com>
Co-authored-by: Kartik Gupta <gupta.kartik18kg@gmail.com>
Co-authored-by: Nakul Nagargade <133095394+nakulnagargade@users.noreply.github.com>
Co-authored-by: Nakul Nagargade <nakul@tooljet.com>
Co-authored-by: Akshay <akshaysasidharan93@gmail.com>
2024-07-01 08:46:22 +05:30

169 lines
6 KiB
JavaScript

import React, { useState } from 'react';
import { DraggableBox } from './DraggableBox';
import Fuse from 'fuse.js';
import { isEmpty } from 'lodash';
import { useTranslation } from 'react-i18next';
import { useAppVersionStore } from '@/_stores/appVersionStore';
import { shallow } from 'zustand/shallow';
import { SearchBox } from '@/_components';
import { LEGACY_ITEMS } from './WidgetManager/constants';
export const WidgetManager = function WidgetManager({ componentTypes, zoomLevel, darkMode, disabled }) {
const [filteredComponents, setFilteredComponents] = useState(componentTypes);
const [searchQuery, setSearchQuery] = useState('');
const { t } = useTranslation();
const { isVersionReleased } = useAppVersionStore(
(state) => ({
isVersionReleased: state.isVersionReleased,
}),
shallow
);
function handleSearchQueryChange(e) {
const { value } = e.target;
setSearchQuery(value);
filterComponents(value);
}
function filterComponents(value) {
if (value !== '') {
const fuse = new Fuse(componentTypes, {
keys: ['displayName'],
shouldSort: true,
threshold: 0.4,
});
const results = fuse.search(value);
// Find the indices of ToggleSwitchLegacy and ToggleSwitch
const legacyIndex = componentTypes.findIndex((component) => component?.name === 'ToggleSwitchLegacy');
const toggleIndex = componentTypes.findIndex((component) => component?.name === 'ToggleSwitch');
// Swap the indices (if both are found)
if (legacyIndex !== -1 && toggleIndex !== -1) {
[componentTypes[legacyIndex], componentTypes[toggleIndex]] = [
componentTypes[toggleIndex],
componentTypes[legacyIndex],
];
}
setFilteredComponents(results.map((result) => result.item));
} else {
setFilteredComponents(componentTypes);
}
}
function renderComponentCard(component, index) {
return <DraggableBox key={index} index={index} component={component} zoomLevel={zoomLevel} />;
}
function renderList(header, items) {
if (isEmpty(items)) return null;
return (
<div className="component-card-group-container">
<span className="widget-header">{header}</span>
<div className="component-card-group-wrapper">
{items.map((component, i) => renderComponentCard(component, i))}
</div>
</div>
);
}
function segregateSections() {
if (filteredComponents.length === 0) {
return (
<div className="empty">
<p className="empty-title">{t('widgetManager.noResults', 'No results found')}</p>
<p className={`empty-subtitle ${darkMode ? 'text-white-50' : 'text-secondary'}`}>
{t(
'widgetManager.tryAdjustingFilterMessage',
"Try adjusting your search or filter to find what you're looking for."
)}
</p>
<button
className=" btn-sm tj-tertiary-btn mt-3"
onClick={() => {
setFilteredComponents(componentTypes);
setSearchQuery('');
}}
>
{t('widgetManager.clearQuery', 'clear query')}
</button>
</div>
);
}
const commonSection = { title: t('widgetManager.commonlyUsed', 'commonly used'), items: [] };
const layoutsSection = { title: t('widgetManager.layouts', 'layouts'), items: [] };
const formSection = { title: t('widgetManager.forms', 'forms'), items: [] };
const integrationSection = { title: t('widgetManager.integrations', 'integrations'), items: [] };
const otherSection = { title: t('widgetManager.others', 'others'), items: [] };
const legacySection = { title: 'Legacy', items: [] };
const allWidgets = [];
const commonItems = ['Table', 'Button', 'Text', 'TextInput', 'Datepicker', 'Form'];
const formItems = [
'Form',
'TextInput',
'NumberInput',
'PasswordInput',
'Textarea',
'ToggleSwitch',
'Dropdown',
'Multiselect',
'RichTextEditor',
'Checkbox',
'RadioButton',
'Datepicker',
'DateRangePicker',
'FilePicker',
'StarRating',
];
const integrationItems = ['Map'];
const layoutItems = ['Container', 'Listview', 'Tabs', 'Modal'];
filteredComponents.forEach((f) => {
if (searchQuery) allWidgets.push(f);
if (commonItems.includes(f.name)) commonSection.items.push(f);
if (formItems.includes(f.name)) formSection.items.push(f);
else if (integrationItems.includes(f.name)) integrationSection.items.push(f);
else if (LEGACY_ITEMS.includes(f.name)) legacySection.items.push(f);
else if (layoutItems.includes(f.name)) layoutsSection.items.push(f);
else otherSection.items.push(f);
});
if (allWidgets.length > 0) {
return <>{renderList(undefined, allWidgets)}</>;
} else {
return (
<>
{renderList(commonSection.title, commonSection.items)}
{renderList(layoutsSection.title, layoutsSection.items)}
{renderList(formSection.title, formSection.items)}
{renderList(otherSection.title, otherSection.items)}
{renderList(integrationSection.title, integrationSection.items)}
{renderList(legacySection.title, legacySection.items)}
</>
);
}
}
return (
<div className={`components-container ${(isVersionReleased || disabled) && 'disabled'}`}>
<p className="widgets-manager-header">Components</p>
<div className="input-icon tj-app-input">
<SearchBox
dataCy={`widget-search-box`}
initialValue={''}
callBack={(e) => handleSearchQueryChange(e)}
onClearCallback={() => {
setSearchQuery('');
filterComponents('');
}}
placeholder={t('globals.searchComponents', 'Search widgets')}
customClass={`tj-widgets-search-input tj-text-xsm`}
showClearButton={false}
width={266}
/>
</div>
<div className="widgets-list col-sm-12 col-lg-12 row">{segregateSections()}</div>
</div>
);
};