mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
rebase
This commit is contained in:
commit
a86c7addd0
108 changed files with 9894 additions and 1414 deletions
|
|
@ -6,11 +6,11 @@ import LogoNavDropdown from '@/_components/LogoNavDropdown';
|
|||
import HeaderActions from './HeaderActions';
|
||||
import { AppVersionsManager } from './AppVersionsManager';
|
||||
import RealtimeAvatars from '@/Editor/RealtimeAvatars';
|
||||
// import UpdatePresence from '@/Editor/Header/UpdatePresence';
|
||||
import SolidIcon from '@/_ui/Icon/SolidIcons';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import RightTopHeaderButtons from './RightTopHeaderButtons/RightTopHeaderButtons';
|
||||
import BuildSuggestions from './BuildSuggestions';
|
||||
import UpdatePresenceMultiPlayer from './UpdatePresenceMultiPlayer';
|
||||
|
||||
export const EditorHeader = ({ darkMode }) => {
|
||||
const { isSaving, saveError, isVersionReleased } = useStore(
|
||||
|
|
@ -98,18 +98,14 @@ export const EditorHeader = ({ darkMode }) => {
|
|||
<RealtimeAvatars />
|
||||
</div>
|
||||
)}
|
||||
{/* {shouldEnableMultiplayer && <UpdatePresence />} */}
|
||||
{shouldEnableMultiplayer && <UpdatePresenceMultiPlayer />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="navbar-seperator"></div>
|
||||
{/* <div className="d-flex align-items-center p-0" style={{ marginRight: '12px' }}></div> */}
|
||||
</div>
|
||||
<div className="d-flex align-items-center p-0">
|
||||
<div className="d-flex version-manager-container p-0 mx-2 align-items-center ">
|
||||
{/* {editingVersion && ( */}
|
||||
{/* <EnvironmentManager darkMode={darkMode} /> */}
|
||||
{/* )} */}
|
||||
{/* <div className="navbar-seperator"></div> */}
|
||||
<div className="d-flex p-0 mx-2 align-items-center ">
|
||||
<AppVersionsManager darkMode={darkMode} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,416 +0,0 @@
|
|||
import React from 'react';
|
||||
import { appService, appsService, authenticationService } from '@/_services';
|
||||
import Modal from 'react-bootstrap/Modal';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import _, { debounce } from 'lodash';
|
||||
import { validateName } from '@/_helpers/utils';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getPrivateRoute, replaceEditorURL, getHostURL } from '@/_helpers/routes';
|
||||
import { ToolTip } from '@/_components/ToolTip';
|
||||
import SolidIcon from '@/_ui/Icon/SolidIcons';
|
||||
import cx from 'classnames';
|
||||
import { TOOLTIP_MESSAGES } from '@/_helpers/constants';
|
||||
import { useAppDataStore } from '@/_stores/appDataStore';
|
||||
import { retrieveWhiteLabelText } from '@white-label/whiteLabelling';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
|
||||
class ManageAppUsersComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.isUserAdmin = authenticationService.currentSessionValue?.admin;
|
||||
this.whiteLabelText = retrieveWhiteLabelText();
|
||||
|
||||
this.state = {
|
||||
showModal: false,
|
||||
appId: null,
|
||||
isSlugVerificationInProgress: false,
|
||||
addingUser: false,
|
||||
newUser: {},
|
||||
newSlug: {
|
||||
value: null,
|
||||
error: '',
|
||||
},
|
||||
isSlugUpdated: false,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Only will fail for existed apps before the app/workspace url revamp which has
|
||||
special chars or spaces in their app slugs
|
||||
*/
|
||||
validateThePreExistingSlugs = () => {
|
||||
const existedSlugErrors = validateName(this.props.slug, 'App slug', true, false, false, false);
|
||||
this.setState({
|
||||
newSlug: {
|
||||
value: this.props.slug,
|
||||
error: existedSlugErrors.errorMsg,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const appId = this.props.appId;
|
||||
this.setState({ appId });
|
||||
}
|
||||
|
||||
hideModal = () => {
|
||||
this.setState({
|
||||
showModal: false,
|
||||
newSlug: {
|
||||
value: this.props.slug,
|
||||
error: '',
|
||||
},
|
||||
isSlugVerificationInProgress: false,
|
||||
isSlugUpdated: false,
|
||||
});
|
||||
};
|
||||
|
||||
addUser = () => {
|
||||
this.setState({
|
||||
addingUser: true,
|
||||
});
|
||||
|
||||
const { organizationUserId, role } = this.state.newUser;
|
||||
|
||||
appService
|
||||
.createAppUser(this.state.appId, organizationUserId, role)
|
||||
.then(() => {
|
||||
this.setState({ addingUser: false, newUser: {} });
|
||||
toast.success('Added user successfully');
|
||||
})
|
||||
.catch(({ error }) => {
|
||||
this.setState({ addingUser: false });
|
||||
toast.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
toggleAppVisibility = () => {
|
||||
const newState = !this.props.isPublic;
|
||||
this.setState({
|
||||
ischangingVisibility: true,
|
||||
});
|
||||
useStore.getState().setIsPublic(newState);
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
appsService
|
||||
.setVisibility(this.state.appId, newState)
|
||||
.then(() => {
|
||||
this.setState({
|
||||
ischangingVisibility: false,
|
||||
});
|
||||
|
||||
if (newState) {
|
||||
toast('Application is now public.');
|
||||
} else {
|
||||
toast('Application visibility set to private');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({
|
||||
ischangingVisibility: false,
|
||||
});
|
||||
toast.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
delayedSlugChange = debounce((e) => {
|
||||
this.handleInputChange(e.target.value, 'slug');
|
||||
}, 500);
|
||||
|
||||
handleInputChange = (value, field) => {
|
||||
this.setState({
|
||||
newSlug: {
|
||||
value: this.state.newSlug?.value,
|
||||
error: '',
|
||||
isSlugUpdated: false,
|
||||
},
|
||||
});
|
||||
|
||||
const error = validateName(value, `App ${field}`, true, false, !(field === 'slug'), !(field === 'slug'));
|
||||
|
||||
if (!_.isEmpty(value) && value !== this.props.slug && _.isEmpty(error.errorMsg)) {
|
||||
this.setState({
|
||||
isSlugVerificationInProgress: true,
|
||||
});
|
||||
appsService
|
||||
.setSlug(this.state.appId, value)
|
||||
.then(() => {
|
||||
this.setState({
|
||||
newSlug: {
|
||||
value: value,
|
||||
error: '',
|
||||
},
|
||||
isSlugVerificationInProgress: false,
|
||||
isSlugUpdated: true,
|
||||
});
|
||||
|
||||
replaceEditorURL(value, this.props.pageHandle);
|
||||
useStore.getState().setSlug(value);
|
||||
})
|
||||
.catch(({ error }) => {
|
||||
this.setState({
|
||||
newSlug: {
|
||||
value,
|
||||
error,
|
||||
},
|
||||
isSlugVerificationInProgress: false,
|
||||
isSlugUpdated: false,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
newSlug: {
|
||||
value,
|
||||
error: error?.errorMsg,
|
||||
},
|
||||
isSlugVerificationInProgress: false,
|
||||
isSlugUpdated: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { appId, isSlugVerificationInProgress, newSlug, isSlugUpdated } = this.state;
|
||||
|
||||
const appLink = `${getHostURL()}/applications/`;
|
||||
const shareableLink = appLink + (this.props.slug || appId);
|
||||
const slugButtonClass = !_.isEmpty(newSlug.error) ? 'is-invalid' : 'is-valid';
|
||||
const embeddableLink = `<iframe width="560" height="315" src="${appLink}${this.props.slug}" title="${this.whiteLabelText} app - ${this.props.slug}" frameborder="0" allowfullscreen></iframe>`;
|
||||
|
||||
const shouldShowShareModal = this.props.isVersionReleased
|
||||
? this.props.multiEnvironmentEnabled
|
||||
? this.props.currentEnvironment?.isDefault
|
||||
? true
|
||||
: false
|
||||
: this.props.currentEnvironment?.priority === 1
|
||||
: false;
|
||||
|
||||
const envTooltipFlag =
|
||||
(!this.props.isVersionReleased && this.props.currentEnvironment?.isDefault) ||
|
||||
(!this.props.multiEnvironmentEnabled && this.props.currentEnvironment?.priority === 1);
|
||||
|
||||
return (
|
||||
<ToolTip
|
||||
message={envTooltipFlag ? TOOLTIP_MESSAGES.SHARE_URL_UNAVAILABLE : 'You can only share apps in production'}
|
||||
placement="left"
|
||||
show={!shouldShowShareModal}
|
||||
>
|
||||
<div
|
||||
title={shouldShowShareModal ? 'Share' : ''}
|
||||
className="manage-app-users editor-header-icon tj-secondary-btn"
|
||||
data-cy="share-button-link"
|
||||
>
|
||||
<span
|
||||
className={cx('d-flex', {
|
||||
'share-disabled': !shouldShowShareModal,
|
||||
})}
|
||||
onClick={() => {
|
||||
this.validateThePreExistingSlugs();
|
||||
shouldShowShareModal && this.setState({ showModal: true });
|
||||
}}
|
||||
>
|
||||
<SolidIcon name="share" width="14" className="cursor-pointer" fill="#3E63DD" />
|
||||
</span>
|
||||
<Modal
|
||||
show={this.state.showModal}
|
||||
size="lg"
|
||||
backdrop="static"
|
||||
centered={true}
|
||||
keyboard={true}
|
||||
animation={false}
|
||||
onEscapeKeyDown={this.hideModal}
|
||||
className={`app-sharing-modal animation-fade ${this.props.darkMode ? 'dark-theme' : ''}`}
|
||||
contentClassName={this.props.darkMode ? 'dark-theme' : ''}
|
||||
>
|
||||
<Modal.Header>
|
||||
<Modal.Title data-cy="modal-header">{this.props.t('editor.share', 'Share')}</Modal.Title>
|
||||
<span onClick={this.hideModal} data-cy="modal-close-button">
|
||||
<SolidIcon name="remove" className="cursor-pointer" aria-label="Close" />
|
||||
</span>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{
|
||||
<div class="shareable-link-container">
|
||||
<div className="make-public mb-3">
|
||||
<div className="form-check form-switch d-flex align-items-center">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
onClick={this.toggleAppVisibility}
|
||||
checked={this?.props?.isPublic}
|
||||
disabled={this.state.ischangingVisibility}
|
||||
data-cy="make-public-app-toggle"
|
||||
/>
|
||||
<span className="form-check-label field-name" data-cy="make-public-app-label">
|
||||
{this.props.t('editor.shareModal.makeApplicationPublic', 'Make application public')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="shareable-link tj-app-input mb-2">
|
||||
<label data-cy="shareable-app-link-label" className="field-name">
|
||||
{this.props.t('editor.shareModal.shareableLink', 'Shareable app link')}
|
||||
</label>
|
||||
<div className="input-group">
|
||||
<span className="input-group-text applink-text flex-grow-1 slug-ellipsis" data-cy="app-link">
|
||||
{appLink}
|
||||
</span>
|
||||
<div className="input-with-icon">
|
||||
<input
|
||||
type="text"
|
||||
className={`form-control form-control-sm ${slugButtonClass}`}
|
||||
placeholder={this.props.slug}
|
||||
maxLength={50}
|
||||
onChange={(e) => {
|
||||
e.persist();
|
||||
this.delayedSlugChange(e);
|
||||
}}
|
||||
style={{ maxWidth: '150px' }}
|
||||
defaultValue={this.props.slug}
|
||||
data-cy="app-name-slug-input"
|
||||
/>
|
||||
{isSlugVerificationInProgress && (
|
||||
<div className="icon-container">
|
||||
<div class="spinner-border text-secondary " role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="icon-container">
|
||||
{newSlug?.error ? (
|
||||
<svg
|
||||
width="21"
|
||||
height="20"
|
||||
viewBox="0 0 21 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M3.94252 3.61195C4.31445 3.24003 4.91746 3.24003 5.28939 3.61195L10.3302 8.6528L15.3711 3.61195C15.743 3.24003 16.346 3.24003 16.718 3.61195C17.0899 3.98388 17.0899 4.5869 16.718 4.95882L11.6771 9.99967L16.718 15.0405C17.0899 15.4125 17.0899 16.0155 16.718 16.3874C16.346 16.7593 15.743 16.7593 15.3711 16.3874L10.3302 11.3465L5.28939 16.3874C4.91746 16.7593 4.31445 16.7593 3.94252 16.3874C3.57059 16.0155 3.57059 15.4125 3.94252 15.0405L8.98337 9.99967L3.94252 4.95882C3.57059 4.5869 3.57059 3.98388 3.94252 3.61195Z"
|
||||
fill="#E54D2E"
|
||||
/>
|
||||
</svg>
|
||||
) : (
|
||||
isSlugUpdated &&
|
||||
!isSlugVerificationInProgress && (
|
||||
<svg
|
||||
width="21"
|
||||
height="20"
|
||||
viewBox="0 0 21 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M17.5859 5.24408C17.9114 5.56951 17.9114 6.09715 17.5859 6.42259L9.25259 14.7559C8.92715 15.0814 8.39951 15.0814 8.07407 14.7559L3.90741 10.5893C3.58197 10.2638 3.58197 9.73618 3.90741 9.41074C4.23284 9.08531 4.76048 9.08531 5.08592 9.41074L8.66333 12.9882L16.4074 5.24408C16.7328 4.91864 17.2605 4.91864 17.5859 5.24408Z"
|
||||
fill="#46A758"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<span className="input-group-text">
|
||||
<CopyToClipboard text={shareableLink} onCopy={() => toast.success('Link copied to clipboard')}>
|
||||
<svg
|
||||
className="cursor-pointer"
|
||||
width="17"
|
||||
height="18"
|
||||
viewBox="0 0 17 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
data-cy="copy-app-link-button"
|
||||
>
|
||||
<path
|
||||
d="M9.11154 5.18031H5.88668V4.83302C5.88668 3.29859 7.13059 2.05469 8.66502 2.05469H12.8325C14.3669 2.05469 15.6109 3.29859 15.6109 4.83302V9.00052C15.6109 10.535 14.3669 11.7789 12.8325 11.7789H12.4852V8.554C12.4852 6.69076 10.9748 5.18031 9.11154 5.18031Z"
|
||||
fill="#889096"
|
||||
/>
|
||||
<path
|
||||
d="M8.66502 15.9464H4.49752C2.96309 15.9464 1.71918 14.7025 1.71918 13.168V9.00052C1.71918 7.46609 2.96309 6.22219 4.49752 6.22219H8.66502C10.1994 6.22219 11.4434 7.46609 11.4434 9.00052V13.168C11.4434 14.7025 10.1994 15.9464 8.66502 15.9464Z"
|
||||
fill="#889096"
|
||||
/>
|
||||
</svg>
|
||||
</CopyToClipboard>
|
||||
</span>
|
||||
</div>
|
||||
{newSlug?.error ? (
|
||||
<label className="label tj-input-error" data-cy="app-slug-error-label">
|
||||
{newSlug?.error || ''}
|
||||
</label>
|
||||
) : isSlugUpdated ? (
|
||||
<label
|
||||
className="label label-success"
|
||||
data-cy="app-slug-accepted-label"
|
||||
>{`Slug accepted!`}</label>
|
||||
) : (
|
||||
<label
|
||||
className="label label-info"
|
||||
data-cy="app-slug-info-label"
|
||||
>{`URL-friendly 'slug' consists of lowercase letters, numbers, and hyphens`}</label>
|
||||
)}
|
||||
</div>
|
||||
{this?.props?.isPublic && window?.public_config?.ENABLE_PRIVATE_APP_EMBED === 'true' && (
|
||||
<div className="tj-app-input">
|
||||
<label className="field-name" data-cy="iframe-link-label">
|
||||
{this.props.t('editor.shareModal.embeddableLink', 'Embedded app link')}
|
||||
</label>
|
||||
<span className={`tj-text-input justify-content-between ${this.props.darkMode ? 'dark' : ''}`}>
|
||||
<span data-cy="iframe-link">{embeddableLink}</span>
|
||||
<span className="copy-container">
|
||||
<CopyToClipboard
|
||||
text={embeddableLink}
|
||||
onCopy={() => toast.success('Link copied to clipboard')}
|
||||
>
|
||||
<svg
|
||||
className="cursor-pointer"
|
||||
width="17"
|
||||
height="18"
|
||||
viewBox="0 0 17 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
data-cy="iframe-link-copy-button"
|
||||
>
|
||||
<path
|
||||
d="M9.11154 5.18031H5.88668V4.83302C5.88668 3.29859 7.13059 2.05469 8.66502 2.05469H12.8325C14.3669 2.05469 15.6109 3.29859 15.6109 4.83302V9.00052C15.6109 10.535 14.3669 11.7789 12.8325 11.7789H12.4852V8.554C12.4852 6.69076 10.9748 5.18031 9.11154 5.18031Z"
|
||||
fill="#889096"
|
||||
/>
|
||||
<path
|
||||
d="M8.66502 15.9464H4.49752C2.96309 15.9464 1.71918 14.7025 1.71918 13.168V9.00052C1.71918 7.46609 2.96309 6.22219 4.49752 6.22219H8.66502C10.1994 6.22219 11.4434 7.46609 11.4434 9.00052V13.168C11.4434 14.7025 10.1994 15.9464 8.66502 15.9464Z"
|
||||
fill="#889096"
|
||||
/>
|
||||
</svg>
|
||||
</CopyToClipboard>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
</Modal.Body>
|
||||
|
||||
<Modal.Footer className="manage-app-users-footer">
|
||||
{this.isUserAdmin && (
|
||||
<Link
|
||||
to={getPrivateRoute('workspace_settings')}
|
||||
target="_blank"
|
||||
className={`btn border-0 default-secondary-button float-right1`}
|
||||
data-cy="manage-users-button"
|
||||
>
|
||||
Manage users
|
||||
</Link>
|
||||
)}
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
</div>
|
||||
</ToolTip>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const ManageAppUsers = withTranslation()(ManageAppUsersComponent);
|
||||
33
frontend/src/AppBuilder/Header/UpdatePresenceMultiPlayer.jsx
Normal file
33
frontend/src/AppBuilder/Header/UpdatePresenceMultiPlayer.jsx
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import React, { useEffect } from 'react';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { useUpdatePresence } from '@y-presence/react';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
export default function UpdatePresenceMultiPlayer() {
|
||||
const { user } = useStore(
|
||||
(state) => ({
|
||||
user: state.user,
|
||||
}),
|
||||
shallow
|
||||
);
|
||||
const updatePresence = useUpdatePresence();
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
const initialPresence = {
|
||||
firstName: user.firstName ?? '',
|
||||
lastName: user.lastName ?? '',
|
||||
email: user.email ?? '',
|
||||
image: '',
|
||||
editingVersionId: '',
|
||||
x: 0,
|
||||
y: 0,
|
||||
color: '',
|
||||
};
|
||||
updatePresence(initialPresence);
|
||||
}
|
||||
}, [user, updatePresence]);
|
||||
|
||||
return <></>;
|
||||
}
|
||||
|
|
@ -33,7 +33,6 @@ const PreviewSettings = ({ isMobileLayout, showHeader, darkMode }) => {
|
|||
<>
|
||||
<AppVersionsManager darkMode={darkMode} />
|
||||
<div className="navbar-seperator"></div>
|
||||
{/* <EnvironmentManager darkMode={darkMode} /> */}
|
||||
</>
|
||||
)}
|
||||
<span>
|
||||
|
|
@ -78,8 +77,6 @@ const PreviewSettings = ({ isMobileLayout, showHeader, darkMode }) => {
|
|||
</Offcanvas.Header>
|
||||
{previewNavbar && (
|
||||
<Offcanvas.Body>
|
||||
<span style={{ marginTop: '4px' }}>{/* <EnvironmentManager darkMode={darkMode} /> */}</span>
|
||||
<hr className="m-0" />
|
||||
<span>
|
||||
<AppVersionsManager darkMode={darkMode} />
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -97,10 +97,6 @@ export const Viewer = ({ id: appId, darkMode, moduleId = 'canvas', switchDarkMod
|
|||
const switchPage = useStore((state) => state.switchPage);
|
||||
|
||||
const showHeader = !globalSettings?.hideHeader && isAppLoaded;
|
||||
// ---remove
|
||||
const handleAppEnvironmentChanged = useCallback((environment) => {
|
||||
console.log('setAppVersionCurrentEnvironment', environment);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
updateCanvasHeight(currentPageComponents);
|
||||
|
|
@ -151,7 +147,6 @@ export const Viewer = ({ id: appId, darkMode, moduleId = 'canvas', switchDarkMod
|
|||
pages={pages}
|
||||
currentPageId={currentPageId ?? homePageId}
|
||||
showViewerNavigation={!isPagesSidebarHidden}
|
||||
handleAppEnvironmentChanged={handleAppEnvironmentChanged}
|
||||
changeToDarkMode={changeToDarkMode}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -163,7 +158,6 @@ export const Viewer = ({ id: appId, darkMode, moduleId = 'canvas', switchDarkMod
|
|||
pages={pages}
|
||||
currentPageId={currentPageId ?? homePageId}
|
||||
showViewerNavigation={!isPagesSidebarHidden}
|
||||
handleAppEnvironmentChanged={handleAppEnvironmentChanged}
|
||||
changeToDarkMode={changeToDarkMode}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -216,14 +210,13 @@ export const Viewer = ({ id: appId, darkMode, moduleId = 'canvas', switchDarkMod
|
|||
pages={pages}
|
||||
currentPageId={currentPageId ?? homePageId}
|
||||
showViewerNavigation={!isPagesSidebarHidden}
|
||||
handleAppEnvironmentChanged={handleAppEnvironmentChanged}
|
||||
switchPage={switchPage}
|
||||
changeToDarkMode={changeToDarkMode}
|
||||
/>
|
||||
)}
|
||||
<AppCanvas moduleId={moduleId} isViewerSidebarPinned={isSidebarPinned} />
|
||||
</div>
|
||||
{isAppLoaded && <TooljetBanner isDarkMode={darkMode} />}
|
||||
<TooljetBanner isDarkMode={darkMode} />
|
||||
{isMobilePreviewMode && <div className="hide-drawer-transition" style={{ right: 0 }}></div>}
|
||||
{isMobilePreviewMode && <div className="hide-drawer-transition" style={{ left: 0 }}></div>}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ const useAppData = (appId, moduleId, mode = 'edit', { environmentId, versionId }
|
|||
}
|
||||
const constantsResp = isPublicAccess
|
||||
? await orgEnvironmentConstantService.getConstantsFromPublicApp(slug)
|
||||
: await orgEnvironmentConstantService.getConstantsFromEnvironment(editorEnvironmentId);
|
||||
: await orgEnvironmentConstantService.getConstantsFromApp(editorEnvironmentId);
|
||||
|
||||
const pages = appData.pages.map((page) => {
|
||||
return page;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export const BoundedBox = ({ properties, fireEvent, darkMode, setExposedVariable
|
|||
|
||||
useEffect(() => {
|
||||
const handleImageLoad = () => {
|
||||
const wrapperElement = document.querySelector(`.widget-${id} .lmGPCf`);
|
||||
const wrapperElement = document.querySelector(`[widgetid="${id}"] .lmGPCf`);
|
||||
if (wrapperElement) {
|
||||
const { width, height } = wrapperElement.getBoundingClientRect();
|
||||
// Use the width and height of bounding image for further calculations
|
||||
|
|
@ -35,7 +35,7 @@ export const BoundedBox = ({ properties, fireEvent, darkMode, setExposedVariable
|
|||
}
|
||||
};
|
||||
|
||||
const imageElement = document.querySelector(`.widget-${id} .gVmiLs`);
|
||||
const imageElement = document.querySelector(`[widgetid="${id}"] .gVmiLs`);
|
||||
if (imageElement) {
|
||||
imageElement.addEventListener('load', handleImageLoad);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export const Button = function Button(props) {
|
|||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
click: async function () {
|
||||
if (!disable) {
|
||||
if (!disable && !loading) {
|
||||
fireEvent('onClick');
|
||||
}
|
||||
},
|
||||
|
|
@ -170,9 +170,11 @@ export const Button = function Button(props) {
|
|||
computedStyles['--tblr-btn-color-clicked'] = tinycolor(computedBgColor).darken(15).toString();
|
||||
}
|
||||
const handleClick = () => {
|
||||
const event1 = new CustomEvent('submitForm', { detail: { buttonComponentId: id } });
|
||||
document.dispatchEvent(event1);
|
||||
fireEvent('onClick');
|
||||
if (!disable && !loading) {
|
||||
const event1 = new CustomEvent('submitForm', { detail: { buttonComponentId: id } });
|
||||
document.dispatchEvent(event1);
|
||||
fireEvent('onClick');
|
||||
}
|
||||
};
|
||||
const renderButton = () => (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import React, { useState, useEffect, useMemo, memo, useCallback } from 'react';
|
||||
import React, { useState, useEffect, useMemo, memo, useCallback, useRef } from 'react';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import Plotly from 'plotly.js-dist-min';
|
||||
import createPlotlyComponent from 'react-plotly.js/factory';
|
||||
import { isJson } from '@/_helpers/utils';
|
||||
import { isStringValidJson } from '@/_helpers/utils';
|
||||
const Plot = createPlotlyComponent(Plotly);
|
||||
import { isEqual } from 'lodash';
|
||||
import { deepClone } from '@/_helpers/utilities/utils.helpers';
|
||||
|
||||
var tinycolor = require('tinycolor2');
|
||||
|
||||
export const Chart = function Chart({
|
||||
|
|
@ -19,6 +20,7 @@ export const Chart = function Chart({
|
|||
setExposedVariables,
|
||||
dataCy,
|
||||
}) {
|
||||
const isInitialRender = useRef(true);
|
||||
const [loadingState, setLoadingState] = useState(false);
|
||||
|
||||
const getColor = (color) => {
|
||||
|
|
@ -51,7 +53,13 @@ export const Chart = function Chart({
|
|||
|
||||
const jsonData = typeof jsonDescription === 'object' ? JSON.stringify(jsonDescription) : jsonDescription;
|
||||
|
||||
const isDescriptionJson = plotFromJson ? isJson(jsonData) : false;
|
||||
let isDescriptionJson = false;
|
||||
if (plotFromJson) {
|
||||
isDescriptionJson = isStringValidJson(jsonData);
|
||||
if (!isDescriptionJson) {
|
||||
console.log('Throw error');
|
||||
}
|
||||
}
|
||||
|
||||
const jsonChartData = isDescriptionJson ? JSON.parse(jsonData).data : [];
|
||||
|
||||
|
|
@ -67,6 +75,7 @@ export const Chart = function Chart({
|
|||
const chartTitle = plotFromJson ? chartLayout?.title ?? title : title;
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
const { xaxis, yaxis } = chartLayout;
|
||||
let xAxisTitle, yAxisTitle;
|
||||
if (xaxis) {
|
||||
|
|
@ -172,7 +181,7 @@ export const Chart = function Chart({
|
|||
);
|
||||
|
||||
const handleClick = useCallback((data) => {
|
||||
if (data.length > 0) {
|
||||
if (!disabledState && data.length > 0) {
|
||||
const {
|
||||
x: xAxisLabel,
|
||||
y: yAxisLabel,
|
||||
|
|
@ -194,13 +203,32 @@ export const Chart = function Chart({
|
|||
}, []);
|
||||
|
||||
const handleDoubleClick = useCallback(() => {
|
||||
fireEvent('onDoubleClick');
|
||||
if (!disabledState) {
|
||||
fireEvent('onDoubleClick');
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('clearClickedPoint', () => {
|
||||
setExposedVariable('clickedDataPoint', {});
|
||||
});
|
||||
const { xaxis, yaxis } = chartLayout;
|
||||
let xAxisTitle, yAxisTitle;
|
||||
if (xaxis) {
|
||||
xAxisTitle = xaxis?.title?.text;
|
||||
}
|
||||
if (yaxis) {
|
||||
yAxisTitle = yaxis?.title?.text;
|
||||
}
|
||||
const exposedVariables = {
|
||||
chartTitle: chartTitle,
|
||||
xAxisTitle: xAxisTitle,
|
||||
yAxisTitle: yAxisTitle,
|
||||
clearClickedPoint: () => {
|
||||
setExposedVariable('clickedDataPoint', {});
|
||||
},
|
||||
};
|
||||
|
||||
setExposedVariables(exposedVariables);
|
||||
isInitialRender.current = false;
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
|
|
@ -221,6 +249,7 @@ export const Chart = function Chart({
|
|||
}}
|
||||
onClick={handleClick}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
disabledState={disabledState}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -229,17 +258,17 @@ export const Chart = function Chart({
|
|||
|
||||
// onClick event was not working when the component is re-rendered for every click. Hance, memoization is used
|
||||
const PlotComponent = memo(
|
||||
({ data, layout, config, onClick, onDoubleClick }) => {
|
||||
({ data, layout, config, onClick, onDoubleClick, disabledState }) => {
|
||||
return (
|
||||
<Plot
|
||||
data={data}
|
||||
layout={deepClone(layout)} // Cloning the layout since the object is getting mutated inside the package
|
||||
config={config}
|
||||
onClick={(e) => {
|
||||
onClick(e.points);
|
||||
if (!disabledState) onClick(e.points);
|
||||
}}
|
||||
onDoubleClick={() => {
|
||||
onDoubleClick();
|
||||
if (!disabledState) onDoubleClick();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { resolveWidgetFieldValue } from '@/_helpers/utils';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import Loader from '@/ToolJetUI/Loader/Loader';
|
||||
import OverflowTooltip from '@/_components/OverflowTooltip';
|
||||
|
||||
|
|
@ -8,21 +7,26 @@ export const Checkbox = ({
|
|||
properties,
|
||||
styles,
|
||||
fireEvent,
|
||||
componentName,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
validation,
|
||||
dataCy,
|
||||
component,
|
||||
validate,
|
||||
width,
|
||||
}) => {
|
||||
const isInitialRender = useRef(true);
|
||||
const defaultValueFromProperties = properties.defaultValue ?? false;
|
||||
const isMandatory = validation?.mandatory ?? false;
|
||||
const [defaultValue, setDefaultValue] = useState(defaultValueFromProperties);
|
||||
const [checked, setChecked] = useState(defaultValueFromProperties);
|
||||
const [value, setValue] = React.useState(defaultValueFromProperties);
|
||||
const [userInteracted, setUserInteracted] = useState(false);
|
||||
|
||||
const { label } = properties;
|
||||
const textColor = styles.textColor === '#1B1F24' ? 'var(--text-primary)' : styles.textColor;
|
||||
const textColor = ['#1B1F24', '#000', '#000000ff'].includes(styles.textColor)
|
||||
? 'var(--text-primary)'
|
||||
: styles.textColor;
|
||||
const { loadingState, disabledState } = properties;
|
||||
const { checkboxColor, boxShadow, alignment, uncheckedColor, borderColor, handleColor } = styles;
|
||||
|
||||
|
|
@ -31,8 +35,6 @@ export const Checkbox = ({
|
|||
const [visibility, setVisibility] = useState(properties.visibility);
|
||||
const { isValid, validationError } = validate(checked);
|
||||
|
||||
const isMandatory = resolveWidgetFieldValue(component?.definition?.validation?.mandatory?.value);
|
||||
|
||||
const toggleValue = (e) => {
|
||||
const isChecked = e.target.checked;
|
||||
setChecked(isChecked);
|
||||
|
|
@ -48,28 +50,11 @@ export const Checkbox = ({
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
const setCheckedAndNotify = async (status) => {
|
||||
await setExposedVariable('value', status);
|
||||
if (status) {
|
||||
fireEvent('onCheck');
|
||||
} else {
|
||||
fireEvent('onUnCheck');
|
||||
}
|
||||
setChecked(status);
|
||||
setValue(status);
|
||||
};
|
||||
|
||||
const exposedVariables = {
|
||||
value: defaultValueFromProperties,
|
||||
setChecked: setCheckedAndNotify,
|
||||
setValue: setCheckedAndNotify,
|
||||
};
|
||||
|
||||
if (isInitialRender.current) return;
|
||||
setDefaultValue(defaultValueFromProperties);
|
||||
setChecked(defaultValueFromProperties);
|
||||
setValue(defaultValueFromProperties);
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
setExposedVariable('value', defaultValueFromProperties);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultValueFromProperties]);
|
||||
|
||||
|
|
@ -89,79 +74,108 @@ export const Checkbox = ({
|
|||
}, [loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('label', label);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [label]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isLoading', loading);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loading]);
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isVisible', visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isDisabled', disable);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isValid', isValid);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isValid]);
|
||||
useEffect(() => {
|
||||
setExposedVariable('setLoading', async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setVisibility', async function (state) {
|
||||
setVisibility(state);
|
||||
setExposedVariable('isVisible', state);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility]);
|
||||
const setCheckedAndNotify = async (status) => {
|
||||
await setExposedVariable('value', status);
|
||||
if (status) {
|
||||
fireEvent('onCheck');
|
||||
} else {
|
||||
fireEvent('onUnCheck');
|
||||
}
|
||||
setChecked(status);
|
||||
setValue(status);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setDisable', async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
const exposedVariables = {
|
||||
value: defaultValueFromProperties,
|
||||
setChecked: setCheckedAndNotify,
|
||||
setValue: setCheckedAndNotify,
|
||||
setLoading: async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
},
|
||||
setVisibility: async function (visibility) {
|
||||
setVisibility(visibility);
|
||||
setExposedVariable('isVisible', visibility);
|
||||
},
|
||||
setDisable: async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
},
|
||||
toggle: () => {
|
||||
setExposedVariable('toggle', async function () {
|
||||
setExposedVariable('value', !checked);
|
||||
fireEvent('onChange');
|
||||
setChecked(!checked);
|
||||
setValue(!checked);
|
||||
setUserInteracted(true);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
},
|
||||
label: label,
|
||||
isMandatory: isMandatory,
|
||||
isLoading: loading,
|
||||
isVisible: visibility,
|
||||
isDisabled: disable,
|
||||
isValid: isValid,
|
||||
};
|
||||
|
||||
setDefaultValue(defaultValueFromProperties);
|
||||
setChecked(defaultValueFromProperties);
|
||||
setValue(defaultValueFromProperties);
|
||||
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
isInitialRender.current = false;
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('toggle', async function () {
|
||||
setExposedVariable('value', !checked);
|
||||
fireEvent('onChange');
|
||||
setChecked(!checked);
|
||||
setValue(!checked);
|
||||
setUserInteracted(true);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [checked, value]);
|
||||
}, []);
|
||||
|
||||
const handleToggleChange = () => {
|
||||
const newCheckedState = !checked;
|
||||
setChecked(newCheckedState);
|
||||
setValue(newCheckedState);
|
||||
setExposedVariable('value', newCheckedState).then(() => {
|
||||
fireEvent('onChange');
|
||||
if (newCheckedState) {
|
||||
fireEvent('onCheck');
|
||||
} else {
|
||||
fireEvent('onUnCheck');
|
||||
}
|
||||
});
|
||||
setExposedVariable('value', newCheckedState);
|
||||
fireEvent('onChange');
|
||||
if (newCheckedState) {
|
||||
fireEvent('onCheck');
|
||||
} else {
|
||||
fireEvent('onUnCheck');
|
||||
}
|
||||
setUserInteracted(true);
|
||||
};
|
||||
|
||||
|
|
@ -239,7 +253,7 @@ export const Checkbox = ({
|
|||
</div>
|
||||
{validationError && visibility && !checked && userInteracted && (
|
||||
<div
|
||||
data-cy={`${String(component.name).toLowerCase()}-invalid-feedback`}
|
||||
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
|
||||
style={{
|
||||
color: 'var(--status-error-strong)',
|
||||
fontSize: '11px',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable import/no-unresolved */
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import CodeMirror from '@uiw/react-codemirror';
|
||||
import { okaidia } from '@uiw/codemirror-theme-okaidia';
|
||||
import { githubLight } from '@uiw/codemirror-theme-github';
|
||||
|
|
@ -17,12 +17,14 @@ const langSupport = Object.freeze({
|
|||
css: sass(),
|
||||
});
|
||||
|
||||
export const CodeEditor = ({ height, darkMode, properties, styles, exposedVariables, setExposedVariable, dataCy }) => {
|
||||
export const CodeEditor = ({ id, height, darkMode, properties, styles, setExposedVariable, dataCy }) => {
|
||||
const { enableLineNumber, mode, placeholder } = properties;
|
||||
const { visibility, disabledState } = styles;
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
const codeChanged = debounce((code) => {
|
||||
setExposedVariable('value', code);
|
||||
setValue(code);
|
||||
}, 500);
|
||||
|
||||
const editorStyles = {
|
||||
|
|
@ -63,7 +65,7 @@ export const CodeEditor = ({ height, darkMode, properties, styles, exposedVariab
|
|||
}}
|
||||
>
|
||||
<CodeMirror
|
||||
value={exposedVariables.value}
|
||||
value={value}
|
||||
placeholder={placeholder}
|
||||
height={'100%'}
|
||||
minHeight={editorHeight}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { SketchPicker } from 'react-color';
|
||||
|
||||
export const ColorPicker = function ({
|
||||
|
|
@ -17,6 +17,7 @@ export const ColorPicker = function ({
|
|||
const defaultColor = properties.defaultColor;
|
||||
const [showColorPicker, setShowColorPicker] = useState(false);
|
||||
const [color, setColor] = useState(defaultColor);
|
||||
const colorPickerRef = useRef(null);
|
||||
|
||||
const getRGBAValueFromHex = (hex) => {
|
||||
let c = hex.substring(1).split('');
|
||||
|
|
@ -82,21 +83,19 @@ export const ColorPicker = function ({
|
|||
}
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setColor]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let exposedVariables = {};
|
||||
if (/^#(([\dA-Fa-f]{3}){1,2}|([\dA-Fa-f]{4}){1,2})$/.test(defaultColor)) {
|
||||
if (defaultColor !== color) {
|
||||
exposedVariables = {
|
||||
selectedColorHex: defaultColor,
|
||||
selectedColorRGB: hexToRgb(defaultColor),
|
||||
selectedColorRGBA: hexToRgba(defaultColor),
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
exposedVariables = {
|
||||
selectedColorHex: defaultColor,
|
||||
selectedColorRGB: hexToRgb(defaultColor),
|
||||
selectedColorRGBA: hexToRgba(defaultColor),
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
setColor(defaultColor);
|
||||
}
|
||||
setColor(defaultColor);
|
||||
} else {
|
||||
exposedVariables = {
|
||||
selectedColorHex: undefined,
|
||||
|
|
@ -110,6 +109,21 @@ export const ColorPicker = function ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultColor]);
|
||||
|
||||
useEffect(() => {
|
||||
if (showColorPicker) {
|
||||
const handleClickOutside = (event) => {
|
||||
if (colorPickerRef.current && !colorPickerRef.current.contains(event.target)) {
|
||||
setShowColorPicker(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}
|
||||
}, [showColorPicker]);
|
||||
|
||||
const handleColorChange = (colorCode) => {
|
||||
let exposedVariables = {};
|
||||
const { r, g, b, a } = colorCode.rgb;
|
||||
|
|
@ -147,23 +161,20 @@ export const ColorPicker = function ({
|
|||
: { display: 'none' };
|
||||
|
||||
return (
|
||||
<div style={{ baseStyle, boxShadow }} className="form-control" data-cy={dataCy}>
|
||||
<div className="d-flex h-100 justify-content-between align-items-center" onClick={() => setShowColorPicker(true)}>
|
||||
<span>{color}</span>
|
||||
{!(color === `Invalid Color`) && <div style={backgroundColorDivStyle}></div>}
|
||||
<div>
|
||||
<div style={{ baseStyle, boxShadow }} className="form-control" data-cy={dataCy}>
|
||||
<div
|
||||
className="d-flex h-100 justify-content-between align-items-center"
|
||||
onClick={() => setShowColorPicker(true)}
|
||||
>
|
||||
<span>{color}</span>
|
||||
{!(color === `Invalid Color`) && <div style={backgroundColorDivStyle}></div>}
|
||||
</div>
|
||||
</div>
|
||||
{showColorPicker && (
|
||||
<>
|
||||
<div
|
||||
className="position-absolute bottom-0"
|
||||
style={{ left: 0, right: 0 }}
|
||||
onMouseLeave={() => setShowColorPicker(false)}
|
||||
width={width}
|
||||
>
|
||||
<SketchPicker color={color} onChangeComplete={handleColorChange} />
|
||||
</div>
|
||||
<div onClick={() => setShowColorPicker(false)}></div>
|
||||
</>
|
||||
<div className="position-relative top-0 mt-1" ref={colorPickerRef} width={width}>
|
||||
<SketchPicker color={color} onChangeComplete={handleColorChange} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,33 +1,18 @@
|
|||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { isEqual } from 'lodash';
|
||||
import iframeContent from './iframe.html';
|
||||
|
||||
import { useDataQueries } from '@/_stores/dataQueriesStore';
|
||||
import { useGridStore } from '@/_stores/gridStore';
|
||||
import { isQueryRunnable } from '@/_helpers/utils';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
export const CustomComponent = (props) => {
|
||||
const { height, properties, styles, id, setExposedVariable, exposedVariables, fireEvent, dataCy, component } = props;
|
||||
const dataQueries = useDataQueries();
|
||||
|
||||
const showPlaceholder = useGridStore((state) => {
|
||||
const { resizingComponentId, draggingComponentId } = state;
|
||||
if (
|
||||
(resizingComponentId === null && draggingComponentId === id) ||
|
||||
(draggingComponentId === null && resizingComponentId === id) ||
|
||||
id === 'resizingComponentId'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, shallow);
|
||||
|
||||
const { height, properties, styles, id, setExposedVariable, dataCy } = props;
|
||||
const exposedVariables = useStore((state) => state.getExposedValueOfComponent(id), shallow);
|
||||
const onEvent = useStore((state) => state.eventsSlice.onEvent, shallow);
|
||||
const { visibility, boxShadow } = styles;
|
||||
const { code, data } = properties;
|
||||
const [customProps, setCustomProps] = useState(data);
|
||||
const iFrameRef = useRef(null);
|
||||
const dataQueryRef = useRef(dataQueries);
|
||||
|
||||
const customPropRef = useRef(data);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -42,17 +27,13 @@ export const CustomComponent = (props) => {
|
|||
sendMessageToIframe({ message: 'DATA_UPDATED' });
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setExposedVariable, customProps, exposedVariables.data]);
|
||||
}, [customProps, exposedVariables.data]);
|
||||
|
||||
useEffect(() => {
|
||||
sendMessageToIframe({ message: 'CODE_UPDATED' });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [code]);
|
||||
|
||||
useEffect(() => {
|
||||
dataQueryRef.current = dataQueries;
|
||||
}, [dataQueries]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('message', (e) => {
|
||||
try {
|
||||
|
|
@ -60,17 +41,11 @@ export const CustomComponent = (props) => {
|
|||
if (e.data.message === 'UPDATE_DATA') {
|
||||
setCustomProps({ ...customPropRef.current, ...e.data.updatedObj });
|
||||
} else if (e.data.message === 'RUN_QUERY') {
|
||||
const filteredQuery = dataQueryRef.current.filter(
|
||||
(query) => query.name === e.data.queryName && isQueryRunnable(query)
|
||||
);
|
||||
const parameters = e.data.parameters ? JSON.parse(e.data.parameters) : {};
|
||||
filteredQuery.length === 1 &&
|
||||
fireEvent('onTrigger', {
|
||||
component,
|
||||
queryId: filteredQuery[0].id,
|
||||
queryName: filteredQuery[0].name,
|
||||
parameters,
|
||||
});
|
||||
const options = {
|
||||
parameters: e.data.parameters,
|
||||
queryName: e.data.queryName,
|
||||
};
|
||||
onEvent('onTrigger', [], options);
|
||||
} else {
|
||||
sendMessageToIframe(e.data);
|
||||
}
|
||||
|
|
@ -90,7 +65,7 @@ export const CustomComponent = (props) => {
|
|||
{
|
||||
message: 'INIT_RESPONSE',
|
||||
componentId: id,
|
||||
data: customProps,
|
||||
data: customPropRef.current,
|
||||
code: code,
|
||||
},
|
||||
'*'
|
||||
|
|
@ -121,14 +96,12 @@ export const CustomComponent = (props) => {
|
|||
|
||||
return (
|
||||
<div className="card" style={{ display: visibility ? '' : 'none', height, boxShadow }} data-cy={dataCy}>
|
||||
{showPlaceholder ? null : (
|
||||
<iframe
|
||||
srcDoc={iframeContent}
|
||||
style={{ width: '100%', height: '100%', border: 'none' }}
|
||||
ref={iFrameRef}
|
||||
data-id={id}
|
||||
></iframe>
|
||||
)}
|
||||
<iframe
|
||||
srcDoc={iframeContent}
|
||||
style={{ width: '100%', height: '100%', border: 'none' }}
|
||||
ref={iFrameRef}
|
||||
data-id={id}
|
||||
></iframe>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,27 +1,29 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import DatePickerComponent from 'react-datepicker';
|
||||
import moment from 'moment';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import './datepicker.scss';
|
||||
import cx from 'classnames';
|
||||
|
||||
export const Datepicker = function Datepicker({
|
||||
height,
|
||||
properties,
|
||||
styles,
|
||||
exposedVariables,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
validate,
|
||||
onComponentClick,
|
||||
component,
|
||||
id,
|
||||
darkMode,
|
||||
fireEvent,
|
||||
dataCy,
|
||||
}) {
|
||||
const isInitialRender = useRef(true);
|
||||
const { enableTime, enableDate, defaultValue, disabledDates } = properties;
|
||||
const format = typeof properties.format === 'string' ? properties.format : '';
|
||||
const { visibility, disabledState, borderRadius, boxShadow } = styles;
|
||||
|
||||
const [date, setDate] = useState(null);
|
||||
const [date, setDate] = useState(defaultValue);
|
||||
const [excludedDates, setExcludedDates] = useState([]);
|
||||
const [showValidationError, setShowValidationError] = useState(false);
|
||||
|
||||
|
|
@ -46,6 +48,7 @@ export const Datepicker = function Datepicker({
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
const dateMomentInstance = defaultValue && moment(defaultValue, selectedDateFormat);
|
||||
if (dateMomentInstance && dateMomentInstance.isValid()) {
|
||||
setDate(dateMomentInstance.toDate());
|
||||
|
|
@ -70,14 +73,32 @@ export const Datepicker = function Datepicker({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disabledDates, format]);
|
||||
|
||||
const validationData = validate(exposedVariables.value);
|
||||
const validationData = validate(computeDateString(date));
|
||||
const { isValid, validationError } = validationData;
|
||||
|
||||
useEffect(() => {
|
||||
isInitialRender.current = false;
|
||||
setExposedVariable('isValid', isValid);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isValid]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
isValid,
|
||||
};
|
||||
const dateMomentInstance = defaultValue && moment(defaultValue, selectedDateFormat);
|
||||
if (dateMomentInstance && dateMomentInstance.isValid()) {
|
||||
setDate(dateMomentInstance.toDate());
|
||||
exposedVariables.value = defaultValue;
|
||||
} else {
|
||||
setDate(null);
|
||||
exposedVariables.value = undefined;
|
||||
}
|
||||
setExposedVariables(exposedVariables);
|
||||
isInitialRender.current = false;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
data-disabled={disabledState}
|
||||
|
|
@ -94,13 +115,14 @@ export const Datepicker = function Datepicker({
|
|||
className={`input-field form-control ${
|
||||
!isValid && showValidationError ? 'is-invalid' : ''
|
||||
} validation-without-icon px-2 ${darkMode ? 'bg-dark color-white' : 'bg-light'}`}
|
||||
popperClassName={cx('tj-datepicker-widget', { 'dark-theme': darkMode })}
|
||||
selected={date}
|
||||
value={date !== null ? computeDateString(date) : 'select date'}
|
||||
onChange={(date) => onDateChange(date)}
|
||||
showTimeInput={enableTime ? true : false}
|
||||
showTimeSelectOnly={enableDate ? false : true}
|
||||
onFocus={(event) => {
|
||||
onComponentClick(id, component, event);
|
||||
onComponentClick(id);
|
||||
}}
|
||||
showMonthDropdown
|
||||
showYearDropdown
|
||||
|
|
|
|||
|
|
@ -10,11 +10,14 @@ export const DaterangePicker = function DaterangePicker({
|
|||
properties,
|
||||
styles,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
width,
|
||||
darkMode,
|
||||
fireEvent,
|
||||
dataCy,
|
||||
id,
|
||||
}) {
|
||||
const isInitialRender = useRef(true);
|
||||
const { borderRadius, visibility, disabledState, boxShadow } = styles;
|
||||
const { defaultStartDate, defaultEndDate } = properties;
|
||||
const formatProp = typeof properties.format === 'string' ? properties.format : '';
|
||||
|
|
@ -26,12 +29,28 @@ export const DaterangePicker = function DaterangePicker({
|
|||
const dateRangeRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setStartDate(moment(defaultStartDate, formatProp));
|
||||
setExposedVariable('startDate', moment(defaultStartDate, formatProp).format(formatProp));
|
||||
}, [defaultStartDate, formatProp]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setEndDate(moment(defaultEndDate, formatProp));
|
||||
setExposedVariable('endDate', moment(defaultEndDate, formatProp).format(formatProp));
|
||||
}, [defaultEndDate, formatProp]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
startDate: moment(defaultStartDate, formatProp).format(formatProp),
|
||||
endDate: moment(defaultEndDate, formatProp).format(formatProp),
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
setStartDate(moment(defaultStartDate, formatProp));
|
||||
setEndDate(moment(defaultEndDate, formatProp));
|
||||
setExposedVariable('startDate', startDate.format(formatProp));
|
||||
setExposedVariable('endDate', endDate.format(formatProp));
|
||||
isInitialRender.current = false;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultEndDate, defaultStartDate, formatProp]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
dateRangeRef.current.container.querySelector('.DateRangePickerInput').style.borderRadius = `${Number.parseFloat(
|
||||
|
|
@ -63,6 +82,11 @@ export const DaterangePicker = function DaterangePicker({
|
|||
|
||||
function focusChanged(focus) {
|
||||
setFocusedInput(focus);
|
||||
if (focus) {
|
||||
document.querySelector(`.ele-${id}`).style.zIndex = 3;
|
||||
} else {
|
||||
document.querySelector(`.ele-${id}`).style.zIndex = '';
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import _ from 'lodash';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import Select, { components } from 'react-select';
|
||||
import TriangleDownArrow from '@/_ui/Icon/bulkIcons/TriangleDownArrow';
|
||||
import TriangleUpArrow from '@/_ui/Icon/bulkIcons/TriangleUpArrow';
|
||||
|
|
@ -10,22 +10,20 @@ export const DropDown = function DropDown({
|
|||
properties,
|
||||
styles,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
fireEvent,
|
||||
darkMode,
|
||||
onComponentClick,
|
||||
id,
|
||||
component,
|
||||
exposedVariables,
|
||||
dataCy,
|
||||
}) {
|
||||
const isInitialRender = useRef(true);
|
||||
let { label, value, advanced, schema, placeholder, display_values, values } = properties;
|
||||
const { selectedTextColor, borderRadius, visibility, disabledState, justifyContent, boxShadow } = styles;
|
||||
const [currentValue, setCurrentValue] = useState(() => (advanced ? findDefaultItem(schema) : value));
|
||||
const { value: exposedValue } = exposedVariables;
|
||||
const [showValidationError, setShowValidationError] = useState(false);
|
||||
const validationData = validate(value);
|
||||
const { isValid, validationError } = validationData;
|
||||
|
||||
function findDefaultItem(schema) {
|
||||
const foundItem = schema?.find((item) => item?.default === true);
|
||||
return !hasVisibleFalse(foundItem?.value) ? foundItem?.value : undefined;
|
||||
|
|
@ -63,10 +61,13 @@ export const DropDown = function DropDown({
|
|||
const setExposedItem = (value, index, onSelectFired = false) => {
|
||||
setCurrentValue(value);
|
||||
if (onSelectFired) {
|
||||
setExposedVariable('value', value);
|
||||
fireEvent('onSelect');
|
||||
} else setExposedVariable('value', value);
|
||||
setExposedVariable('selectedOptionLabel', index === undefined ? undefined : display_values?.[index]);
|
||||
}
|
||||
const exposedVariables = {
|
||||
value,
|
||||
selectedOptionLabel: index === undefined ? undefined : display_values?.[index],
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
};
|
||||
|
||||
function selectOption(value) {
|
||||
|
|
@ -79,19 +80,71 @@ export const DropDown = function DropDown({
|
|||
setExposedItem(undefined, undefined, true);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('selectOption', async function (value) {
|
||||
selectOption(value);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(values), setCurrentValue, JSON.stringify(display_values)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isValid', isValid);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isValid]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('value', currentValue);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
const index = values?.indexOf(currentValue);
|
||||
setExposedVariable('selectedOptionLabel', display_values?.[index]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentValue, JSON.stringify(display_values), JSON.stringify(values)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('label', label);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [label]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
if (advanced) {
|
||||
setExposedVariable(
|
||||
'optionLabels',
|
||||
schema?.filter((item) => item?.visible)?.map((item) => item.label)
|
||||
);
|
||||
if (hasVisibleFalse(currentValue)) {
|
||||
setCurrentValue(findDefaultItem(schema));
|
||||
}
|
||||
} else setExposedVariable('optionLabels', display_values);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(schema), advanced, JSON.stringify(display_values), currentValue]);
|
||||
|
||||
useEffect(() => {
|
||||
const index = values?.indexOf(currentValue);
|
||||
let optionLabels = display_values;
|
||||
if (advanced) {
|
||||
optionLabels = schema?.filter((item) => item?.visible)?.map((item) => item.label);
|
||||
}
|
||||
const exposedVariables = {
|
||||
selectOption: async function (value) {
|
||||
selectOption(value);
|
||||
},
|
||||
isValid: isValid,
|
||||
value: currentValue,
|
||||
selectedOptionLabel: display_values?.[index],
|
||||
label: label,
|
||||
optionLabels: optionLabels,
|
||||
};
|
||||
|
||||
setExposedVariables(exposedVariables);
|
||||
if (hasVisibleFalse(currentValue)) {
|
||||
setCurrentValue(findDefaultItem(schema));
|
||||
}
|
||||
isInitialRender.current = false;
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let newValue = undefined;
|
||||
let index = null;
|
||||
|
|
@ -104,16 +157,6 @@ export const DropDown = function DropDown({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(value), JSON.stringify(values)]);
|
||||
|
||||
useEffect(() => {
|
||||
let index = null;
|
||||
if (exposedValue !== currentValue) {
|
||||
setExposedVariable('value', currentValue);
|
||||
}
|
||||
index = values?.indexOf(currentValue);
|
||||
setExposedVariable('selectedOptionLabel', display_values?.[index]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentValue, JSON.stringify(display_values), JSON.stringify(values)]);
|
||||
|
||||
useEffect(() => {
|
||||
let newValue = undefined;
|
||||
let index = null;
|
||||
|
|
@ -125,24 +168,6 @@ export const DropDown = function DropDown({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(values)]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('label', label);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [label]);
|
||||
|
||||
useEffect(() => {
|
||||
if (advanced) {
|
||||
setExposedVariable(
|
||||
'optionLabels',
|
||||
schema?.filter((item) => item?.visible)?.map((item) => item.label)
|
||||
);
|
||||
if (hasVisibleFalse(currentValue)) {
|
||||
setCurrentValue(findDefaultItem(schema));
|
||||
}
|
||||
} else setExposedVariable('optionLabels', display_values);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(schema), advanced, JSON.stringify(display_values), currentValue]);
|
||||
|
||||
function hasVisibleFalse(value) {
|
||||
for (let i = 0; i < schema?.length; i++) {
|
||||
if (schema[i].value === value && schema[i].visible === false) {
|
||||
|
|
@ -227,42 +252,6 @@ export const DropDown = function DropDown({
|
|||
backgroundColor: darkMode ? 'rgb(31,40,55)' : 'white',
|
||||
}),
|
||||
};
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const handleDropdownOpen = () => {
|
||||
setIsOpen(true);
|
||||
};
|
||||
|
||||
const handleDropdownClose = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const DropdownIndicator = (props) => {
|
||||
return (
|
||||
<components.DropdownIndicator {...props}>
|
||||
<div onClick={() => (isOpen ? handleDropdownClose() : handleDropdownOpen())}>
|
||||
{isOpen ? (
|
||||
<TriangleUpArrow width={'18'} className="cursor-pointer" fill={'var(--borders-strong)'} />
|
||||
) : (
|
||||
<TriangleDownArrow width={'18'} className="cursor-pointer" fill={'var(--borders-strong)'} />
|
||||
)}
|
||||
</div>
|
||||
</components.DropdownIndicator>
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (isOpen && !event.target.closest('.dropdown-widget')) {
|
||||
handleDropdownClose();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
};
|
||||
}, [isOpen]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -271,7 +260,7 @@ export const DropDown = function DropDown({
|
|||
style={{ height, display: visibility ? '' : 'none' }}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onComponentClick(id, component, event);
|
||||
onComponentClick(id);
|
||||
}}
|
||||
data-cy={dataCy}
|
||||
>
|
||||
|
|
@ -297,13 +286,9 @@ export const DropDown = function DropDown({
|
|||
styles={customStyles}
|
||||
isLoading={properties.loadingState}
|
||||
onInputChange={onSearchTextChange}
|
||||
onFocus={(event) => onComponentClick(event, component, id)}
|
||||
onFocus={(event) => onComponentClick(id)}
|
||||
menuPortalTarget={document.body}
|
||||
placeholder={placeholder}
|
||||
onMenuOpen={handleDropdownOpen}
|
||||
onMenuClose={handleDropdownClose}
|
||||
menuIsOpen={isOpen}
|
||||
components={{ DropdownIndicator }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { resolveReferences } from '@/_helpers/utils';
|
||||
import { useCurrentState } from '@/_stores/currentStateStore';
|
||||
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
||||
import Select, { components } from 'react-select';
|
||||
import ClearIndicatorIcon from '@/_ui/Icon/bulkIcons/ClearIndicator';
|
||||
|
|
@ -16,6 +14,8 @@ import CustomOption from './CustomOption';
|
|||
import Label from '@/_ui/Label';
|
||||
import cx from 'classnames';
|
||||
import { getInputBackgroundColor, getInputBorderColor, getInputFocusedColor } from './utils';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
const { DropdownIndicator, ClearIndicator } = components;
|
||||
const INDICATOR_CONTAINER_WIDTH = 60;
|
||||
|
|
@ -55,11 +55,20 @@ export const DropdownV2 = ({
|
|||
darkMode,
|
||||
onComponentClick,
|
||||
id,
|
||||
component,
|
||||
exposedVariables,
|
||||
componentName,
|
||||
validation,
|
||||
dataCy,
|
||||
}) => {
|
||||
const { label, value, advanced, schema, placeholder, loadingState: dropdownLoadingState, disabledState } = properties;
|
||||
const {
|
||||
label,
|
||||
value,
|
||||
advanced,
|
||||
schema,
|
||||
placeholder,
|
||||
loadingState: dropdownLoadingState,
|
||||
disabledState,
|
||||
optionsLoadingState,
|
||||
} = properties;
|
||||
const {
|
||||
selectedTextColor,
|
||||
fieldBorderRadius,
|
||||
|
|
@ -79,11 +88,11 @@ export const DropdownV2 = ({
|
|||
accentColor,
|
||||
padding,
|
||||
} = styles;
|
||||
const isInitialRender = useRef(true);
|
||||
const [currentValue, setCurrentValue] = useState(() => (advanced ? findDefaultItem(schema) : value));
|
||||
const { value: exposedValue } = exposedVariables;
|
||||
const currentState = useCurrentState();
|
||||
const isMandatory = resolveReferences(component?.definition?.validation?.mandatory?.value, currentState);
|
||||
const options = component?.definition?.properties?.options?.value;
|
||||
const getResolvedValue = useStore((state) => state.getResolvedValue, shallow);
|
||||
const isMandatory = validation?.mandatory ?? false;
|
||||
const options = properties?.options;
|
||||
const validationData = validate(currentValue);
|
||||
const { isValid, validationError } = validationData;
|
||||
const ref = React.useRef(null);
|
||||
|
|
@ -106,13 +115,14 @@ export const DropdownV2 = ({
|
|||
let _options = advanced ? schema : options;
|
||||
if (Array.isArray(_options)) {
|
||||
let _selectOptions = _options
|
||||
.filter((data) => resolveReferences(advanced ? data?.visible : data?.visible?.value, currentState))
|
||||
.filter((data) => getResolvedValue(advanced ? data?.visible : data?.visible?.value) ?? true)
|
||||
.map((data) => ({
|
||||
...data,
|
||||
label: resolveReferences(data?.label, currentState),
|
||||
value: resolveReferences(data?.value, currentState),
|
||||
isDisabled: resolveReferences(advanced ? data?.disable : data?.disable?.value, currentState),
|
||||
label: String(getResolvedValue(data?.label)),
|
||||
value: getResolvedValue(data?.value),
|
||||
isDisabled: getResolvedValue(advanced ? data?.disable : data?.disable?.value) ?? false,
|
||||
}));
|
||||
|
||||
return _selectOptions;
|
||||
} else {
|
||||
return [];
|
||||
|
|
@ -139,6 +149,7 @@ export const DropdownV2 = ({
|
|||
const onSearchTextChange = (searchText, actionProps) => {
|
||||
if (actionProps.action === 'input-change') {
|
||||
setSearchInputValue(searchText);
|
||||
setExposedVariable('searchText', searchText);
|
||||
fireEvent('onSearchTextChanged');
|
||||
}
|
||||
};
|
||||
|
|
@ -174,11 +185,21 @@ export const DropdownV2 = ({
|
|||
}, [properties.visibility, dropdownLoadingState, disabledState]);
|
||||
|
||||
// Exposed variables
|
||||
|
||||
useEffect(() => {
|
||||
if (exposedValue !== currentValue) {
|
||||
const _selectedOption = selectOptions.find((option) => option.value === currentValue);
|
||||
setExposedVariable('selectedOption', pick(_selectedOption, ['label', 'value']));
|
||||
}
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('value', currentValue);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentValue]);
|
||||
|
||||
useEffect(() => {
|
||||
const _selectedOption = selectOptions.find((option) => option.value === currentValue);
|
||||
setExposedVariable('selectedOption', pick(_selectedOption, ['label', 'value']));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentValue, JSON.stringify(selectOptions)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
const _options = selectOptions?.map(({ label, value }) => ({ label, value }));
|
||||
setExposedVariable('options', _options);
|
||||
|
||||
|
|
@ -191,33 +212,75 @@ export const DropdownV2 = ({
|
|||
}, [currentValue, JSON.stringify(selectOptions)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('label', label);
|
||||
setExposedVariable('searchText', searchInputValue);
|
||||
setExposedVariable('isValid', isValid);
|
||||
setExposedVariable('isVisible', properties.visibility);
|
||||
setExposedVariable('isLoading', dropdownLoadingState);
|
||||
setExposedVariable('isDisabled', disabledState);
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility, dropdownLoadingState, disabledState, isMandatory, label, searchInputValue, isValid]);
|
||||
}, [label]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('searchText', searchInputValue);
|
||||
}, [searchInputValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isValid', isValid);
|
||||
}, [isValid]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isVisible', properties.visibility);
|
||||
}, [properties.visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isLoading', dropdownLoadingState);
|
||||
}, [dropdownLoadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isDisabled', disabledState);
|
||||
}, [disabledState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
const _options = selectOptions?.map(({ label, value }) => ({ label, value }));
|
||||
const exposedVariables = {
|
||||
clear: async function () {
|
||||
setCurrentValue(null);
|
||||
},
|
||||
setVisibility: async function (value) {
|
||||
setVisibility(value);
|
||||
setExposedVariable('isVisible', value);
|
||||
},
|
||||
setLoading: async function (value) {
|
||||
setIsDropdownLoading(value);
|
||||
setExposedVariable('isLoading', value);
|
||||
},
|
||||
setDisable: async function (value) {
|
||||
setIsDropdownDisabled(value);
|
||||
setExposedVariable('isDisabled', value);
|
||||
},
|
||||
selectOption: async function (value) {
|
||||
let _value = value;
|
||||
if (isObject(value) && has(value, 'value')) _value = value?.value;
|
||||
selectOption(_value);
|
||||
},
|
||||
options: _options,
|
||||
value: currentValue,
|
||||
label: label,
|
||||
searchText: searchInputValue,
|
||||
isValid: isValid,
|
||||
isVisible: properties.visibility,
|
||||
isLoading: dropdownLoadingState,
|
||||
isDisabled: disabledState,
|
||||
isMandatory: isMandatory,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
isInitialRender.current = false;
|
||||
}, []);
|
||||
|
||||
const customStyles = {
|
||||
|
|
@ -343,7 +406,7 @@ export const DropdownV2 = ({
|
|||
return (
|
||||
<>
|
||||
<div
|
||||
data-cy={`label-${String(component.name).toLowerCase()} `}
|
||||
data-cy={`label-${String(componentName).toLowerCase()} `}
|
||||
className={cx('dropdown-widget', 'd-flex', {
|
||||
[alignment === 'top' &&
|
||||
((labelWidth != 0 && label?.length != 0) ||
|
||||
|
|
@ -361,7 +424,7 @@ export const DropdownV2 = ({
|
|||
width: '100%',
|
||||
}}
|
||||
onMouseDown={(event) => {
|
||||
onComponentClick(id, component, event);
|
||||
onComponentClick(id);
|
||||
// This following line is needed because sometimes after clicking on canvas then also dropdown remains selected
|
||||
useEditorStore.getState().actions.setHoveredComponent('');
|
||||
}}
|
||||
|
|
@ -397,7 +460,7 @@ export const DropdownV2 = ({
|
|||
isLoading={isDropdownLoading}
|
||||
onInputChange={onSearchTextChange}
|
||||
inputValue={searchInputValue}
|
||||
onFocus={() => {
|
||||
onMenuOpen={() => {
|
||||
fireEvent('onFocus');
|
||||
}}
|
||||
onMenuInputFocus={() => setIsFocused(true)}
|
||||
|
|
@ -425,7 +488,7 @@ export const DropdownV2 = ({
|
|||
iconColor={iconColor}
|
||||
isSearchable={false}
|
||||
darkMode={darkMode}
|
||||
optionsLoadingState={properties.optionsLoadingState}
|
||||
optionsLoadingState={optionsLoadingState && advanced}
|
||||
menuPlacement="auto"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,57 +1,46 @@
|
|||
import React, { useEffect, useMemo } from 'react';
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { resolveWidgetFieldValue } from '@/_helpers/utils';
|
||||
import { toast } from 'react-hot-toast';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import * as XLSX from 'xlsx/xlsx.mjs';
|
||||
|
||||
import { useAppInfo } from '@/_stores/appDataStore';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
|
||||
export const FilePicker = ({
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
component,
|
||||
fireEvent,
|
||||
onComponentOptionChanged,
|
||||
onEvent,
|
||||
darkMode,
|
||||
styles,
|
||||
properties,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
dataCy,
|
||||
}) => {
|
||||
//* properties definitions
|
||||
const instructionText =
|
||||
component.definition.properties.instructionText?.value ?? 'Drag and drop files here or click to select files';
|
||||
const enableDropzone = component.definition.properties.enableDropzone.value ?? true;
|
||||
const enablePicker = component.definition.properties?.enablePicker?.value ?? true;
|
||||
const maxFileCount = component.definition.properties.maxFileCount?.value ?? 2;
|
||||
const enableMultiple = component.definition.properties.enableMultiple?.value ?? false;
|
||||
const fileType = component.definition.properties.fileType?.value ?? 'image/*';
|
||||
const maxSize = component.definition.properties.maxSize?.value ?? 1048576;
|
||||
const minSize = component.definition.properties.minSize?.value ?? 0;
|
||||
const parseContent = resolveWidgetFieldValue(component.definition.properties.parseContent?.value);
|
||||
const fileTypeFromExtension = component.definition.properties.parseFileType?.value ?? 'auto-detect';
|
||||
const parsedEnableDropzone = typeof enableDropzone !== 'boolean' ? resolveWidgetFieldValue(enableDropzone) : true;
|
||||
const parsedEnablePicker = typeof enablePicker !== 'boolean' ? resolveWidgetFieldValue(enablePicker) : true;
|
||||
|
||||
const parsedMaxFileCount = typeof maxFileCount !== 'number' ? resolveWidgetFieldValue(maxFileCount) : maxFileCount;
|
||||
const parsedEnableMultiple =
|
||||
typeof enableMultiple !== 'boolean' ? resolveWidgetFieldValue(enableMultiple) : enableMultiple;
|
||||
const parsedFileType = resolveWidgetFieldValue(fileType);
|
||||
const parsedMinSize = typeof fileType !== 'number' ? resolveWidgetFieldValue(minSize) : minSize;
|
||||
const parsedMaxSize = typeof fileType !== 'number' ? resolveWidgetFieldValue(maxSize) : maxSize;
|
||||
//* styles definitions
|
||||
const widgetVisibility = component.definition.styles?.visibility?.value ?? true;
|
||||
const disabledState = component.definition.styles?.disabledState?.value ?? false;
|
||||
|
||||
const parsedDisabledState =
|
||||
typeof disabledState !== 'boolean' ? resolveWidgetFieldValue(disabledState) : disabledState;
|
||||
const parsedWidgetVisibility =
|
||||
typeof widgetVisibility !== 'boolean' ? resolveWidgetFieldValue(widgetVisibility) : widgetVisibility;
|
||||
//* resolved properties d
|
||||
const isInitialRender = useRef(true);
|
||||
const instructionText = properties?.instructionText ?? 'Drag and drop files here or click to select files';
|
||||
const enableDropzone = properties?.enableDropzone ?? true;
|
||||
const enablePicker = properties?.enablePicker ?? true;
|
||||
const maxFileCount = properties?.maxFileCount ?? 2;
|
||||
const enableMultiple = properties?.enableMultiple ?? false;
|
||||
const fileType = properties?.fileType ?? 'image/*';
|
||||
const maxSize = properties?.maxSize ?? 1048576;
|
||||
const minSize = properties?.minSize ?? 0;
|
||||
const parseContent = properties.parseContent;
|
||||
const fileTypeFromExtension = properties.parseFileType ?? 'auto-detect';
|
||||
//* resolved styles
|
||||
const widgetVisibility = styles?.visibility ?? true;
|
||||
const disabledState = styles?.disabledState ?? false;
|
||||
|
||||
const { events: allAppEvents } = useAppInfo();
|
||||
|
||||
const filePickerEvents = allAppEvents.filter((event) => event.target === 'component' && event.sourceId === id);
|
||||
console.log(filePickerEvents);
|
||||
|
||||
const bgThemeColor = darkMode ? '#232E3C' : '#fff';
|
||||
|
||||
|
|
@ -68,9 +57,9 @@ export const FilePicker = ({
|
|||
color: '#bdbdbd',
|
||||
outline: 'none',
|
||||
transition: 'border .24s ease-in-out',
|
||||
display: parsedWidgetVisibility ? 'flex' : 'none',
|
||||
display: widgetVisibility ? 'flex' : 'none',
|
||||
height,
|
||||
backgroundColor: !parsedDisabledState && bgThemeColor,
|
||||
backgroundColor: !disabledState && bgThemeColor,
|
||||
boxShadow: styles.boxShadow,
|
||||
};
|
||||
|
||||
|
|
@ -90,14 +79,14 @@ export const FilePicker = ({
|
|||
|
||||
const { getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject, acceptedFiles, fileRejections } =
|
||||
useDropzone({
|
||||
accept: { parsedFileType: [parsedFileType] },
|
||||
noClick: !parsedEnablePicker || disablePicker,
|
||||
noDrag: !parsedEnableDropzone || disablePicker,
|
||||
accept: { parsedFileType: [fileType] },
|
||||
noClick: !enablePicker || disablePicker,
|
||||
noDrag: !enableDropzone || disablePicker,
|
||||
noKeyboard: true,
|
||||
maxFiles: parsedMaxFileCount,
|
||||
minSize: parsedMinSize,
|
||||
maxSize: parsedMaxSize,
|
||||
multiple: parsedEnableMultiple,
|
||||
maxFiles: maxFileCount,
|
||||
minSize: minSize,
|
||||
maxSize: maxSize,
|
||||
multiple: enableMultiple,
|
||||
disabled: disablePicker,
|
||||
validator: validateFileExists,
|
||||
onDropRejected: () => (selectedFiles.length > 0 ? setShowSelectedFiles(true) : setShowSelectedFiles(false)),
|
||||
|
|
@ -107,9 +96,9 @@ export const FilePicker = ({
|
|||
const style = useMemo(
|
||||
() => ({
|
||||
...baseStyle,
|
||||
...(isDragActive && parsedEnableDropzone ? activeStyle : {}),
|
||||
...(isDragAccept && parsedEnableDropzone ? acceptStyle : {}),
|
||||
...(isDragReject && parsedEnableDropzone ? rejectStyle : {}),
|
||||
...(isDragActive && enableDropzone ? activeStyle : {}),
|
||||
...(isDragAccept && enableDropzone ? acceptStyle : {}),
|
||||
...(isDragReject && enableDropzone ? rejectStyle : {}),
|
||||
}),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[baseStyle, isDragActive, isDragAccept, acceptStyle, isDragReject]
|
||||
|
|
@ -123,7 +112,7 @@ export const FilePicker = ({
|
|||
function validateFileExists(_file) {
|
||||
const selectedFilesCount = selectedFiles.length;
|
||||
|
||||
if (selectedFilesCount === parsedMaxFileCount) {
|
||||
if (selectedFilesCount === maxFileCount) {
|
||||
return {
|
||||
code: 'max_file_count_reached',
|
||||
message: `Max file count reached`,
|
||||
|
|
@ -134,14 +123,13 @@ export const FilePicker = ({
|
|||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (parsedDisabledState) setDisablePicker(true);
|
||||
|
||||
if (selectedFiles.length === parsedMaxFileCount && parsedEnableMultiple) {
|
||||
if (disabledState) setDisablePicker(true);
|
||||
else if (selectedFiles.length === maxFileCount && enableMultiple) {
|
||||
setDisablePicker(true);
|
||||
} else {
|
||||
setDisablePicker(false);
|
||||
}
|
||||
}, [selectedFiles.length, parsedDisabledState, parsedMaxFileCount, parsedEnableMultiple]);
|
||||
}, [selectedFiles.length, disabledState, maxFileCount, enableMultiple]);
|
||||
|
||||
/**
|
||||
* *getFileData()
|
||||
|
|
@ -220,35 +208,38 @@ export const FilePicker = ({
|
|||
const fileSize = formatFileSize(rejectedFileSize);
|
||||
|
||||
if (code === errorType.MIN_SIZE) {
|
||||
return `File size ${fileSize} is too small. Minimum size is ${formatFileSize(parsedMinSize)}`;
|
||||
return `File size ${fileSize} is too small. Minimum size is ${formatFileSize(minSize)}`;
|
||||
}
|
||||
if (code === errorType.MAX_SIZE) {
|
||||
return `File size ${fileSize} is too large. Maximum size is ${formatFileSize(parsedMaxSize)}`;
|
||||
return `File size ${fileSize} is too large. Maximum size is ${formatFileSize(maxSize)}`;
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
if (acceptedFiles.length === 0 && selectedFiles.length === 0) {
|
||||
onComponentOptionChanged(component, 'file', [], id);
|
||||
setExposedVariable('file', []);
|
||||
// onComponentOptionChanged(component, 'file', [], id);
|
||||
}
|
||||
|
||||
if (acceptedFiles.length !== 0 && onEvent) {
|
||||
const fileData = parsedEnableMultiple ? [...selectedFiles] : [];
|
||||
if (acceptedFiles.length !== 0 && fireEvent) {
|
||||
const fileData = enableMultiple ? [...selectedFiles] : [];
|
||||
if (parseContent) {
|
||||
onComponentOptionChanged(component, 'isParsing', true, id);
|
||||
setExposedVariable('isParsing', true);
|
||||
// onComponentOptionChanged(component, 'isParsing', true, id);
|
||||
}
|
||||
acceptedFiles.map((acceptedFile) => {
|
||||
const acceptedFileData = fileReader(acceptedFile);
|
||||
acceptedFileData.then((data) => {
|
||||
if (fileData.length < parsedMaxFileCount) {
|
||||
if (fileData.length < maxFileCount) {
|
||||
fileData.push(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onEvent('onFileSelected', filePickerEvents, { component })
|
||||
fireEvent('onFileSelected', id, 'canvas', { component })
|
||||
.then(() => {
|
||||
setAccepted(true);
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
@ -256,15 +247,17 @@ export const FilePicker = ({
|
|||
setTimeout(() => {
|
||||
setShowSelectedFiles(true);
|
||||
setAccepted(false);
|
||||
onComponentOptionChanged(component, 'isParsing', false, id);
|
||||
setExposedVariable('isParsing', false);
|
||||
// onComponentOptionChanged(component, 'isParsing', false, id);
|
||||
resolve();
|
||||
}, 600);
|
||||
});
|
||||
})
|
||||
.then(() => onEvent('onFileLoaded', filePickerEvents, { component }))
|
||||
.then(() => fireEvent('onFileLoaded', id, 'canvas', { component }))
|
||||
.then(() => {
|
||||
setSelectedFiles(fileData);
|
||||
onComponentOptionChanged(component, 'file', fileData, id);
|
||||
setExposedVariable('file', fileData);
|
||||
// onComponentOptionChanged(component, 'file', fileData, id);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -288,20 +281,32 @@ export const FilePicker = ({
|
|||
copy.splice(index, 1);
|
||||
return copy;
|
||||
});
|
||||
onEvent('onFileDeselected', filePickerEvents);
|
||||
fireEvent('onFileDeselected', id);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
isInitialRender.current = false;
|
||||
if (selectedFiles.length === 0) {
|
||||
setShowSelectedFiles(false);
|
||||
}
|
||||
onComponentOptionChanged(component, 'file', selectedFiles, id);
|
||||
setExposedVariable('clearFiles', async function () {
|
||||
setSelectedFiles([]);
|
||||
});
|
||||
setExposedVariable('file', selectedFiles);
|
||||
// onComponentOptionChanged(component, 'file', selectedFiles, id);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedFiles]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
clearFiles: async function () {
|
||||
setSelectedFiles([]);
|
||||
},
|
||||
file: [],
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
setShowSelectedFiles(false);
|
||||
isInitialRender.current = false;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section>
|
||||
<div className="container" {...getRootProps({ style, className: 'dropzone' })} data-cy={dataCy}>
|
||||
|
|
@ -342,12 +347,12 @@ export const FilePicker = ({
|
|||
)}
|
||||
|
||||
<FilePicker.Signifiers
|
||||
signifier={isDragAccept && !(selectedFiles.length === parsedMaxFileCount)}
|
||||
signifier={isDragAccept && !(selectedFiles.length === maxFileCount)}
|
||||
feedback={'All files will be accepted'}
|
||||
cls="text-lime mt-3"
|
||||
/>
|
||||
<FilePicker.Signifiers
|
||||
signifier={isDragAccept && selectedFiles.length === parsedMaxFileCount}
|
||||
signifier={isDragAccept && selectedFiles.length === maxFileCount}
|
||||
feedback={'Max file reached!'}
|
||||
cls="text-red mt-3"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ export const Form = function Form(props) {
|
|||
fireEvent('onInvalid');
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
|
|
@ -112,7 +111,7 @@ export const Form = function Form(props) {
|
|||
}, [advanced]);
|
||||
|
||||
useEffect(() => {
|
||||
setUIComponents(generateUIComponents(JSONSchema, advanced));
|
||||
setUIComponents(generateUIComponents(JSONSchema, advanced, component.name));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(JSONSchema), advanced]);
|
||||
|
||||
|
|
@ -142,7 +141,8 @@ export const Form = function Form(props) {
|
|||
} else {
|
||||
Object.keys(childComponents ?? {}).forEach((childId) => {
|
||||
if (childrenData[childId]?.name) {
|
||||
formattedChildData[childrenData[childId].name] = { ...omit(childrenData[childId], 'name'), id: childId };
|
||||
const componentName = childComponents?.[childId]?.component?.name;
|
||||
formattedChildData[componentName] = { ...omit(childrenData[childId], 'name'), id: childId };
|
||||
childValidation = childValidation && (childrenData[childId]?.isValid ?? true);
|
||||
}
|
||||
});
|
||||
|
|
@ -247,7 +247,7 @@ export const Form = function Form(props) {
|
|||
) : (
|
||||
<fieldset disabled={disabledState}>
|
||||
{!advanced && (
|
||||
<>
|
||||
<div className={'json-form-wrapper-disabled'}>
|
||||
<SubContainer
|
||||
parentComponent={component}
|
||||
containerCanvasWidth={width}
|
||||
|
|
@ -270,7 +270,7 @@ export const Form = function Form(props) {
|
|||
parentRef={parentRef}
|
||||
currentLayout={currentLayout}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
{advanced &&
|
||||
uiComponents?.map((item, index) => {
|
||||
|
|
@ -287,8 +287,8 @@ export const Form = function Form(props) {
|
|||
'ToggleSwitch',
|
||||
'ToggleSwitchV2',
|
||||
].includes(uiComponents?.[index + 1]?.component)
|
||||
? `json-form-wrapper`
|
||||
: `json-form-wrapper form-label-restricted`
|
||||
? `json-form-wrapper json-form-wrapper-disabled`
|
||||
: `json-form-wrapper json-form-wrapper-disabled form-label-restricted`
|
||||
}
|
||||
key={index}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { componentTypes } from '@/Editor/WidgetManager/components';
|
||||
export function generateUIComponents(JSONSchema, advanced) {
|
||||
import { useCurrentStateStore } from '@/_stores/currentStateStore';
|
||||
|
||||
export function generateUIComponents(JSONSchema, advanced, componentName) {
|
||||
if (advanced) {
|
||||
if (typeof JSONSchema?.properties !== 'object' || JSONSchema?.properties == null) {
|
||||
return;
|
||||
|
|
@ -11,6 +13,17 @@ export function generateUIComponents(JSONSchema, advanced) {
|
|||
if (itemType) {
|
||||
uiComponentsDraft.push(structuredClone(componentTypes.find((component) => component?.component == 'Text')));
|
||||
//only add if there is a valid item type
|
||||
} else {
|
||||
useCurrentStateStore.getState().actions.setErrors({
|
||||
[componentName]: {
|
||||
type: 'component',
|
||||
data: {
|
||||
message: `JSON Schema consists of invalid input type: ${value?.type}`,
|
||||
status: 'Failed',
|
||||
},
|
||||
},
|
||||
});
|
||||
uiComponentsDraft.push(undefined);
|
||||
}
|
||||
uiComponentsDraft.push(structuredClone(componentTypes.find((component) => component?.component == itemType)));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,24 +3,11 @@ import React, { useState, useEffect } from 'react';
|
|||
import * as Icons from '@tabler/icons-react';
|
||||
import cx from 'classnames';
|
||||
|
||||
export const Icon = ({
|
||||
properties,
|
||||
styles,
|
||||
fireEvent,
|
||||
width,
|
||||
height,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
darkMode,
|
||||
dataCy,
|
||||
component,
|
||||
}) => {
|
||||
export const Icon = ({ properties, styles, fireEvent, width, height, setExposedVariables, darkMode, dataCy }) => {
|
||||
const { icon } = properties;
|
||||
const { iconColor, visibility, boxShadow } = styles;
|
||||
// eslint-disable-next-line import/namespace
|
||||
const IconElement = Icons[icon];
|
||||
const { definition } = component;
|
||||
const { events = [] } = definition;
|
||||
|
||||
const color = iconColor === '#000' ? (darkMode ? '#fff' : '#000') : iconColor;
|
||||
|
||||
|
|
@ -42,13 +29,10 @@ export const Icon = ({
|
|||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setIconVisibility]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx('icon-widget', { 'd-none': !showIcon }, { 'cursor-pointer': events.length > 0 })}
|
||||
data-cy={dataCy}
|
||||
>
|
||||
<div className={cx('icon-widget', { 'd-none': !showIcon }, { 'cursor-pointer': false })} data-cy={dataCy}>
|
||||
<IconElement
|
||||
color={color}
|
||||
style={{ width, height, boxShadow, color: iconColor }}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import LazyLoad, { forceCheck } from 'react-lazyload';
|
|||
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch';
|
||||
|
||||
export const Image = function Image({
|
||||
component,
|
||||
componentName,
|
||||
height,
|
||||
properties,
|
||||
styles,
|
||||
|
|
@ -15,10 +15,7 @@ export const Image = function Image({
|
|||
}) {
|
||||
const { source, loadingState, alternativeText, zoomButtons, rotateButton } = properties;
|
||||
const { visibility, disabledState, borderType, backgroundColor, padding, imageFit, boxShadow } = styles;
|
||||
const {
|
||||
definition: { events },
|
||||
} = component;
|
||||
const hasOnClickEvent = events.some((event) => event.eventId === 'onClick');
|
||||
const hasOnClickEvent = false;
|
||||
const widgetVisibility = visibility ?? true;
|
||||
const imageRef = useRef(null);
|
||||
const [imageOffset, setImageOffset] = useState(0);
|
||||
|
|
@ -130,7 +127,7 @@ export const Image = function Image({
|
|||
return (
|
||||
<div
|
||||
data-disabled={disabledState}
|
||||
data-cy={`draggable-widget-${String(component.name).toLowerCase()}`}
|
||||
data-cy={`draggable-widget-${String(componentName).toLowerCase()}`}
|
||||
style={{
|
||||
display: widgetVisibility ? 'flex' : 'none',
|
||||
justifyContent: 'center',
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import React, { useRef } from 'react';
|
||||
import { default as BootstrapModal } from 'react-bootstrap/Modal';
|
||||
import { SubContainer } from '@/Editor/SubContainer';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import '@/_styles/widgets/kanban.scss';
|
||||
|
||||
export const Modal = function Modal({ showModal, setShowModal, kanbanProps }) {
|
||||
const parentRef = useRef(null);
|
||||
const { id, containerProps, exposedVariables, component } = kanbanProps;
|
||||
const exposedVariables = useStore((state) => state.getExposedValueOfComponent(kanbanProps.id), shallow);
|
||||
const { id, containerProps, component } = kanbanProps;
|
||||
|
||||
const renderCloseButton = () => {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -106,6 +106,16 @@ export const Listview = function Listview({
|
|||
);
|
||||
const filteredData = deepClone(childrenData);
|
||||
if (filteredData?.[0]) {
|
||||
// update the name of the component in the data
|
||||
Object.keys(filteredData?.[0]).forEach((item) => {
|
||||
const { id } = _.get(filteredData?.[0], item, {});
|
||||
const oldName = item;
|
||||
const newName = _.get(childComponents, `${id}.component.name`, '');
|
||||
if (oldName !== newName) {
|
||||
_.set(filteredData[0], newName, _.get(filteredData[0], oldName));
|
||||
_.unset(filteredData[0], oldName);
|
||||
}
|
||||
});
|
||||
Object.keys(filteredData?.[0]).forEach((item) => {
|
||||
if (!componentNamesSet?.has(item)) {
|
||||
for (const key in filteredData) {
|
||||
|
|
@ -173,13 +183,17 @@ export const Listview = function Listview({
|
|||
removeComponent={removeComponent}
|
||||
listViewItemOptions={{ index }}
|
||||
exposedVariables={childrenData[index]}
|
||||
onOptionChange={function ({ component, optionName, value }) {
|
||||
onOptionChange={function ({ component, optionName, value, componentId }) {
|
||||
setChildrenData((prevData) => {
|
||||
const changedData = { [component.name]: { [optionName]: value } };
|
||||
const existingDataAtIndex = prevData[index] ?? {};
|
||||
const newDataAtIndex = {
|
||||
...prevData[index],
|
||||
[component.name]: { ...existingDataAtIndex[component.name], ...changedData[component.name] },
|
||||
[component.name]: {
|
||||
...existingDataAtIndex[component.name],
|
||||
...changedData[component.name],
|
||||
id: componentId,
|
||||
},
|
||||
};
|
||||
const newChildrenData = { ...prevData, [index]: newDataAtIndex };
|
||||
return { ...prevData, ...newChildrenData };
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import React, { useState, useCallback, useEffect } from 'react';
|
||||
import React, { useState, useCallback, useEffect, useRef } from 'react';
|
||||
import { GoogleMap, LoadScript, Marker, Autocomplete, Polygon } from '@react-google-maps/api';
|
||||
import { resolveWidgetFieldValue } from '@/_helpers/utils';
|
||||
import { darkModeStyles } from './styles';
|
||||
|
|
@ -9,32 +9,30 @@ export const Map = function Map({
|
|||
id,
|
||||
width,
|
||||
height,
|
||||
component,
|
||||
darkMode,
|
||||
onComponentClick,
|
||||
onComponentOptionChanged,
|
||||
onComponentOptionsChanged,
|
||||
onComponentClick = () => {},
|
||||
onComponentOptionChanged = () => {},
|
||||
onComponentOptionsChanged = () => {},
|
||||
styles,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
dataCy,
|
||||
properties,
|
||||
fireEvent,
|
||||
}) {
|
||||
const center = component.definition.properties.initialLocation.value;
|
||||
const isInitialRender = useRef(true);
|
||||
const center = properties?.initialLocation ?? { lat: 0, lng: 0 };
|
||||
const { polygonPoints = [], defaultMarkers = [] } = properties;
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const addNewMarkersProp = component.definition.properties.addNewMarkers;
|
||||
const canAddNewMarkers = addNewMarkersProp ? resolveWidgetFieldValue(addNewMarkersProp.value) : false;
|
||||
const canAddNewMarkers = properties?.addNewMarkers ?? false;
|
||||
const canSearch = properties?.canSearch ?? false;
|
||||
const widgetVisibility = styles?.visibility ?? true;
|
||||
const disabledState = styles?.disabledState ?? false;
|
||||
|
||||
const canSearchProp = component.definition.properties.canSearch;
|
||||
const canSearch = canSearchProp ? resolveWidgetFieldValue(canSearchProp.value) : false;
|
||||
const widgetVisibility = component.definition.styles?.visibility?.value ?? true;
|
||||
const disabledState = component.definition.styles?.disabledState?.value ?? false;
|
||||
|
||||
const parsedDisabledState =
|
||||
typeof disabledState !== 'boolean' ? resolveWidgetFieldValue(disabledState) : disabledState;
|
||||
// const parsedDisabledState =
|
||||
// typeof disabledState !== 'boolean' ? resolveWidgetFieldValue(disabledState) : disabledState;
|
||||
|
||||
let parsedWidgetVisibility = widgetVisibility;
|
||||
|
||||
|
|
@ -58,6 +56,16 @@ export const Map = function Map({
|
|||
setMarkers(defaultMarkers);
|
||||
}, [JSON.stringify(defaultMarkers)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('center', center);
|
||||
}, [center]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('markers', defaultMarkers);
|
||||
}, [defaultMarkers]);
|
||||
|
||||
function handleMapClick(e) {
|
||||
if (!canAddNewMarkers) {
|
||||
return;
|
||||
|
|
@ -66,11 +74,12 @@ export const Map = function Map({
|
|||
const lat = e.latLng.lat();
|
||||
const lng = e.latLng.lng();
|
||||
|
||||
const newMarkers = markers;
|
||||
const newMarkers = [...markers];
|
||||
newMarkers.push({ lat, lng });
|
||||
setMarkers(newMarkers);
|
||||
|
||||
onComponentOptionChanged(component, 'markers', newMarkers).then(() => fireEvent('onCreateMarker'));
|
||||
setExposedVariable('markers', newMarkers);
|
||||
fireEvent('onCreateMarker');
|
||||
// onComponentOptionChanged(component, 'markers', newMarkers).then(() => fireEvent('onCreateMarker'));
|
||||
}
|
||||
|
||||
function addMapUrlToJson(centerJson) {
|
||||
|
|
@ -88,17 +97,24 @@ export const Map = function Map({
|
|||
|
||||
const newCenter = gmap.center?.toJSON();
|
||||
setMapCenter(newCenter);
|
||||
|
||||
onComponentOptionsChanged(component, [
|
||||
['bounds', bounds],
|
||||
['center', addMapUrlToJson(newCenter)],
|
||||
]).then(() => fireEvent('onBoundsChange'));
|
||||
const exposedVariables = {
|
||||
bounds,
|
||||
center: addMapUrlToJson(newCenter),
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
fireEvent('onBoundsChange');
|
||||
// onComponentOptionsChanged(component, [
|
||||
// ['bounds', bounds],
|
||||
// ['center', addMapUrlToJson(newCenter)],
|
||||
// ]).then(() => fireEvent('onBoundsChange'));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
const resolvedCenter = resolveWidgetFieldValue(center);
|
||||
setMapCenter(resolvedCenter);
|
||||
onComponentOptionsChanged(component, [['center', addMapUrlToJson(resolvedCenter)]]);
|
||||
setExposedVariable('center', addMapUrlToJson(resolvedCenter));
|
||||
// onComponentOptionsChanged(component, [['center', addMapUrlToJson(resolvedCenter)]]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [center]);
|
||||
|
||||
|
|
@ -106,11 +122,14 @@ export const Map = function Map({
|
|||
const onLoad = useCallback(function onLoad(mapInstance) {
|
||||
setGmap(mapInstance);
|
||||
const centerJson = mapInstance.center?.toJSON();
|
||||
onComponentOptionsChanged(component, [['center', addMapUrlToJson(centerJson)]]);
|
||||
setExposedVariable('center', addMapUrlToJson(centerJson));
|
||||
// onComponentOptionsChanged(component, [['center', addMapUrlToJson(centerJson)]]);
|
||||
});
|
||||
|
||||
function handleMarkerClick(index) {
|
||||
onComponentOptionChanged(component, 'selectedMarker', markers[index]).then(() => fireEvent('onMarkerClick'));
|
||||
setExposedVariable('selectedMarker', markers[index]);
|
||||
fireEvent('onMarkerClick');
|
||||
// onComponentOptionChanged(component, 'selectedMarker', markers[index]).then(() => fireEvent('onMarkerClick'));
|
||||
}
|
||||
|
||||
function onPlaceChanged() {
|
||||
|
|
@ -124,18 +143,27 @@ export const Map = function Map({
|
|||
}
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setLocation', async function (lat, lng) {
|
||||
if (lat && lng) setMapCenter(resolveWidgetFieldValue({ lat, lng }));
|
||||
});
|
||||
}, [setMapCenter]);
|
||||
const resolvedCenter = resolveWidgetFieldValue(center);
|
||||
const exposedVariables = {
|
||||
setLocation: async function (lat, lng) {
|
||||
if (lat && lng) setMapCenter(resolveWidgetFieldValue({ lat, lng }));
|
||||
},
|
||||
center: addMapUrlToJson(resolvedCenter),
|
||||
markers: defaultMarkers,
|
||||
};
|
||||
|
||||
setMapCenter(resolvedCenter);
|
||||
setExposedVariables(exposedVariables);
|
||||
isInitialRender.current = false;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
data-disabled={parsedDisabledState}
|
||||
data-disabled={disabledState}
|
||||
style={{ height, display: parsedWidgetVisibility ? '' : 'none', boxShadow: styles.boxShadow }}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onComponentClick(id, component, event);
|
||||
onComponentClick(id);
|
||||
}}
|
||||
className="map-widget"
|
||||
data-cy={dataCy}
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ export const Modal = function Modal({
|
|||
const parentRef = useRef(null);
|
||||
const controlBoxRef = useRef(null);
|
||||
const isInitialRender = useRef(true);
|
||||
|
||||
const title = properties.title ?? '';
|
||||
const titleAlignment = properties.titleAlignment ?? 'left';
|
||||
const size = properties.size ?? 'lg';
|
||||
|
||||
/**** Start - Logic to reset the zIndex of modal control box ****/
|
||||
|
|
@ -251,6 +251,7 @@ export const Modal = function Modal({
|
|||
parentRef,
|
||||
id,
|
||||
title,
|
||||
titleAlignment,
|
||||
hideTitleBar,
|
||||
hideCloseButton,
|
||||
hideModal,
|
||||
|
|
@ -288,6 +289,7 @@ const Component = ({ children, ...restProps }) => {
|
|||
parentRef,
|
||||
id,
|
||||
title,
|
||||
titleAlignment,
|
||||
hideTitleBar,
|
||||
hideCloseButton,
|
||||
hideModal,
|
||||
|
|
@ -310,7 +312,14 @@ const Component = ({ children, ...restProps }) => {
|
|||
)}
|
||||
{!hideTitleBar && (
|
||||
<BootstrapModal.Header style={{ ...customStyles.modalHeader }} data-cy={`modal-header`}>
|
||||
<BootstrapModal.Title id="contained-modal-title-vcenter" data-cy={`modal-title`}>
|
||||
<BootstrapModal.Title
|
||||
style={{
|
||||
textAlign: titleAlignment,
|
||||
width: '100%',
|
||||
}}
|
||||
id="contained-modal-title-vcenter"
|
||||
data-cy={`modal-title`}
|
||||
>
|
||||
{title}
|
||||
</BootstrapModal.Title>
|
||||
{!hideCloseButton && (
|
||||
|
|
|
|||
|
|
@ -25,23 +25,21 @@ const DropdownIndicator = ({ isOpen, toggleDropdown }) => {
|
|||
|
||||
export const Multiselect = function Multiselect({
|
||||
id,
|
||||
component,
|
||||
height,
|
||||
properties,
|
||||
styles,
|
||||
exposedVariables,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
onComponentClick,
|
||||
darkMode,
|
||||
fireEvent,
|
||||
componentName,
|
||||
dataCy,
|
||||
}) {
|
||||
const { label, value, values, display_values, showAllOption } = properties;
|
||||
const { borderRadius, visibility, disabledState, boxShadow } = styles;
|
||||
const [selected, setSelected] = useState([]);
|
||||
const [searched, setSearched] = useState('');
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
let selectOptions = [];
|
||||
try {
|
||||
|
|
@ -54,40 +52,15 @@ export const Multiselect = function Multiselect({
|
|||
console.log(err);
|
||||
}
|
||||
|
||||
const handleDropdownOpen = () => {
|
||||
setIsOpen(true);
|
||||
};
|
||||
// useEffect(() => {
|
||||
// let newValues = [];
|
||||
|
||||
const handleDropdownClose = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
// if (_.intersection(values, value)?.length === value?.length) newValues = value;
|
||||
|
||||
const toggleDropdown = () => {
|
||||
setIsOpen((prevState) => !prevState);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (isOpen && !event.target.closest('.multiselect-widget')) {
|
||||
handleDropdownClose();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
};
|
||||
}, [isOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
let newValues = [];
|
||||
|
||||
if (_.intersection(values, value)?.length === value?.length) newValues = value;
|
||||
|
||||
setExposedVariable('values', newValues);
|
||||
setSelected(selectOptions.filter((option) => newValues.includes(option.value)));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(values), JSON.stringify(display_values)]);
|
||||
// setExposedVariable('values', newValues);
|
||||
// setSelected(selectOptions.filter((option) => newValues.includes(option.value)));
|
||||
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// }, [JSON.stringify(values), JSON.stringify(display_values)]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('values', value);
|
||||
|
|
@ -96,14 +69,9 @@ export const Multiselect = function Multiselect({
|
|||
}, [JSON.stringify(value), JSON.stringify(display_values)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (value && !selected) {
|
||||
if (value) {
|
||||
setSelected(selectOptions.filter((option) => properties.value.includes(option.value)));
|
||||
}
|
||||
|
||||
if (JSON.stringify(exposedVariables.values) === '{}') {
|
||||
setSelected(selectOptions.filter((option) => properties.value.includes(option.value)));
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const onChangeHandler = (items) => {
|
||||
|
|
@ -189,14 +157,14 @@ export const Multiselect = function Multiselect({
|
|||
style={{ height, display: visibility ? '' : 'none' }}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onComponentClick(id, component, event);
|
||||
onComponentClick(id);
|
||||
}}
|
||||
>
|
||||
<div className="col-auto my-auto d-flex align-items-center">
|
||||
<label
|
||||
style={{ marginRight: label ? '1rem' : '', marginBottom: 0 }}
|
||||
className={`form-label py-1 ${darkMode ? 'text-light' : 'text-secondary'}`}
|
||||
data-cy={`multiselect-label-${component.name.toLowerCase()}`}
|
||||
data-cy={`multiselect-label-${componentName.toLowerCase()}`}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
|
|
@ -213,22 +181,34 @@ export const Multiselect = function Multiselect({
|
|||
ItemRenderer={ItemRenderer}
|
||||
filterOptions={filterOptions}
|
||||
debounceDuration={0}
|
||||
isOpen={isOpen}
|
||||
onMenuOpen={handleDropdownOpen}
|
||||
onMenuClose={handleDropdownClose}
|
||||
ArrowRenderer={() => <DropdownIndicator isOpen={isOpen} toggleDropdown={toggleDropdown} />}
|
||||
// isOpen={isOpen}
|
||||
// onMenuOpen={handleDropdownOpen}
|
||||
// onMenuClose={handleDropdownClose}
|
||||
// ArrowRenderer={() => <DropdownIndicator isOpen={isOpen} toggleDropdown={toggleDropdown} />}
|
||||
onMenuToggle={(isOpen) => {
|
||||
/*
|
||||
This is a hack added so that elememt shows up above the other sibling elements.
|
||||
This is needed since dropdown is added attached to the widget itself and not the body.
|
||||
*/
|
||||
if (!document.querySelector(`.ele-${id}`)) {
|
||||
return;
|
||||
}
|
||||
if (isOpen) {
|
||||
document.querySelector(`.ele-${id}`).style.zIndex = 3;
|
||||
// get all instances to handle for listview
|
||||
const elements = document.querySelectorAll(`[id='${id}']`) || [];
|
||||
elements.forEach((element) => {
|
||||
// check if dropdown is open and set z-index
|
||||
const child = element.querySelector(`.dropdown-container`);
|
||||
if (child && child.hasAttribute('aria-expanded') && child.getAttribute('aria-expanded') === 'true') {
|
||||
const listViewParent = child?.closest('.list-item');
|
||||
if (listViewParent) listViewParent.style.zIndex = 1;
|
||||
element.style.zIndex = 3;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
document.querySelector(`.ele-${id}`).style.zIndex = '';
|
||||
const elements = document.querySelectorAll(`[id='${id}']`) || [];
|
||||
elements.forEach((element) => {
|
||||
// check if dropdown is open and unset z-index
|
||||
const child = element.querySelector(`.dropdown-container`);
|
||||
if (child && child.hasAttribute('aria-expanded') && child.getAttribute('aria-expanded') === 'false') {
|
||||
const listViewParent = child?.closest('.list-item');
|
||||
if (listViewParent) listViewParent.style.zIndex = '';
|
||||
element.style.zIndex = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { resolveReferences } from '@/_helpers/utils';
|
||||
import { useCurrentState } from '@/_stores/currentStateStore';
|
||||
import _, { has, isEmpty, isObject } from 'lodash';
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import _, { has, isObject } from 'lodash';
|
||||
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
||||
import Select from 'react-select';
|
||||
import './multiselectV2.scss';
|
||||
import CustomMenuList from '../DropdownV2/CustomMenuList';
|
||||
|
|
@ -14,10 +12,11 @@ import Label from '@/_ui/Label';
|
|||
const tinycolor = require('tinycolor2');
|
||||
import { CustomDropdownIndicator, CustomClearIndicator } from '../DropdownV2/DropdownV2';
|
||||
import { getInputBackgroundColor, getInputBorderColor, getInputFocusedColor } from '../DropdownV2/utils';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
export const MultiselectV2 = ({
|
||||
id,
|
||||
component,
|
||||
height,
|
||||
properties,
|
||||
styles,
|
||||
|
|
@ -27,6 +26,8 @@ export const MultiselectV2 = ({
|
|||
darkMode,
|
||||
fireEvent,
|
||||
validate,
|
||||
validation,
|
||||
componentName,
|
||||
width,
|
||||
}) => {
|
||||
let {
|
||||
|
|
@ -57,11 +58,11 @@ export const MultiselectV2 = ({
|
|||
padding,
|
||||
accentColor,
|
||||
} = styles;
|
||||
const isInitialRender = useRef(true);
|
||||
const [selected, setSelected] = useState([]);
|
||||
const currentState = useCurrentState();
|
||||
const isMandatory = resolveReferences(component?.definition?.validation?.mandatory?.value, currentState);
|
||||
const options = component?.definition?.properties?.options?.value;
|
||||
const values = component?.definition?.properties?.values?.value;
|
||||
const options = properties?.options;
|
||||
const values = properties?.values;
|
||||
const isMandatory = validation?.mandatory ?? false;
|
||||
const multiselectRef = React.useRef(null);
|
||||
const labelRef = React.useRef(null);
|
||||
const validationData = validate(selected?.length ? selected?.map((option) => option.value) : null);
|
||||
|
|
@ -69,6 +70,7 @@ export const MultiselectV2 = ({
|
|||
const valueContainerRef = React.useRef(null);
|
||||
const [visibility, setVisibility] = useState(properties.visibility);
|
||||
const [isMultiSelectLoading, setIsMultiSelectLoading] = useState(multiSelectLoadingState);
|
||||
const getResolvedValue = useStore((state) => state.getResolvedValue, shallow);
|
||||
const [isMultiSelectDisabled, setIsMultiSelectDisabled] = useState(disabledState);
|
||||
const [isSelectAllSelected, setIsSelectAllSelected] = useState(false);
|
||||
const [searchInputValue, setSearchInputValue] = useState('');
|
||||
|
|
@ -87,12 +89,12 @@ export const MultiselectV2 = ({
|
|||
const _options = advanced ? schema : options;
|
||||
let _selectOptions = Array.isArray(_options)
|
||||
? _options
|
||||
.filter((data) => resolveReferences(advanced ? data?.visible : data?.visible?.value, currentState))
|
||||
.filter((data) => getResolvedValue(advanced ? data?.visible : data?.visible?.value) ?? true)
|
||||
.map((data) => ({
|
||||
...data,
|
||||
label: resolveReferences(data?.label, currentState),
|
||||
value: resolveReferences(data?.value, currentState),
|
||||
isDisabled: resolveReferences(advanced ? data?.disable : data?.disable?.value, currentState),
|
||||
label: getResolvedValue(data?.label),
|
||||
value: getResolvedValue(data?.value),
|
||||
isDisabled: getResolvedValue(advanced ? data?.disable : data?.disable?.value) ?? false,
|
||||
}))
|
||||
: [];
|
||||
return _selectOptions;
|
||||
|
|
@ -126,6 +128,10 @@ export const MultiselectV2 = ({
|
|||
const onChangeHandler = (items, action) => {
|
||||
setSelected(items);
|
||||
if (action.action === 'select-option') {
|
||||
setExposedVariable(
|
||||
'values',
|
||||
items.map((item) => item.value)
|
||||
);
|
||||
fireEvent('onSelect');
|
||||
}
|
||||
};
|
||||
|
|
@ -142,6 +148,7 @@ export const MultiselectV2 = ({
|
|||
}, [advanced, JSON.stringify(schema), JSON.stringify(values)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable(
|
||||
'selectedOptions',
|
||||
Array.isArray(selected) && selected?.map(({ label, value }) => ({ label, value }))
|
||||
|
|
@ -154,15 +161,34 @@ export const MultiselectV2 = ({
|
|||
}, [JSON.stringify(selected), selectOptions]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('label', label);
|
||||
setExposedVariable('isVisible', properties.visibility);
|
||||
setExposedVariable('isLoading', multiSelectLoadingState);
|
||||
setExposedVariable('isDisabled', disabledState);
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
setExposedVariable('isValid', isValid);
|
||||
}, [label]);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [label, properties.visibility, multiSelectLoadingState, disabledState, isMandatory, isValid]);
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isVisible', properties.visibility);
|
||||
}, [properties.visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isLoading', multiSelectLoadingState);
|
||||
}, [multiSelectLoadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isDisabled', disabledState);
|
||||
}, [disabledState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isValid', isValid);
|
||||
}, [isValid]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
|
|
@ -178,8 +204,17 @@ export const MultiselectV2 = ({
|
|||
setDisable: async function (value) {
|
||||
setIsMultiSelectDisabled(value);
|
||||
},
|
||||
label: label,
|
||||
isVisible: properties.visibility,
|
||||
isLoading: multiSelectLoadingState,
|
||||
isDisabled: disabledState,
|
||||
isMandatory: isMandatory,
|
||||
isValid: isValid,
|
||||
selectedOptions: Array.isArray(selected) && selected?.map(({ label, value }) => ({ label, value })),
|
||||
options: Array.isArray(selectOptions) && selectOptions?.map(({ label, value }) => ({ label, value })),
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
isInitialRender.current = false;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -216,7 +251,7 @@ export const MultiselectV2 = ({
|
|||
}
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectOptions, selected, setSelected]);
|
||||
}, [selectOptions, selected]);
|
||||
|
||||
const onSearchTextChange = (searchText, actionProps) => {
|
||||
if (actionProps.action === 'input-change') {
|
||||
|
|
@ -370,7 +405,7 @@ export const MultiselectV2 = ({
|
|||
<>
|
||||
<div
|
||||
ref={multiselectRef}
|
||||
data-cy={`label-${String(component.name).toLowerCase()} `}
|
||||
data-cy={`label-${String(componentName).toLowerCase()} `}
|
||||
className={cx('multiselect-widget', 'd-flex', {
|
||||
[alignment === 'top' &&
|
||||
((labelWidth != 0 && label?.length != 0) || (auto && labelWidth == 0 && label && label?.length != 0))
|
||||
|
|
@ -387,7 +422,7 @@ export const MultiselectV2 = ({
|
|||
width: '100%',
|
||||
}}
|
||||
onMouseDown={(event) => {
|
||||
onComponentClick(id, component, event);
|
||||
onComponentClick(id);
|
||||
// This following line is needed because sometimes after clicking on canvas then also dropdown remains selected
|
||||
useEditorStore.getState().actions.setHoveredComponent('');
|
||||
}}
|
||||
|
|
@ -451,7 +486,7 @@ export const MultiselectV2 = ({
|
|||
setIsSelectAllSelected={setIsSelectAllSelected}
|
||||
setSelected={setSelected}
|
||||
iconColor={iconColor}
|
||||
optionsLoadingState={optionsLoadingState}
|
||||
optionsLoadingState={optionsLoadingState && advanced}
|
||||
darkMode={darkMode}
|
||||
fireEvent={() => fireEvent('onSelect')}
|
||||
menuPlacement="auto"
|
||||
|
|
|
|||
|
|
@ -3,24 +3,28 @@ import './numberinput.scss';
|
|||
import SolidIcon from '@/_ui/Icon/SolidIcons';
|
||||
import * as Icons from '@tabler/icons-react';
|
||||
import Loader from '@/ToolJetUI/Loader/Loader';
|
||||
import { resolveWidgetFieldValue } from '@/_helpers/utils';
|
||||
|
||||
const tinycolor = require('tinycolor2');
|
||||
import Label from '@/_ui/Label';
|
||||
import { useGridStore } from '@/_stores/gridStore';
|
||||
|
||||
export const NumberInput = function NumberInput({
|
||||
id,
|
||||
height,
|
||||
properties,
|
||||
validate,
|
||||
styles,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
fireEvent,
|
||||
component,
|
||||
darkMode,
|
||||
dataCy,
|
||||
isResizing,
|
||||
validation,
|
||||
componentName,
|
||||
}) {
|
||||
const isInitialRender = useRef(true);
|
||||
const { loadingState, disabledState, label, placeholder } = properties;
|
||||
const isResizing = useGridStore((state) => state.resizingComponentId === id);
|
||||
const {
|
||||
padding,
|
||||
borderRadius,
|
||||
|
|
@ -38,10 +42,9 @@ export const NumberInput = function NumberInput({
|
|||
} = styles;
|
||||
|
||||
const textColor = darkMode && ['#232e3c', '#000000ff'].includes(styles.textColor) ? '#CFD3D8' : styles.textColor;
|
||||
const isMandatory = resolveWidgetFieldValue(component?.definition?.validation?.mandatory?.value) ?? false;
|
||||
const minValue = resolveWidgetFieldValue(component?.definition?.validation?.minValue?.value) ?? null;
|
||||
const maxValue = resolveWidgetFieldValue(component?.definition?.validation?.maxValue?.value) ?? null;
|
||||
|
||||
const isMandatory = validation?.mandatory ?? false;
|
||||
const minValue = validation?.minValue ?? null;
|
||||
const maxValue = validation?.maxValue ?? null;
|
||||
const [visibility, setVisibility] = useState(properties.visibility);
|
||||
const [loading, setLoading] = useState(loadingState);
|
||||
const [showValidationError, setShowValidationError] = useState(false);
|
||||
|
|
@ -56,6 +59,7 @@ export const NumberInput = function NumberInput({
|
|||
const _width = (width / 100) * 70; // Max width which label can go is 70% for better UX calculate width based on this value
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('label', label);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [label]);
|
||||
|
|
@ -79,6 +83,7 @@ export const NumberInput = function NumberInput({
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
if (!isNaN(value)) {
|
||||
setExposedVariable('value', value);
|
||||
}
|
||||
|
|
@ -86,54 +91,103 @@ export const NumberInput = function NumberInput({
|
|||
}, [value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isLoading', loading);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loading]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setLoading', async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isVisible', visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setVisibility', async function (state) {
|
||||
setVisibility(state);
|
||||
setExposedVariable('isVisible', state);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setDisable', async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disabledState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isDisabled', disable);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isValid', isValid);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isValid]);
|
||||
|
||||
useEffect(() => {
|
||||
disable !== disabledState && setDisable(disabledState);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disabledState]);
|
||||
useEffect(() => {
|
||||
visibility !== properties.visibility && setVisibility(properties.visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility]);
|
||||
useEffect(() => {
|
||||
loading !== loadingState && setLoading(loadingState);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
setFocus: async function () {
|
||||
inputRef.current.focus();
|
||||
},
|
||||
setBlur: async function () {
|
||||
inputRef.current.blur();
|
||||
},
|
||||
setText: async function (text) {
|
||||
if (text) {
|
||||
const newValue = Number(parseFloat(text));
|
||||
setValue(newValue);
|
||||
setExposedVariable('value', text);
|
||||
fireEvent('onChange');
|
||||
}
|
||||
},
|
||||
clear: async function () {
|
||||
setValue('');
|
||||
setExposedVariable('value', '');
|
||||
fireEvent('onChange');
|
||||
},
|
||||
setLoading: async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
},
|
||||
setVisibility: async function (state) {
|
||||
setVisibility(state);
|
||||
setExposedVariable('isVisible', state);
|
||||
},
|
||||
setDisable: async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
},
|
||||
label: label,
|
||||
isMandatory: isMandatory,
|
||||
isLoading: loading,
|
||||
isVisible: visibility,
|
||||
isDisabled: disable,
|
||||
isValid: isValid,
|
||||
};
|
||||
if (!isNaN(value)) {
|
||||
exposedVariables.value = value;
|
||||
}
|
||||
setExposedVariables(exposedVariables);
|
||||
|
||||
isInitialRender.current = false;
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (labelRef?.current) {
|
||||
const absolutewidth = labelRef?.current?.getBoundingClientRect()?.width;
|
||||
setLabelWidth(absolutewidth);
|
||||
} else setLabelWidth(0);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
isResizing,
|
||||
|
|
@ -148,11 +202,6 @@ export const NumberInput = function NumberInput({
|
|||
alignment,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isValid', isValid);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isValid]);
|
||||
|
||||
const computedStyles = {
|
||||
height: height == 36 ? (padding == 'default' ? '36px' : '40px') : padding == 'default' ? height : height + 4,
|
||||
borderRadius: `${borderRadius}px`,
|
||||
|
|
@ -206,18 +255,6 @@ export const NumberInput = function NumberInput({
|
|||
fireEvent('onChange');
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
disable !== disabledState && setDisable(disabledState);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disabledState]);
|
||||
useEffect(() => {
|
||||
visibility !== properties.visibility && setVisibility(properties.visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility]);
|
||||
useEffect(() => {
|
||||
loading !== loadingState && setLoading(loadingState);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loadingState]);
|
||||
|
||||
const handleIncrement = (e) => {
|
||||
e.preventDefault(); // Prevent the default button behavior (form submission, page reload)
|
||||
|
|
@ -238,29 +275,6 @@ export const NumberInput = function NumberInput({
|
|||
fireEvent('onChange');
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
setExposedVariable('setFocus', async function () {
|
||||
inputRef.current.focus();
|
||||
});
|
||||
setExposedVariable('setBlur', async function () {
|
||||
inputRef.current.blur();
|
||||
});
|
||||
setExposedVariable('setText', async function (text) {
|
||||
if (text) {
|
||||
const newValue = Number(parseFloat(text));
|
||||
setValue(newValue);
|
||||
setExposedVariable('value', text);
|
||||
fireEvent('onChange');
|
||||
}
|
||||
});
|
||||
|
||||
setExposedVariable('clear', async function () {
|
||||
setValue('');
|
||||
setExposedVariable('value', '');
|
||||
fireEvent('onChange');
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const loaderStyle = {
|
||||
right:
|
||||
|
|
@ -286,7 +300,7 @@ export const NumberInput = function NumberInput({
|
|||
return (
|
||||
<>
|
||||
<div
|
||||
data-cy={`label-${String(component.name).toLowerCase()}`}
|
||||
data-cy={`label-${String(componentName).toLowerCase()}`}
|
||||
className={`text-input tj-number-input-widget d-flex ${
|
||||
defaultAlignment === 'top' &&
|
||||
((width != 0 && label && label?.length != 0) || (auto && width == 0 && label && label?.length != 0))
|
||||
|
|
@ -358,6 +372,7 @@ export const NumberInput = function NumberInput({
|
|||
data-cy={dataCy}
|
||||
min={minValue}
|
||||
max={maxValue}
|
||||
autoComplete="off"
|
||||
onKeyUp={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
setValue(e.target.value);
|
||||
|
|
@ -440,7 +455,7 @@ export const NumberInput = function NumberInput({
|
|||
</div>
|
||||
{showValidationError && visibility && (
|
||||
<div
|
||||
data-cy={`${String(component.name).toLowerCase()}-invalid-feedback`}
|
||||
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
|
||||
style={{
|
||||
color: errTextColor !== '#D72D39' ? errTextColor : 'var(--status-error-strong)',
|
||||
textAlign: direction == 'left' && 'end',
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import { Document, Page } from 'react-pdf/dist/esm/entry.webpack';
|
|||
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
|
||||
import 'react-pdf/dist/esm/Page/TextLayer.css'; // Required to fix duplicate text appearing at the bottom from the previous page
|
||||
import { debounce } from 'lodash';
|
||||
import PasswordResponses from 'react-pdf/dist/cjs/PasswordResponses';
|
||||
require('pdfjs-dist/build/pdf.worker.entry.js');
|
||||
// The above line is required to fix the issue of pdf becoming black when resizing
|
||||
|
||||
export const PDF = React.memo(({ styles, properties, width, height, component, dataCy }) => {
|
||||
const pdfName = component.name;
|
||||
export const PDF = React.memo(({ styles, properties, width, height, componentName, dataCy }) => {
|
||||
const { visibility, boxShadow } = styles;
|
||||
const { url, scale, pageControls, showDownloadOption } = properties;
|
||||
const [numPages, setNumPages] = useState(null);
|
||||
|
|
@ -17,6 +19,7 @@ export const PDF = React.memo(({ styles, properties, width, height, component, d
|
|||
const [error, setError] = useState(true);
|
||||
const [pageLoading, setPageLoading] = useState(true);
|
||||
const [hasButtonClicked, setButtonClick] = useState(false);
|
||||
const [isPasswordPromptClosed, setIsPasswordPromptClosed] = useState(false);
|
||||
|
||||
const onDocumentLoadSuccess = async (document) => {
|
||||
const { numPages: nextNumPages } = document;
|
||||
|
|
@ -60,6 +63,10 @@ export const PDF = React.memo(({ styles, properties, width, height, component, d
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [numPages, options]);
|
||||
|
||||
useEffect(() => {
|
||||
setIsPasswordPromptClosed(false);
|
||||
}, [url]);
|
||||
|
||||
const updatePage = useCallback(
|
||||
(offset) => {
|
||||
const { offsetTop } = pageRef.current[pageNumber + offset - 1];
|
||||
|
|
@ -82,25 +89,74 @@ export const PDF = React.memo(({ styles, properties, width, height, component, d
|
|||
width: '15px',
|
||||
height: '15px',
|
||||
};
|
||||
const renderPDF = () => (
|
||||
<Document
|
||||
file={url}
|
||||
onLoadSuccess={onDocumentLoadSuccess}
|
||||
onLoadError={onDocumentLoadError}
|
||||
className="pdf-document"
|
||||
>
|
||||
{Array.from(new Array(numPages), (el, index) => (
|
||||
<Page
|
||||
pageNumber={index + 1}
|
||||
width={scale ? width - 12 : undefined}
|
||||
height={scale ? undefined : height}
|
||||
key={`page_${index + 1}`}
|
||||
inputRef={(el) => (pageRef.current[index] = el)}
|
||||
/>
|
||||
))}
|
||||
</Document>
|
||||
);
|
||||
|
||||
function onPassword(callback, reason) {
|
||||
function callbackProxy(password) {
|
||||
setIsPasswordPromptClosed(false);
|
||||
if (password === null) {
|
||||
setIsPasswordPromptClosed(true);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(password);
|
||||
}
|
||||
|
||||
switch (reason) {
|
||||
case PasswordResponses.NEED_PASSWORD: {
|
||||
const password = prompt('Enter the password to open this PDF file.');
|
||||
callbackProxy(password);
|
||||
break;
|
||||
}
|
||||
case PasswordResponses.INCORRECT_PASSWORD: {
|
||||
const password = prompt('Invalid password. Please try again.');
|
||||
callbackProxy(password);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
const renderPDF = () => {
|
||||
if (isPasswordPromptClosed)
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column' }}>
|
||||
<p style={{ marginBottom: '6px' }}>Password prompt closed</p>
|
||||
<button
|
||||
class="pdf-retry-button"
|
||||
data-cy="draggable-widget-button3"
|
||||
type="default"
|
||||
onClick={() => setIsPasswordPromptClosed(false)}
|
||||
>
|
||||
<div>
|
||||
<div>
|
||||
<span>
|
||||
<p class="tj-text-sm">Retry</p>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<Document
|
||||
file={url}
|
||||
onLoadSuccess={onDocumentLoadSuccess}
|
||||
onLoadError={onDocumentLoadError}
|
||||
onPassword={onPassword}
|
||||
className="pdf-document"
|
||||
>
|
||||
{Array.from(new Array(numPages), (el, index) => (
|
||||
<Page
|
||||
pageNumber={index + 1}
|
||||
width={scale ? width - 12 : undefined}
|
||||
height={scale ? undefined : height}
|
||||
key={`page_${index + 1}`}
|
||||
inputRef={(el) => (pageRef.current[index] = el)}
|
||||
/>
|
||||
))}
|
||||
</Document>
|
||||
);
|
||||
};
|
||||
async function downloadFile(url, pdfName) {
|
||||
const pdf = await fetch(url);
|
||||
const pdfBlog = await pdf.blob();
|
||||
|
|
@ -168,7 +224,7 @@ export const PDF = React.memo(({ styles, properties, width, height, component, d
|
|||
<div
|
||||
className="download-icon-outer-wrapper text-dark"
|
||||
style={downloadIconOuterWrapperStyles}
|
||||
onClick={() => downloadFile(url, pdfName)}
|
||||
onClick={() => downloadFile(url, componentName)}
|
||||
>
|
||||
<img
|
||||
src="assets/images/icons/download.svg"
|
||||
|
|
|
|||
|
|
@ -1,26 +1,20 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
|
||||
export const Pagination = ({
|
||||
id,
|
||||
height,
|
||||
properties,
|
||||
styles,
|
||||
exposedVariables,
|
||||
setExposedVariable,
|
||||
fireEvent,
|
||||
darkMode,
|
||||
dataCy,
|
||||
width,
|
||||
}) => {
|
||||
const isInitialRender = useRef(true);
|
||||
const { visibility, disabledState, boxShadow } = styles;
|
||||
const [currentPage, setCurrentPage] = useState(() => properties?.defaultPageIndex ?? 1);
|
||||
|
||||
useEffect(() => {
|
||||
if (exposedVariables.currentPageIndex === null) setExposedVariable('currentPageIndex', currentPage);
|
||||
|
||||
if (exposedVariables.totalPages === null) setExposedVariable('totalPages', properties.numberOfPages);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [exposedVariables]);
|
||||
|
||||
const pageChanged = (number) => {
|
||||
setCurrentPage(number);
|
||||
setExposedVariable('currentPageIndex', number);
|
||||
|
|
@ -49,7 +43,13 @@ export const Pagination = ({
|
|||
|
||||
useEffect(() => {
|
||||
if (properties.defaultPageIndex) {
|
||||
pageChanged(properties.defaultPageIndex);
|
||||
if (!isInitialRender.current) {
|
||||
pageChanged(properties.defaultPageIndex);
|
||||
} else {
|
||||
setCurrentPage(properties.defaultPageIndex);
|
||||
setExposedVariable('currentPageIndex', properties.defaultPageIndex);
|
||||
isInitialRender.current = false;
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.defaultPageIndex]);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import * as Icons from '@tabler/icons-react';
|
|||
import Loader from '@/ToolJetUI/Loader/Loader';
|
||||
import SolidIcon from '@/_ui/Icon/SolidIcons';
|
||||
import Label from '@/_ui/Label';
|
||||
import { useEditorStore } from '@/_stores/editorStore';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { useGridStore } from '@/_stores/gridStore';
|
||||
|
||||
export const PasswordInput = function PasswordInput({
|
||||
height,
|
||||
|
|
@ -12,16 +13,17 @@ export const PasswordInput = function PasswordInput({
|
|||
properties,
|
||||
styles,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
fireEvent,
|
||||
component,
|
||||
darkMode,
|
||||
dataCy,
|
||||
isResizing,
|
||||
validation,
|
||||
componentName,
|
||||
id,
|
||||
}) {
|
||||
const textInputRef = useRef();
|
||||
const labelRef = useRef();
|
||||
|
||||
const isInitialRender = useRef(true);
|
||||
const { loadingState, disabledState, label, placeholder } = properties;
|
||||
const {
|
||||
padding,
|
||||
|
|
@ -40,13 +42,14 @@ export const PasswordInput = function PasswordInput({
|
|||
accentColor,
|
||||
} = styles;
|
||||
|
||||
const components = useStore((state) => state.getCurrentPageComponents() || {});
|
||||
const isMandatory = validation?.mandatory ?? false;
|
||||
const isResizing = useGridStore((state) => state.resizingComponentId === id);
|
||||
const [disable, setDisable] = useState(disabledState || loadingState);
|
||||
const [passwordValue, setPasswordValue] = useState(properties.value);
|
||||
const [visibility, setVisibility] = useState(properties.visibility);
|
||||
const { isValid, validationError } = validate(passwordValue);
|
||||
const [showValidationError, setShowValidationError] = useState(false);
|
||||
|
||||
const isMandatory = resolveWidgetFieldValue(component?.definition?.validation?.mandatory?.value);
|
||||
const [labelWidth, setLabelWidth] = useState(0);
|
||||
const defaultAlignment = alignment === 'side' || alignment === 'top' ? alignment : 'side';
|
||||
const [iconVisibility, setIconVisibility] = useState(false);
|
||||
|
|
@ -55,7 +58,6 @@ export const PasswordInput = function PasswordInput({
|
|||
const tinycolor = require('tinycolor2');
|
||||
|
||||
const _width = (width / 100) * 70; // Max width which label can go is 70% for better UX calculate width based on this value
|
||||
console.log('style---', styles);
|
||||
const computedStyles = {
|
||||
height: height == 36 ? (padding == 'default' ? '36px' : '40px') : padding == 'default' ? height : height + 4,
|
||||
borderRadius: `${borderRadius}px`,
|
||||
|
|
@ -70,7 +72,11 @@ export const PasswordInput = function PasswordInput({
|
|||
padding: styles?.iconVisibility ? '8px 10px 8px 29px' : '8px 10px 8px 10px',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
color: textColor !== '#1B1F24' ? textColor : disable || loading ? 'var(--text-disabled)' : 'var(--text-primary)',
|
||||
color: !['#11181C', '#1B1F24'].includes(textColor)
|
||||
? textColor
|
||||
: disable || loading
|
||||
? 'var(--text-disabled)'
|
||||
: 'var(--text-primary)',
|
||||
borderColor: isFocused
|
||||
? accentColor != '4368E3'
|
||||
? accentColor
|
||||
|
|
@ -104,6 +110,7 @@ export const PasswordInput = function PasswordInput({
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('label', label);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [label]);
|
||||
|
|
@ -146,92 +153,93 @@ export const PasswordInput = function PasswordInput({
|
|||
}, [loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isValid', isValid);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isValid]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isLoading', loading);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loading]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isVisible', visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isDisabled', disable);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setPasswordValue(properties.value);
|
||||
setExposedVariable('value', properties?.value ?? '');
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.value]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setFocus', async function () {
|
||||
textInputRef.current.focus();
|
||||
});
|
||||
setExposedVariable('setBlur', async function () {
|
||||
textInputRef.current.blur();
|
||||
});
|
||||
const exposedVariables = {
|
||||
setFocus: async function () {
|
||||
textInputRef.current.focus();
|
||||
},
|
||||
setBlur: async function () {
|
||||
textInputRef.current.blur();
|
||||
},
|
||||
setText: async function (text) {
|
||||
setPasswordValue(text);
|
||||
setExposedVariable('value', text);
|
||||
fireEvent('onChange');
|
||||
},
|
||||
clear: async function () {
|
||||
setPasswordValue('');
|
||||
setExposedVariable('value', '');
|
||||
fireEvent('onChange');
|
||||
},
|
||||
setLoading: async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
},
|
||||
setVisibility: async function (state) {
|
||||
setVisibility(state);
|
||||
setExposedVariable('isVisible', state);
|
||||
},
|
||||
setDisable: async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
},
|
||||
label: label,
|
||||
isValid: isValid,
|
||||
isMandatory: isMandatory,
|
||||
isLoading: loading,
|
||||
isVisible: visibility,
|
||||
isDisabled: disable,
|
||||
value: properties?.value ?? '',
|
||||
};
|
||||
|
||||
setPasswordValue(properties.value ?? '');
|
||||
setExposedVariables(exposedVariables);
|
||||
isInitialRender.current = false;
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setText', async function (text) {
|
||||
setPasswordValue(text);
|
||||
setExposedVariable('value', text);
|
||||
fireEvent('onChange');
|
||||
});
|
||||
setExposedVariable('clear', async function () {
|
||||
setPasswordValue('');
|
||||
setExposedVariable('value', '');
|
||||
fireEvent('onChange');
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setPasswordValue]);
|
||||
|
||||
const iconName = styles.icon; // Replace with the name of the icon you want
|
||||
// eslint-disable-next-line import/namespace
|
||||
const IconElement = Icons[iconName] == undefined ? Icons['IconHome2'] : Icons[iconName];
|
||||
// eslint-disable-next-line import/namespace
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isLoading', loading);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loading]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setLoading', async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isVisible', visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setVisibility', async function (state) {
|
||||
setVisibility(state);
|
||||
setExposedVariable('isVisible', state);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setDisable', async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disabledState]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isDisabled', disable);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
|
||||
const currentPageId = useEditorStore.getState().currentPageId;
|
||||
const components = useEditorStore.getState().appDefinition?.pages?.[currentPageId]?.components || {};
|
||||
|
||||
const isChildOfForm = Object.keys(components).some((key) => {
|
||||
if (key == id) {
|
||||
const { parent } = components[key].component;
|
||||
|
|
@ -249,7 +257,7 @@ export const PasswordInput = function PasswordInput({
|
|||
const renderInput = () => (
|
||||
<>
|
||||
<div
|
||||
data-cy={`label-${String(component.name).toLowerCase()}`}
|
||||
data-cy={`label-${String(componentName).toLowerCase()}`}
|
||||
className={`text-input d-flex ${
|
||||
defaultAlignment === 'top' &&
|
||||
((width != 0 && label && label?.length != 0) || (auto && width == 0 && label && label?.length != 0))
|
||||
|
|
@ -350,6 +358,7 @@ export const PasswordInput = function PasswordInput({
|
|||
!isValid && showValidationError ? 'is-invalid' : ''
|
||||
} validation-without-icon `}
|
||||
ref={textInputRef}
|
||||
autoComplete="new-password"
|
||||
onKeyUp={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
setPasswordValue(e.target.value);
|
||||
|
|
@ -385,7 +394,7 @@ export const PasswordInput = function PasswordInput({
|
|||
</div>
|
||||
{showValidationError && visibility && (
|
||||
<div
|
||||
data-cy={`${String(component.name).toLowerCase()}-invalid-feedback`}
|
||||
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
|
||||
style={{
|
||||
color: errTextColor !== '#D72D39' ? errTextColor : 'var(--status-error-strong)',
|
||||
textAlign: direction == 'left' && 'end',
|
||||
|
|
@ -400,7 +409,13 @@ export const PasswordInput = function PasswordInput({
|
|||
</>
|
||||
);
|
||||
const renderContainer = (children) => {
|
||||
return !isChildOfForm ? <form autoComplete="off">{children}</form> : <div>{children}</div>;
|
||||
return !isChildOfForm ? (
|
||||
<form onSubmit={(e) => e.preventDefault()} autoComplete="off">
|
||||
{children}
|
||||
</form>
|
||||
) : (
|
||||
<div>{children}</div>
|
||||
);
|
||||
};
|
||||
|
||||
return renderContainer(renderInput());
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import QrReader from 'react-qr-reader';
|
||||
import ErrorModal from './ErrorModal';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export const RadioButton = function RadioButton({
|
||||
|
|
@ -12,6 +12,7 @@ export const RadioButton = function RadioButton({
|
|||
darkMode,
|
||||
dataCy,
|
||||
}) {
|
||||
const isInitialRender = useRef(true);
|
||||
const { label, value, values, display_values } = properties;
|
||||
const { visibility, disabledState, activeColor, boxShadow } = styles;
|
||||
const textColor = darkMode && styles.textColor === '#000' ? '#fff' : styles.textColor;
|
||||
|
|
@ -36,6 +37,12 @@ export const RadioButton = function RadioButton({
|
|||
fireEvent('onSelectionChange');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('value', value);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
value: value,
|
||||
|
|
@ -44,8 +51,9 @@ export const RadioButton = function RadioButton({
|
|||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
isInitialRender.current = false;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [value, setValue]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import Slider from 'rc-slider';
|
|||
import 'rc-slider/assets/index.css';
|
||||
|
||||
export const RangeSlider = function RangeSlider({ height, properties, styles, setExposedVariable, fireEvent, dataCy }) {
|
||||
const isInitialRender = useRef(true);
|
||||
const { value, min, max, enableTwoHandle } = properties;
|
||||
const { trackColor, handleColor, lineColor, visibility, boxShadow } = styles;
|
||||
const sliderRef = useRef(null);
|
||||
|
|
@ -23,12 +24,14 @@ export const RangeSlider = function RangeSlider({ height, properties, styles, se
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setSliderValue(singleHandleValue);
|
||||
setExposedVariable('value', singleHandleValue);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [singleHandleValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setRangeValue(twoHandlesArray);
|
||||
setExposedVariable('value', twoHandlesArray);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
@ -36,6 +39,10 @@ export const RangeSlider = function RangeSlider({ height, properties, styles, se
|
|||
|
||||
useEffect(() => {
|
||||
setExposedVariable('value', enableTwoHandle ? twoHandlesArray : singleHandleValue);
|
||||
if (isInitialRender.current) {
|
||||
enableTwoHandle ? setRangeValue(twoHandlesArray) : setSliderValue(singleHandleValue);
|
||||
}
|
||||
isInitialRender.current = false;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [enableTwoHandle]);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export const Pagination = function Pagination({
|
|||
|
||||
useEffect(() => {
|
||||
setPageCount(autoPageCount);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [autoPageCount]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -43,11 +44,11 @@ export const Pagination = function Pagination({
|
|||
}
|
||||
|
||||
function goToNextPage() {
|
||||
gotoPage(pageIndex + 1);
|
||||
gotoPage(Number(pageIndex) + 1);
|
||||
}
|
||||
|
||||
function goToPreviousPage() {
|
||||
gotoPage(pageIndex - 1);
|
||||
gotoPage(Number(pageIndex) - 1);
|
||||
}
|
||||
|
||||
if (loadingState) {
|
||||
|
|
@ -63,7 +64,7 @@ export const Pagination = function Pagination({
|
|||
return (
|
||||
<div className="pagination-container d-flex h-100 align-items-center custom-gap-4" data-cy="pagination-section">
|
||||
<div className="d-flex">
|
||||
{!serverSide && tableWidth > 460 && (
|
||||
{tableWidth > 460 && (
|
||||
<ButtonSolid
|
||||
variant="ghostBlack"
|
||||
className="tj-text-xsm"
|
||||
|
|
@ -119,27 +120,24 @@ export const Pagination = function Pagination({
|
|||
className="d-flex align-items-center tj-text-xsm h-100 page-info custom-gap-4"
|
||||
data-cy={`page-index-details`}
|
||||
>
|
||||
{serverSide && <span className="color-slate-11">{pageIndex}</span>}
|
||||
{!serverSide && (
|
||||
<>
|
||||
<input
|
||||
type="text"
|
||||
className={`form-control h-100`}
|
||||
value={pageIndex}
|
||||
onChange={(event) => {
|
||||
const value = Number(event.target.value);
|
||||
if (value <= pageCount) gotoPage(value);
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
className="font-weight-500 total-page-number"
|
||||
style={{ width: 'max-content' }}
|
||||
data-cy={`total-page-number-${autoPageOptions.length || 1}`}
|
||||
>
|
||||
of {pageCount || 1}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
<>
|
||||
<input
|
||||
type="text"
|
||||
className={`form-control h-100`}
|
||||
value={pageIndex}
|
||||
onChange={(event) => {
|
||||
const value = Number(event.target.value);
|
||||
if (value <= pageCount) gotoPage(value);
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
className="font-weight-500 total-page-number"
|
||||
style={{ width: 'max-content' }}
|
||||
data-cy={`total-page-number-${autoPageOptions.length || 1}`}
|
||||
>
|
||||
of {pageCount || 1}
|
||||
</span>
|
||||
</>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
<ButtonSolid
|
||||
|
|
@ -153,20 +151,20 @@ export const Pagination = function Pagination({
|
|||
borderRadius: '6px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
cursor: (!autoCanNextPage && !serverSide) || !enableNextButton ? 'not-allowed' : 'pointer',
|
||||
cursor: pageIndex === pageCount || !enableNextButton ? 'not-allowed' : 'pointer',
|
||||
}}
|
||||
leftIcon="cheveronright"
|
||||
fill={`var(--icons-default)`}
|
||||
iconWidth="14"
|
||||
size="md"
|
||||
disabled={(!autoCanNextPage && !serverSide) || !enableNextButton}
|
||||
disabled={pageIndex === pageCount || !enableNextButton}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
goToNextPage();
|
||||
}}
|
||||
data-cy={`pagination-button-to-next`}
|
||||
></ButtonSolid>
|
||||
{!serverSide && tableWidth > 460 && (
|
||||
{tableWidth > 460 && (
|
||||
<ButtonSolid
|
||||
variant="ghostBlack"
|
||||
className="tj-text-xsm"
|
||||
|
|
@ -178,7 +176,7 @@ export const Pagination = function Pagination({
|
|||
borderRadius: '6px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
cursor: !autoCanNextPage && !serverSide ? 'not-allowed' : 'pointer',
|
||||
cursor: pageIndex === pageCount ? 'not-allowed' : 'pointer',
|
||||
}}
|
||||
leftIcon="cheveronrightdouble"
|
||||
fill={`var(--icons-default)`}
|
||||
|
|
@ -188,7 +186,7 @@ export const Pagination = function Pagination({
|
|||
event.stopPropagation();
|
||||
gotoPage(pageCount);
|
||||
}}
|
||||
disabled={!autoCanNextPage && !serverSide}
|
||||
disabled={pageIndex === pageCount}
|
||||
data-cy={`pagination-button-to-last`}
|
||||
></ButtonSolid>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -147,9 +147,9 @@ const StringColumn = ({
|
|||
<span
|
||||
style={{
|
||||
maxHeight: isMaxRowHeightAuto
|
||||
? 'auto'
|
||||
? 'fit-content'
|
||||
: maxRowHeightValue
|
||||
? maxRowHeightValue
|
||||
? `${maxRowHeightValue}px`
|
||||
: cellSize === 'condensed'
|
||||
? '39px'
|
||||
: '45px',
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import {
|
|||
determineJustifyContentValue,
|
||||
resolveWidgetFieldValue,
|
||||
} from '@/_helpers/utils';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { useExportData } from 'react-table-plugins';
|
||||
import Papa from 'papaparse';
|
||||
import { Pagination } from './Pagination';
|
||||
|
|
@ -107,7 +109,6 @@ export function Table({
|
|||
// events,
|
||||
setProperty,
|
||||
mode,
|
||||
exposedVariables,
|
||||
}) {
|
||||
const {
|
||||
color,
|
||||
|
|
@ -150,8 +151,10 @@ export function Table({
|
|||
isMaxRowHeightAuto,
|
||||
columnHeaderWrap,
|
||||
} = loadPropertiesAndStyles(properties, styles, darkMode, component);
|
||||
const exposedVariables = useStore((state) => state.getExposedValueOfComponent(id), shallow);
|
||||
const updatedDataReference = useRef([]);
|
||||
const preSelectRow = useRef(false);
|
||||
const initialPageCountRef = useRef(null);
|
||||
const { events: allAppEvents } = useAppInfo();
|
||||
|
||||
const tableEvents = allAppEvents.filter((event) => event.target === 'component' && event.sourceId === id);
|
||||
|
|
@ -424,7 +427,7 @@ export function Table({
|
|||
}
|
||||
}
|
||||
|
||||
tableData = tableData || [];
|
||||
tableData = _.isArray(tableData) ? tableData : [];
|
||||
|
||||
const tableRef = useRef();
|
||||
|
||||
|
|
@ -575,6 +578,8 @@ export function Table({
|
|||
highlightSelectedRow,
|
||||
JSON.stringify(tableActionEvents),
|
||||
JSON.stringify(tableColumnEvents),
|
||||
maxRowHeightValue,
|
||||
isMaxRowHeightAuto,
|
||||
] // Hack: need to fix
|
||||
);
|
||||
|
||||
|
|
@ -661,8 +666,8 @@ export function Table({
|
|||
data,
|
||||
defaultColumn,
|
||||
initialState: { pageIndex: 0, pageSize: 1 },
|
||||
pageCount: -1,
|
||||
manualPagination: false,
|
||||
pageCount: initialPageCountRef.current,
|
||||
manualPagination: serverSidePagination,
|
||||
getExportFileBlob,
|
||||
getExportFileName,
|
||||
disableSortBy: !enabledSort,
|
||||
|
|
@ -870,6 +875,15 @@ export function Table({
|
|||
}
|
||||
}, [clientSidePagination, serverSidePagination, rows, rowsPerPage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialPageCountRef.current && serverSidePagination && data?.length && totalRecords) {
|
||||
initialPageCountRef.current = Math.ceil(totalRecords / data?.length);
|
||||
}
|
||||
if (!serverSidePagination) {
|
||||
initialPageCountRef.current = Math.ceil(data?.length / rowsPerPage);
|
||||
}
|
||||
}, [serverSidePagination, totalRecords, data?.length, rowsPerPage]);
|
||||
|
||||
useEffect(() => {
|
||||
const pageData = page.map((row) => row.original);
|
||||
if (preSelectRow.current) {
|
||||
|
|
@ -1763,7 +1777,7 @@ export function Table({
|
|||
serverSide={serverSidePagination}
|
||||
autoGotoPage={gotoPage}
|
||||
autoCanNextPage={canNextPage}
|
||||
autoPageCount={pageCount}
|
||||
autoPageCount={initialPageCountRef.current}
|
||||
autoPageOptions={pageOptions}
|
||||
onPageIndexChanged={onPageIndexChanged}
|
||||
pageIndex={paginationInternalPageIndex}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -109,12 +109,12 @@ const Text = ({
|
|||
<span
|
||||
style={{
|
||||
maxHeight: isMaxRowHeightAuto
|
||||
? 'auto'
|
||||
? 'fit-content'
|
||||
: maxRowHeightValue
|
||||
? maxRowHeightValue - 16 // decreasing 16px for padding fix
|
||||
? `${maxRowHeightValue}px`
|
||||
: cellSize === 'condensed'
|
||||
? '23px'
|
||||
: '29px',
|
||||
? '39px'
|
||||
: '45px',
|
||||
}}
|
||||
ref={nonEditableCellValueRef}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ export default function generateColumnsData({
|
|||
cellSize,
|
||||
maxRowHeightValue,
|
||||
}) {
|
||||
const isValueRowDependent = (value) => {
|
||||
return (
|
||||
(typeof value === 'string' || Array.isArray(value)) && (value.includes('cellValue') || value.includes('rowData'))
|
||||
);
|
||||
};
|
||||
|
||||
return columnProperties.map((column) => {
|
||||
if (!column) return;
|
||||
const columnSize = columnSizes[column?.id] || columnSizes[column?.name] || column.columnSize;
|
||||
|
|
@ -51,8 +57,8 @@ export default function generateColumnsData({
|
|||
columnType === 'image'
|
||||
) {
|
||||
columnOptions.selectOptions = [];
|
||||
const values = resolveReferences(column.values, []);
|
||||
const labels = resolveReferences(column.labels, []);
|
||||
const values = resolveReferences(column.values);
|
||||
const labels = resolveReferences(column.labels);
|
||||
|
||||
if (Array.isArray(labels) && Array.isArray(values)) {
|
||||
columnOptions.selectOptions = labels.map((label, index) => {
|
||||
|
|
@ -60,13 +66,34 @@ export default function generateColumnsData({
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// This is done to ensure that if row dependent properties are not used, the default value is used and performance is not affected
|
||||
const rowDependentMap = {
|
||||
cellBackgroundColor: isValueRowDependent(column.cellBackgroundColor),
|
||||
textColor: isValueRowDependent(column.textColor),
|
||||
minValue: isValueRowDependent(column.minValue),
|
||||
maxValue: isValueRowDependent(column.maxValue),
|
||||
minLength: isValueRowDependent(column.minLength),
|
||||
maxLength: isValueRowDependent(column.maxLength),
|
||||
regex: isValueRowDependent(column.regex),
|
||||
customRule: isValueRowDependent(column.customRule),
|
||||
isEditable: isValueRowDependent(column.isEditable),
|
||||
minDate: isValueRowDependent(column.minDate),
|
||||
maxDate: isValueRowDependent(column.maxDate),
|
||||
borderRadius: isValueRowDependent(column.borderRadius),
|
||||
multiselect: false,
|
||||
};
|
||||
|
||||
let useDynamicOptions = false;
|
||||
if (columnType === 'select' || columnType === 'newMultiSelect') {
|
||||
columnOptions.selectOptions = [];
|
||||
const useDynamicOptions = resolveReferences(column?.useDynamicOptions);
|
||||
useDynamicOptions = resolveReferences(column?.useDynamicOptions, currentState);
|
||||
if (useDynamicOptions) {
|
||||
const dynamicOptions = resolveReferences(column?.dynamicOptions || []);
|
||||
rowDependentMap['multiselect'] = isValueRowDependent(column?.dynamicOptions);
|
||||
const dynamicOptions = resolveReferences(column?.dynamicOptions || [], currentState);
|
||||
columnOptions.selectOptions = Array.isArray(dynamicOptions) ? dynamicOptions : [];
|
||||
} else {
|
||||
rowDependentMap['multiselect'] = isValueRowDependent(JSON.stringify(column?.options));
|
||||
const options = column?.options ?? [];
|
||||
columnOptions.selectOptions =
|
||||
options?.map((option) => ({
|
||||
|
|
@ -101,6 +128,7 @@ export default function generateColumnsData({
|
|||
};
|
||||
}
|
||||
const width = columnSize || defaultColumn.width;
|
||||
|
||||
return {
|
||||
id: column.id,
|
||||
Header: resolveReferences(column.name) ?? '',
|
||||
|
|
@ -146,6 +174,14 @@ export default function generateColumnsData({
|
|||
exposeToCodeHinter((prevState) => ({ ...prevState, ...customResolvables }));
|
||||
}
|
||||
cellValue = cellValue === undefined || cellValue === null ? '' : cellValue;
|
||||
column = { ...column };
|
||||
|
||||
Object.keys(rowDependentMap).map((key) => {
|
||||
column[key] = rowDependentMap[key]
|
||||
? resolveReferences(cell.column?.[key], currentState, '', { cellValue, rowData })
|
||||
: column[key];
|
||||
});
|
||||
|
||||
switch (columnType) {
|
||||
case 'string':
|
||||
case undefined:
|
||||
|
|
@ -260,9 +296,8 @@ export default function generateColumnsData({
|
|||
};
|
||||
|
||||
const allowedDecimalPlaces = column?.decimalPlaces ?? null;
|
||||
|
||||
const removingExcessDecimalPlaces = (cellValue, allowedDecimalPlaces) => {
|
||||
allowedDecimalPlaces = resolveReferences(allowedDecimalPlaces);
|
||||
allowedDecimalPlaces = resolveReferences(allowedDecimalPlaces, currentState, 2, { cellValue, rowData });
|
||||
if (cellValue?.toString()?.includes('.')) {
|
||||
const splittedCellValue = cellValue?.toString()?.split('.');
|
||||
const decimalPlacesUnderLimit = splittedCellValue[1].split('').splice(0, allowedDecimalPlaces).join('');
|
||||
|
|
@ -270,7 +305,6 @@ export default function generateColumnsData({
|
|||
}
|
||||
return cellValue;
|
||||
};
|
||||
|
||||
cellValue = allowedDecimalPlaces ? removingExcessDecimalPlaces(cellValue, allowedDecimalPlaces) : cellValue;
|
||||
|
||||
if (isEditable) {
|
||||
|
|
@ -445,8 +479,26 @@ export default function generateColumnsData({
|
|||
currentState,
|
||||
customResolveObjects: { cellValue },
|
||||
});
|
||||
|
||||
const { isValid, validationError } = validationData;
|
||||
let rowOptions = [];
|
||||
if ((columnType === 'select' || columnType === 'newMultiSelect') && rowDependentMap['multiselect']) {
|
||||
if (useDynamicOptions) {
|
||||
const dynamicOptions = resolveReferences(column?.dynamicOptions || [], currentState, [], {
|
||||
rowData,
|
||||
cellValue,
|
||||
});
|
||||
rowOptions = Array.isArray(dynamicOptions) ? dynamicOptions : [];
|
||||
} else {
|
||||
const options = column?.options ?? [];
|
||||
|
||||
rowOptions =
|
||||
options?.map((option) => ({
|
||||
label: resolveReferences(option.label, currentState, [], { rowData, cellValue }),
|
||||
value: resolveReferences(option.value, currentState, [], { rowData, cellValue }),
|
||||
})) ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="h-100 d-flex align-items-center flex-column justify-content-center"
|
||||
|
|
@ -468,7 +520,7 @@ export default function generateColumnsData({
|
|||
)}
|
||||
{['newMultiSelect', 'select'].includes(columnType) && (
|
||||
<CustomSelect
|
||||
options={columnOptions.selectOptions}
|
||||
options={rowOptions.length > 0 ? rowOptions : columnOptions.selectOptions}
|
||||
value={cellValue}
|
||||
search={true}
|
||||
onChange={(value) => {
|
||||
|
|
@ -614,12 +666,23 @@ export default function generateColumnsData({
|
|||
);
|
||||
}
|
||||
case 'datepicker': {
|
||||
const textColor = resolveReferences(column.textColor, '', { cellValue, rowData });
|
||||
const isTimeChecked = resolveReferences(column?.isTimeChecked);
|
||||
const isTwentyFourHrFormatEnabled = resolveReferences(column?.isTwentyFourHrFormatEnabled);
|
||||
const disabledDates = resolveReferences(column?.disabledDates);
|
||||
const parseInUnixTimestamp = resolveReferences(column?.parseInUnixTimestamp);
|
||||
const isDateSelectionEnabled = resolveReferences(column?.isDateSelectionEnabled);
|
||||
const textColor = resolveReferences(column.textColor, currentState, '', { cellValue, rowData });
|
||||
const isTimeChecked = resolveReferences(column?.isTimeChecked, currentState, false, { cellValue, rowData });
|
||||
const isTwentyFourHrFormatEnabled = resolveReferences(
|
||||
column?.isTwentyFourHrFormatEnabled,
|
||||
currentState,
|
||||
false,
|
||||
{ cellValue, rowData }
|
||||
);
|
||||
const disabledDates = resolveReferences(column?.disabledDates, currentState, [], { cellValue, rowData });
|
||||
const parseInUnixTimestamp = resolveReferences(column?.parseInUnixTimestamp, currentState, '', {
|
||||
cellValue,
|
||||
rowData,
|
||||
});
|
||||
const isDateSelectionEnabled = resolveReferences(column?.isDateSelectionEnabled, currentState, true, {
|
||||
cellValue,
|
||||
rowData,
|
||||
});
|
||||
const cellStyles = {
|
||||
color: textColor ?? '',
|
||||
};
|
||||
|
|
@ -688,20 +751,30 @@ export default function generateColumnsData({
|
|||
);
|
||||
}
|
||||
case 'link': {
|
||||
const linkTarget = resolveReferences(column?.linkTarget ?? '{{true}}');
|
||||
const displayText = column?.displayText ? resolveReferences(column.displayText) : '';
|
||||
column = {
|
||||
...column,
|
||||
linkColor: column?.linkColor ?? '#1B1F24',
|
||||
underlineColor: column?.underlineColor ?? '#4368E3',
|
||||
};
|
||||
const linkTarget = resolveReferences(column?.linkTarget ?? '{{true}}', currentState, '', {
|
||||
cellValue,
|
||||
rowData,
|
||||
});
|
||||
const displayText = resolveReferences(column?.displayText ?? '{{}}', currentState, '', {
|
||||
cellValue,
|
||||
rowData,
|
||||
});
|
||||
const linkColor = resolveReferences(column?.linkColor ?? '#1B1F24', currentState, '', {
|
||||
cellValue,
|
||||
rowData,
|
||||
});
|
||||
const underlineColor = resolveReferences(column.underlineColor ?? '', currentState, '', {
|
||||
cellValue,
|
||||
rowData,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="h-100 d-flex align-items-center">
|
||||
<Link
|
||||
cellValue={cellValue}
|
||||
linkTarget={linkTarget}
|
||||
linkColor={column.linkColor}
|
||||
underlineColor={column.underlineColor}
|
||||
linkColor={linkColor}
|
||||
underlineColor={underlineColor}
|
||||
underline={column.underline}
|
||||
displayText={displayText}
|
||||
darkMode={darkMode}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
.tj-datepicker-widget {
|
||||
&.react-datepicker-popper {
|
||||
z-index: 3;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
border-radius: 6px !important;
|
||||
border: 1px solid var(--slate5) !important;
|
||||
box-shadow: 0px 32px 64px -12px rgba(16, 24, 40, 0.14);
|
||||
|
|
@ -35,11 +36,11 @@
|
|||
border: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
input[type="time"] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
input[type="time"]::-webkit-calendar-picker-indicator {
|
||||
display: block;
|
||||
top: 0;
|
||||
|
|
@ -58,17 +59,17 @@
|
|||
padding: 6px 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
.tj-datepicker-widget-left {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
|
||||
.tj-datepicker-widget-right {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
|
||||
.tj-datepicker-widget-arrows {
|
||||
box-shadow: 0px 1px 0px 0px #0000000B;
|
||||
border: 1px solid var(--borders-default);
|
||||
|
|
@ -78,87 +79,87 @@
|
|||
padding: 4px;
|
||||
background-color: var(--surfaces-surface-01) !important;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__navigation-icon--previous {
|
||||
right: 0px;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__navigation-icon--next {
|
||||
left: 0px;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker {
|
||||
width: 250px;
|
||||
border: none;
|
||||
background-color: var(--surfaces-surface-01);
|
||||
}
|
||||
|
||||
|
||||
.dark-theme {
|
||||
.react-datepicker {
|
||||
background-color: #232e3c;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__month {
|
||||
margin: 6px
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__navigation--next {
|
||||
right: 14px;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__navigation--previous {
|
||||
left: 14px;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__week,
|
||||
.react-datepicker__day-names {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__day-names {
|
||||
.react-datepicker__day-name {
|
||||
color: var(--text-placeholder)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__day--selected {
|
||||
border-radius: 8px;
|
||||
background-color: var(--primary-brand) !important;
|
||||
color: var(--surfaces-surface-01) !important
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__navigation-icon::before {
|
||||
border-color: #000;
|
||||
border-width: 1px 1px 0 0;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__day {
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
|
||||
|
||||
&:hover {
|
||||
background-color: var(--interactive-overlays-fill-hover);
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__day--today {
|
||||
border: 1px solid var(--primary-brand);
|
||||
border-radius: 8px;
|
||||
background-color: var(--surfaces-surface-01);
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__day--keyboard-selected {
|
||||
background-color: var(--surfaces-surface-01);
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker-time__input {
|
||||
input {
|
||||
width: 205px !important;
|
||||
|
|
@ -174,55 +175,58 @@
|
|||
.react-datepicker__month-container {
|
||||
float: inherit;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__time-container .react-datepicker__time {
|
||||
color: var(--text-primary);
|
||||
background: var(--surfaces-surface-01);
|
||||
}
|
||||
|
||||
.dark-theme {
|
||||
|
||||
.react-datepicker-popper,
|
||||
.tj-datepicker-widget {
|
||||
background-color: #232e3c;
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__time-container,
|
||||
.react-datepicker__time-container .react-datepicker__time {
|
||||
background-color: #232e3c;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__header {
|
||||
background-color: #232e3c;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
|
||||
.react-datepicker__month-container {
|
||||
background-color: #232e3c;
|
||||
color: #fff;
|
||||
|
||||
|
||||
.react-datepicker__month {
|
||||
background-color: #232e3c;
|
||||
|
||||
|
||||
.react-datepicker__day {
|
||||
color: #fff
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
li.react-datepicker__time-list-item:hover {
|
||||
background-color: #CCD1D533 !important;
|
||||
}
|
||||
|
||||
select {
|
||||
color: #fff
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tj-datepicker-widget-month-selector,
|
||||
.tj-datepicker-widget-year-selector {
|
||||
&:hover {
|
||||
background-color: var(--interactive-overlays-fill-hover);
|
||||
border-radius: 6px;
|
||||
background-color: var(--interactive-overlays-fill-hover);
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,7 +251,6 @@
|
|||
.react-datepicker__day,
|
||||
.react-datepicker__time-name {
|
||||
margin: 0px;
|
||||
// width: 32px;
|
||||
}
|
||||
|
||||
.react-datepicker__day-names {
|
||||
|
|
@ -259,7 +262,8 @@
|
|||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tj-datepicker-widget-month-selector, .tj-datepicker-widget-year-selector {
|
||||
.tj-datepicker-widget-month-selector,
|
||||
.tj-datepicker-widget-year-selector {
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
|
|
@ -279,7 +283,6 @@
|
|||
padding: 0px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
// margin-right: 6px !important;
|
||||
color: var(--text-primary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
|
@ -287,9 +290,6 @@
|
|||
/* Optional: Style when select is focused */
|
||||
select:focus {
|
||||
outline: none;
|
||||
/* Remove default focus outline */
|
||||
// box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||
/* Add a subtle box-shadow when focused */
|
||||
}
|
||||
|
||||
.react-datepicker__triangle {
|
||||
|
|
@ -317,10 +317,6 @@
|
|||
margin: 0px;
|
||||
}
|
||||
|
||||
.react-datepicker__time-list {
|
||||
// padding: 4px 6px;
|
||||
}
|
||||
|
||||
.react-datepicker__time-list-item {
|
||||
height: 28px !important;
|
||||
color: var(--text-primary) !important;
|
||||
|
|
@ -354,6 +350,7 @@
|
|||
|
||||
.react-datepicker__time-box {
|
||||
display: flex;
|
||||
|
||||
ul {
|
||||
padding: 0px 10px 0px 10px !important;
|
||||
}
|
||||
|
|
@ -420,10 +417,16 @@
|
|||
|
||||
td {
|
||||
&.isEditable {
|
||||
&:hover, &:focus-within {
|
||||
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
.table-column-datepicker-input {
|
||||
padding-right: 40px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.react-datepicker-popper {
|
||||
z-index: 4 !important;
|
||||
}
|
||||
|
|
@ -17,12 +17,13 @@ export const Tabs = function Tabs({
|
|||
styles,
|
||||
darkMode,
|
||||
dataCy,
|
||||
properties,
|
||||
}) {
|
||||
const { tabWidth, boxShadow } = styles;
|
||||
const { defaultTab } = properties;
|
||||
|
||||
const widgetVisibility = component.definition.styles?.visibility?.value ?? true;
|
||||
const disabledState = component.definition.styles?.disabledState?.value ?? false;
|
||||
const defaultTab = component.definition.properties.defaultTab.value;
|
||||
// config for tabs. Includes title
|
||||
const tabs = isExpectedDataType(resolveWidgetFieldValue(component.definition.properties?.tabs?.value), 'array');
|
||||
let parsedTabs = tabs;
|
||||
|
|
@ -43,7 +44,6 @@ export const Tabs = function Tabs({
|
|||
|
||||
// Default tab
|
||||
let parsedDefaultTab = defaultTab;
|
||||
parsedDefaultTab = resolveWidgetFieldValue(parsedDefaultTab, 1);
|
||||
|
||||
const parsedDisabledState =
|
||||
typeof disabledState !== 'boolean' ? resolveWidgetFieldValue(disabledState) : disabledState;
|
||||
|
|
@ -137,7 +137,6 @@ export const Tabs = function Tabs({
|
|||
}
|
||||
return true; // Render by default if no specific conditions are met
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
data-disabled={parsedDisabledState}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import DOMPurify from 'dompurify';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import Markdown from 'react-markdown';
|
||||
|
|
@ -11,7 +11,18 @@ const VERTICAL_ALIGNMENT_VS_CSS_VALUE = {
|
|||
bottom: 'flex-end',
|
||||
};
|
||||
|
||||
export const Text = function Text({ height, properties, fireEvent, styles, darkMode, setExposedVariable, dataCy }) {
|
||||
let count = 0;
|
||||
|
||||
export const Text = function Text({
|
||||
height,
|
||||
properties,
|
||||
fireEvent,
|
||||
styles,
|
||||
darkMode,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
dataCy,
|
||||
}) {
|
||||
let {
|
||||
textSize,
|
||||
textColor,
|
||||
|
|
@ -32,13 +43,14 @@ export const Text = function Text({ height, properties, fireEvent, styles, darkM
|
|||
borderRadius,
|
||||
isScrollRequired,
|
||||
} = styles;
|
||||
const isInitialRender = useRef(true);
|
||||
const { loadingState, textFormat, disabledState } = properties;
|
||||
const [text, setText] = useState(() => computeText());
|
||||
const [visibility, setVisibility] = useState(properties.visibility);
|
||||
const [isLoading, setLoading] = useState(loadingState);
|
||||
const [isDisabled, setIsDisabled] = useState(disabledState);
|
||||
const color = ['#000', '#000000'].includes(textColor) ? (darkMode ? '#fff' : '#000') : textColor;
|
||||
|
||||
count = count + 1;
|
||||
useEffect(() => {
|
||||
if (visibility !== properties.visibility) setVisibility(properties.visibility);
|
||||
if (isLoading !== loadingState) setLoading(loadingState);
|
||||
|
|
@ -48,49 +60,63 @@ export const Text = function Text({ height, properties, fireEvent, styles, darkM
|
|||
}, [properties.visibility, loadingState, disabledState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
const text = computeText();
|
||||
setText(text);
|
||||
setExposedVariable('text', text);
|
||||
}, [properties.text]);
|
||||
|
||||
setExposedVariable('setText', async function (text) {
|
||||
setText(text);
|
||||
setExposedVariable('text', text);
|
||||
});
|
||||
setExposedVariable('clear', async function (text) {
|
||||
setText('');
|
||||
setExposedVariable('text', '');
|
||||
});
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isVisible', properties.visibility);
|
||||
}, [properties.visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isLoading', loadingState);
|
||||
}, [loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isDisabled', disabledState);
|
||||
}, [disabledState]);
|
||||
|
||||
setExposedVariable('visibility', async function (value) {
|
||||
setVisibility(value);
|
||||
});
|
||||
|
||||
setExposedVariable('setVisibility', async function (value) {
|
||||
setVisibility(value);
|
||||
});
|
||||
|
||||
setExposedVariable('setLoading', async function (value) {
|
||||
setLoading(value);
|
||||
});
|
||||
|
||||
setExposedVariable('setDisable', async function (value) {
|
||||
setIsDisabled(value);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
text: computeText(),
|
||||
setText: async function (text) {
|
||||
setText(text);
|
||||
setExposedVariable('text', text);
|
||||
},
|
||||
clear: async function () {
|
||||
setText('');
|
||||
setExposedVariable('text', '');
|
||||
},
|
||||
isVisible: properties.visibility,
|
||||
isLoading: loadingState,
|
||||
isDisabled: disabledState,
|
||||
visibility: async function (value) {
|
||||
setExposedVariable('isVisible', value);
|
||||
setVisibility(value);
|
||||
},
|
||||
setVisibility: async function (value) {
|
||||
setExposedVariable('isVisible', value);
|
||||
setVisibility(value);
|
||||
},
|
||||
setLoading: async function (value) {
|
||||
setExposedVariable('isLoading', value);
|
||||
setLoading(value);
|
||||
},
|
||||
setDisable: async function (value) {
|
||||
setExposedVariable('isDisabled', value);
|
||||
setIsDisabled(value);
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
setText(text);
|
||||
isInitialRender.current = false;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
properties.text,
|
||||
setText,
|
||||
setVisibility,
|
||||
properties.visibility,
|
||||
loadingState,
|
||||
disabledState,
|
||||
setIsDisabled,
|
||||
setLoading,
|
||||
]);
|
||||
}, []);
|
||||
|
||||
function computeText() {
|
||||
return properties.text === 0 || properties.text === false ? properties.text?.toString() : properties.text;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
|
||||
export const TextArea = function TextArea({
|
||||
height,
|
||||
|
|
@ -8,9 +8,11 @@ export const TextArea = function TextArea({
|
|||
setExposedVariables,
|
||||
dataCy,
|
||||
}) {
|
||||
const isInitialRender = useRef(true);
|
||||
const [value, setValue] = useState(properties.value);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setValue(properties.value);
|
||||
setExposedVariable('value', properties.value);
|
||||
|
||||
|
|
@ -27,11 +29,14 @@ export const TextArea = function TextArea({
|
|||
setValue('');
|
||||
setExposedVariable('value', '');
|
||||
},
|
||||
value: properties.value,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
setValue(properties.value);
|
||||
isInitialRender.current = false;
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setValue]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<textarea
|
||||
|
|
|
|||
|
|
@ -5,24 +5,28 @@ import * as Icons from '@tabler/icons-react';
|
|||
import Loader from '@/ToolJetUI/Loader/Loader';
|
||||
const tinycolor = require('tinycolor2');
|
||||
import Label from '@/_ui/Label';
|
||||
import { useGridStore } from '@/_stores/gridStore';
|
||||
|
||||
export const TextInput = function TextInput({
|
||||
id,
|
||||
height,
|
||||
validate,
|
||||
properties,
|
||||
validation,
|
||||
styles,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
fireEvent,
|
||||
component,
|
||||
componentName,
|
||||
darkMode,
|
||||
dataCy,
|
||||
isResizing,
|
||||
validate,
|
||||
}) {
|
||||
const isInitialRender = useRef(true);
|
||||
const textInputRef = useRef();
|
||||
const labelRef = useRef();
|
||||
|
||||
const { loadingState, disabledState, label, placeholder } = properties;
|
||||
const isResizing = useGridStore((state) => state.resizingComponentId === id);
|
||||
const isMandatory = validation?.mandatory || false;
|
||||
|
||||
const {
|
||||
padding,
|
||||
|
|
@ -43,10 +47,10 @@ export const TextInput = function TextInput({
|
|||
const [disable, setDisable] = useState(disabledState || loadingState);
|
||||
const [value, setValue] = useState(properties.value);
|
||||
const [visibility, setVisibility] = useState(properties.visibility);
|
||||
// const isValid = true; // TODO: remove this and uncomment the below line
|
||||
const { isValid, validationError } = validate(value);
|
||||
const [showValidationError, setShowValidationError] = useState(false);
|
||||
|
||||
const isMandatory = resolveWidgetFieldValue(component?.definition?.validation?.mandatory?.value);
|
||||
const [labelWidth, setLabelWidth] = useState(0);
|
||||
const defaultAlignment = alignment === 'side' || alignment === 'top' ? alignment : 'side';
|
||||
const [loading, setLoading] = useState(loadingState);
|
||||
|
|
@ -56,7 +60,11 @@ export const TextInput = function TextInput({
|
|||
const computedStyles = {
|
||||
height: height == 36 ? (padding == 'default' ? '36px' : '40px') : padding == 'default' ? height : height + 4,
|
||||
borderRadius: `${borderRadius}px`,
|
||||
color: textColor !== '#1B1F24' ? textColor : disable || loading ? 'var(--text-disabled)' : 'var(--text-primary)',
|
||||
color: !['#1B1F24', '#000', '#000000ff'].includes(textColor)
|
||||
? textColor
|
||||
: disable || loading
|
||||
? 'var(--text-disabled)'
|
||||
: 'var(--text-primary)',
|
||||
borderColor: isFocused
|
||||
? accentColor != '4368E3'
|
||||
? accentColor
|
||||
|
|
@ -127,6 +135,7 @@ export const TextInput = function TextInput({
|
|||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('label', label);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [label]);
|
||||
|
|
@ -152,29 +161,41 @@ export const TextInput = function TextInput({
|
|||
}, [isValid]);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(properties.value);
|
||||
setExposedVariable('value', properties.value);
|
||||
if (isInitialRender.current) return;
|
||||
if (properties.value === undefined) {
|
||||
setValue('');
|
||||
setExposedVariable('value', '');
|
||||
} else {
|
||||
setValue(properties.value);
|
||||
setExposedVariable('value', properties.value);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.value]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
setFocus: async function () {
|
||||
textInputRef.current.focus();
|
||||
},
|
||||
setBlur: async function () {
|
||||
textInputRef.current.blur();
|
||||
},
|
||||
disable: async function (value) {
|
||||
setDisable(value);
|
||||
},
|
||||
visibility: async function (value) {
|
||||
setVisibility(value);
|
||||
},
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isLoading', loading);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loading]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isVisible', visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isDisabled', disable);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
|
||||
useEffect(() => {
|
||||
const exposedVariables = {
|
||||
|
|
@ -188,63 +209,54 @@ export const TextInput = function TextInput({
|
|||
setExposedVariable('value', '');
|
||||
fireEvent('onChange');
|
||||
},
|
||||
setFocus: async function () {
|
||||
textInputRef.current.focus();
|
||||
},
|
||||
setBlur: async function () {
|
||||
textInputRef.current.blur();
|
||||
},
|
||||
disable: async function (value) {
|
||||
setDisable(value);
|
||||
},
|
||||
visibility: async function (value) {
|
||||
setVisibility(value);
|
||||
},
|
||||
setVisibility: async function (value) {
|
||||
setVisibility(value);
|
||||
setExposedVariable('isVisible', value);
|
||||
},
|
||||
setDisable: async function (value) {
|
||||
setDisable(value);
|
||||
setExposedVariable('isDisabled', value);
|
||||
},
|
||||
setLoading: async function (value) {
|
||||
setLoading(value);
|
||||
setExposedVariable('isLoading', value);
|
||||
},
|
||||
label: label,
|
||||
isValid: isValid,
|
||||
value: properties.value,
|
||||
isMandatory: isMandatory,
|
||||
isLoading: loading,
|
||||
isVisible: visibility,
|
||||
isDisabled: disable,
|
||||
};
|
||||
setValue(properties.value);
|
||||
|
||||
setExposedVariables(exposedVariables);
|
||||
isInitialRender.current = false;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setValue]);
|
||||
}, []);
|
||||
|
||||
const iconName = styles.icon; // Replace with the name of the icon you want
|
||||
// eslint-disable-next-line import/namespace
|
||||
const IconElement = Icons[iconName] == undefined ? Icons['IconHome2'] : Icons[iconName];
|
||||
// eslint-disable-next-line import/namespace
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isLoading', loading);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loading]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setLoading', async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isVisible', visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setVisibility', async function (state) {
|
||||
setVisibility(state);
|
||||
setExposedVariable('isVisible', state);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setDisable', async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disabledState]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('isDisabled', disable);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
data-cy={`label-${String(component.name).toLowerCase()} `}
|
||||
data-cy={`label-${String(componentName).toLowerCase()} `}
|
||||
className={`text-input d-flex ${
|
||||
defaultAlignment === 'top' &&
|
||||
((width != 0 && label?.length != 0) || (auto && width == 0 && label && label?.length != 0))
|
||||
|
|
@ -343,7 +355,7 @@ export const TextInput = function TextInput({
|
|||
</div>
|
||||
{showValidationError && visibility && (
|
||||
<div
|
||||
data-cy={`${String(component.name).toLowerCase()}-invalid-feedback`}
|
||||
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
|
||||
style={{
|
||||
color: errTextColor,
|
||||
textAlign: direction == 'left' && 'end',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ export const Timer = function Timer({ height, properties = {}, styles, setExpose
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [time]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('value', {});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
intervalId && clearInterval(intervalId);
|
||||
setState('initial');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { resolveWidgetFieldValue } from '@/_helpers/utils';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import Loader from '@/ToolJetUI/Loader/Loader';
|
||||
import OverflowTooltip from '@/_components/OverflowTooltip';
|
||||
|
||||
|
|
@ -94,15 +93,18 @@ export const ToggleSwitchV2 = ({
|
|||
styles,
|
||||
fireEvent,
|
||||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
dataCy,
|
||||
component,
|
||||
validation,
|
||||
componentName,
|
||||
validate,
|
||||
width,
|
||||
}) => {
|
||||
const isInitialRender = useRef(true);
|
||||
const defaultValue = properties.defaultValue ?? false;
|
||||
|
||||
const [on, setOn] = useState(Boolean(defaultValue));
|
||||
const label = properties.label;
|
||||
const isMandatory = validation?.mandatory ?? false;
|
||||
const { isValid, validationError } = validate(on);
|
||||
const [showValidationError, setShowValidationError] = useState(true);
|
||||
const [loading, setLoading] = useState(properties?.loadingState);
|
||||
|
|
@ -110,8 +112,6 @@ export const ToggleSwitchV2 = ({
|
|||
const [visibility, setVisibility] = useState(properties.visibility);
|
||||
const [userInteracted, setUserInteracted] = useState(false);
|
||||
|
||||
const isMandatory = resolveWidgetFieldValue(component?.definition?.validation?.mandatory?.value);
|
||||
|
||||
const { toggleSwitchColor, boxShadow, alignment, borderColor } = styles;
|
||||
const textColor = styles.textColor === '#1B1F24' ? 'var(--text-primary)' : styles.textColor;
|
||||
|
||||
|
|
@ -124,6 +124,7 @@ export const ToggleSwitchV2 = ({
|
|||
// Exposing the initially set false value once on load
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('value', defaultValue);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
||||
|
|
@ -152,55 +153,70 @@ export const ToggleSwitchV2 = ({
|
|||
}, [properties.loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('label', label);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [label]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isMandatory', isMandatory);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isMandatory]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isLoading', loading);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [loading]);
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isVisible', visibility);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isDisabled', disable);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [disable]);
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) return;
|
||||
setExposedVariable('isValid', isValid);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isValid]);
|
||||
useEffect(() => {
|
||||
setExposedVariable('setLoading', async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.loadingState]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setVisibility', async function (state) {
|
||||
setVisibility(state);
|
||||
setExposedVariable('isVisible', state);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.visibility]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setDisable', async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [properties.disabledState]);
|
||||
const exposedVariables = {
|
||||
setValue: async function (value) {
|
||||
setOn(value);
|
||||
setExposedVariable('value', value);
|
||||
setUserInteracted(true);
|
||||
},
|
||||
setVisibility: async function (state) {
|
||||
setVisibility(state);
|
||||
setExposedVariable('isVisible', state);
|
||||
},
|
||||
setDisable: async function (disable) {
|
||||
setDisable(disable);
|
||||
setExposedVariable('isDisabled', disable);
|
||||
},
|
||||
setLoading: async function (loading) {
|
||||
setLoading(loading);
|
||||
setExposedVariable('isLoading', loading);
|
||||
},
|
||||
label: label,
|
||||
isMandatory: isMandatory,
|
||||
isLoading: loading,
|
||||
isVisible: visibility,
|
||||
isDisabled: disable,
|
||||
isValid: isValid,
|
||||
value: defaultValue,
|
||||
};
|
||||
setExposedVariables(exposedVariables);
|
||||
setOn(defaultValue);
|
||||
isInitialRender.current = false;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('toggle', async function () {
|
||||
|
|
@ -212,15 +228,6 @@ export const ToggleSwitchV2 = ({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [on]);
|
||||
|
||||
useEffect(() => {
|
||||
setExposedVariable('setValue', async function (value) {
|
||||
setOn(value);
|
||||
setExposedVariable('value', value);
|
||||
setUserInteracted(true);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const renderInput = () => (
|
||||
<div
|
||||
data-disabled={properties.disabledState}
|
||||
|
|
@ -289,7 +296,7 @@ export const ToggleSwitchV2 = ({
|
|||
{renderInput()}
|
||||
{showValidationError && isMandatory && userInteracted && !on && visibility && (
|
||||
<div
|
||||
data-cy={`${String(component.name).toLowerCase()}-invalid-feedback`}
|
||||
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
|
||||
style={{
|
||||
color: 'var(--status-error-strong)',
|
||||
fontSize: '11px',
|
||||
|
|
|
|||
22
frontend/src/Editor/Components/datepicker.scss
Normal file
22
frontend/src/Editor/Components/datepicker.scss
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
.tj-datepicker-widget {
|
||||
select {
|
||||
color: var(--text-primary) !important;
|
||||
background-color: var(--surfaces-surface-01) !important
|
||||
}
|
||||
|
||||
select option {
|
||||
color: var(--text-primary) !important;
|
||||
background-color: var(--surfaces-surface-01) !important
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// .dark-theme {
|
||||
// select {
|
||||
// color: #fff !important
|
||||
// }
|
||||
|
||||
// select option {
|
||||
// color: #fff !important // This needs to be black since this has no effect on mac but has on windows
|
||||
// }
|
||||
// }
|
||||
|
|
@ -8,6 +8,7 @@ import {
|
|||
redirectToErrorPage,
|
||||
} from './routes';
|
||||
import { ERROR_TYPES } from './constants';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
|
||||
/* [* Be cautious: READ THE CASES BEFORE TOUCHING THE CODE. OTHERWISE YOU MAY SEE ENDLESS REDIRECTIONS (AKA ROUTES-BURMUDA-TRIANGLE) *]
|
||||
What is this function?
|
||||
|
|
@ -133,6 +134,14 @@ export const authorizeUserAndHandleErrors = (workspace_id, workspace_slug, callb
|
|||
authenticationService
|
||||
.authorize()
|
||||
.then((data) => {
|
||||
useStore.getState().setUser({
|
||||
email: data.current_user.email,
|
||||
firstName: data.current_user.first_name,
|
||||
lastName: data.current_user.last_name,
|
||||
id: data.current_user.id,
|
||||
avatarId: data.current_user.avatar_id,
|
||||
groups: data.group_permissions.map((group) => group.group),
|
||||
});
|
||||
/* CASE-1 */
|
||||
const { current_organization_name } = data;
|
||||
/* add the user details like permission and user previlliage details to the subject */
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import { CreateEventHandlerDto, UpdateEventHandlerDto } from '@dto/event-handler
|
|||
import { APP_RESOURCE_ACTIONS } from 'src/constants/global.constant';
|
||||
import { VersionReleaseDto } from '@dto/version-release.dto';
|
||||
import { AppsServiceSep } from '@apps/services/apps.service.sep';
|
||||
import { mergeDefaultComponentData } from 'src/helpers/components.helper';
|
||||
|
||||
@Controller({
|
||||
path: 'apps',
|
||||
|
|
@ -93,7 +94,7 @@ export class AppsControllerV2 {
|
|||
|
||||
response['data_queries'] = seralizedQueries;
|
||||
response['definition'] = app.editingVersion?.definition;
|
||||
response['pages'] = pagesForVersion;
|
||||
response['pages'] = mergeDefaultComponentData(pagesForVersion);
|
||||
response['events'] = eventsForVersion;
|
||||
|
||||
//! if editing version exists, camelize the definition
|
||||
|
|
@ -148,7 +149,7 @@ export class AppsControllerV2 {
|
|||
name: app.name,
|
||||
slug: app.slug,
|
||||
events: eventsForVersion,
|
||||
pages: pagesForVersion,
|
||||
pages: mergeDefaultComponentData(pagesForVersion),
|
||||
homePageId: versionToLoad.homePageId,
|
||||
globalSettings: { ...versionToLoad.globalSettings, theme: appTheme },
|
||||
showViewerNavigation: versionToLoad.showViewerNavigation,
|
||||
|
|
@ -198,7 +199,7 @@ export class AppsControllerV2 {
|
|||
return {
|
||||
...appData,
|
||||
editing_version: editingVersion,
|
||||
pages: pagesForVersion,
|
||||
pages: mergeDefaultComponentData(pagesForVersion),
|
||||
events: eventsForVersion,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
import { cloneDeep } from 'lodash';
|
||||
import { merge } from 'lodash';
|
||||
import { mergeWith } from 'lodash';
|
||||
import { isArray } from 'lodash';
|
||||
import { componentTypes } from './widget-config';
|
||||
|
||||
export enum LayoutDimensionUnits {
|
||||
COUNT = 'count',
|
||||
PERCENT = 'percent',
|
||||
|
|
@ -8,3 +14,58 @@ export const resolveGridPositionForComponent = (dimension: number, type: string)
|
|||
const numberOfGrids = 43;
|
||||
return Math.round((dimension * numberOfGrids) / 100);
|
||||
};
|
||||
|
||||
export const mergeDefaultComponentData = (pages) => {
|
||||
return pages.map((page) => ({
|
||||
...page,
|
||||
components: buildComponentMetaDefinition(page.components),
|
||||
}));
|
||||
};
|
||||
|
||||
export const buildComponentMetaDefinition = (components = {}) => {
|
||||
for (const componentId in components) {
|
||||
const currentComponentData = components[componentId];
|
||||
|
||||
const componentMeta = cloneDeep(
|
||||
componentTypes.find((comp) => currentComponentData.component.component === comp.component)
|
||||
);
|
||||
|
||||
const mergedDefinition = {
|
||||
// ...componentMeta.definition,
|
||||
properties: mergeWith(
|
||||
componentMeta.definition.properties,
|
||||
currentComponentData?.component?.definition?.properties,
|
||||
(objValue, srcValue) => {
|
||||
if (currentComponentData?.component?.component === 'Table' && isArray(objValue)) {
|
||||
return srcValue;
|
||||
}
|
||||
}
|
||||
),
|
||||
styles: merge(componentMeta.definition.styles, currentComponentData?.component.definition.styles),
|
||||
generalStyles: merge(
|
||||
componentMeta.definition.generalStyles,
|
||||
currentComponentData?.component.definition.generalStyles
|
||||
),
|
||||
validation: merge(componentMeta.definition.validation, currentComponentData?.component.definition.validation),
|
||||
others: merge(componentMeta.definition.others, currentComponentData?.component.definition.others),
|
||||
general: merge(componentMeta.definition.general, currentComponentData?.component.definition.general),
|
||||
};
|
||||
|
||||
const mergedComponent = {
|
||||
component: {
|
||||
...componentMeta,
|
||||
...currentComponentData.component,
|
||||
},
|
||||
layouts: {
|
||||
...currentComponentData.layouts,
|
||||
},
|
||||
withDefaultChildren: componentMeta.withDefaultChildren ?? false,
|
||||
};
|
||||
|
||||
mergedComponent.component.definition = mergedDefinition;
|
||||
|
||||
components[componentId] = mergedComponent;
|
||||
}
|
||||
|
||||
return components;
|
||||
};
|
||||
|
|
|
|||
121
server/src/helpers/widget-config/boundedBox.js
Normal file
121
server/src/helpers/widget-config/boundedBox.js
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
export const boundedBoxConfig = {
|
||||
name: 'BoundedBox',
|
||||
displayName: 'Bounded Box',
|
||||
description: 'An infinitely customizable image annotation widget',
|
||||
component: 'BoundedBox',
|
||||
defaultSize: {
|
||||
width: 30,
|
||||
height: 420,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
imageUrl: {
|
||||
type: 'code',
|
||||
displayName: 'Image URL',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: `https://exaple.com/photos/three-cars.jpg`,
|
||||
},
|
||||
},
|
||||
|
||||
defaultValue: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'array', element: { type: 'object' } }] },
|
||||
defaultValue: "{{[{type: 'RECTANGLE',width: 40,height:24, x:41,y:62,text:'Car'}]}}",
|
||||
},
|
||||
},
|
||||
selector: {
|
||||
type: 'select',
|
||||
displayName: 'Selector',
|
||||
options: [
|
||||
{ name: 'Rectangle', value: 'RECTANGLE' },
|
||||
{ name: 'Point', value: 'POINT' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'RECTANGLE',
|
||||
},
|
||||
},
|
||||
labels: {
|
||||
type: 'code',
|
||||
displayName: 'List of labels',
|
||||
validation: {
|
||||
schema: { type: 'array' },
|
||||
element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: `{{['Car', 'Tree']}}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onChange: { displayName: 'On change' },
|
||||
},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
annotations: [
|
||||
{
|
||||
type: 'RECTANGLE',
|
||||
x: 41,
|
||||
y: 62,
|
||||
width: 40,
|
||||
height: 24,
|
||||
text: 'Car',
|
||||
id: 'ce103db2-b2a6-46f5-a4f0-5f4eaa6f3663',
|
||||
},
|
||||
{
|
||||
type: 'RECTANGLE',
|
||||
x: 41,
|
||||
y: 12,
|
||||
width: 40,
|
||||
height: 24,
|
||||
text: 'Tree',
|
||||
id: 'b1a7315e-2b15-4bc8-a1c6-a042dab44f27',
|
||||
},
|
||||
],
|
||||
},
|
||||
actions: [],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
defaultValue: {
|
||||
value:
|
||||
"{{[\t{type: 'RECTANGLE',width: 40,height:24, x:41,y:62,text:'Car'},{type: 'RECTANGLE',width: 40,height:24, x:41,y:12,text:'Tree'}\t]}}",
|
||||
},
|
||||
imageUrl: {
|
||||
value: `https://burst.shopifycdn.com/photos/three-cars-are-parked-on-stone-paved-street.jpg?width=746&format=pjpg&exif=1&iptc=1`,
|
||||
},
|
||||
selector: { value: `RECTANGLE` },
|
||||
labels: { value: `{{['Tree', 'Car', 'Stree light']}}` },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
238
server/src/helpers/widget-config/button.js
Normal file
238
server/src/helpers/widget-config/button.js
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
export const buttonConfig = {
|
||||
name: 'Button',
|
||||
displayName: 'Button',
|
||||
description: 'Trigger actions: queries, alerts, set variables etc.',
|
||||
component: 'Button',
|
||||
defaultSize: {
|
||||
width: 4,
|
||||
height: 40,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
text: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
tooltip: {
|
||||
type: 'code',
|
||||
displayName: 'Tooltip',
|
||||
validation: { schema: { type: 'string' } },
|
||||
section: 'additionalActions',
|
||||
placeholder: 'Enter tooltip text',
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onClick: { displayName: 'On click' },
|
||||
onHover: { displayName: 'On hover' },
|
||||
},
|
||||
styles: {
|
||||
type: {
|
||||
type: 'switch',
|
||||
displayName: 'Type',
|
||||
validation: { schema: { type: 'string' } },
|
||||
options: [
|
||||
{ displayName: 'Solid', value: 'primary' },
|
||||
{ displayName: 'Outline', value: 'outline' },
|
||||
],
|
||||
accordian: 'button',
|
||||
},
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
conditionallyRender: {
|
||||
key: 'type',
|
||||
value: 'primary',
|
||||
},
|
||||
accordian: 'button',
|
||||
},
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
accordian: 'button',
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
accordian: 'button',
|
||||
},
|
||||
loaderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Loader color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
accordian: 'button',
|
||||
},
|
||||
|
||||
icon: {
|
||||
type: 'icon',
|
||||
displayName: 'Icon',
|
||||
validation: { schema: { type: 'string' } },
|
||||
accordian: 'button',
|
||||
|
||||
visibility: false,
|
||||
},
|
||||
iconColor: {
|
||||
type: 'color',
|
||||
displayName: 'Icon color',
|
||||
validation: { schema: { type: 'string' } },
|
||||
accordian: 'button',
|
||||
visibility: false,
|
||||
},
|
||||
|
||||
direction: {
|
||||
type: 'switch',
|
||||
displayName: '',
|
||||
validation: { schema: { type: 'string' } },
|
||||
showLabel: false,
|
||||
isIcon: true,
|
||||
options: [
|
||||
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
|
||||
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
|
||||
],
|
||||
accordian: 'button',
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'numberInput',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
defaultValue: false,
|
||||
},
|
||||
accordian: 'button',
|
||||
},
|
||||
boxShadow: {
|
||||
type: 'boxShadow',
|
||||
displayName: 'Box shadow',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
accordian: 'button',
|
||||
conditionallyRender: {
|
||||
key: 'type',
|
||||
value: 'primary',
|
||||
},
|
||||
},
|
||||
|
||||
padding: {
|
||||
type: 'switch',
|
||||
displayName: 'Padding',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
options: [
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
accordian: 'container',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
buttonText: 'Button',
|
||||
isVisible: true,
|
||||
isDisabled: false,
|
||||
isLoading: false,
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'click',
|
||||
displayName: 'Click',
|
||||
},
|
||||
{
|
||||
handle: 'setText',
|
||||
displayName: 'Set text',
|
||||
params: [{ handle: 'text', displayName: 'Text', defaultValue: 'New Text' }],
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setDisable',
|
||||
displayName: 'Set disable',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setLoading',
|
||||
displayName: 'Set loading',
|
||||
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'disable',
|
||||
displayName: 'Disable(deprecated)',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'visibility',
|
||||
displayName: 'Visibility(deprecated)',
|
||||
params: [{ handle: 'visible', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'loading',
|
||||
displayName: 'Loading(deprecated)',
|
||||
params: [{ handle: 'loading', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
text: { value: `Button` },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
tooltip: { value: '' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
textColor: { value: '#FFFFFF' },
|
||||
borderColor: { value: '#4368E3' },
|
||||
loaderColor: { value: '#FFFFFF' },
|
||||
borderRadius: { value: '{{6}}' },
|
||||
backgroundColor: { value: '#4368E3' },
|
||||
iconColor: { value: '#FFFFFF' },
|
||||
direction: { value: 'left' },
|
||||
padding: { value: 'default' },
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000090' },
|
||||
icon: { value: 'IconAlignBoxBottomLeft' },
|
||||
iconVisibility: { value: false },
|
||||
type: { value: 'primary' },
|
||||
},
|
||||
},
|
||||
};
|
||||
153
server/src/helpers/widget-config/buttonGroup.js
Normal file
153
server/src/helpers/widget-config/buttonGroup.js
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
export const buttonGroupConfig = {
|
||||
name: 'ButtonGroup',
|
||||
displayName: 'Button Group',
|
||||
description: 'Group of buttons',
|
||||
component: 'ButtonGroup',
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Button group',
|
||||
},
|
||||
},
|
||||
values: {
|
||||
type: 'code',
|
||||
displayName: 'values',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'array', element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } }],
|
||||
},
|
||||
defaultValue: '[]',
|
||||
},
|
||||
},
|
||||
labels: {
|
||||
type: 'code',
|
||||
displayName: 'Labels',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'array', element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } }],
|
||||
},
|
||||
defaultValue: '[]',
|
||||
},
|
||||
},
|
||||
defaultSelected: {
|
||||
type: 'code',
|
||||
displayName: 'Default selected',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'array', element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } }],
|
||||
},
|
||||
defaultValue: '[1]',
|
||||
},
|
||||
},
|
||||
multiSelection: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable multiple selection',
|
||||
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultSize: {
|
||||
width: 12,
|
||||
height: 80,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
events: {
|
||||
onClick: { displayName: 'On click' },
|
||||
},
|
||||
styles: {
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'number',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
selectedTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Selected text colour',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#fff',
|
||||
},
|
||||
},
|
||||
selectedBackgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Selected background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#007bff',
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
selected: [1],
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
label: { value: `Button group` },
|
||||
defaultSelected: { value: '{{[1]}}' },
|
||||
values: { value: '{{[1,2,3]}}' },
|
||||
labels: { value: '{{[]}}' },
|
||||
multiSelection: { value: '{{false}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
backgroundColor: { value: '' },
|
||||
textColor: { value: '' },
|
||||
visibility: { value: '{{true}}' },
|
||||
borderRadius: { value: '{{4}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
selectedTextColor: { value: '' },
|
||||
selectedBackgroundColor: { value: '' },
|
||||
},
|
||||
},
|
||||
};
|
||||
111
server/src/helpers/widget-config/calendar.js
Normal file
111
server/src/helpers/widget-config/calendar.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
export const calendarConfig = {
|
||||
name: 'Calendar',
|
||||
displayName: 'Calendar',
|
||||
description: 'Display calendar events',
|
||||
component: 'Calendar',
|
||||
defaultSize: {
|
||||
width: 30,
|
||||
height: 600,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
dateFormat: { type: 'code', displayName: 'Date format' },
|
||||
defaultDate: { type: 'code', displayName: 'Default date' },
|
||||
events: { type: 'code', displayName: 'Events' },
|
||||
resources: { type: 'code', displayName: 'Resources' },
|
||||
defaultView: { type: 'code', displayName: 'Default view' },
|
||||
startTime: {
|
||||
type: 'code',
|
||||
displayName: 'Start time on week and day view',
|
||||
},
|
||||
endTime: { type: 'code', displayName: 'End time on week and day view' },
|
||||
displayToolbar: { type: 'toggle', displayName: 'Show toolbar' },
|
||||
displayViewSwitcher: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show view switcher',
|
||||
},
|
||||
highlightToday: { type: 'toggle', displayName: 'Highlight today' },
|
||||
showPopOverOnEventClick: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show popover when event is clicked',
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onCalendarEventSelect: { displayName: 'On Event Select' },
|
||||
onCalendarSlotSelect: { displayName: 'On Slot Select' },
|
||||
onCalendarNavigate: { displayName: 'On Date Navigate' },
|
||||
onCalendarViewChange: { displayName: 'On View Change' },
|
||||
},
|
||||
styles: {
|
||||
visibility: { type: 'toggle', displayName: 'Visibility' },
|
||||
cellSizeInViewsClassifiedByResource: {
|
||||
type: 'select',
|
||||
displayName: 'Cell size in views classified by resource',
|
||||
options: [
|
||||
{ name: 'Compact', value: 'compact' },
|
||||
{ name: 'Spacious', value: 'spacious' },
|
||||
],
|
||||
},
|
||||
weekDateFormat: {
|
||||
type: 'code',
|
||||
displayName: 'Header date format on week view',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
selectedEvent: {},
|
||||
selectedSlots: {},
|
||||
currentView: 'month',
|
||||
currentDate: undefined,
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
dateFormat: {
|
||||
value: 'MM-DD-YYYY HH:mm:ss A Z',
|
||||
},
|
||||
defaultDate: {
|
||||
value: '{{moment().format("MM-DD-YYYY HH:mm:ss A Z")}}',
|
||||
},
|
||||
events: {
|
||||
value:
|
||||
"{{[\n\t\t{\n\t\t\t title: 'Sample event',\n\t\t\t start: `${moment().startOf('day').format('MM-DD-YYYY HH:mm:ss A Z')}`,\n\t\t\t end: `${moment().endOf('day').format('MM-DD-YYYY HH:mm:ss A Z')}`,\n\t\t\t allDay: false,\n\t\t\t color: '#4D72DA'\n\t\t}\n]}}",
|
||||
},
|
||||
resources: {
|
||||
value: '{{[]}}',
|
||||
},
|
||||
defaultView: {
|
||||
value: "{{'month'}}",
|
||||
},
|
||||
startTime: {
|
||||
value: "{{moment().startOf('day').format('MM-DD-YYYY HH:mm:ss A Z')}}",
|
||||
},
|
||||
endTime: {
|
||||
value: "{{moment().endOf('day').format('MM-DD-YYYY HH:mm:ss A Z')}}",
|
||||
},
|
||||
displayToolbar: {
|
||||
value: true,
|
||||
},
|
||||
displayViewSwitcher: {
|
||||
value: true,
|
||||
},
|
||||
highlightToday: {
|
||||
value: true,
|
||||
},
|
||||
showPopOverOnEventClick: {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
cellSizeInViewsClassifiedByResource: { value: 'spacious' },
|
||||
weekDateFormat: { value: 'DD MMM' },
|
||||
},
|
||||
},
|
||||
};
|
||||
238
server/src/helpers/widget-config/chart.js
Normal file
238
server/src/helpers/widget-config/chart.js
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
export const chartConfig = {
|
||||
name: 'Chart',
|
||||
displayName: 'Chart',
|
||||
description: 'Visualize data',
|
||||
component: 'Chart',
|
||||
defaultSize: {
|
||||
width: 20,
|
||||
height: 400,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
title: {
|
||||
type: 'code',
|
||||
displayName: 'Title',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defaultValue: 'This title can be changed',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: 'json',
|
||||
displayName: 'Data',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'array' }] },
|
||||
defaultValue: '',
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
markerColor: {
|
||||
type: 'color',
|
||||
displayName: 'Marker color',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defaultValue: '#CDE1F8',
|
||||
},
|
||||
},
|
||||
showAxes: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show axes',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
showGridLines: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show grid lines',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
type: {
|
||||
type: 'select',
|
||||
displayName: 'Chart type',
|
||||
options: [
|
||||
{ name: 'Line', value: 'line' },
|
||||
{ name: 'Bar', value: 'bar' },
|
||||
{ name: 'Pie', value: 'pie' },
|
||||
],
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'boolean' }, { type: 'number' }],
|
||||
},
|
||||
defaultValue: 'line',
|
||||
},
|
||||
},
|
||||
jsonDescription: {
|
||||
type: 'json',
|
||||
displayName: 'Json Description',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'object' }],
|
||||
},
|
||||
defaultValue: '{ "data": [ { "x": [ "Jan", "Feb", "Mar" ], "y": [ 100, 80, 40 ], "type": "bar" } ] }',
|
||||
},
|
||||
},
|
||||
plotFromJson: {
|
||||
type: 'toggle',
|
||||
displayName: 'Use Plotly JSON schema',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
barmode: {
|
||||
type: 'select',
|
||||
displayName: 'Bar mode',
|
||||
options: [
|
||||
{ name: 'Stack', value: 'stack' },
|
||||
{ name: 'Group', value: 'group' },
|
||||
{ name: 'Overlay', value: 'overlay' },
|
||||
{ name: 'Relative', value: 'relative' },
|
||||
],
|
||||
validation: {
|
||||
schema: {
|
||||
schemas: { type: 'string' },
|
||||
},
|
||||
defaultValue: 'group',
|
||||
},
|
||||
},
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'clearClickedPoint',
|
||||
displayName: 'Clear clicked point',
|
||||
},
|
||||
],
|
||||
events: {
|
||||
onClick: { displayName: 'On data point click' },
|
||||
onDoubleClick: { displayName: 'On double click' },
|
||||
},
|
||||
styles: {
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background color',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
|
||||
},
|
||||
padding: {
|
||||
type: 'code',
|
||||
displayName: 'Padding',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'number' }, { type: 'string' }],
|
||||
},
|
||||
defaultValue: 50,
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'number',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
show: null,
|
||||
chartTitle: null,
|
||||
xAxisTitle: null,
|
||||
yAxisTitle: null,
|
||||
clickedDataPoint: {},
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
title: { value: 'This title can be changed' },
|
||||
markerColor: { value: '#CDE1F8' },
|
||||
showAxes: { value: '{{true}}' },
|
||||
showGridLines: { value: '{{true}}' },
|
||||
plotFromJson: { value: '{{false}}' },
|
||||
loadingState: { value: `{{false}}` },
|
||||
barmode: { value: `group` },
|
||||
jsonDescription: {
|
||||
value: `{
|
||||
"data": [
|
||||
{
|
||||
"x": [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar"
|
||||
],
|
||||
"y": [
|
||||
100,
|
||||
80,
|
||||
40
|
||||
],
|
||||
"type": "bar"
|
||||
}
|
||||
]
|
||||
}`,
|
||||
},
|
||||
type: { value: `line` },
|
||||
data: {
|
||||
value: `[
|
||||
{ "x": "Jan", "y": 100},
|
||||
{ "x": "Feb", "y": 80},
|
||||
{ "x": "Mar", "y": 40}
|
||||
]`,
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
backgroundColor: { value: '#fff' },
|
||||
padding: { value: '50' },
|
||||
borderRadius: { value: '{{4}}' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
198
server/src/helpers/widget-config/checkbox.js
Normal file
198
server/src/helpers/widget-config/checkbox.js
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
export const checkboxConfig = {
|
||||
name: 'Checkbox',
|
||||
displayName: 'Checkbox',
|
||||
description: 'Single checkbox toggle',
|
||||
component: 'Checkbox',
|
||||
defaultSize: {
|
||||
width: 6,
|
||||
height: 30,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
},
|
||||
defaultValue: {
|
||||
type: 'switch',
|
||||
displayName: 'Default state',
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
options: [
|
||||
{ displayName: 'On', value: '{{true}}' },
|
||||
{ displayName: 'Off', value: '{{false}}' },
|
||||
],
|
||||
accordian: 'label',
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
tooltip: {
|
||||
type: 'code',
|
||||
displayName: 'Tooltip',
|
||||
validation: { schema: { type: 'string' } },
|
||||
section: 'additionalActions',
|
||||
placeholder: 'Enter tooltip text',
|
||||
},
|
||||
},
|
||||
validation: {
|
||||
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
|
||||
customRule: {
|
||||
type: 'code',
|
||||
displayName: 'Custom validation',
|
||||
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onChange: { displayName: 'On change' },
|
||||
onCheck: { displayName: 'On check (Deprecated)' },
|
||||
onUnCheck: { displayName: 'On uncheck (Deprecated)' },
|
||||
},
|
||||
styles: {
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
accordian: 'label',
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
accordian: 'switch',
|
||||
},
|
||||
checkboxColor: {
|
||||
type: 'color',
|
||||
displayName: 'Checked color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
accordian: 'switch',
|
||||
},
|
||||
uncheckedColor: {
|
||||
type: 'color',
|
||||
displayName: 'Unchecked color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
accordian: 'switch',
|
||||
},
|
||||
handleColor: {
|
||||
type: 'color',
|
||||
displayName: 'Handle color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
accordian: 'switch',
|
||||
},
|
||||
boxShadow: {
|
||||
type: 'boxShadow',
|
||||
displayName: 'Box shadow',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
accordian: 'switch',
|
||||
},
|
||||
|
||||
alignment: {
|
||||
type: 'switch',
|
||||
displayName: 'Alignment',
|
||||
validation: { schema: { type: 'string' } },
|
||||
options: [
|
||||
{ displayName: 'Left', value: 'left' },
|
||||
{ displayName: 'Right', value: 'right' },
|
||||
],
|
||||
accordian: 'label',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: false,
|
||||
label: 'Label',
|
||||
isMandatory: false,
|
||||
isVisible: true,
|
||||
isDisabled: false,
|
||||
isLoading: false,
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'toggle',
|
||||
displayName: 'toggle',
|
||||
},
|
||||
{
|
||||
handle: 'setValue',
|
||||
displayName: 'Set value',
|
||||
params: [{ handle: 'value', displayName: 'value' }],
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setDisable',
|
||||
displayName: 'Set disable',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setLoading',
|
||||
displayName: 'Set loading',
|
||||
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setChecked',
|
||||
displayName: 'Set checked (Deprecated)',
|
||||
params: [{ handle: 'status', displayName: 'status' }],
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
label: { value: 'Label' },
|
||||
defaultValue: { value: '{{false}}' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
tooltip: { value: '' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
disabledState: { value: '{{false}}' },
|
||||
textColor: { value: '#1B1F24' },
|
||||
checkboxColor: { value: '#4368E3' },
|
||||
uncheckedColor: { value: '#E4E7EB' },
|
||||
borderColor: { value: '#CCD1D5' },
|
||||
handleColor: { value: '#FFFFFF' },
|
||||
alignment: { value: 'right' },
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000090' },
|
||||
},
|
||||
validation: {
|
||||
mandatory: { value: '{{false}}' },
|
||||
customRule: { value: null },
|
||||
},
|
||||
},
|
||||
};
|
||||
116
server/src/helpers/widget-config/circularProgressbar.js
Normal file
116
server/src/helpers/widget-config/circularProgressbar.js
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
export const circularProgressbarConfig = {
|
||||
name: 'CircularProgressBar',
|
||||
displayName: 'Circular Progressbar',
|
||||
description: 'Show circular progress',
|
||||
component: 'CircularProgressBar',
|
||||
defaultSize: {
|
||||
width: 7,
|
||||
height: 50,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
text: {
|
||||
type: 'code',
|
||||
displayName: 'Text',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'text',
|
||||
},
|
||||
},
|
||||
progress: {
|
||||
type: 'code',
|
||||
displayName: 'Progress',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
color: {
|
||||
type: 'color',
|
||||
displayName: 'Color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#375FCF',
|
||||
},
|
||||
},
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text Color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#fff',
|
||||
},
|
||||
},
|
||||
textSize: {
|
||||
type: 'code',
|
||||
displayName: 'Text size',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 16,
|
||||
},
|
||||
},
|
||||
strokeWidth: {
|
||||
type: 'code',
|
||||
displayName: 'Stroke width',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 8,
|
||||
},
|
||||
},
|
||||
counterClockwise: {
|
||||
type: 'code',
|
||||
displayName: 'Counter clockwise',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
circleRatio: {
|
||||
type: 'code',
|
||||
displayName: 'Circle ratio',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 1,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
text: {
|
||||
value: '',
|
||||
},
|
||||
progress: {
|
||||
value: '{{50}}',
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
color: { value: '' },
|
||||
textColor: { value: '' },
|
||||
textSize: { value: '{{16}}' },
|
||||
strokeWidth: { value: '{{8}}' },
|
||||
counterClockwise: { value: '{{false}}' },
|
||||
circleRatio: { value: '{{1}}' },
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
87
server/src/helpers/widget-config/codeEditor.js
Normal file
87
server/src/helpers/widget-config/codeEditor.js
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
export const codeEditorConfig = {
|
||||
name: 'CodeEditor',
|
||||
displayName: 'Code Editor',
|
||||
description: 'Edit source code',
|
||||
component: 'CodeEditor',
|
||||
defaultSize: {
|
||||
width: 15,
|
||||
height: 120,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
enableLineNumber: {
|
||||
type: 'code',
|
||||
displayName: 'Show line number',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
mode: {
|
||||
type: 'code',
|
||||
displayName: 'Mode',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'javascript',
|
||||
},
|
||||
},
|
||||
placeholder: {
|
||||
type: 'code',
|
||||
displayName: 'Placeholder',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'placeholder',
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'code',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: '',
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
enableLineNumber: { value: '{{true}}' },
|
||||
mode: { value: 'javascript' },
|
||||
placeholder: { value: '' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
borderRadius: { value: '{{4}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
50
server/src/helpers/widget-config/colorPicker.js
Normal file
50
server/src/helpers/widget-config/colorPicker.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
export const colorPickerConfig = {
|
||||
name: 'ColorPicker',
|
||||
displayName: 'Color Picker',
|
||||
description: 'Choose colors from a palette',
|
||||
component: 'ColorPicker',
|
||||
properties: {
|
||||
defaultColor: { type: 'color', displayName: 'Default color' },
|
||||
},
|
||||
defaultSize: {
|
||||
width: 9,
|
||||
height: 40,
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
displayName: 'Set Color',
|
||||
handle: 'setColor',
|
||||
params: [{ handle: 'color', displayName: 'color', defaultValue: '#ffffff', type: 'color' }],
|
||||
},
|
||||
],
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
events: {
|
||||
onChange: { displayName: 'On change' },
|
||||
},
|
||||
styles: {
|
||||
visibility: { type: 'toggle', displayName: 'Visibility' },
|
||||
},
|
||||
exposedVariables: {
|
||||
selectedColorHex: '#000000',
|
||||
selectedColorRGB: 'rgb(0,0,0)',
|
||||
selectedColorRGBA: 'rgba(0, 0, 0, 1)',
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
defaultColor: {
|
||||
value: '#000000',
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
89
server/src/helpers/widget-config/container.js
Normal file
89
server/src/helpers/widget-config/container.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
export const containerConfig = {
|
||||
name: 'Container',
|
||||
displayName: 'Container',
|
||||
description: 'Group components',
|
||||
defaultSize: {
|
||||
width: 5,
|
||||
height: 200,
|
||||
},
|
||||
component: 'Container',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#fff',
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'code',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }],
|
||||
},
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#fff',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
visible: { value: '{{true}}' },
|
||||
loadingState: { value: `{{false}}` },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
backgroundColor: { value: '#fff' },
|
||||
borderRadius: { value: '4' },
|
||||
borderColor: { value: '#fff' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
65
server/src/helpers/widget-config/customComponent.js
Normal file
65
server/src/helpers/widget-config/customComponent.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
export const customComponentConfig = {
|
||||
name: 'CustomComponent',
|
||||
displayName: 'Custom Component',
|
||||
description: 'Create React components',
|
||||
component: 'CustomComponent',
|
||||
properties: {
|
||||
data: { type: 'code', displayName: 'Data', validation: { schema: { type: 'object' }, defaultValue: '{}' } },
|
||||
code: { type: 'code', displayName: 'Code' },
|
||||
},
|
||||
defaultSize: {
|
||||
width: 20,
|
||||
height: 140,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
data: { value: `{{{ title: 'Hi! There', buttonText: 'Update Title'}}}` },
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
visible: { value: '{{true}}' },
|
||||
data: {
|
||||
value: `{{{ title: 'Hi! There', buttonText: 'Update Title'}}}`,
|
||||
},
|
||||
code: {
|
||||
value: `import React from 'https://cdn.skypack.dev/react';
|
||||
import ReactDOM from 'https://cdn.skypack.dev/react-dom';
|
||||
import { Button, Container } from 'https://cdn.skypack.dev/@material-ui/core';
|
||||
const MyCustomComponent = ({data, updateData, runQuery}) => (
|
||||
<Container>
|
||||
<h1>{data.title}</h1>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
onClick={() => {updateData({title: 'Hello World!!'})}}
|
||||
>
|
||||
{data.buttonText}
|
||||
</Button>
|
||||
</Container>
|
||||
);
|
||||
const ConnectedComponent = Tooljet.connectComponent(MyCustomComponent);
|
||||
ReactDOM.render(<ConnectedComponent />, document.body);`,
|
||||
skipResolve: true,
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
113
server/src/helpers/widget-config/datepicker.js
Normal file
113
server/src/helpers/widget-config/datepicker.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
export const datepickerConfig = {
|
||||
name: 'Datepicker',
|
||||
displayName: 'Date Picker',
|
||||
description: 'Choose date and time',
|
||||
component: 'Datepicker',
|
||||
defaultSize: {
|
||||
width: 5,
|
||||
height: 30,
|
||||
},
|
||||
validation: {
|
||||
customRule: { type: 'code', displayName: 'Custom validation' },
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
defaultValue: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '01/01/2022',
|
||||
},
|
||||
},
|
||||
format: {
|
||||
type: 'code',
|
||||
displayName: 'Format',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'DD/MM/YYYY',
|
||||
},
|
||||
},
|
||||
enableTime: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable time selection?',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
enableDate: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable date selection?',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledDates: {
|
||||
type: 'code',
|
||||
displayName: 'Disabled dates',
|
||||
validation: {
|
||||
schema: { type: 'array', element: { type: 'string' } },
|
||||
defaultValue: "['01/01/2022']",
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onSelect: { displayName: 'On select' },
|
||||
},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'code',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: '',
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
validation: {
|
||||
customRule: { value: '' },
|
||||
},
|
||||
properties: {
|
||||
defaultValue: { value: '01/01/2022' },
|
||||
format: { value: 'DD/MM/YYYY' },
|
||||
enableTime: { value: '{{false}}' },
|
||||
enableDate: { value: '{{true}}' },
|
||||
disabledDates: { value: '{{[]}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
borderRadius: { value: '{{4}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
104
server/src/helpers/widget-config/daterangepicker.js
Normal file
104
server/src/helpers/widget-config/daterangepicker.js
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
export const daterangepickerConfig = {
|
||||
name: 'DateRangePicker',
|
||||
displayName: 'Range Picker',
|
||||
description: 'Choose date ranges',
|
||||
component: 'DaterangePicker',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 30,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
defaultStartDate: {
|
||||
type: 'code',
|
||||
displayName: 'Default start date',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defautlValue: '01/04/2022',
|
||||
},
|
||||
},
|
||||
defaultEndDate: {
|
||||
type: 'code',
|
||||
displayName: 'Default end date',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defautlValue: '10/04/2022',
|
||||
},
|
||||
},
|
||||
format: {
|
||||
type: 'code',
|
||||
displayName: 'Format',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defautlValue: 'DD/MM/YYYY',
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onSelect: { displayName: 'On select' },
|
||||
},
|
||||
styles: {
|
||||
borderRadius: {
|
||||
type: 'code',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'number' }, { type: 'string' }],
|
||||
},
|
||||
defautlValue: 4,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defautlValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defautlValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
endDate: {},
|
||||
startDate: {},
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
defaultStartDate: { value: '01/04/2022' },
|
||||
defaultEndDate: { value: '10/04/2022' },
|
||||
|
||||
format: { value: 'DD/MM/YYYY' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
borderRadius: { value: '4' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
49
server/src/helpers/widget-config/divider.js
Normal file
49
server/src/helpers/widget-config/divider.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
export const dividerConfig = {
|
||||
name: 'Divider',
|
||||
displayName: 'Divider',
|
||||
description: 'Separator between components',
|
||||
component: 'Divider',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 10,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {},
|
||||
events: {},
|
||||
styles: {
|
||||
dividerColor: {
|
||||
type: 'color',
|
||||
displayName: 'Divider color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000000',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: {},
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
dividerColor: { value: '#000000' },
|
||||
},
|
||||
},
|
||||
};
|
||||
205
server/src/helpers/widget-config/dropdown.js
Normal file
205
server/src/helpers/widget-config/dropdown.js
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
export const dropdownConfig = {
|
||||
name: 'DropdownLegacy',
|
||||
displayName: 'Dropdown (Legacy)',
|
||||
description: 'Single item selector',
|
||||
defaultSize: {
|
||||
width: 8,
|
||||
height: 30,
|
||||
},
|
||||
component: 'DropDown',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
validation: {
|
||||
customRule: { type: 'code', displayName: 'Custom validation' },
|
||||
},
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Select',
|
||||
},
|
||||
},
|
||||
placeholder: {
|
||||
type: 'code',
|
||||
displayName: 'Placeholder',
|
||||
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Select an option',
|
||||
},
|
||||
},
|
||||
advanced: {
|
||||
type: 'toggle',
|
||||
displayName: 'Advanced',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
value: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: false,
|
||||
},
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }],
|
||||
},
|
||||
defaultValue: 2,
|
||||
},
|
||||
},
|
||||
values: {
|
||||
type: 'code',
|
||||
displayName: 'Option values',
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: false,
|
||||
},
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'array',
|
||||
element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }] },
|
||||
},
|
||||
defaultValue: "['one', 'two', 'three']",
|
||||
},
|
||||
},
|
||||
display_values: {
|
||||
type: 'code',
|
||||
displayName: 'Option labels',
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: false,
|
||||
},
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'array',
|
||||
element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }] },
|
||||
},
|
||||
defaultValue: "['one', 'two', 'three']",
|
||||
},
|
||||
},
|
||||
|
||||
schema: {
|
||||
type: 'code',
|
||||
displayName: 'Schema',
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Options loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onSelect: { displayName: 'On select' },
|
||||
onSearchTextChanged: { displayName: 'On search text changed' },
|
||||
},
|
||||
styles: {
|
||||
borderRadius: {
|
||||
type: 'code',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'number' }, { type: 'string' }],
|
||||
},
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
selectedTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Selected text color',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defaultValue: '#000000',
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
justifyContent: {
|
||||
type: 'alignButtons',
|
||||
displayName: 'Align Text',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defaultValue: 'left',
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: 2,
|
||||
searchText: '',
|
||||
label: 'Select',
|
||||
optionLabels: ['one', 'two', 'three'],
|
||||
selectedOptionLabel: 'two',
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'selectOption',
|
||||
displayName: 'Select option',
|
||||
params: [{ handle: 'select', displayName: 'Select' }],
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
validation: {
|
||||
customRule: { value: null },
|
||||
},
|
||||
properties: {
|
||||
advanced: { value: `{{false}}` },
|
||||
schema: {
|
||||
value:
|
||||
"{{[\t{label: 'One',value: 1,disable: false,visible: true,default: true},{label: 'Two',value: 2,disable: false,visible: true},{label: 'Three',value: 3,disable: false,visible: true}\t]}}",
|
||||
},
|
||||
|
||||
label: { value: 'Select' },
|
||||
value: { value: '{{2}}' },
|
||||
values: { value: '{{[1,2,3]}}' },
|
||||
display_values: { value: '{{["one", "two", "three"]}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
placeholder: { value: 'Select an option' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
borderRadius: { value: '4' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
justifyContent: { value: 'left' },
|
||||
},
|
||||
},
|
||||
};
|
||||
330
server/src/helpers/widget-config/dropdownV2.js
Normal file
330
server/src/helpers/widget-config/dropdownV2.js
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
export const dropdownV2Config = {
|
||||
name: 'Dropdown',
|
||||
displayName: 'Dropdown',
|
||||
description: 'Single item selector',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 40,
|
||||
},
|
||||
component: 'DropdownV2',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
validation: {
|
||||
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
|
||||
customRule: {
|
||||
type: 'code',
|
||||
displayName: 'Custom validation',
|
||||
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Select',
|
||||
},
|
||||
accordian: 'Data',
|
||||
},
|
||||
placeholder: {
|
||||
type: 'code',
|
||||
displayName: 'Placeholder',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Select an option',
|
||||
},
|
||||
accordian: 'Data',
|
||||
},
|
||||
advanced: {
|
||||
type: 'toggle',
|
||||
displayName: 'Dynamic options',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
},
|
||||
accordian: 'Options',
|
||||
},
|
||||
schema: {
|
||||
type: 'code',
|
||||
displayName: 'Schema',
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: true,
|
||||
},
|
||||
accordian: 'Options',
|
||||
},
|
||||
optionsLoadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Options loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
},
|
||||
accordian: 'Options',
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
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',
|
||||
},
|
||||
tooltip: {
|
||||
type: 'code',
|
||||
displayName: 'Tooltip',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Enter tooltip text',
|
||||
},
|
||||
section: 'additionalActions',
|
||||
placeholder: 'Enter tooltip text',
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onSelect: { displayName: 'On select' },
|
||||
onSearchTextChanged: { displayName: 'On search text changed' },
|
||||
onFocus: { displayName: 'On focus' },
|
||||
onBlur: { displayName: 'On blur' },
|
||||
},
|
||||
styles: {
|
||||
labelColor: {
|
||||
type: 'color',
|
||||
displayName: 'Color',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
|
||||
accordian: 'label',
|
||||
},
|
||||
alignment: {
|
||||
type: 'switch',
|
||||
displayName: 'Alignment',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'side' },
|
||||
options: [
|
||||
{ displayName: 'Side', value: 'side' },
|
||||
{ displayName: 'Top', value: 'top' },
|
||||
],
|
||||
accordian: 'label',
|
||||
},
|
||||
direction: {
|
||||
type: 'switch',
|
||||
displayName: 'Direction',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'left' },
|
||||
showLabel: false,
|
||||
isIcon: true,
|
||||
options: [
|
||||
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
|
||||
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
|
||||
],
|
||||
accordian: 'label',
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
labelWidth: {
|
||||
type: 'slider',
|
||||
displayName: 'Width',
|
||||
accordian: 'label',
|
||||
conditionallyRender: {
|
||||
key: 'alignment',
|
||||
value: 'side',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
auto: {
|
||||
type: 'checkbox',
|
||||
displayName: 'auto',
|
||||
showLabel: false,
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
accordian: 'label',
|
||||
conditionallyRender: {
|
||||
key: 'alignment',
|
||||
value: 'side',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
|
||||
fieldBackgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
|
||||
accordian: 'field',
|
||||
},
|
||||
fieldBorderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
|
||||
accordian: 'field',
|
||||
},
|
||||
accentColor: {
|
||||
type: 'color',
|
||||
displayName: 'Accent',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
|
||||
accordian: 'field',
|
||||
},
|
||||
selectedTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
|
||||
accordian: 'field',
|
||||
},
|
||||
errTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Error text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
|
||||
accordian: 'field',
|
||||
},
|
||||
icon: {
|
||||
type: 'icon',
|
||||
displayName: 'Icon',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'IconHome2' },
|
||||
accordian: 'field',
|
||||
visibility: false,
|
||||
},
|
||||
iconColor: {
|
||||
type: 'color',
|
||||
displayName: '',
|
||||
showLabel: false,
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#6A727C',
|
||||
},
|
||||
accordian: 'field',
|
||||
},
|
||||
fieldBorderRadius: {
|
||||
type: 'input',
|
||||
displayName: 'Border radius',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: '6' },
|
||||
accordian: 'field',
|
||||
},
|
||||
boxShadow: {
|
||||
type: 'boxShadow',
|
||||
displayName: 'Box shadow',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: '0px 0px 0px 0px #00000040',
|
||||
},
|
||||
accordian: 'field',
|
||||
},
|
||||
padding: {
|
||||
type: 'switch',
|
||||
displayName: 'Padding',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: 'default',
|
||||
},
|
||||
options: [
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
accordian: 'container',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
searchText: '',
|
||||
label: 'Select',
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'selectOption',
|
||||
displayName: 'Select option',
|
||||
params: [{ handle: 'select', displayName: 'Select' }],
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
params: [{ handle: 'setVisibility', displayName: 'Value', defaultValue: `{{true}}`, type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'clear',
|
||||
displayName: 'Clear',
|
||||
},
|
||||
{
|
||||
handle: 'setLoading',
|
||||
displayName: 'Set loading',
|
||||
params: [{ handle: 'setLoading', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setDisable',
|
||||
displayName: 'Set disable',
|
||||
params: [{ handle: 'setDisable', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
validation: {
|
||||
mandatory: { value: '{{false}}' },
|
||||
customRule: { value: null },
|
||||
},
|
||||
properties: {
|
||||
advanced: { value: `{{false}}` },
|
||||
schema: {
|
||||
value:
|
||||
"{{[\t{label: 'option1',value: 1,disable: false,visible: true,default: true},{label: 'option2',value: 2,disable: false,visible: true},{label: 'option3',value: 3,disable: false,visible: true}\t]}}",
|
||||
},
|
||||
options: {
|
||||
value: [
|
||||
{
|
||||
label: 'option1',
|
||||
value: '1',
|
||||
disable: { value: false },
|
||||
visible: { value: true },
|
||||
default: { value: false },
|
||||
},
|
||||
{
|
||||
label: 'option2',
|
||||
value: '2',
|
||||
disable: { value: false },
|
||||
visible: { value: true },
|
||||
default: { value: true },
|
||||
},
|
||||
{
|
||||
label: 'option3',
|
||||
value: '3',
|
||||
disable: { value: false },
|
||||
visible: { value: true },
|
||||
default: { value: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
label: { value: 'Select' },
|
||||
value: { value: '{{"2"}}' },
|
||||
optionsLoadingState: { value: '{{false}}' },
|
||||
placeholder: { value: 'Select an option' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
tooltip: { value: '' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
labelColor: { value: '#1B1F24' },
|
||||
labelWidth: { value: '33' },
|
||||
auto: { value: '{{true}}' },
|
||||
fieldBorderRadius: { value: '6' },
|
||||
selectedTextColor: { value: '#1B1F24' },
|
||||
fieldBorderColor: { value: '#CCD1D5' },
|
||||
errTextColor: { value: '#D72D39' },
|
||||
fieldBackgroundColor: { value: '#fff' },
|
||||
direction: { value: 'left' },
|
||||
alignment: { value: 'side' },
|
||||
padding: { value: 'default' },
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000090' },
|
||||
icon: { value: 'IconHome2' },
|
||||
iconVisibility: { value: false },
|
||||
iconColor: { value: '#6A727C' },
|
||||
accentColor: { value: '#4368E3' },
|
||||
},
|
||||
},
|
||||
};
|
||||
192
server/src/helpers/widget-config/filepicker.js
Normal file
192
server/src/helpers/widget-config/filepicker.js
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
export const filepickerConfig = {
|
||||
name: 'FilePicker',
|
||||
displayName: 'File Picker',
|
||||
description: 'File Picker',
|
||||
component: 'FilePicker',
|
||||
defaultSize: {
|
||||
width: 15,
|
||||
height: 100,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'clearFiles',
|
||||
displayName: 'Clear Files',
|
||||
},
|
||||
],
|
||||
properties: {
|
||||
instructionText: {
|
||||
type: 'code',
|
||||
displayName: 'Instruction text',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Instruction text',
|
||||
},
|
||||
},
|
||||
enableDropzone: {
|
||||
type: 'code',
|
||||
displayName: 'Use drop zone',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
enablePicker: {
|
||||
type: 'code',
|
||||
displayName: 'Use file picker',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
enableMultiple: {
|
||||
type: 'code',
|
||||
displayName: 'Pick multiple files',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
maxFileCount: {
|
||||
type: 'code',
|
||||
displayName: 'Max file count',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }],
|
||||
},
|
||||
defaultValue: 2,
|
||||
},
|
||||
},
|
||||
fileType: {
|
||||
type: 'code',
|
||||
displayName: 'Accept file types',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defaultValue: 'image/*',
|
||||
},
|
||||
},
|
||||
maxSize: {
|
||||
type: 'code',
|
||||
displayName: 'Max size limit (Bytes)',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }],
|
||||
},
|
||||
defaultValue: 1048576,
|
||||
},
|
||||
},
|
||||
minSize: {
|
||||
type: 'code',
|
||||
displayName: 'Min size limit (Bytes)',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }],
|
||||
},
|
||||
defaultValue: 50,
|
||||
},
|
||||
},
|
||||
parseContent: {
|
||||
type: 'toggle',
|
||||
displayName: 'Parse content',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
parseFileType: {
|
||||
type: 'select',
|
||||
displayName: 'File type',
|
||||
options: [
|
||||
{ name: 'Autodetect from extension', value: 'auto-detect' },
|
||||
{ name: 'CSV', value: 'csv' },
|
||||
{ name: 'Microsoft Excel - xls', value: 'vnd.ms-excel' },
|
||||
{
|
||||
name: 'Microsoft Excel - xlsx',
|
||||
value: 'vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
},
|
||||
],
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defaultValue: 'auto-detect',
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onFileSelected: { displayName: 'On File Selected' },
|
||||
onFileLoaded: { displayName: 'On File Loaded' },
|
||||
onFileDeselected: { displayName: 'On File Deselected' },
|
||||
},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'code',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }],
|
||||
},
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
file: [{ name: '', content: '', dataURL: '', type: '', parsedData: '' }],
|
||||
isParsing: false,
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
instructionText: { value: 'Drag and drop files here or click to select files' },
|
||||
enableDropzone: { value: '{{true}}' },
|
||||
enablePicker: { value: '{{true}}' },
|
||||
maxFileCount: { value: '{{2}}' },
|
||||
enableMultiple: { value: '{{false}}' },
|
||||
fileType: { value: '{{"image/*"}}' },
|
||||
maxSize: { value: '{{1048576}}' },
|
||||
minSize: { value: '{{50}}' },
|
||||
parseContent: { value: '{{false}}' },
|
||||
parseFileType: { value: 'auto-detect' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
borderRadius: { value: '{{4}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
330
server/src/helpers/widget-config/form.js
Normal file
330
server/src/helpers/widget-config/form.js
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
export const formConfig = {
|
||||
name: 'Form',
|
||||
displayName: 'Form',
|
||||
description: 'Wrapper for multiple components',
|
||||
defaultSize: {
|
||||
width: 13,
|
||||
height: 330,
|
||||
},
|
||||
defaultChildren: [
|
||||
{
|
||||
componentName: 'Text',
|
||||
layout: {
|
||||
top: 40,
|
||||
left: 10,
|
||||
height: 30,
|
||||
width: 17,
|
||||
},
|
||||
properties: ['text'],
|
||||
styles: [
|
||||
'textSize',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'textColor',
|
||||
'isScrollRequired',
|
||||
'lineHeight',
|
||||
'textIndent',
|
||||
'textAlign',
|
||||
'verticalAlignment',
|
||||
'decoration',
|
||||
'transformation',
|
||||
'letterSpacing',
|
||||
'wordSpacing',
|
||||
'fontVariant',
|
||||
'backgroundColor',
|
||||
'borderColor',
|
||||
'borderRadius',
|
||||
'boxShadow',
|
||||
'padding',
|
||||
],
|
||||
defaultValue: {
|
||||
text: 'User Details',
|
||||
fontWeight: 'bold',
|
||||
textSize: 18,
|
||||
textColor: '#000',
|
||||
backgroundColor: '#fff00000',
|
||||
textAlign: 'left',
|
||||
decoration: 'none',
|
||||
transformation: 'none',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
textIndent: '0',
|
||||
letterSpacing: '0',
|
||||
wordSpacing: '0',
|
||||
fontVariant: 'normal',
|
||||
verticalAlignment: 'top',
|
||||
padding: 'default',
|
||||
boxShadow: '0px 0px 0px 0px #00000090',
|
||||
borderRadius: '0',
|
||||
isScrollRequired: 'enabled',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Text',
|
||||
layout: {
|
||||
top: 90,
|
||||
left: 10,
|
||||
height: 30,
|
||||
},
|
||||
properties: ['text'],
|
||||
styles: [
|
||||
'textSize',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'textColor',
|
||||
'isScrollRequired',
|
||||
'lineHeight',
|
||||
'textIndent',
|
||||
'textAlign',
|
||||
'verticalAlignment',
|
||||
'decoration',
|
||||
'transformation',
|
||||
'letterSpacing',
|
||||
'wordSpacing',
|
||||
'fontVariant',
|
||||
'backgroundColor',
|
||||
'borderColor',
|
||||
'borderRadius',
|
||||
'boxShadow',
|
||||
'padding',
|
||||
],
|
||||
defaultValue: {
|
||||
text: 'Name',
|
||||
fontWeight: 'normal',
|
||||
textSize: 14,
|
||||
textColor: '#000',
|
||||
backgroundColor: '#fff00000',
|
||||
textAlign: 'left',
|
||||
decoration: 'none',
|
||||
transformation: 'none',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
textIndent: '0',
|
||||
letterSpacing: '0',
|
||||
wordSpacing: '0',
|
||||
fontVariant: 'normal',
|
||||
verticalAlignment: 'top',
|
||||
padding: 'default',
|
||||
boxShadow: '0px 0px 0px 0px #00000090',
|
||||
borderRadius: '0',
|
||||
isScrollRequired: 'enabled',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Text',
|
||||
layout: {
|
||||
top: 160,
|
||||
left: 10,
|
||||
height: 30,
|
||||
},
|
||||
properties: ['text'],
|
||||
styles: [
|
||||
'textSize',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'textColor',
|
||||
'isScrollRequired',
|
||||
'lineHeight',
|
||||
'textIndent',
|
||||
'textAlign',
|
||||
'verticalAlignment',
|
||||
'decoration',
|
||||
'transformation',
|
||||
'letterSpacing',
|
||||
'wordSpacing',
|
||||
'fontVariant',
|
||||
'backgroundColor',
|
||||
'borderColor',
|
||||
'borderRadius',
|
||||
'boxShadow',
|
||||
'padding',
|
||||
],
|
||||
defaultValue: {
|
||||
text: 'Age',
|
||||
fontWeight: 'normal',
|
||||
textSize: 14,
|
||||
textColor: '#000',
|
||||
backgroundColor: '#fff00000',
|
||||
textAlign: 'left',
|
||||
decoration: 'none',
|
||||
transformation: 'none',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
textIndent: '0',
|
||||
letterSpacing: '0',
|
||||
wordSpacing: '0',
|
||||
fontVariant: 'normal',
|
||||
verticalAlignment: 'top',
|
||||
padding: 'default',
|
||||
boxShadow: '0px 0px 0px 0px #00000090',
|
||||
borderRadius: '0',
|
||||
isScrollRequired: 'enabled',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'TextInput',
|
||||
layout: {
|
||||
top: 120,
|
||||
left: 10,
|
||||
height: 30,
|
||||
width: 25,
|
||||
},
|
||||
properties: ['placeholder', 'label'],
|
||||
defaultValue: {
|
||||
placeholder: 'Enter your name',
|
||||
label: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'NumberInput',
|
||||
layout: {
|
||||
top: 190,
|
||||
left: 10,
|
||||
height: 30,
|
||||
width: 25,
|
||||
},
|
||||
properties: ['value', 'label'],
|
||||
defaultValue: {
|
||||
value: 24,
|
||||
label: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Button',
|
||||
layout: {
|
||||
top: 240,
|
||||
left: 10,
|
||||
height: 30,
|
||||
width: 10,
|
||||
},
|
||||
properties: ['text'],
|
||||
defaultValue: {
|
||||
text: 'Submit',
|
||||
},
|
||||
},
|
||||
],
|
||||
component: 'Form',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
buttonToSubmit: {
|
||||
type: 'select',
|
||||
displayName: 'Button to submit form',
|
||||
options: [{ name: 'None', value: 'none' }],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'none',
|
||||
},
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
advanced: {
|
||||
type: 'toggle',
|
||||
displayName: ' Use custom schema',
|
||||
},
|
||||
JSONSchema: {
|
||||
type: 'code',
|
||||
displayName: 'JSON Schema',
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onSubmit: { displayName: 'On submit' },
|
||||
onInvalid: { displayName: 'On invalid' },
|
||||
},
|
||||
styles: {
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'code',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }],
|
||||
},
|
||||
defaultValue: 0,
|
||||
},
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#fff',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
data: {},
|
||||
isValid: true,
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'submitForm',
|
||||
displayName: 'Submit Form',
|
||||
},
|
||||
{
|
||||
handle: 'resetForm',
|
||||
displayName: 'Reset Form',
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
loadingState: { value: '{{false}}' },
|
||||
advanced: { value: '{{false}}' },
|
||||
JSONSchema: {
|
||||
value:
|
||||
"{{ {title: 'User registration form', properties: {firstname: {type: 'textinput',value: 'Maria',label:'First name', validation:{maxLength:6}, styles: {backgroundColor: '#f6f5ff',textColor: 'black'},},lastname:{type: 'textinput',value: 'Doe', label:'Last name', styles: {backgroundColor: '#f6f5ff',textColor: 'black'},},age:{type:'number', label:'Age'},}, submitButton: {value: 'Submit', styles: {backgroundColor: '#3a433b',borderColor:'#595959'}}} }}",
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
backgroundColor: { value: '#fff' },
|
||||
borderRadius: { value: '0' },
|
||||
borderColor: { value: '#fff' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
52
server/src/helpers/widget-config/html.js
Normal file
52
server/src/helpers/widget-config/html.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
export const htmlConfig = {
|
||||
name: 'Html',
|
||||
displayName: 'HTML Viewer',
|
||||
description: 'View HTML content',
|
||||
component: 'Html',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 310,
|
||||
},
|
||||
properties: {
|
||||
rawHtml: {
|
||||
type: 'code',
|
||||
displayName: 'Raw HTML',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: `<body><div><h1>Hello World</h1></div></body>`,
|
||||
},
|
||||
},
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
rawHtml: {
|
||||
value: `<body><main><section class="hero" style="height:306px;display: flex;
|
||||
justify-content: center;padding:0 1px;align-items: center;text-align:center">You can build your custom HTML-CSS template here</section></main></body>`,
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
72
server/src/helpers/widget-config/icon.js
Normal file
72
server/src/helpers/widget-config/icon.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
export const iconConfig = {
|
||||
name: 'Icon',
|
||||
displayName: 'Icon',
|
||||
description: 'Icon',
|
||||
defaultSize: {
|
||||
width: 5,
|
||||
height: 48,
|
||||
},
|
||||
component: 'Icon',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
icon: {
|
||||
type: 'iconPicker',
|
||||
displayName: 'Icon',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'IconHome2',
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onClick: { displayName: 'On click' },
|
||||
onHover: { displayName: 'On hover' },
|
||||
},
|
||||
styles: {
|
||||
iconColor: {
|
||||
type: 'color',
|
||||
displayName: 'Icon color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
actions: [
|
||||
{
|
||||
handle: 'click',
|
||||
displayName: 'Click',
|
||||
},
|
||||
{
|
||||
displayName: 'Set Visibility',
|
||||
handle: 'setVisibility',
|
||||
params: [{ handle: 'value', displayName: 'Value', defaultValue: '{{true}}', type: 'toggle' }],
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
icon: { value: 'IconHome2' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
iconColor: { value: '#000' },
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
59
server/src/helpers/widget-config/iframe.js
Normal file
59
server/src/helpers/widget-config/iframe.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
export const iframeConfig = {
|
||||
name: 'Iframe',
|
||||
displayName: 'Iframe',
|
||||
description: 'Embed external content',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 310,
|
||||
},
|
||||
component: 'IFrame',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
source: {
|
||||
type: 'code',
|
||||
displayName: 'URL',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'https://tooljet.io/',
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
source: { value: 'https://tooljet.io/' },
|
||||
visible: { value: '{{true}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
145
server/src/helpers/widget-config/image.js
Normal file
145
server/src/helpers/widget-config/image.js
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
export const imageConfig = {
|
||||
name: 'Image',
|
||||
displayName: 'Image',
|
||||
description: 'Show image files',
|
||||
defaultSize: {
|
||||
width: 3,
|
||||
height: 100,
|
||||
},
|
||||
component: 'Image',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
source: {
|
||||
type: 'code',
|
||||
displayName: 'URL',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'https://www.svgrepo.com/image.svg',
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
alternativeText: {
|
||||
type: 'code',
|
||||
displayName: 'Alternative text',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'this is an image',
|
||||
},
|
||||
},
|
||||
zoomButtons: {
|
||||
type: 'toggle',
|
||||
displayName: 'Zoom button',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
rotateButton: {
|
||||
type: 'toggle',
|
||||
displayName: 'Rotate button',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onClick: { displayName: 'On click' },
|
||||
},
|
||||
styles: {
|
||||
borderType: {
|
||||
type: 'select',
|
||||
displayName: 'Border type',
|
||||
options: [
|
||||
{ name: 'None', value: 'none' },
|
||||
{ name: 'Rounded', value: 'rounded' },
|
||||
{ name: 'Circle', value: 'rounded-circle' },
|
||||
{ name: 'Thumbnail', value: 'img-thumbnail' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'none',
|
||||
},
|
||||
},
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#ffffff',
|
||||
},
|
||||
},
|
||||
padding: {
|
||||
type: 'code',
|
||||
displayName: 'Padding',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 0,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
imageFit: {
|
||||
type: 'select',
|
||||
displayName: 'Image fit',
|
||||
options: [
|
||||
{ name: 'fill', value: 'fill' },
|
||||
{ name: 'contain', value: 'contain' },
|
||||
{ name: 'cover', value: 'cover' },
|
||||
{ name: 'scale-down', value: 'scale-down' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'contain',
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
source: { value: 'https://www.svgrepo.com/show/34217/image.svg' },
|
||||
visible: { value: '{{true}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
alternativeText: { value: '' },
|
||||
zoomButtons: { value: '{{false}}' },
|
||||
rotateButton: { value: '{{false}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
borderType: { value: 'none' },
|
||||
padding: { value: '0' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
imageFit: { value: 'contain' },
|
||||
backgroundColor: { value: '' },
|
||||
},
|
||||
},
|
||||
};
|
||||
158
server/src/helpers/widget-config/index.js
Normal file
158
server/src/helpers/widget-config/index.js
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import { buttonConfig } from './button';
|
||||
import { tableConfig } from './table';
|
||||
import { chartConfig } from './chart';
|
||||
import { modalConfig } from './modal';
|
||||
import { formConfig } from './form';
|
||||
import { textinputConfig } from './textinput';
|
||||
import { numberinputConfig } from './numberinput';
|
||||
import { passinputConfig } from './passwordinput';
|
||||
import { datepickerConfig } from './datepicker';
|
||||
import { checkboxConfig } from './checkbox';
|
||||
import { radiobuttonConfig } from './radiobutton';
|
||||
import { toggleswitchConfig } from './toggleswitch';
|
||||
import { toggleSwitchV2Config } from './toggleswitchv2';
|
||||
import { textareaConfig } from './textarea';
|
||||
import { daterangepickerConfig } from './daterangepicker';
|
||||
import { textConfig } from './text';
|
||||
import { imageConfig } from './image';
|
||||
import { containerConfig } from './container';
|
||||
import { dropdownConfig } from './dropdown';
|
||||
import { dropdownV2Config } from './dropdownV2';
|
||||
import { multiselectConfig } from './multiselect';
|
||||
import { multiselectV2Config } from './multiselectV2';
|
||||
import { richtextareaConfig } from './richtextarea';
|
||||
import { mapConfig } from './map';
|
||||
import { qrscannerConfig } from './qrscanner';
|
||||
import { starratingConfig } from './starrating';
|
||||
import { dividerConfig } from './divider';
|
||||
import { filepickerConfig } from './filepicker';
|
||||
import { calendarConfig } from './calendar';
|
||||
import { iframeConfig } from './iframe';
|
||||
import { codeEditorConfig } from './codeEditor';
|
||||
import { tabsConfig } from './tabs';
|
||||
import { timerConfig } from './timer';
|
||||
import { listviewConfig } from './listview';
|
||||
import { tagsConfig } from './tags';
|
||||
import { paginationConfig } from './pagination';
|
||||
import { circularProgressbarConfig } from './circularProgressbar';
|
||||
import { spinnerConfig } from './spinner';
|
||||
import { statisticsConfig } from './statistics';
|
||||
import { rangeSliderConfig } from './rangeslider';
|
||||
import { timelineConfig } from './timeline';
|
||||
import { svgImageConfig } from './svgImage';
|
||||
import { htmlConfig } from './html';
|
||||
import { verticalDividerConfig } from './verticalDivider';
|
||||
import { customComponentConfig } from './customComponent';
|
||||
import { buttonGroupConfig } from './buttonGroup';
|
||||
import { pdfConfig } from './pdf';
|
||||
import { stepsConfig } from './steps';
|
||||
import { kanbanConfig } from './kanban';
|
||||
import { colorPickerConfig } from './colorPicker';
|
||||
import { treeSelectConfig } from './treeSelect';
|
||||
import { linkConfig } from './link';
|
||||
import { iconConfig } from './icon';
|
||||
import { boundedBoxConfig } from './boundedBox';
|
||||
import { kanbanBoardConfig } from './kanbanBoard';
|
||||
|
||||
const widgets = {
|
||||
buttonConfig,
|
||||
tableConfig,
|
||||
chartConfig,
|
||||
modalConfig,
|
||||
formConfig,
|
||||
textinputConfig,
|
||||
numberinputConfig,
|
||||
passinputConfig,
|
||||
datepickerConfig,
|
||||
checkboxConfig,
|
||||
radiobuttonConfig,
|
||||
toggleswitchConfig, //!Depreciated
|
||||
toggleSwitchV2Config,
|
||||
textareaConfig,
|
||||
daterangepickerConfig,
|
||||
textConfig,
|
||||
imageConfig,
|
||||
containerConfig,
|
||||
dropdownConfig, //!Depreciated
|
||||
dropdownV2Config,
|
||||
multiselectConfig,
|
||||
multiselectV2Config, //!Depreciated
|
||||
richtextareaConfig,
|
||||
mapConfig,
|
||||
qrscannerConfig,
|
||||
starratingConfig,
|
||||
dividerConfig,
|
||||
filepickerConfig,
|
||||
calendarConfig,
|
||||
iframeConfig,
|
||||
codeEditorConfig,
|
||||
tabsConfig,
|
||||
timerConfig,
|
||||
listviewConfig,
|
||||
tagsConfig,
|
||||
paginationConfig,
|
||||
circularProgressbarConfig,
|
||||
spinnerConfig,
|
||||
statisticsConfig,
|
||||
rangeSliderConfig,
|
||||
timelineConfig,
|
||||
svgImageConfig,
|
||||
htmlConfig,
|
||||
verticalDividerConfig,
|
||||
customComponentConfig,
|
||||
buttonGroupConfig,
|
||||
pdfConfig,
|
||||
stepsConfig,
|
||||
kanbanConfig,
|
||||
kanbanBoardConfig, //!Depreciated
|
||||
colorPickerConfig,
|
||||
treeSelectConfig,
|
||||
linkConfig,
|
||||
iconConfig,
|
||||
boundedBoxConfig,
|
||||
};
|
||||
|
||||
const universalProps = {
|
||||
properties: {},
|
||||
general: {
|
||||
tooltip: { type: 'code', displayName: 'Tooltip', validation: { schema: { type: 'string' } } },
|
||||
},
|
||||
others: {},
|
||||
events: {},
|
||||
styles: {},
|
||||
validate: true,
|
||||
generalStyles: {
|
||||
boxShadow: { type: 'boxShadow', displayName: 'Box Shadow' },
|
||||
},
|
||||
definition: {
|
||||
others: {},
|
||||
events: [],
|
||||
styles: {},
|
||||
generalStyles: {
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000040' },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const combineProperties = (widget, universal, isArray = false) => {
|
||||
return {
|
||||
...universal,
|
||||
...widget,
|
||||
properties: { ...universal.properties, ...widget.properties },
|
||||
general: { ...universal.general, ...widget.general },
|
||||
others: { ...universal.others, ...widget.others },
|
||||
events: isArray ? [...universal.events, ...widget.events] : { ...universal.events, ...widget.events },
|
||||
styles: { ...universal.styles, ...widget.styles },
|
||||
generalStyles: { ...universal.generalStyles, ...widget.generalStyles },
|
||||
exposedVariables: { ...universal.exposedVariables, ...widget.exposedVariables },
|
||||
};
|
||||
};
|
||||
|
||||
export const componentTypes = Object.values(widgets).map((widget) => {
|
||||
return {
|
||||
...combineProperties(widget, universalProps),
|
||||
definition: combineProperties(widget.definition, universalProps.definition, true),
|
||||
};
|
||||
});
|
||||
|
||||
export default widgets;
|
||||
163
server/src/helpers/widget-config/kanban.js
Normal file
163
server/src/helpers/widget-config/kanban.js
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
export const kanbanConfig = {
|
||||
name: 'Kanban',
|
||||
displayName: 'Kanban',
|
||||
description: 'Task management board',
|
||||
component: 'Kanban',
|
||||
defaultSize: {
|
||||
width: 40,
|
||||
height: 490,
|
||||
},
|
||||
defaultChildren: [
|
||||
{
|
||||
componentName: 'Text',
|
||||
layout: {
|
||||
top: 20,
|
||||
left: 4,
|
||||
height: 30,
|
||||
},
|
||||
properties: ['text'],
|
||||
accessorKey: 'text',
|
||||
styles: ['fontWeight', 'textSize', 'textColor'],
|
||||
defaultValue: {
|
||||
text: '{{cardData.title}}',
|
||||
fontWeight: 'bold',
|
||||
textSize: 16,
|
||||
textColor: '#000',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Text',
|
||||
layout: {
|
||||
top: 50,
|
||||
left: 4,
|
||||
height: 30,
|
||||
},
|
||||
properties: ['text'],
|
||||
accessorKey: 'text',
|
||||
styles: ['textSize', 'textColor'],
|
||||
defaultValue: {
|
||||
text: '{{cardData.description}}',
|
||||
textSize: 14,
|
||||
textColor: '#000',
|
||||
},
|
||||
},
|
||||
],
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
columnData: { type: 'code', displayName: 'Column data' },
|
||||
cardData: { type: 'code', displayName: 'Card data' },
|
||||
cardWidth: {
|
||||
type: 'code',
|
||||
displayName: 'Card width',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
},
|
||||
},
|
||||
cardHeight: {
|
||||
type: 'code',
|
||||
displayName: 'Card height',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
},
|
||||
},
|
||||
enableAddCard: { type: 'toggle', displayName: 'Enable add card' },
|
||||
showDeleteButton: { type: 'toggle', displayName: 'Show delete button' },
|
||||
},
|
||||
events: {
|
||||
onUpdate: { displayName: 'On update' },
|
||||
onAddCardClick: { displayName: 'On add card click' },
|
||||
onCardRemoved: { displayName: 'Card removed' },
|
||||
onCardAdded: { displayName: 'Card added' },
|
||||
onCardMoved: { displayName: 'Card moved' },
|
||||
onCardSelected: { displayName: 'Card selected' },
|
||||
},
|
||||
styles: {
|
||||
disabledState: { type: 'toggle', displayName: 'Disable' },
|
||||
visibility: { type: 'toggle', displayName: 'Visibility' },
|
||||
accentColor: { type: 'color', displayName: 'Accent color' },
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'addCard',
|
||||
displayName: 'Add Card',
|
||||
params: [
|
||||
{
|
||||
handle: 'cardDetails',
|
||||
displayName: 'Card Details',
|
||||
defaultValue: `{{{ id: "c11", title: "Title 11", description: "Description 11", columnId: "r3" }}}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'deleteCard',
|
||||
displayName: 'Delete Card',
|
||||
params: [{ handle: 'id', displayName: 'Card Id', defaultValue: `{{components.kanban1?.lastSelectedCard?.id}}` }],
|
||||
},
|
||||
{
|
||||
handle: 'moveCard',
|
||||
displayName: 'Move Card',
|
||||
params: [
|
||||
{ handle: 'cardId', displayName: 'Card Id', defaultValue: `{{components.kanban1?.lastSelectedCard?.id}}` },
|
||||
{ handle: 'columnId', displayName: 'Destination Column Id', defaultValue: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'updateCardData',
|
||||
displayName: 'Update Card Data',
|
||||
params: [
|
||||
{ handle: 'id', displayName: 'Card Id', defaultValue: `{{components.kanban1?.lastSelectedCard?.id}}` },
|
||||
{
|
||||
handle: 'value',
|
||||
displayName: 'Value',
|
||||
defaultValue: `{{{...components.kanban1?.lastSelectedCard, title: 'New Title'}}}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
exposedVariables: {
|
||||
updatedCardData: {},
|
||||
lastAddedCard: {},
|
||||
lastRemovedCard: {},
|
||||
lastCardMovement: {},
|
||||
lastSelectedCard: {},
|
||||
lastUpdatedCard: {},
|
||||
lastCardUpdate: [],
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
columnData: {
|
||||
value:
|
||||
'{{[{ "id": "r1", "title": "To Do" },{ "id": "r2", "title": "In Progress" },{ "id": "r3", "title": "Done" }]}}',
|
||||
},
|
||||
cardData: {
|
||||
value:
|
||||
'{{[{ id: "c1", title: "Title 1", description: "Description 1", columnId: "r1" },{ id: "c2", title: "Title 2", description: "Description 2", columnId: "r1" },{ id: "c3", title: "Title 3", description: "Description 3",columnId: "r2" },{ id: "c4", title: "Title 4", description: "Description 4",columnId: "r3" },{ id: "c5", title: "Title 5", description: "Description 5",columnId: "r3" }, { id: "c6", title: "Title 6", description: "Description 6", columnId: "r1" },{ id: "c7", title: "Title 7", description: "Description 7", columnId: "r1" },{ id: "c8", title: "Title 8", description: "Description 8",columnId: "r2" },{ id: "c9", title: "Title 9", description: "Description 9",columnId: "r3" },{ id: "c10", title: "Title 10", description: "Description 10",columnId: "r3" }]}}',
|
||||
},
|
||||
cardWidth: {
|
||||
value: '{{302}}',
|
||||
},
|
||||
cardHeight: {
|
||||
value: '{{100}}',
|
||||
},
|
||||
enableAddCard: {
|
||||
value: `{{true}}`,
|
||||
},
|
||||
showDeleteButton: {
|
||||
value: `{{true}}`,
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
accentColor: { value: '#4d72fa' },
|
||||
},
|
||||
},
|
||||
};
|
||||
68
server/src/helpers/widget-config/kanbanBoard.js
Normal file
68
server/src/helpers/widget-config/kanbanBoard.js
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
//! KanbanBoard widget is deprecated. This config allows backward compatibility with existing KanbanBoard widgets.
|
||||
|
||||
export const kanbanBoardConfig = {
|
||||
name: 'KanbanBoard',
|
||||
displayName: 'Kanban Board',
|
||||
description: 'Task management board',
|
||||
component: 'KanbanBoard',
|
||||
defaultSize: {
|
||||
width: 40,
|
||||
height: 490,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
columns: { type: 'code', displayName: 'Columns' },
|
||||
cardData: { type: 'code', displayName: 'Card Data' },
|
||||
enableAddCard: { type: 'toggle', displayName: 'Enable Add Card' },
|
||||
},
|
||||
events: {
|
||||
onCardAdded: { displayName: 'Card added' },
|
||||
onCardRemoved: { displayName: 'Card removed' },
|
||||
onCardMoved: { displayName: 'Card moved' },
|
||||
onCardSelected: { displayName: 'Card selected' },
|
||||
onCardUpdated: { displayName: 'Card updated' },
|
||||
},
|
||||
styles: {
|
||||
disabledState: { type: 'toggle', displayName: 'Disable' },
|
||||
visibility: { type: 'toggle', displayName: 'Visibility' },
|
||||
width: { type: 'number', displayName: 'Width' },
|
||||
minWidth: { type: 'number', displayName: 'Min Width' },
|
||||
accentColor: { type: 'color', displayName: 'Accent color' },
|
||||
},
|
||||
exposedVariables: {
|
||||
columns: {},
|
||||
lastAddedCard: {},
|
||||
lastRemovedCard: {},
|
||||
lastCardMovement: {},
|
||||
lastUpdatedCard: {},
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
columns: {
|
||||
value: '{{[{ "id": "1", "title": "to do" },{ "id": "2", "title": "in progress" }]}}',
|
||||
},
|
||||
cardData: {
|
||||
value:
|
||||
'{{[{ id: "01", title: "one", columnId: "1" },{ id: "02", title: "two", columnId: "1" },{ id: "03", title: "three", columnId: "2" }]}}',
|
||||
},
|
||||
enableAddCard: {
|
||||
value: `{{true}}`,
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
width: { value: '{{400}}' },
|
||||
minWidth: { value: '{{200}}' },
|
||||
textColor: { value: '' },
|
||||
},
|
||||
},
|
||||
};
|
||||
111
server/src/helpers/widget-config/link.js
Normal file
111
server/src/helpers/widget-config/link.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
export const linkConfig = {
|
||||
name: 'Link',
|
||||
displayName: 'Link',
|
||||
description: 'Add link to the text',
|
||||
defaultSize: {
|
||||
width: 6,
|
||||
height: 30,
|
||||
},
|
||||
component: 'Link',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
linkTarget: {
|
||||
type: 'code',
|
||||
displayName: 'Link target',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'https://dev.to/',
|
||||
},
|
||||
},
|
||||
linkText: {
|
||||
type: 'code',
|
||||
displayName: 'Link text',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Click here',
|
||||
},
|
||||
},
|
||||
targetType: {
|
||||
type: 'select',
|
||||
displayName: 'Target type',
|
||||
options: [
|
||||
{ name: 'New Tab', value: 'new' },
|
||||
{ name: 'Same Tab', value: 'same' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onClick: { displayName: 'On click' },
|
||||
onHover: { displayName: 'On hover' },
|
||||
},
|
||||
styles: {
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#375FCF',
|
||||
},
|
||||
},
|
||||
textSize: {
|
||||
type: 'number',
|
||||
displayName: 'Text size',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 14,
|
||||
},
|
||||
},
|
||||
underline: {
|
||||
type: 'select',
|
||||
displayName: 'Underline',
|
||||
options: [
|
||||
{ name: 'Never', value: 'no-underline' },
|
||||
{ name: 'On Hover', value: 'on-hover' },
|
||||
{ name: 'Always', value: 'underline' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'on-hover',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
actions: [
|
||||
{
|
||||
handle: 'click',
|
||||
displayName: 'Click',
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
linkTarget: { value: 'https://dev.to/' },
|
||||
linkText: { value: 'Click here' },
|
||||
targetType: { value: 'new' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
textColor: { value: '#375FCF' },
|
||||
textSize: { value: '{{14}}' },
|
||||
underline: { value: 'on-hover' },
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
198
server/src/helpers/widget-config/listview.js
Normal file
198
server/src/helpers/widget-config/listview.js
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
export const listviewConfig = {
|
||||
name: 'Listview',
|
||||
displayName: 'List View',
|
||||
description: 'List multiple items',
|
||||
defaultSize: {
|
||||
width: 30,
|
||||
height: 300,
|
||||
},
|
||||
defaultChildren: [
|
||||
{
|
||||
componentName: 'Image',
|
||||
layout: {
|
||||
top: 15,
|
||||
left: 3,
|
||||
height: 100,
|
||||
},
|
||||
properties: ['source'],
|
||||
accessorKey: 'imageURL',
|
||||
},
|
||||
{
|
||||
componentName: 'Text',
|
||||
layout: {
|
||||
top: 50,
|
||||
left: 11,
|
||||
height: 30,
|
||||
},
|
||||
properties: ['text'],
|
||||
accessorKey: 'text',
|
||||
},
|
||||
{
|
||||
componentName: 'Button',
|
||||
layout: {
|
||||
top: 50,
|
||||
left: 26,
|
||||
height: 30,
|
||||
},
|
||||
incrementWidth: 2,
|
||||
properties: ['text'],
|
||||
accessorKey: 'buttonText',
|
||||
},
|
||||
],
|
||||
component: 'Listview',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
data: {
|
||||
type: 'code',
|
||||
displayName: 'List data',
|
||||
validation: {
|
||||
schema: { type: 'array', element: { type: 'object' } },
|
||||
defaultValue: "[{text: 'Sample text 1'}]",
|
||||
},
|
||||
},
|
||||
mode: {
|
||||
type: 'select',
|
||||
displayName: 'Mode',
|
||||
options: [
|
||||
{ name: 'list', value: 'list' },
|
||||
{ name: 'grid', value: 'grid' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'list',
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
type: 'number',
|
||||
displayName: 'Columns',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 3,
|
||||
},
|
||||
conditionallyRender: {
|
||||
key: 'mode',
|
||||
value: 'grid',
|
||||
},
|
||||
},
|
||||
rowHeight: {
|
||||
type: 'code',
|
||||
displayName: 'Row height',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 100,
|
||||
},
|
||||
},
|
||||
showBorder: {
|
||||
type: 'code',
|
||||
displayName: 'Show bottom border',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
conditionallyRender: {
|
||||
key: 'mode',
|
||||
value: 'list',
|
||||
},
|
||||
},
|
||||
enablePagination: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable pagination',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
rowsPerPage: {
|
||||
type: 'code',
|
||||
displayName: 'Rows per page',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onRowClicked: { displayName: 'Row clicked (Deprecated)' },
|
||||
onRecordClicked: { displayName: 'Record clicked' },
|
||||
},
|
||||
styles: {
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#fff',
|
||||
},
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#dadcde',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'number',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
data: [{}],
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
data: {
|
||||
value: `{{[
|
||||
{ imageURL: 'https://www.svgrepo.com/show/34217/image.svg', text: 'Sample text 1', buttonText: 'Button 1' },
|
||||
{ imageURL: 'https://www.svgrepo.com/show/34217/image.svg', text: 'Sample text 1', buttonText: 'Button 2' },
|
||||
{ imageURL: 'https://www.svgrepo.com/show/34217/image.svg', text: 'Sample text 1', buttonText: 'Button 3' },
|
||||
]}}`,
|
||||
},
|
||||
mode: { value: 'list' },
|
||||
columns: { value: '{{3}}' },
|
||||
rowHeight: {
|
||||
value: '100',
|
||||
},
|
||||
visible: { value: '{{true}}' },
|
||||
showBorder: { value: '{{true}}' },
|
||||
rowsPerPage: { value: '{{10}}' },
|
||||
enablePagination: { value: '{{false}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
backgroundColor: { value: '#fff' },
|
||||
borderColor: { value: '#dadcde' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
borderRadius: { value: '{{4}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
152
server/src/helpers/widget-config/map.js
Normal file
152
server/src/helpers/widget-config/map.js
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
export const mapConfig = {
|
||||
name: 'Map',
|
||||
displayName: 'Map',
|
||||
description: 'Display map locations',
|
||||
component: 'Map',
|
||||
defaultSize: {
|
||||
width: 16,
|
||||
height: 420,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
initialLocation: {
|
||||
type: 'code',
|
||||
displayName: 'Initial location',
|
||||
tip: 'This location will be the initial center of the map',
|
||||
options: {
|
||||
mode: 'javascript',
|
||||
theme: 'duotone-light',
|
||||
className: 'map-location-input pr-2',
|
||||
},
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'array', element: { type: 'object' } }, { type: 'object' }],
|
||||
},
|
||||
defaultValue: `{{ {"lat": 40.7128, "lng": -73.935242} }}`,
|
||||
},
|
||||
},
|
||||
defaultMarkers: {
|
||||
type: 'code',
|
||||
displayName: 'Default markers',
|
||||
options: {
|
||||
mode: 'javascript',
|
||||
theme: 'duotone-light',
|
||||
className: 'map-location-input pr-2',
|
||||
},
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'array', element: { type: 'object' } }, { type: 'object' }],
|
||||
},
|
||||
defaultValue: `{{ [{"lat": 40.7128, "lng": -73.935242}] }}`,
|
||||
},
|
||||
},
|
||||
polygonPoints: {
|
||||
type: 'code',
|
||||
displayName: 'Polygon points',
|
||||
options: {
|
||||
mode: 'javascript',
|
||||
theme: 'duotone-light',
|
||||
className: 'map-location-input pr-2',
|
||||
},
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'array', element: { type: 'object' } }, { type: 'object' }],
|
||||
},
|
||||
defaultValue: `{{[{"lat": 40.7032, "lng": -73.975242},{"lat": 40.7532, "lng": -73.943242},{"lat": 40.7032, "lng": -73.916242}]}}`,
|
||||
},
|
||||
},
|
||||
addNewMarkers: {
|
||||
type: 'toggle',
|
||||
displayName: 'Add new markers',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
canSearch: {
|
||||
type: 'toggle',
|
||||
displayName: 'Search for places',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onBoundsChange: { displayName: 'On bounds change' },
|
||||
onCreateMarker: { displayName: 'On create marker' },
|
||||
onMarkerClick: { displayName: 'On marker click' },
|
||||
onPolygonClick: { displayName: 'On polygon click' },
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'setLocation',
|
||||
displayName: 'Set Location',
|
||||
params: [
|
||||
{ handle: 'lat', displayName: 'Latitude' },
|
||||
{ handle: 'lng', displayName: 'Longitude' },
|
||||
],
|
||||
},
|
||||
],
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
center: {},
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
initialLocation: {
|
||||
value: `{{ {"lat": 40.7128, "lng": -73.935242} }}`,
|
||||
},
|
||||
defaultMarkers: {
|
||||
value: `{{ [{"lat": 40.7128, "lng": -73.935242}] }}`,
|
||||
},
|
||||
polygonPoints: {
|
||||
value: `{{[\n\t\t{"lat": 40.7032, "lng": -73.975242},\n\t\t{"lat": 40.7532, "lng": -73.943242},\n\t\t{"lat": 40.7032, "lng": -73.916242}\n]}}`,
|
||||
},
|
||||
canSearch: {
|
||||
value: `{{true}}`,
|
||||
},
|
||||
addNewMarkers: { value: `{{true}}` },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
195
server/src/helpers/widget-config/modal.js
Normal file
195
server/src/helpers/widget-config/modal.js
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
export const modalConfig = {
|
||||
name: 'Modal',
|
||||
displayName: 'Modal',
|
||||
description: 'Show pop-up windows',
|
||||
component: 'Modal',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 34,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
title: {
|
||||
type: 'code',
|
||||
displayName: 'Title',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'This title can be changed',
|
||||
},
|
||||
},
|
||||
titleAlignment: {
|
||||
type: 'select',
|
||||
displayName: 'Title alignment',
|
||||
options: [
|
||||
{ name: 'left', value: 'left' },
|
||||
{ name: 'center', value: 'center' },
|
||||
{ name: 'right', value: 'right' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'left',
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
useDefaultButton: {
|
||||
type: 'toggle',
|
||||
displayName: 'Use default trigger button',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
triggerButtonLabel: {
|
||||
type: 'code',
|
||||
displayName: 'Trigger button label',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defaultValue: 'Launch Modal',
|
||||
},
|
||||
},
|
||||
hideTitleBar: { type: 'toggle', displayName: 'Hide title bar' },
|
||||
hideCloseButton: { type: 'toggle', displayName: 'Hide close button' },
|
||||
hideOnEsc: { type: 'toggle', displayName: 'Close on escape key' },
|
||||
closeOnClickingOutside: { type: 'toggle', displayName: 'Close on clicking outside' },
|
||||
|
||||
size: {
|
||||
type: 'select',
|
||||
displayName: 'Modal size',
|
||||
options: [
|
||||
{ name: 'small', value: 'sm' },
|
||||
{ name: 'medium', value: 'lg' },
|
||||
{ name: 'large', value: 'xl' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'lg',
|
||||
},
|
||||
},
|
||||
modalHeight: {
|
||||
type: 'code',
|
||||
displayName: 'Modal height',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '400px',
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onOpen: { displayName: 'On open' },
|
||||
onClose: { displayName: 'On close' },
|
||||
},
|
||||
styles: {
|
||||
headerBackgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Header background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#ffffffff',
|
||||
},
|
||||
},
|
||||
headerTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Header title color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000000',
|
||||
},
|
||||
},
|
||||
bodyBackgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Body background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#ffffffff',
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
triggerButtonBackgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Trigger button background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
triggerButtonTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Trigger button text color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
show: false,
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'open',
|
||||
displayName: 'Open',
|
||||
},
|
||||
{
|
||||
handle: 'close',
|
||||
displayName: 'Close',
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
title: { value: 'This title can be changed' },
|
||||
titleAlignment: { value: 'left' },
|
||||
loadingState: { value: `{{false}}` },
|
||||
useDefaultButton: { value: `{{true}}` },
|
||||
triggerButtonLabel: { value: `Launch Modal` },
|
||||
size: { value: 'lg' },
|
||||
hideTitleBar: { value: '{{false}}' },
|
||||
hideCloseButton: { value: '{{false}}' },
|
||||
hideOnEsc: { value: '{{true}}' },
|
||||
closeOnClickingOutside: { value: '{{false}}' },
|
||||
modalHeight: { value: '400px' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
headerBackgroundColor: { value: '#ffffffff' },
|
||||
headerTextColor: { value: '#000000' },
|
||||
bodyBackgroundColor: { value: '#ffffffff' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
visibility: { value: '{{true}}' },
|
||||
triggerButtonBackgroundColor: { value: '#4D72FA' },
|
||||
triggerButtonTextColor: { value: '#ffffffff' },
|
||||
},
|
||||
},
|
||||
};
|
||||
136
server/src/helpers/widget-config/multiselect.js
Normal file
136
server/src/helpers/widget-config/multiselect.js
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
export const multiselectConfig = {
|
||||
name: 'MultiselectLegacy',
|
||||
displayName: 'Multiselect (Legacy)',
|
||||
description: 'Multiple item selector',
|
||||
defaultSize: {
|
||||
width: 12,
|
||||
height: 30,
|
||||
},
|
||||
component: 'Multiselect',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'selectOption',
|
||||
displayName: 'Select Option',
|
||||
params: [
|
||||
{
|
||||
handle: 'option',
|
||||
displayName: 'Option',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'deselectOption',
|
||||
displayName: 'Deselect Option',
|
||||
params: [
|
||||
{
|
||||
handle: 'option',
|
||||
displayName: 'Option',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'clearSelections',
|
||||
displayName: 'Clear selections',
|
||||
},
|
||||
],
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Select',
|
||||
},
|
||||
},
|
||||
value: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
validation: {
|
||||
schema: { type: 'array', element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
defaultValue: "['two', 'three']",
|
||||
},
|
||||
},
|
||||
values: {
|
||||
type: 'code',
|
||||
displayName: 'Option values',
|
||||
validation: {
|
||||
schema: { type: 'array', element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
defaultValue: "['one', 'two', 'three']",
|
||||
},
|
||||
},
|
||||
display_values: {
|
||||
type: 'code',
|
||||
displayName: 'Option labels',
|
||||
validation: {
|
||||
schema: { type: 'array', element: { type: 'string' } },
|
||||
defaultValue: "['one', 'two', 'three']",
|
||||
},
|
||||
},
|
||||
showAllOption: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable select All option',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onSelect: { displayName: 'On select' },
|
||||
onSearchTextChanged: { displayName: 'On search text changed' },
|
||||
},
|
||||
styles: {
|
||||
borderRadius: {
|
||||
type: 'code',
|
||||
displayName: 'Border radius',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
values: {},
|
||||
searchText: '',
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
label: { value: 'Select' },
|
||||
value: { value: '{{[2,3]}}' },
|
||||
values: { value: '{{[1,2,3]}}' },
|
||||
display_values: { value: '{{["one", "two", "three"]}}' },
|
||||
visible: { value: '{{true}}' },
|
||||
showAllOption: { value: '{{false}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
borderRadius: { value: '4' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
371
server/src/helpers/widget-config/multiselectV2.js
Normal file
371
server/src/helpers/widget-config/multiselectV2.js
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
export const multiselectV2Config = {
|
||||
name: 'Multiselect',
|
||||
displayName: 'Multiselect',
|
||||
description: 'Multiple item selector',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 40,
|
||||
},
|
||||
component: 'MultiselectV2',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
validation: {
|
||||
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
|
||||
customRule: {
|
||||
type: 'code',
|
||||
displayName: 'Custom validation',
|
||||
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
|
||||
},
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'selectOptions',
|
||||
displayName: 'Select Options',
|
||||
params: [
|
||||
{
|
||||
handle: 'option',
|
||||
displayName: 'Option',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'deselectOptions',
|
||||
displayName: 'Deselect Options',
|
||||
params: [
|
||||
{
|
||||
handle: 'option',
|
||||
displayName: 'Option',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'clear',
|
||||
displayName: 'Clear',
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
params: [{ handle: 'setVisibility', displayName: 'Value', defaultValue: `{{true}}`, type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setLoading',
|
||||
displayName: 'Set loading',
|
||||
params: [{ handle: 'setLoading', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setDisable',
|
||||
displayName: 'Set disable',
|
||||
params: [{ handle: 'setDisable', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
],
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Label',
|
||||
},
|
||||
accordian: 'Data',
|
||||
},
|
||||
placeholder: {
|
||||
type: 'code',
|
||||
displayName: 'Placeholder',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Select the options',
|
||||
},
|
||||
accordian: 'Data',
|
||||
},
|
||||
advanced: {
|
||||
type: 'toggle',
|
||||
displayName: 'Dynamic options',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
accordian: 'Options',
|
||||
},
|
||||
value: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: false,
|
||||
},
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }],
|
||||
},
|
||||
},
|
||||
accordian: 'Options',
|
||||
},
|
||||
schema: {
|
||||
type: 'code',
|
||||
displayName: 'Schema',
|
||||
conditionallyRender: {
|
||||
key: 'advanced',
|
||||
value: true,
|
||||
},
|
||||
accordian: 'Options',
|
||||
},
|
||||
showAllOption: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable select all option',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
accordian: 'Options',
|
||||
},
|
||||
optionsLoadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Options loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
accordian: 'Options',
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
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',
|
||||
},
|
||||
tooltip: {
|
||||
type: 'code',
|
||||
displayName: 'Tooltip',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '' },
|
||||
section: 'additionalActions',
|
||||
placeholder: 'Enter tooltip text',
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onSelect: { displayName: 'On select' },
|
||||
onSearchTextChanged: { displayName: 'On search text changed' },
|
||||
onFocus: { displayName: 'On focus' },
|
||||
onBlur: { displayName: 'On blur' },
|
||||
},
|
||||
|
||||
styles: {
|
||||
labelColor: {
|
||||
type: 'color',
|
||||
displayName: 'Color',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
|
||||
accordian: 'label',
|
||||
},
|
||||
alignment: {
|
||||
type: 'switch',
|
||||
displayName: 'Alignment',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'side' },
|
||||
options: [
|
||||
{ displayName: 'Side', value: 'side' },
|
||||
{ displayName: 'Top', value: 'top' },
|
||||
],
|
||||
accordian: 'label',
|
||||
},
|
||||
direction: {
|
||||
type: 'switch',
|
||||
displayName: 'Direction',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'left' },
|
||||
showLabel: false,
|
||||
isIcon: true,
|
||||
options: [
|
||||
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
|
||||
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
|
||||
],
|
||||
accordian: 'label',
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
labelWidth: {
|
||||
type: 'slider',
|
||||
displayName: 'Width',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
accordian: 'label',
|
||||
conditionallyRender: {
|
||||
key: 'alignment',
|
||||
value: 'side',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
auto: {
|
||||
type: 'checkbox',
|
||||
displayName: 'auto',
|
||||
showLabel: false,
|
||||
validation: { schema: { type: 'boolean' } },
|
||||
accordian: 'label',
|
||||
conditionallyRender: {
|
||||
key: 'alignment',
|
||||
value: 'side',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
|
||||
fieldBackgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
|
||||
accordian: 'field',
|
||||
},
|
||||
|
||||
fieldBorderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
|
||||
accordian: 'field',
|
||||
},
|
||||
accentColor: {
|
||||
type: 'color',
|
||||
displayName: 'Accent',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
|
||||
accordian: 'field',
|
||||
},
|
||||
selectedTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
|
||||
accordian: 'field',
|
||||
},
|
||||
errTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Error Text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
|
||||
accordian: 'field',
|
||||
},
|
||||
icon: {
|
||||
type: 'icon',
|
||||
displayName: 'Icon',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'IconHome2' },
|
||||
accordian: 'field',
|
||||
visibility: false,
|
||||
},
|
||||
iconColor: {
|
||||
type: 'color',
|
||||
displayName: 'Icon color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#6A727C',
|
||||
},
|
||||
accordian: 'field',
|
||||
showLabel: false,
|
||||
},
|
||||
fieldBorderRadius: {
|
||||
type: 'input',
|
||||
displayName: 'Border radius',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: '6' },
|
||||
accordian: 'field',
|
||||
},
|
||||
boxShadow: {
|
||||
type: 'boxShadow',
|
||||
displayName: 'Box Shadow',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: '0px 0px 0px 0px #00000090',
|
||||
},
|
||||
accordian: 'field',
|
||||
},
|
||||
padding: {
|
||||
type: 'switch',
|
||||
displayName: 'Padding',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: 'default',
|
||||
},
|
||||
options: [
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
accordian: 'container',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
searchText: '',
|
||||
},
|
||||
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
validation: {
|
||||
mandatory: { value: false },
|
||||
customRule: { value: null },
|
||||
},
|
||||
properties: {
|
||||
label: { value: 'Select' },
|
||||
values: { value: ['1', '2'] },
|
||||
advanced: { value: `{{false}}` },
|
||||
showAllOption: { value: '{{false}}' },
|
||||
optionsLoadingState: { value: '{{false}}' },
|
||||
placeholder: { value: 'Select the options' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
schema: {
|
||||
value:
|
||||
"{{[\t{label: 'option1',value: 1,disable: false,visible: true,default: true},{label: 'option2',value: 2,disable: false,visible: true},{label: 'option3',value: 3,disable: false,visible: true}\t]}}",
|
||||
},
|
||||
options: {
|
||||
value: [
|
||||
{
|
||||
label: 'option1',
|
||||
value: '1',
|
||||
disable: { value: false },
|
||||
visible: { value: true },
|
||||
default: { value: false },
|
||||
},
|
||||
{
|
||||
label: 'option2',
|
||||
value: '2',
|
||||
disable: { value: false },
|
||||
visible: { value: true },
|
||||
default: { value: true },
|
||||
},
|
||||
{
|
||||
label: 'option3',
|
||||
value: '3',
|
||||
disable: { value: false },
|
||||
visible: { value: true },
|
||||
default: { value: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
tooltip: { value: '' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
labelColor: { value: '#1B1F24' },
|
||||
labelWidth: { value: '33' },
|
||||
auto: { value: '{{true}}' },
|
||||
fieldBorderRadius: { value: '6' },
|
||||
selectedTextColor: { value: '#1B1F24' },
|
||||
fieldBorderColor: { value: '#CCD1D5' },
|
||||
errTextColor: { value: '#D72D39' },
|
||||
fieldBackgroundColor: { value: '#fff' },
|
||||
direction: { value: 'left' },
|
||||
alignment: { value: 'side' },
|
||||
padding: { value: 'default' },
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000090' },
|
||||
icon: { value: 'IconHome2' },
|
||||
iconVisibility: { value: false },
|
||||
iconColor: { value: '#6A727C' },
|
||||
accentColor: { value: '#4368E3' },
|
||||
},
|
||||
},
|
||||
};
|
||||
300
server/src/helpers/widget-config/numberinput.js
Normal file
300
server/src/helpers/widget-config/numberinput.js
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
export const numberinputConfig = {
|
||||
name: 'NumberInput',
|
||||
displayName: 'Number Input',
|
||||
description: 'Numeric input field',
|
||||
component: 'NumberInput',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 40,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
|
||||
},
|
||||
value: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: 0,
|
||||
},
|
||||
},
|
||||
placeholder: {
|
||||
type: 'code',
|
||||
displayName: 'Placeholder',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Enter your input',
|
||||
},
|
||||
},
|
||||
decimalPlaces: {
|
||||
type: 'code',
|
||||
displayName: 'Decimal places',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 2,
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: false },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: false },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
tooltip: {
|
||||
type: 'code',
|
||||
displayName: 'Tooltip',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
|
||||
section: 'additionalActions',
|
||||
placeholder: 'Enter tooltip text',
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onChange: { displayName: 'On change' },
|
||||
onFocus: { displayName: 'On focus' },
|
||||
onBlur: { displayName: 'On blur' },
|
||||
onEnterPressed: { displayName: 'On enter pressed' },
|
||||
},
|
||||
styles: {
|
||||
color: {
|
||||
type: 'color',
|
||||
displayName: 'Text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
|
||||
accordian: 'label',
|
||||
},
|
||||
alignment: {
|
||||
type: 'switch',
|
||||
displayName: 'Alignment',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'side' },
|
||||
options: [
|
||||
{ displayName: 'Side', value: 'side' },
|
||||
{ displayName: 'Top', value: 'top' },
|
||||
],
|
||||
accordian: 'label',
|
||||
},
|
||||
direction: {
|
||||
type: 'switch',
|
||||
displayName: '',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'left' },
|
||||
showLabel: false,
|
||||
isIcon: true,
|
||||
options: [
|
||||
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
|
||||
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
|
||||
],
|
||||
accordian: 'label',
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
width: {
|
||||
type: 'slider',
|
||||
displayName: 'Width',
|
||||
accordian: 'label',
|
||||
conditionallyRender: {
|
||||
key: 'alignment',
|
||||
value: 'side',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
auto: {
|
||||
type: 'checkbox',
|
||||
displayName: 'auto',
|
||||
showLabel: false,
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
accordian: 'label',
|
||||
conditionallyRender: {
|
||||
key: 'alignment',
|
||||
value: 'side',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
|
||||
accordian: 'field',
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
|
||||
accordian: 'field',
|
||||
},
|
||||
accentColor: {
|
||||
type: 'color',
|
||||
displayName: 'Accent',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
|
||||
accordian: 'field',
|
||||
},
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
|
||||
accordian: 'field',
|
||||
},
|
||||
errTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Error text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
|
||||
accordian: 'field',
|
||||
},
|
||||
icon: {
|
||||
type: 'icon',
|
||||
displayName: 'Icon',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'IconHome2' },
|
||||
accordian: 'field',
|
||||
visibility: false,
|
||||
},
|
||||
iconColor: {
|
||||
type: 'color',
|
||||
displayName: 'Icon color',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#CFD3D859' },
|
||||
accordian: 'field',
|
||||
visibility: false,
|
||||
showLabel: false,
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'numberInput',
|
||||
displayName: 'Border radius',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
|
||||
accordian: 'field',
|
||||
},
|
||||
boxShadow: {
|
||||
type: 'boxShadow',
|
||||
displayName: 'Box Shadow',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: '0px 0px 0px 0px #00000040',
|
||||
},
|
||||
accordian: 'field',
|
||||
},
|
||||
padding: {
|
||||
type: 'switch',
|
||||
displayName: 'Padding',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: 'default',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
options: [
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
accordian: 'container',
|
||||
},
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'setText',
|
||||
displayName: 'Set text',
|
||||
params: [{ handle: 'text', displayName: 'text', defaultValue: '100' }],
|
||||
},
|
||||
{
|
||||
handle: 'clear',
|
||||
displayName: 'Clear',
|
||||
},
|
||||
{
|
||||
handle: 'setFocus',
|
||||
displayName: 'Set focus',
|
||||
},
|
||||
{
|
||||
handle: 'setBlur',
|
||||
displayName: 'Set blur',
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setDisable',
|
||||
displayName: 'Set disable',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setLoading',
|
||||
displayName: 'Set loading',
|
||||
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
],
|
||||
exposedVariables: {
|
||||
value: 99,
|
||||
isMandatory: false,
|
||||
isVisible: true,
|
||||
isDisabled: false,
|
||||
isLoading: false,
|
||||
},
|
||||
validation: {
|
||||
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
|
||||
regex: { type: 'code', displayName: 'Regex', placeholder: '^d+$' },
|
||||
minValue: { type: 'code', displayName: 'Min value', placeholder: 'Enter min value' },
|
||||
maxValue: { type: 'code', displayName: 'Max value', placeholder: 'Enter max value' },
|
||||
customRule: {
|
||||
type: 'code',
|
||||
displayName: 'Custom validation',
|
||||
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
|
||||
},
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
validation: {
|
||||
mandatory: { value: '{{false}}' },
|
||||
regex: { value: '' },
|
||||
minValue: { value: '' },
|
||||
maxValue: { value: '' },
|
||||
customRule: { value: '' },
|
||||
},
|
||||
properties: {
|
||||
value: { value: '0' },
|
||||
label: { value: 'Label' },
|
||||
maxValue: { value: '' },
|
||||
minValue: { value: '' },
|
||||
placeholder: { value: '0' },
|
||||
decimalPlaces: { value: '{{2}}' },
|
||||
tooltip: { value: '' },
|
||||
visibility: { value: '{{true}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
borderRadius: { value: '{{6}}' },
|
||||
backgroundColor: { value: '#fff' },
|
||||
borderColor: { value: '#CCD1D5' },
|
||||
accentColor: { value: '#4368E3' },
|
||||
errTextColor: { value: '#D72D39' },
|
||||
textColor: { value: '#1B1F24' },
|
||||
color: { value: '#1B1F24' },
|
||||
iconColor: { value: '#CFD3D859' },
|
||||
direction: { value: 'left' },
|
||||
width: { value: '{{33}}' },
|
||||
alignment: { value: 'side' },
|
||||
auto: { value: '{{true}}' },
|
||||
padding: { value: 'default' },
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000040' },
|
||||
icon: { value: 'IconHome2' },
|
||||
iconVisibility: { value: false },
|
||||
},
|
||||
},
|
||||
};
|
||||
78
server/src/helpers/widget-config/pagination.js
Normal file
78
server/src/helpers/widget-config/pagination.js
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
export const paginationConfig = {
|
||||
name: 'Pagination',
|
||||
displayName: 'Pagination',
|
||||
description: 'Navigate pages',
|
||||
component: 'Pagination',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 30,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
numberOfPages: {
|
||||
type: 'code',
|
||||
displayName: 'Number of pages',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: '{{5}}',
|
||||
},
|
||||
},
|
||||
defaultPageIndex: {
|
||||
type: 'code',
|
||||
displayName: 'Default page index',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: '{{1}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
validation: {},
|
||||
events: {
|
||||
onPageChange: { displayName: 'On Page Change' },
|
||||
},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
totalPages: null,
|
||||
currentPageIndex: null,
|
||||
},
|
||||
definition: {
|
||||
validation: {},
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
numberOfPages: {
|
||||
value: '{{5}}',
|
||||
},
|
||||
defaultPageIndex: {
|
||||
value: '{{1}}',
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
296
server/src/helpers/widget-config/passwordinput.js
Normal file
296
server/src/helpers/widget-config/passwordinput.js
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
export const passinputConfig = {
|
||||
name: 'PasswordInput',
|
||||
displayName: 'Password Input',
|
||||
description: 'Secure text input',
|
||||
component: 'PasswordInput',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 40,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
|
||||
},
|
||||
placeholder: {
|
||||
type: 'code',
|
||||
displayName: 'Placeholder',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Password',
|
||||
},
|
||||
},
|
||||
value: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
defaultValue: 'default value',
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: false },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: false },
|
||||
section: 'additionalActions',
|
||||
},
|
||||
tooltip: {
|
||||
type: 'code',
|
||||
displayName: 'Tooltip',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
|
||||
section: 'additionalActions',
|
||||
placeholder: 'Enter tooltip text',
|
||||
},
|
||||
},
|
||||
validation: {
|
||||
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
|
||||
regex: {
|
||||
type: 'code',
|
||||
displayName: 'Regex',
|
||||
placeholder: '^(?=.*[a-z])(?=.*[A-Z])(?=.*d)[a-zA-Zd]{8,}$',
|
||||
},
|
||||
minLength: { type: 'code', displayName: 'Min length', placeholder: 'Enter min length' },
|
||||
maxLength: { type: 'code', displayName: 'Max length', placeholder: 'Enter max length' },
|
||||
customRule: {
|
||||
type: 'code',
|
||||
displayName: 'Custom validation',
|
||||
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onChange: { displayName: 'On change' },
|
||||
onFocus: { displayName: 'On focus' },
|
||||
onBlur: { displayName: 'On blur' },
|
||||
onEnterPressed: { displayName: 'On enter pressed' },
|
||||
},
|
||||
styles: {
|
||||
color: {
|
||||
type: 'color',
|
||||
displayName: 'Text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
|
||||
accordian: 'label',
|
||||
},
|
||||
alignment: {
|
||||
type: 'switch',
|
||||
displayName: 'Alignment',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'side' },
|
||||
options: [
|
||||
{ displayName: 'Side', value: 'side' },
|
||||
{ displayName: 'Top', value: 'top' },
|
||||
],
|
||||
accordian: 'label',
|
||||
},
|
||||
direction: {
|
||||
type: 'switch',
|
||||
displayName: '',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'left' },
|
||||
showLabel: false,
|
||||
isIcon: true,
|
||||
options: [
|
||||
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
|
||||
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
|
||||
],
|
||||
accordian: 'label',
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
width: {
|
||||
type: 'slider',
|
||||
displayName: 'Width',
|
||||
accordian: 'label',
|
||||
conditionallyRender: {
|
||||
key: 'alignment',
|
||||
value: 'side',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
auto: {
|
||||
type: 'checkbox',
|
||||
displayName: 'auto',
|
||||
showLabel: false,
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
accordian: 'label',
|
||||
conditionallyRender: {
|
||||
key: 'alignment',
|
||||
value: 'side',
|
||||
},
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
|
||||
accordian: 'field',
|
||||
},
|
||||
accentColor: {
|
||||
type: 'color',
|
||||
displayName: 'Accent',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
|
||||
accordian: 'field',
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
|
||||
accordian: 'field',
|
||||
},
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
|
||||
accordian: 'field',
|
||||
},
|
||||
errTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Error text',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
|
||||
accordian: 'field',
|
||||
},
|
||||
icon: {
|
||||
type: 'icon',
|
||||
displayName: 'Icon',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'IconLock' },
|
||||
accordian: 'field',
|
||||
visibility: false,
|
||||
},
|
||||
iconColor: {
|
||||
type: 'color',
|
||||
displayName: 'Icon color',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#CFD3D859' },
|
||||
accordian: 'field',
|
||||
visibility: false,
|
||||
showLabel: false,
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'numberInput',
|
||||
displayName: 'Border radius',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
|
||||
accordian: 'field',
|
||||
},
|
||||
boxShadow: {
|
||||
type: 'boxShadow',
|
||||
displayName: 'Box shadow',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: '0px 0px 0px 0px #00000040',
|
||||
},
|
||||
accordian: 'field',
|
||||
},
|
||||
|
||||
padding: {
|
||||
type: 'switch',
|
||||
displayName: 'Padding',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: 'default',
|
||||
},
|
||||
options: [
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
isFxNotRequired: true,
|
||||
accordian: 'container',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: '',
|
||||
isMandatory: false,
|
||||
isVisible: true,
|
||||
isDisabled: false,
|
||||
isLoading: false,
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'setText',
|
||||
displayName: 'Set text',
|
||||
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New Text' }],
|
||||
},
|
||||
{
|
||||
handle: 'clear',
|
||||
displayName: 'Clear',
|
||||
},
|
||||
{
|
||||
handle: 'setFocus',
|
||||
displayName: 'Set focus',
|
||||
},
|
||||
{
|
||||
handle: 'setBlur',
|
||||
displayName: 'Set blur',
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setDisable',
|
||||
displayName: 'Set disable',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setLoading',
|
||||
displayName: 'Set loading',
|
||||
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
placeholder: { value: 'Password' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
tooltip: { value: '' },
|
||||
label: { value: 'Label' },
|
||||
value: { value: '' },
|
||||
},
|
||||
validation: {
|
||||
mandatory: { value: false },
|
||||
regex: { value: '' },
|
||||
minLength: { value: '' },
|
||||
maxLength: { value: '' },
|
||||
customRule: { value: '' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
borderRadius: { value: '{{6}}' },
|
||||
backgroundColor: { value: '#fff' },
|
||||
borderColor: { value: '#CCD1D5' },
|
||||
accentColor: { value: '#4368E3' },
|
||||
errTextColor: { value: '#D72D39' },
|
||||
textColor: { value: '#1B1F24' },
|
||||
iconColor: { value: '#CFD3D859' },
|
||||
direction: { value: 'left' },
|
||||
width: { value: '{{33}}' },
|
||||
alignment: { value: 'side' },
|
||||
color: { value: '#1B1F24' },
|
||||
auto: { value: '{{true}}' },
|
||||
padding: { value: 'default' },
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000040' },
|
||||
icon: { value: 'IconLock' },
|
||||
iconVisibility: { value: true },
|
||||
},
|
||||
},
|
||||
};
|
||||
73
server/src/helpers/widget-config/pdf.js
Normal file
73
server/src/helpers/widget-config/pdf.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
export const pdfConfig = {
|
||||
name: 'PDF',
|
||||
displayName: 'PDF',
|
||||
description: 'Embed PDF documents',
|
||||
component: 'PDF',
|
||||
properties: {
|
||||
url: {
|
||||
type: 'code',
|
||||
displayName: 'File URL',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'https://upload.wikimedia.org/wikipedia/commons/general.pdf',
|
||||
},
|
||||
},
|
||||
scale: {
|
||||
type: 'toggle',
|
||||
displayName: 'Scale page to width',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
},
|
||||
pageControls: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show page controls',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
},
|
||||
showDownloadOption: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show download button',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
},
|
||||
},
|
||||
defaultSize: {
|
||||
width: 20,
|
||||
height: 640,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
url: {
|
||||
value:
|
||||
'https://upload.wikimedia.org/wikipedia/commons/e/ee/Guideline_No._GD-Ed-2214_Marman_Clamp_Systems_Design_Guidelines.pdf',
|
||||
},
|
||||
scale: {
|
||||
value: '{{true}}',
|
||||
},
|
||||
pageControls: {
|
||||
value: `{{true}}`,
|
||||
},
|
||||
showDownloadOption: {
|
||||
value: `{{true}}`,
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
51
server/src/helpers/widget-config/qrscanner.js
Normal file
51
server/src/helpers/widget-config/qrscanner.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
export const qrscannerConfig = {
|
||||
name: 'QrScanner',
|
||||
displayName: 'QR Scanner',
|
||||
description: 'Scan QR codes and hold its data',
|
||||
component: 'QrScanner',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 300,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {},
|
||||
events: {
|
||||
onDetect: { displayName: 'On detect' },
|
||||
},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
lastDetectedValue: '',
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{true}}' },
|
||||
},
|
||||
properties: {},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
123
server/src/helpers/widget-config/radiobutton.js
Normal file
123
server/src/helpers/widget-config/radiobutton.js
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
export const radiobuttonConfig = {
|
||||
name: 'RadioButton',
|
||||
displayName: 'Radio Button',
|
||||
description: 'Select one from multiple choices',
|
||||
component: 'RadioButton',
|
||||
defaultSize: {
|
||||
width: 6,
|
||||
height: 60,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Select',
|
||||
},
|
||||
},
|
||||
value: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }] },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
values: {
|
||||
type: 'code',
|
||||
displayName: 'Option values',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'array',
|
||||
element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }] },
|
||||
},
|
||||
defaultValue: [true, false],
|
||||
},
|
||||
},
|
||||
display_values: {
|
||||
type: 'code',
|
||||
displayName: 'Option labels',
|
||||
validation: {
|
||||
schema: { type: 'array', element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
defaultValue: ['yes', 'no'],
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onSelectionChange: { displayName: 'On select' },
|
||||
},
|
||||
styles: {
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000000',
|
||||
},
|
||||
},
|
||||
activeColor: {
|
||||
type: 'color',
|
||||
displayName: 'Active color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000000',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'selectOption',
|
||||
displayName: 'Select Option',
|
||||
params: [
|
||||
{
|
||||
handle: 'option',
|
||||
displayName: 'Option',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
exposedVariables: {
|
||||
value: true,
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
label: { value: 'Select' },
|
||||
value: { value: '{{true}}' },
|
||||
values: { value: '{{[true,false]}}' },
|
||||
display_values: { value: '{{["yes", "no"]}}' },
|
||||
visible: { value: '{{true}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
textColor: { value: '' },
|
||||
activeColor: { value: '' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
113
server/src/helpers/widget-config/rangeslider.js
Normal file
113
server/src/helpers/widget-config/rangeslider.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
export const rangeSliderConfig = {
|
||||
name: 'RangeSlider',
|
||||
displayName: 'Range Slider',
|
||||
description: 'Adjust value range',
|
||||
component: 'RangeSlider',
|
||||
defaultSize: {
|
||||
width: 9,
|
||||
height: 30,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
min: {
|
||||
type: 'number',
|
||||
displayName: 'Min',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 0,
|
||||
},
|
||||
},
|
||||
max: {
|
||||
type: 'number',
|
||||
displayName: 'Max',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 100,
|
||||
},
|
||||
},
|
||||
value: {
|
||||
type: 'code',
|
||||
displayName: 'Value',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 50,
|
||||
},
|
||||
},
|
||||
enableTwoHandle: {
|
||||
type: 'toggle',
|
||||
displayName: 'Two handles',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onChange: { displayName: 'On change' },
|
||||
},
|
||||
styles: {
|
||||
lineColor: {
|
||||
type: 'color',
|
||||
displayName: 'Line color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#375FCF',
|
||||
},
|
||||
},
|
||||
handleColor: {
|
||||
type: 'color',
|
||||
displayName: 'Handle color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#375FCF',
|
||||
},
|
||||
},
|
||||
trackColor: {
|
||||
type: 'color',
|
||||
displayName: 'Track color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#375FCF',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'code',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: null,
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: true },
|
||||
showOnMobile: { value: false },
|
||||
},
|
||||
properties: {
|
||||
min: {
|
||||
value: '{{0}}',
|
||||
},
|
||||
max: {
|
||||
value: '{{100}}',
|
||||
},
|
||||
value: {
|
||||
value: '{{50}}',
|
||||
},
|
||||
enableTwoHandle: { value: false },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
lineColor: { value: '' },
|
||||
handleColor: { value: '' },
|
||||
trackColor: { value: '' },
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
73
server/src/helpers/widget-config/richtextarea.js
Normal file
73
server/src/helpers/widget-config/richtextarea.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
export const richtextareaConfig = {
|
||||
name: 'RichTextEditor',
|
||||
displayName: 'Text Editor',
|
||||
description: 'Rich text editor',
|
||||
component: 'RichTextEditor',
|
||||
defaultSize: {
|
||||
width: 16,
|
||||
height: 210,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
placeholder: {
|
||||
type: 'code',
|
||||
displayName: 'Placeholder',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Placeholder text',
|
||||
},
|
||||
},
|
||||
defaultValue: {
|
||||
type: 'code',
|
||||
displayName: 'Default value',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Default text',
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: '',
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
placeholder: { value: 'Placeholder text' },
|
||||
defaultValue: { value: '' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
60
server/src/helpers/widget-config/spinner.js
Normal file
60
server/src/helpers/widget-config/spinner.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
export const spinnerConfig = {
|
||||
name: 'Spinner',
|
||||
displayName: 'Spinner',
|
||||
description: 'Indicate loading state',
|
||||
component: 'Spinner',
|
||||
defaultSize: {
|
||||
width: 4,
|
||||
height: 30,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
colour: {
|
||||
type: 'color',
|
||||
displayName: 'Colour',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#0565ff',
|
||||
},
|
||||
},
|
||||
size: {
|
||||
type: 'select',
|
||||
displayName: 'Size',
|
||||
options: [
|
||||
{ name: 'small', value: 'sm' },
|
||||
{ name: 'large', value: 'lg' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'sm',
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
size: { value: 'sm' },
|
||||
colour: { value: '#0565ff' },
|
||||
},
|
||||
},
|
||||
};
|
||||
117
server/src/helpers/widget-config/starrating.js
Normal file
117
server/src/helpers/widget-config/starrating.js
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
export const starratingConfig = {
|
||||
name: 'StarRating',
|
||||
displayName: 'Rating',
|
||||
description: 'Star rating',
|
||||
component: 'StarRating',
|
||||
defaultSize: {
|
||||
width: 10,
|
||||
height: 30,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
label: {
|
||||
type: 'code',
|
||||
displayName: 'Label',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Select your rating',
|
||||
},
|
||||
},
|
||||
maxRating: {
|
||||
type: 'code',
|
||||
displayName: 'Number of stars',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 5,
|
||||
},
|
||||
},
|
||||
defaultSelected: {
|
||||
type: 'code',
|
||||
displayName: 'Default no of selected stars',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 5,
|
||||
},
|
||||
},
|
||||
allowHalfStar: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable half star',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
tooltips: {
|
||||
type: 'code',
|
||||
displayName: 'Tooltips',
|
||||
validation: {
|
||||
schema: { type: 'array', element: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
defaultValue: '[]',
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
onChange: { displayName: 'On Change' },
|
||||
},
|
||||
styles: {
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Star color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#ffb400',
|
||||
},
|
||||
},
|
||||
labelColor: {
|
||||
type: 'color',
|
||||
displayName: 'Label color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000000',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: 0,
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
label: { value: 'Select your rating' },
|
||||
maxRating: { value: '5' },
|
||||
defaultSelected: { value: '5' },
|
||||
allowHalfStar: { value: '{{false}}' },
|
||||
visible: { value: '{{true}}' },
|
||||
tooltips: { value: '{{[]}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
textColor: { value: '#ffb400' },
|
||||
labelColor: { value: '' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
105
server/src/helpers/widget-config/statistics.js
Normal file
105
server/src/helpers/widget-config/statistics.js
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
export const statisticsConfig = {
|
||||
name: 'Statistics',
|
||||
displayName: 'Statistics',
|
||||
description: 'Show key metrics',
|
||||
component: 'Statistics',
|
||||
defaultSize: {
|
||||
width: 9,
|
||||
height: 152,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
primaryValueLabel: {
|
||||
type: 'code',
|
||||
displayName: 'Primary value label',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'This months earnings' },
|
||||
},
|
||||
primaryValue: {
|
||||
type: 'code',
|
||||
displayName: 'Primary value',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '682.3',
|
||||
},
|
||||
},
|
||||
hideSecondary: {
|
||||
type: 'toggle',
|
||||
displayName: 'Hide secondary value',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: false },
|
||||
},
|
||||
secondaryValueLabel: {
|
||||
type: 'code',
|
||||
displayName: 'Secondary value label',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'Last month' },
|
||||
},
|
||||
secondaryValue: {
|
||||
type: 'code',
|
||||
displayName: 'Secondary value',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '2.85' },
|
||||
},
|
||||
secondarySignDisplay: {
|
||||
type: 'code',
|
||||
displayName: 'Secondary sign display',
|
||||
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'positive' },
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: false },
|
||||
},
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
primaryLabelColour: {
|
||||
type: 'color',
|
||||
displayName: 'Primary label colour',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#8092AB' },
|
||||
},
|
||||
primaryTextColour: {
|
||||
type: 'color',
|
||||
displayName: 'Primary text colour',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#000000' },
|
||||
},
|
||||
secondaryLabelColour: {
|
||||
type: 'color',
|
||||
displayName: 'Secondary label colour',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#8092AB' },
|
||||
},
|
||||
secondaryTextColour: {
|
||||
type: 'color',
|
||||
displayName: 'Secondary text colour',
|
||||
validation: { schema: { type: 'string' }, defaultValue: '#36AF8B' },
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: { schema: { type: 'boolean' }, defaultValue: true },
|
||||
},
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
primaryValueLabel: { value: 'This months earnings' },
|
||||
primaryValue: { value: '682.3' },
|
||||
secondaryValueLabel: { value: 'Last month' },
|
||||
secondaryValue: { value: '2.85' },
|
||||
secondarySignDisplay: { value: 'positive' },
|
||||
loadingState: { value: `{{false}}` },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
primaryLabelColour: { value: '#8092AB' },
|
||||
primaryTextColour: { value: '#000000' },
|
||||
secondaryLabelColour: { value: '#8092AB' },
|
||||
secondaryTextColour: { value: '#36AF8B' },
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
108
server/src/helpers/widget-config/steps.js
Normal file
108
server/src/helpers/widget-config/steps.js
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
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: '' },
|
||||
},
|
||||
},
|
||||
};
|
||||
55
server/src/helpers/widget-config/svgImage.js
Normal file
55
server/src/helpers/widget-config/svgImage.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
export const svgImageConfig = {
|
||||
name: 'SvgImage',
|
||||
displayName: 'Svg Image',
|
||||
description: 'Display SVG graphics',
|
||||
component: 'SvgImage',
|
||||
properties: {
|
||||
data: {
|
||||
type: 'code',
|
||||
displayName: 'Svg data',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue:
|
||||
"<svg xmlns='http://www.w3.org/2000/svg' class='icon' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='currentColor' fill='none' stroke-linecap='round' stroke-linejoin='round'><path stroke='none' d='M0 0h24v24H0z' fill='none'/><rect x='4' y='4' width='6' height='6' rx='1' /><rect x='4' y='14' width='6' height='6' rx='1' /><rect x='14' y='14' width='6' height='6' rx='1' /><line x1='14' y1='7' x2='20' y2='7' /><line x1='17' y1='4' x2='17' y2='10' /></svg>",
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultSize: {
|
||||
width: 4,
|
||||
height: 50,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
value: {},
|
||||
},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
data: {
|
||||
value:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><rect x="4" y="4" width="6" height="6" rx="1" /><rect x="4" y="14" width="6" height="6" rx="1" /><rect x="14" y="14" width="6" height="6" rx="1" /><line x1="14" y1="7" x2="20" y2="7" /><line x1="17" y1="4" x2="17" y2="10" /></svg>',
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
667
server/src/helpers/widget-config/table.js
Normal file
667
server/src/helpers/widget-config/table.js
Normal file
|
|
@ -0,0 +1,667 @@
|
|||
export const tableConfig = {
|
||||
name: 'Table',
|
||||
displayName: 'Table',
|
||||
description: 'Display paginated tabular data',
|
||||
component: 'Table',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
displayName: 'Title',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: 'code',
|
||||
displayName: 'Table data',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'array',
|
||||
element: { type: 'object' },
|
||||
},
|
||||
defaultValue: "[{ id: 1, name: 'Sarah', email: 'sarah@mail.com' }]",
|
||||
},
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
type: 'array',
|
||||
displayName: 'Table Columns',
|
||||
},
|
||||
useDynamicColumn: {
|
||||
type: 'toggle',
|
||||
displayName: 'Use dynamic column',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
columnData: {
|
||||
type: 'code',
|
||||
displayName: 'Column data',
|
||||
validation: {
|
||||
schema: { type: 'array', element: { type: 'object' } },
|
||||
defaultValue:
|
||||
"{{[{name: 'email', key: 'email', id: '1'}, {name: 'Full name', key: 'name', id: '2', isEditable: true}]}}}",
|
||||
},
|
||||
},
|
||||
rowsPerPage: {
|
||||
type: 'code',
|
||||
displayName: 'Number of rows per page',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 10,
|
||||
},
|
||||
},
|
||||
|
||||
enableNextButton: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable next page button',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
enabledSort: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable column sorting',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
hideColumnSelectorButton: {
|
||||
type: 'toggle',
|
||||
displayName: 'Hide column selector button',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
enablePrevButton: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable previous page button',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
},
|
||||
},
|
||||
totalRecords: {
|
||||
type: 'code',
|
||||
displayName: 'Total records server side',
|
||||
validation: {
|
||||
schema: { type: 'number' },
|
||||
defaultValue: 10,
|
||||
},
|
||||
},
|
||||
enablePagination: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable pagination',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
serverSidePagination: {
|
||||
type: 'clientServerSwitch',
|
||||
displayName: 'Type',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
options: [
|
||||
{ displayName: 'Client side', value: 'clientSide' },
|
||||
{ displayName: 'Server side', value: 'serverSide' },
|
||||
],
|
||||
},
|
||||
serverSideSearch: {
|
||||
type: 'clientServerSwitch',
|
||||
displayName: 'Type',
|
||||
options: [
|
||||
{ displayName: 'Client side', value: 'clientSide' },
|
||||
{ displayName: 'Server side', value: 'serverSide' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
serverSideSort: {
|
||||
type: 'clientServerSwitch',
|
||||
displayName: 'Type',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
options: [
|
||||
{ displayName: 'Client side', value: 'clientSide' },
|
||||
{ displayName: 'Server side', value: 'serverSide' },
|
||||
],
|
||||
},
|
||||
serverSideFilter: {
|
||||
type: 'clientServerSwitch',
|
||||
displayName: 'Type',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
options: [
|
||||
{ displayName: 'Client side', value: 'clientSide' },
|
||||
{ displayName: 'Server side', value: 'serverSide' },
|
||||
],
|
||||
defaultValue: 'clientSide',
|
||||
},
|
||||
actionButtonBackgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#375FCF',
|
||||
},
|
||||
},
|
||||
actionButtonTextColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#fff',
|
||||
},
|
||||
},
|
||||
displaySearchBox: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show search',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
showDownloadButton: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show download button',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
showFilterButton: {
|
||||
type: 'toggle',
|
||||
displayName: 'Enable filtering',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
showBulkUpdateActions: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show update buttons',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
allowSelection: {
|
||||
type: 'toggle',
|
||||
displayName: 'Allow selection',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
showBulkSelector: {
|
||||
type: 'toggle',
|
||||
displayName: 'Bulk selection',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
highlightSelectedRow: {
|
||||
type: 'toggle',
|
||||
displayName: 'Highlight selected row',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
defaultSelectedRow: {
|
||||
type: 'code',
|
||||
displayName: 'Default selected row',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'object',
|
||||
},
|
||||
defaultValue: { id: 1 },
|
||||
},
|
||||
},
|
||||
|
||||
showAddNewRowButton: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show add new row button',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
selectRowOnCellEdit: {
|
||||
type: 'toggle',
|
||||
displayName: 'Select row on cell edit',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
},
|
||||
},
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop ' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
defaultSize: {
|
||||
width: 35,
|
||||
height: 456,
|
||||
},
|
||||
events: {
|
||||
onRowHovered: { displayName: 'Row hovered' },
|
||||
onRowClicked: { displayName: 'Row clicked' },
|
||||
onBulkUpdate: { displayName: 'Save changes' },
|
||||
onPageChanged: { displayName: 'Page changed' },
|
||||
onSearch: { displayName: 'Search' },
|
||||
onCancelChanges: { displayName: 'Cancel changes' },
|
||||
onSort: { displayName: 'Sort applied' },
|
||||
onCellValueChanged: { displayName: 'Cell value changed' },
|
||||
onFilterChanged: { displayName: 'Filter changed' },
|
||||
onNewRowsAdded: { displayName: 'Add new rows' },
|
||||
},
|
||||
styles: {
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Text Color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000',
|
||||
},
|
||||
accordian: 'Data',
|
||||
},
|
||||
columnHeaderWrap: {
|
||||
type: 'switch',
|
||||
displayName: 'Column header',
|
||||
validation: { schema: { type: 'string' } },
|
||||
accordian: 'Data',
|
||||
options: [
|
||||
{ displayName: 'Fixed', value: 'fixed' },
|
||||
{ displayName: 'Wrap', value: 'wrap' },
|
||||
],
|
||||
},
|
||||
tableType: {
|
||||
type: 'select',
|
||||
displayName: 'Row style',
|
||||
options: [
|
||||
{ name: 'Regular', value: 'table-classic' },
|
||||
{ name: 'Bordered', value: 'table-bordered' },
|
||||
{ name: 'Striped', value: 'table-striped' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'table-classic',
|
||||
},
|
||||
accordian: 'Data',
|
||||
},
|
||||
cellSize: {
|
||||
type: 'select',
|
||||
displayName: 'Cell height',
|
||||
options: [
|
||||
{ name: 'Regular', value: 'regular' },
|
||||
{ name: 'Condensed', value: 'condensed' },
|
||||
],
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'regular',
|
||||
},
|
||||
accordian: 'Data',
|
||||
},
|
||||
contentWrap: {
|
||||
type: 'toggle',
|
||||
showLabel: false,
|
||||
toggleLabel: 'Content wrap',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'boolean' }] },
|
||||
},
|
||||
accordian: 'Data',
|
||||
},
|
||||
maxRowHeight: {
|
||||
type: 'switch',
|
||||
displayName: 'Max row height',
|
||||
validation: { schema: { type: 'string' } },
|
||||
accordian: 'Data',
|
||||
options: [
|
||||
{ displayName: 'Auto', value: 'auto' },
|
||||
{ displayName: 'Custom', value: 'custom' },
|
||||
],
|
||||
conditionallyRender: {
|
||||
key: 'contentWrap',
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
maxRowHeightValue: {
|
||||
type: 'tableRowHeightInput',
|
||||
isFxNotRequired: true,
|
||||
showLabel: false,
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
},
|
||||
accordian: 'Data',
|
||||
conditionallyRender: [
|
||||
{
|
||||
key: 'maxRowHeight',
|
||||
value: 'custom',
|
||||
},
|
||||
{
|
||||
key: 'contentWrap',
|
||||
value: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
actionButtonRadius: {
|
||||
type: 'numberInput',
|
||||
displayName: 'Button radius',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'boolean' }] },
|
||||
},
|
||||
accordian: 'Action button',
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'numberInput',
|
||||
displayName: 'Border radius',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
accordian: 'Container',
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: false,
|
||||
},
|
||||
accordian: 'Container',
|
||||
},
|
||||
boxShadow: {
|
||||
type: 'boxShadow',
|
||||
displayName: 'Box Shadow',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
accordian: 'Container',
|
||||
},
|
||||
padding: {
|
||||
type: 'switch',
|
||||
displayName: 'Padding',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] } },
|
||||
options: [
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
accordian: 'Container',
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
selectedRow: {},
|
||||
changeSet: {},
|
||||
dataUpdates: [],
|
||||
pageIndex: 1,
|
||||
searchText: '',
|
||||
selectedRows: [],
|
||||
filters: [],
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'setPage',
|
||||
displayName: 'Set page',
|
||||
params: [
|
||||
{
|
||||
handle: 'page',
|
||||
displayName: 'Page',
|
||||
defaultValue: '{{1}}',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'selectRow',
|
||||
displayName: 'Select row',
|
||||
params: [
|
||||
{ handle: 'key', displayName: 'Key' },
|
||||
{ handle: 'value', displayName: 'Value' },
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'deselectRow',
|
||||
displayName: 'Deselect row',
|
||||
},
|
||||
{
|
||||
handle: 'discardChanges',
|
||||
displayName: 'Discard Changes',
|
||||
},
|
||||
{
|
||||
handle: 'discardNewlyAddedRows',
|
||||
displayName: 'Discard newly added rows',
|
||||
},
|
||||
{
|
||||
displayName: 'Download table data',
|
||||
handle: 'downloadTableData',
|
||||
params: [
|
||||
{
|
||||
handle: 'type',
|
||||
displayName: 'Type',
|
||||
options: [
|
||||
{ name: 'Download as Excel', value: 'xlsx' },
|
||||
{ name: 'Download as CSV', value: 'csv' },
|
||||
{ name: 'Download as PDF', value: 'pdf' },
|
||||
],
|
||||
defaultValue: `{{Download as Excel}}`,
|
||||
type: 'select',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
handle: 'selectAllRows',
|
||||
displayName: 'Select all rows',
|
||||
},
|
||||
{
|
||||
handle: 'deselectAllRows',
|
||||
displayName: 'Deselect all rows',
|
||||
},
|
||||
{
|
||||
handle: 'setFilters',
|
||||
displayName: 'Set filters',
|
||||
params: [{ handle: 'parameters', displayName: 'Parameters' }],
|
||||
},
|
||||
{
|
||||
handle: 'clearFilters',
|
||||
displayName: 'Clear filters',
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
title: { value: 'Table' },
|
||||
visible: { value: '{{true}}' },
|
||||
loadingState: { value: '{{false}}' },
|
||||
data: {
|
||||
value:
|
||||
"{{ [ \n\t\t{ id: 1, name: 'Olivia Nguyen', email: 'olivia.nguyen@example.com', date: '15/05/2022', phone: 9876543210, interest: ['Reading', 'Traveling','Photography'], photo: 'https://reqres.in/img/faces/7-image.jpg' }, \n\t\t{ id: 2, name: 'Liam Patel', email: 'liam.patel@example.com', date: '20/09/2021', phone: 8765432109, interest: ['Cooking','Gardening','Hiking'], photo: 'https://reqres.in/img/faces/5-image.jpg' }, \n\t\t{ id: 3, name: 'Sophia Reyes', email: 'sophia.reyes@example.com', date: '01/01/2023', phone: 7654321098, interest: ['Music','Dancing','Crafting'], photo: 'https://reqres.in/img/faces/3-image.jpg' }, \n\t\t{ id: 4, name: 'Jacob Hernandez', email: 'jacob.hernandez@example.com', date: '10/11/2022', phone: 6543210987, interest: ['Reading', 'Traveling', 'Volunteering'], photo: 'https://reqres.in/img/faces/1-image.jpg' }, \n\t\t{ id: 5, name: 'William Sanchez', email: 'william.sanchez@example.com', date: '07/01/2021', phone: 4321098765, interest: ['Music', 'Dancing', 'Hiking'], photo: 'https://reqres.in/img/faces/4-image.jpg' }, \n\t\t{ id: 6, name: 'Ethan Morales', email: 'ethan.morales@example.com', date: '05/11/2021', phone: 2109876543, interest: ['Cooking', 'Traveling', 'Photography'], photo: 'https://reqres.in/img/faces/6-image.jpg' }, \n\t\t{ id: 7, name: 'Mia Tiana', email: 'mia.tiana@example.com', date: '21/11/2022', phone: 1098705217, interest: ['Music', 'Gardening', 'Hiking'], photo: 'https://reqres.in/img/faces/2-image.jpg' }, \n\t\t{ id: 8, name: 'Lucas Ramirez', email: 'lucas.ramirez@example.com', date: '31/03/2023', phone: 9876543210, interest: ['Reading', 'Dancing', 'Crafting'], photo: 'https://reqres.in/img/faces/9-image.jpg' }, \n\t\t{ id: 9, name: 'Alexander Vela', email: 'alexander.vela@example.com', date: '07/09/2022', phone: 7654321098, interest: ['Music','Gardening','Photography'], photo: 'https://reqres.in/img/faces/8-image.jpg' }, \n\t\t{ id: 10, name: 'Michael Reyes', email: 'michael.reyes@example.com', date: '25/12/2021', phone: 5432109876, interest: ['Cooking','Crafting','Volunteering'], photo: 'https://reqres.in/img/faces/10-image.jpg' } \n] }}",
|
||||
},
|
||||
useDynamicColumn: { value: '{{false}}' },
|
||||
columnData: {
|
||||
value:
|
||||
"{{[{name: 'email', key: 'email', id: '1'}, {name: 'Full name', key: 'name', id: '2', isEditable: true}]}}",
|
||||
},
|
||||
rowsPerPage: { value: '{{10}}' },
|
||||
serverSidePagination: { value: '{{false}}' },
|
||||
enableNextButton: { value: '{{true}}' },
|
||||
enablePrevButton: { value: '{{true}}' },
|
||||
totalRecords: { value: '{{10}}' },
|
||||
enablePagination: { value: '{{true}}' },
|
||||
serverSideSort: { value: '{{false}}' },
|
||||
serverSideFilter: { value: '{{false}}' },
|
||||
displaySearchBox: { value: '{{true}}' },
|
||||
showDownloadButton: { value: '{{true}}' },
|
||||
showFilterButton: { value: '{{true}}' },
|
||||
autogenerateColumns: { value: true, generateNestedColumns: true },
|
||||
isAllColumnsEditable: { value: '{{false}}' },
|
||||
columns: {
|
||||
value: [
|
||||
{
|
||||
name: 'id',
|
||||
id: 'e3ecbf7fa52c4d7210a93edb8f43776267a489bad52bd108be9588f790126737',
|
||||
autogenerated: true,
|
||||
fxActiveFields: [],
|
||||
columnSize: 30,
|
||||
columnType: 'string',
|
||||
},
|
||||
{
|
||||
name: 'photo',
|
||||
key: 'photo',
|
||||
id: 'f23b7d134b2e490ea41e3bb8eeb8c8e37472af243bf6b70d5af294482097e3a2',
|
||||
autogenerated: true,
|
||||
fxActiveFields: [],
|
||||
columnType: 'image',
|
||||
objectFit: 'contain',
|
||||
borderRadius: '100',
|
||||
columnSize: 70,
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
id: '5d2a3744a006388aadd012fcc15cc0dbcb5f9130e0fbb64c558561c97118754a',
|
||||
autogenerated: true,
|
||||
fxActiveFields: [],
|
||||
columnSize: 130,
|
||||
columnType: 'string',
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
id: 'afc9a5091750a1bd4760e38760de3b4be11a43452ae8ae07ce2eebc569fe9a7f',
|
||||
autogenerated: true,
|
||||
fxActiveFields: [],
|
||||
columnSize: 230,
|
||||
columnType: 'string',
|
||||
},
|
||||
{
|
||||
name: 'date',
|
||||
id: '27b75c8af9d34d1eaa1f9bb7f8f9f7b0abf1823e799748c8bb57e74f53b2c1dc',
|
||||
autogenerated: true,
|
||||
fxActiveFields: [],
|
||||
columnType: 'datepicker',
|
||||
isTimeChecked: false,
|
||||
dateFormat: 'DD/MM/YYYY',
|
||||
parseDateFormat: 'DD/MM/YYYY',
|
||||
isDateSelectionEnabled: true,
|
||||
columnSize: 130,
|
||||
},
|
||||
{
|
||||
name: 'phone',
|
||||
id: '9c2e3c40572a4aefb8e179ee39a0e1ac9dc2b2e6634be56e1c05be13c3d1de56',
|
||||
autogenerated: true,
|
||||
fxActiveFields: [],
|
||||
columnType: 'number',
|
||||
columnSize: 140,
|
||||
},
|
||||
{
|
||||
name: 'interest',
|
||||
key: 'interest',
|
||||
id: 'f23b7d134b2e490ea41e3bb8eeb8c8e37472af243bf6b70d5af294482097e3a1',
|
||||
autogenerated: true,
|
||||
fxActiveFields: [],
|
||||
columnType: 'newMultiSelect',
|
||||
columnSize: 300,
|
||||
options: [
|
||||
{
|
||||
label: 'Reading',
|
||||
value: 'Reading',
|
||||
},
|
||||
{
|
||||
label: 'Traveling',
|
||||
value: 'Traveling',
|
||||
},
|
||||
{
|
||||
label: 'Photography',
|
||||
value: 'Photography',
|
||||
},
|
||||
{
|
||||
label: 'Music',
|
||||
value: 'Music',
|
||||
},
|
||||
{
|
||||
label: 'Cooking',
|
||||
value: 'Cooking',
|
||||
},
|
||||
{
|
||||
label: 'Crafting',
|
||||
value: 'Crafting',
|
||||
},
|
||||
{
|
||||
label: 'Voluntering',
|
||||
value: 'Voluntering',
|
||||
},
|
||||
{
|
||||
label: 'Garndening',
|
||||
value: 'Garndening',
|
||||
},
|
||||
{
|
||||
label: 'Dancing',
|
||||
value: 'Dancing',
|
||||
},
|
||||
{
|
||||
label: 'Hiking',
|
||||
value: 'Hiking',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
showBulkUpdateActions: { value: '{{true}}' },
|
||||
showBulkSelector: { value: '{{false}}' },
|
||||
highlightSelectedRow: { value: '{{false}}' },
|
||||
columnSizes: { value: '{{({})}}' },
|
||||
actions: { value: [] },
|
||||
enabledSort: { value: '{{true}}' },
|
||||
hideColumnSelectorButton: { value: '{{false}}' },
|
||||
defaultSelectedRow: { value: '{{{"id":1}}}' },
|
||||
showAddNewRowButton: { value: '{{true}}' },
|
||||
allowSelection: { value: '{{true}}' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
textColor: { value: '#000' },
|
||||
columnHeaderWrap: { value: 'fixed' },
|
||||
actionButtonRadius: { value: '0' },
|
||||
cellSize: { value: 'regular' },
|
||||
borderRadius: { value: '8' },
|
||||
tableType: { value: 'table-classic' },
|
||||
maxRowHeight: { value: 'auto' },
|
||||
maxRowHeightValue: { value: '{{0}}' }, // Setting it here as 0 since TableRowHeightInput component will set the value
|
||||
contentWrap: { value: '{{true}}' },
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000090' },
|
||||
padding: { value: 'default' },
|
||||
},
|
||||
},
|
||||
};
|
||||
183
server/src/helpers/widget-config/tabs.js
Normal file
183
server/src/helpers/widget-config/tabs.js
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
export const tabsConfig = {
|
||||
name: 'Tabs',
|
||||
displayName: 'Tabs',
|
||||
description: 'Organize content in tabs',
|
||||
defaultSize: {
|
||||
width: 30,
|
||||
height: 300,
|
||||
},
|
||||
defaultChildren: [
|
||||
{
|
||||
componentName: 'Image',
|
||||
layout: {
|
||||
top: 60,
|
||||
left: 17,
|
||||
height: 100,
|
||||
},
|
||||
tab: 0,
|
||||
properties: ['source'],
|
||||
defaultValue: {
|
||||
source: 'https://uploads-ssl.webflow.com/6266634263b9179f76b2236e/62666392f32677b5cb2fb84b_logo.svg',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Text',
|
||||
layout: {
|
||||
top: 100,
|
||||
left: 5,
|
||||
height: 50,
|
||||
width: 34,
|
||||
},
|
||||
tab: 1,
|
||||
properties: ['text'],
|
||||
defaultValue: {
|
||||
text: 'Open-source low-code framework to build & deploy internal tools within minutes.',
|
||||
},
|
||||
},
|
||||
{
|
||||
componentName: 'Table',
|
||||
layout: {
|
||||
top: 0,
|
||||
left: 1,
|
||||
width: 41,
|
||||
height: 250,
|
||||
},
|
||||
tab: 2,
|
||||
},
|
||||
],
|
||||
component: 'Tabs',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
tabs: {
|
||||
type: 'code',
|
||||
displayName: 'Tabs',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'array',
|
||||
element: {
|
||||
type: 'object',
|
||||
object: {
|
||||
id: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultValue: [
|
||||
{ title: 'Home', id: '0' },
|
||||
{ title: 'Profile', id: '1' },
|
||||
{ title: 'Settings', id: '2' },
|
||||
],
|
||||
},
|
||||
},
|
||||
defaultTab: {
|
||||
type: 'code',
|
||||
displayName: 'Default tab',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'union',
|
||||
schemas: [{ type: 'string' }, { type: 'number' }],
|
||||
},
|
||||
defaultValue: '0',
|
||||
},
|
||||
},
|
||||
hideTabs: {
|
||||
type: 'toggle',
|
||||
displayName: 'Hide tabs',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
renderOnlyActiveTab: {
|
||||
type: 'toggle',
|
||||
displayName: 'Render only active tab',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
events: { onTabSwitch: { displayName: 'On tab switch' } },
|
||||
styles: {
|
||||
highlightColor: {
|
||||
type: 'color',
|
||||
displayName: 'Highlight color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#375FCF',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
},
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
tabWidth: {
|
||||
type: 'select',
|
||||
displayName: 'Tab width',
|
||||
options: [
|
||||
{ name: 'Auto', value: 'auto' },
|
||||
{ name: 'Equally split', value: 'split' },
|
||||
],
|
||||
},
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'setTab',
|
||||
displayName: 'Set current tab',
|
||||
params: [
|
||||
{
|
||||
handle: 'id',
|
||||
displayName: 'Id',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
exposedVariables: { currentTab: '' },
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
tabs: {
|
||||
value:
|
||||
"{{[ \n\t\t{ title: 'Home', id: '0' }, \n\t\t{ title: 'Profile', id: '1' }, \n\t\t{ title: 'Settings', id: '2' } \n ]}}",
|
||||
},
|
||||
defaultTab: { value: '0' },
|
||||
hideTabs: { value: false },
|
||||
renderOnlyActiveTab: { value: false },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
highlightColor: { value: '#375FCF' },
|
||||
visibility: { value: '{{true}}' },
|
||||
disabledState: { value: '{{false}}' },
|
||||
tabWidth: { value: 'auto' },
|
||||
},
|
||||
},
|
||||
};
|
||||
59
server/src/helpers/widget-config/tags.js
Normal file
59
server/src/helpers/widget-config/tags.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
export const tagsConfig = {
|
||||
name: 'Tags',
|
||||
displayName: 'Tags',
|
||||
description: 'Display tag labels',
|
||||
component: 'Tags',
|
||||
defaultSize: {
|
||||
width: 8,
|
||||
height: 30,
|
||||
},
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
data: {
|
||||
type: 'code',
|
||||
displayName: 'Tags',
|
||||
validation: {
|
||||
schema: {
|
||||
type: 'array',
|
||||
element: {
|
||||
type: 'object',
|
||||
object: { title: { type: 'string' }, color: { type: 'string' }, textColor: { type: 'string' } },
|
||||
},
|
||||
},
|
||||
defaultValue:
|
||||
"{{ [{ title: 'success', color: '#2fb344', textColor: '#fff' }, { title: 'info', color: '#206bc4', textColor: '#fff' }] }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {},
|
||||
styles: {
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
exposedVariables: {},
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
data: {
|
||||
value:
|
||||
"{{ [ \n\t\t{ title: 'success', color: '#2fb344', textColor: '#fff' }, \n\t\t{ title: 'info', color: '#206bc4', textColor: '#fff' }, \n\t\t{ title: 'warning', color: '#f59f00', textColor: '#fff' }, \n\t\t{ title: 'danger', color: '#d63939', textColor: '#fff' } ] }}",
|
||||
},
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
},
|
||||
};
|
||||
298
server/src/helpers/widget-config/text.js
Normal file
298
server/src/helpers/widget-config/text.js
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
export const textConfig = {
|
||||
name: 'Text',
|
||||
displayName: 'Text',
|
||||
description: 'Display text or HTML',
|
||||
component: 'Text',
|
||||
others: {
|
||||
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
|
||||
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
|
||||
},
|
||||
properties: {
|
||||
textFormat: {
|
||||
type: 'switch',
|
||||
displayName: 'Text Format',
|
||||
options: [
|
||||
{ displayName: 'Plain text', value: 'plainText' },
|
||||
{ displayName: 'Markdown', value: 'markdown' },
|
||||
{ displayName: 'HTML', value: 'html' },
|
||||
],
|
||||
isFxNotRequired: true,
|
||||
defaultValue: { value: 'plainText' },
|
||||
fullWidth: true,
|
||||
},
|
||||
text: {
|
||||
type: 'code',
|
||||
displayName: 'TextComponentTextInput', // Keeping this name unique so that we can filter it in Codehinter
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'Hello, there!',
|
||||
},
|
||||
showLabel: false,
|
||||
},
|
||||
loadingState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Show loading state',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
section: 'additionalActions',
|
||||
},
|
||||
visibility: {
|
||||
type: 'toggle',
|
||||
displayName: 'Visibility',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: true,
|
||||
},
|
||||
section: 'additionalActions',
|
||||
},
|
||||
disabledState: {
|
||||
type: 'toggle',
|
||||
displayName: 'Disable',
|
||||
validation: {
|
||||
schema: { type: 'boolean' },
|
||||
defaultValue: false,
|
||||
},
|
||||
section: 'additionalActions',
|
||||
},
|
||||
tooltip: {
|
||||
type: 'code',
|
||||
displayName: 'Tooltip',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
|
||||
section: 'additionalActions',
|
||||
placeholder: 'Enter tooltip text',
|
||||
},
|
||||
},
|
||||
defaultSize: {
|
||||
width: 6,
|
||||
height: 40,
|
||||
},
|
||||
events: {
|
||||
onClick: { displayName: 'On click' },
|
||||
onHover: { displayName: 'On hover' },
|
||||
},
|
||||
styles: {
|
||||
textSize: {
|
||||
type: 'numberInput',
|
||||
displayName: 'Size',
|
||||
validation: {
|
||||
schema: [{ type: 'string' }, { type: 'number' }],
|
||||
defaultValue: 14,
|
||||
},
|
||||
accordian: 'Text',
|
||||
},
|
||||
fontWeight: {
|
||||
type: 'select',
|
||||
displayName: 'Weight',
|
||||
options: [
|
||||
{ name: 'normal', value: 'normal' },
|
||||
{ name: 'bold', value: 'bold' },
|
||||
{ name: 'lighter', value: 'lighter' },
|
||||
{ name: 'bolder', value: 'bolder' },
|
||||
],
|
||||
accordian: 'Text',
|
||||
},
|
||||
fontStyle: {
|
||||
type: 'switch',
|
||||
displayName: 'Style',
|
||||
options: [
|
||||
{ displayName: 'Normal', value: 'normal', iconName: 'minus' },
|
||||
{ displayName: 'Oblique', value: 'oblique', iconName: 'oblique' },
|
||||
{ displayName: 'Italic', value: 'italic', iconName: 'italic' },
|
||||
],
|
||||
isIcon: true,
|
||||
accordian: 'Text',
|
||||
},
|
||||
textColor: {
|
||||
type: 'color',
|
||||
displayName: 'Color',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
accordian: 'Text',
|
||||
},
|
||||
isScrollRequired: {
|
||||
type: 'switch',
|
||||
displayName: 'Scroll',
|
||||
options: [
|
||||
{ displayName: 'Enable', value: 'enabled' },
|
||||
{ displayName: 'Disable', value: 'disabled' },
|
||||
],
|
||||
accordian: 'Text',
|
||||
},
|
||||
lineHeight: { type: 'numberInput', displayName: 'Line height', accordian: 'Text' },
|
||||
textIndent: { type: 'numberInput', displayName: 'Text indent', accordian: 'Text' },
|
||||
textAlign: {
|
||||
type: 'alignButtons',
|
||||
displayName: 'Alignment',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: 'left',
|
||||
},
|
||||
accordian: 'Text',
|
||||
},
|
||||
verticalAlignment: {
|
||||
type: 'switch',
|
||||
displayName: '',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'center' },
|
||||
showLabel: false,
|
||||
isIcon: true,
|
||||
options: [
|
||||
{ displayName: 'alignverticallytop', value: 'top', iconName: 'alignverticallytop' },
|
||||
{ displayName: 'alignverticallycenter', value: 'center', iconName: 'alignverticallycenter' },
|
||||
{ displayName: 'alignverticallybottom', value: 'bottom', iconName: 'alignverticallybottom' },
|
||||
],
|
||||
accordian: 'Text',
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
decoration: {
|
||||
type: 'switch',
|
||||
displayName: 'Decoration',
|
||||
isIcon: true,
|
||||
options: [
|
||||
{ displayName: 'none', value: 'none', iconName: 'minus' },
|
||||
{ displayName: 'underline', value: 'underline', iconName: 'underline' },
|
||||
{ displayName: 'overline', value: 'overline', iconName: 'overline' },
|
||||
{ displayName: 'line-through', value: 'line-through', iconName: 'linethrough' },
|
||||
],
|
||||
accordian: 'Text',
|
||||
},
|
||||
transformation: {
|
||||
type: 'switch',
|
||||
displayName: 'Transformation',
|
||||
isIcon: true,
|
||||
options: [
|
||||
{ displayName: 'none', value: 'none', iconName: 'minus' },
|
||||
{ displayName: 'uppercase', value: 'uppercase', iconName: 'uppercase' },
|
||||
{ displayName: 'lowercase', value: 'lowercase', iconName: 'lowercase' },
|
||||
{ displayName: 'capitalize', value: 'capitalize', iconName: 'capitalize' },
|
||||
],
|
||||
accordian: 'Text',
|
||||
},
|
||||
letterSpacing: { type: 'numberInput', displayName: 'Letter spacing', accordian: 'Text' },
|
||||
wordSpacing: { type: 'numberInput', displayName: 'Word spacing', accordian: 'Text' },
|
||||
fontVariant: {
|
||||
type: 'select',
|
||||
displayName: 'Font variant',
|
||||
options: [
|
||||
{ name: 'normal', value: 'normal' },
|
||||
{ name: 'small-caps', value: 'small-caps' },
|
||||
{ name: 'initial', value: 'initial' },
|
||||
{ name: 'inherit', value: 'inherit' },
|
||||
],
|
||||
accordian: 'Text',
|
||||
},
|
||||
|
||||
backgroundColor: {
|
||||
type: 'color',
|
||||
displayName: 'Background',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#fff00000',
|
||||
},
|
||||
accordian: 'Container',
|
||||
colorPickerPosition: 'top',
|
||||
},
|
||||
borderColor: {
|
||||
type: 'color',
|
||||
displayName: 'Border',
|
||||
validation: {
|
||||
schema: { type: 'string' },
|
||||
defaultValue: '#000000',
|
||||
},
|
||||
accordian: 'Container',
|
||||
colorPickerPosition: 'top',
|
||||
},
|
||||
borderRadius: {
|
||||
type: 'numberInput',
|
||||
displayName: 'Border radius',
|
||||
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
|
||||
accordian: 'Container',
|
||||
},
|
||||
boxShadow: {
|
||||
type: 'boxShadow',
|
||||
displayName: 'Box shadow',
|
||||
validation: {
|
||||
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
|
||||
defaultValue: '0px 0px 0px 0px #00000090',
|
||||
},
|
||||
accordian: 'Container',
|
||||
},
|
||||
padding: {
|
||||
type: 'switch',
|
||||
displayName: 'Padding',
|
||||
validation: { schema: { type: 'string' }, defaultValue: 'default' },
|
||||
options: [
|
||||
{ displayName: 'Default', value: 'default' },
|
||||
{ displayName: 'None', value: 'none' },
|
||||
],
|
||||
accordian: 'Container',
|
||||
isFxNotRequired: true,
|
||||
},
|
||||
},
|
||||
exposedVariables: {
|
||||
text: 'Hello, there!',
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'setText',
|
||||
displayName: 'Set text',
|
||||
params: [{ handle: 'text', displayName: 'Text', defaultValue: 'New text' }],
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
params: [{ handle: 'setVisibility', displayName: 'Value', defaultValue: `{{true}}`, type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'clear',
|
||||
displayName: 'Clear',
|
||||
},
|
||||
{
|
||||
handle: 'setLoading',
|
||||
displayName: 'Set loading',
|
||||
params: [{ handle: 'setLoading', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setDisable',
|
||||
displayName: 'Set disable',
|
||||
params: [{ handle: 'setDisable', displayName: 'Value', defaultValue: `{{false}}`, type: 'toggle' }],
|
||||
},
|
||||
],
|
||||
definition: {
|
||||
others: {
|
||||
showOnDesktop: { value: '{{true}}' },
|
||||
showOnMobile: { value: '{{false}}' },
|
||||
},
|
||||
properties: {
|
||||
textFormat: { value: 'html' },
|
||||
text: { value: `Hello {{globals.currentUser.firstName}}👋` },
|
||||
loadingState: { value: `{{false}}` },
|
||||
disabledState: { value: '{{false}}' },
|
||||
visibility: { value: '{{true}}' },
|
||||
},
|
||||
events: [],
|
||||
styles: {
|
||||
backgroundColor: { value: '#fff00000' },
|
||||
textColor: { value: '#000000' },
|
||||
textSize: { value: '{{14}}' },
|
||||
textAlign: { value: 'left' },
|
||||
fontWeight: { value: 'normal' },
|
||||
decoration: { value: 'none' },
|
||||
transformation: { value: 'none' },
|
||||
fontStyle: { value: 'normal' },
|
||||
lineHeight: { value: '{{1.5}}' },
|
||||
textIndent: { value: '{{0}}' },
|
||||
letterSpacing: { value: '{{0}}' },
|
||||
wordSpacing: { value: '{{0}}' },
|
||||
fontVariant: { value: 'normal' },
|
||||
verticalAlignment: { value: 'center' },
|
||||
padding: { value: 'default' },
|
||||
boxShadow: { value: '0px 0px 0px 0px #00000090' },
|
||||
borderColor: { value: '' },
|
||||
borderRadius: { value: '{{6}}' },
|
||||
isScrollRequired: { value: 'enabled' },
|
||||
},
|
||||
},
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue