From c2fc4fe60f5bddef9fec06a02ae17f68daa7c907 Mon Sep 17 00:00:00 2001 From: devanshu052000 Date: Wed, 28 May 2025 02:59:09 +0530 Subject: [PATCH] Added option for query permission in the popup and integration app permissions modal --- .../src/AppBuilder/QueryPanel/QueryCard.jsx | 62 +++++++++++++++---- .../AppBuilder/QueryPanel/QueryDataPane.jsx | 22 +++++++ .../_stores/slices/queryPanelSlice.js | 6 ++ frontend/src/ToolJetUI/List/list.scss | 1 + 4 files changed, 78 insertions(+), 13 deletions(-) diff --git a/frontend/src/AppBuilder/QueryPanel/QueryCard.jsx b/frontend/src/AppBuilder/QueryPanel/QueryCard.jsx index 088f3c7318..78050de93d 100644 --- a/frontend/src/AppBuilder/QueryPanel/QueryCard.jsx +++ b/frontend/src/AppBuilder/QueryPanel/QueryCard.jsx @@ -1,5 +1,6 @@ import React, { useState, useCallback } from 'react'; import { Tooltip } from 'react-tooltip'; +import { ToolTip } from '@/_components/ToolTip'; import { updateQuerySuggestions } from '@/_helpers/appUtils'; // import { Confirm } from '../Viewer/Confirm'; import { toast } from 'react-hot-toast'; @@ -18,6 +19,7 @@ import Edit from '@/_ui/Icon/bulkIcons/Edit'; import Trash from '@/_ui/Icon/solidIcons/Trash'; import { OverlayTrigger, Popover } from 'react-bootstrap'; import classNames from 'classnames'; +import SolidIcon from '@/_ui/Icon/SolidIcons'; export const QueryCard = ({ dataQuery, darkMode = false, localDs }) => { const appId = useStore((state) => state.app.appId); @@ -31,6 +33,7 @@ export const QueryCard = ({ dataQuery, darkMode = false, localDs }) => { const deleteDataQueries = useStore((state) => state.dataQuery.deleteDataQueries); const duplicateQuery = useStore((state) => state.dataQuery.duplicateQuery); const setPreviewData = useStore((state) => state.queryPanel.setPreviewData); + const toggleQueryPermissionModal = useStore((state) => state.queryPanel.toggleQueryPermissionModal); const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false); const [showQueryMenu, setShowQueryMenu] = useState(false); const hasPermissions = @@ -40,6 +43,9 @@ export const QueryCard = ({ dataQuery, darkMode = false, localDs }) => { canDeleteDataSource() : true; + const featureAccess = useStore((state) => state?.license?.featureAccess, shallow); + const licenseValid = !featureAccess?.licenseStatus?.isExpired && featureAccess?.licenseStatus?.isLicenseValid; + const shouldFreeze = useStore((state) => state.getShouldFreeze()); const QUERY_MENU_OPTIONS = [ @@ -47,16 +53,34 @@ export const QueryCard = ({ dataQuery, darkMode = false, localDs }) => { label: 'Rename', value: 'rename', icon: , + showTooltip: false, }, { label: 'Duplicate', value: 'duplicate', icon: , + showTooltip: false, + }, + { + label: 'Query permission', + value: 'permission', + icon: ( + permission-icon + ), + trailingIcon: !licenseValid ? : undefined, + tooltipText: 'Query permissions are available only in paid plans', + showTooltip: !licenseValid, }, { label: 'Delete', value: 'delete', icon: , + showTooltip: false, }, ]; @@ -67,6 +91,10 @@ export const QueryCard = ({ dataQuery, darkMode = false, localDs }) => { if (value === 'duplicate') { debouncedDuplicateQuery(dataQuery?.id, appId); } + if (value === 'permission') { + if (!licenseValid) return; + toggleQueryPermissionModal(true); + } if (value === 'delete') { deleteDataQuery(); } @@ -198,24 +226,32 @@ export const QueryCard = ({ dataQuery, darkMode = false, localDs }) => { {QUERY_MENU_OPTIONS.map((option) => ( -
{ - e.stopPropagation(); - handleQueryMenuActions(option.value); - }} + message={option?.tooltipText} + placement="right" + show={option?.showTooltip} > -
{option.icon}
{ + e.stopPropagation(); + handleQueryMenuActions(option.value); + }} > - {option?.label} +
{option.icon}
+
+ {option?.label} +
+ {option.trailingIcon && option.trailingIcon}
-
+ ))}
diff --git a/frontend/src/AppBuilder/QueryPanel/QueryDataPane.jsx b/frontend/src/AppBuilder/QueryPanel/QueryDataPane.jsx index 9ac052ae51..a09780734e 100644 --- a/frontend/src/AppBuilder/QueryPanel/QueryDataPane.jsx +++ b/frontend/src/AppBuilder/QueryPanel/QueryDataPane.jsx @@ -16,6 +16,9 @@ import DataSourceSelect from '../QueryManager/Components/DataSourceSelect'; import { OverlayTrigger, Popover } from 'react-bootstrap'; import FolderEmpty from '@/_ui/Icon/solidIcons/FolderEmpty'; import useStore from '@/AppBuilder/_stores/store'; +import AppPermissionsModal from '@/modules/Appbuilder/components/AppPermissionsModal'; +import { shallow } from 'zustand/shallow'; +import { appPermissionService } from '@/_services'; export const QueryDataPane = ({ darkMode }) => { const { t } = useTranslation(); @@ -34,6 +37,11 @@ export const QueryDataPane = ({ darkMode }) => { function isDataSourceLocal(dataQuery) { return dataSources.some((dataSource) => dataSource.id === dataQuery.data_source_id); } + const featureAccess = useStore((state) => state?.license?.featureAccess, shallow); + const licenseValid = !featureAccess?.licenseStatus?.isExpired && featureAccess?.licenseStatus?.isLicenseValid; + const selectedQuery = useStore((state) => state.queryPanel.selectedQuery); + const showQueryPermissionModal = useStore((state) => state.queryPanel.showQueryPermissionModal); + const toggleQueryPermissionModal = useStore((state) => state.queryPanel.toggleQueryPermissionModal); useEffect(() => { setQueryPanelSearchTerm(searchTermForFilters); @@ -171,6 +179,20 @@ export const QueryDataPane = ({ darkMode }) => { {filteredQueries.map((query) => ( ))} + {licenseValid && ( + appPermissionService.getQueryPermission(appId, id)} + createPermission={(id, appId, body) => appPermissionService.createQueryPermission(appId, id, body)} + updatePermission={(id, appId, body) => appPermissionService.updateQueryPermission(appId, id, body)} + deletePermission={(id, appId) => appPermissionService.deleteQueryPermission(appId, id)} + // onSuccess={(data) => updateQueryWithPermissions(selectedQuery?.id, data)} + /> + )} ({ @@ -1113,5 +1114,10 @@ export const createQueryPanelSlice = (set, get) => ({ }; previewQuery(query, false, undefined, moduleId); }, + toggleQueryPermissionModal: (show) => { + set((state) => { + state.queryPanel.showQueryPermissionModal = show; + }); + }, }, }); diff --git a/frontend/src/ToolJetUI/List/list.scss b/frontend/src/ToolJetUI/List/list.scss index c5aa03aada..786f4e88af 100644 --- a/frontend/src/ToolJetUI/List/list.scss +++ b/frontend/src/ToolJetUI/List/list.scss @@ -64,6 +64,7 @@ button:focus:not(:focus-visible) { padding: 10px 14px; cursor: pointer; display: flex; + align-items: center; &:hover { background-color: var(--slate3);