+ );
+ },
+];
+
export const WithDefaultsRelationship: ComponentStory<
typeof RowPermissionBuilder
> = args => ;
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Permissions/PermissionsForm/components/RowPermissionsBuilder/RowPermissionBuilder.tsx b/frontend/libs/console/legacy-ce/src/lib/features/Permissions/PermissionsForm/components/RowPermissionsBuilder/RowPermissionBuilder.tsx
index 9eb3971488c..f14d67efef8 100644
--- a/frontend/libs/console/legacy-ce/src/lib/features/Permissions/PermissionsForm/components/RowPermissionsBuilder/RowPermissionBuilder.tsx
+++ b/frontend/libs/console/legacy-ce/src/lib/features/Permissions/PermissionsForm/components/RowPermissionsBuilder/RowPermissionBuilder.tsx
@@ -1,73 +1,49 @@
import { Table } from '@/features/hasura-metadata-types';
-import React from 'react';
-import AceEditor from 'react-ace';
import { useFormContext } from 'react-hook-form';
-
-import { Builder, JsonItem } from './components';
-import { useIntrospectSchema } from './hooks';
-import { createDisplayJson } from './utils';
+import { RowPermissionsInput } from './components';
+import { usePermissionTables } from './hooks/usePermissionTables';
+import { usePermissionComparators } from './hooks/usePermissionComparators';
+import { useMetadataTable } from '../../../../hasura-metadata-api/metadataHooks';
+import { getMetadataTableCustomName } from './utils/getMetadataTableCustomName';
interface Props {
- tableName: string;
- /**
- * The builder is a recursive structure
- * the nesting describes the level of the structure
- * so react hook form can correctly register the fields
- * e.g. ['filter', 'Title', '_eq'] would be registered as 'filter.Title._eq'
- */
nesting: string[];
table: Table;
dataSourceName: string;
}
export const RowPermissionBuilder = ({
- tableName,
nesting,
table,
dataSourceName,
}: Props) => {
- const { watch } = useFormContext();
- const { data: schema } = useIntrospectSchema();
+ const { watch, setValue } = useFormContext();
// by watching the top level of nesting we can get the values for the whole builder
// this value will always be 'filter' or 'check' depending on the query type
- const value = watch(nesting[0]);
- const json = createDisplayJson(value || {});
+ const permissionsKey = nesting[0];
- if (!schema) {
- return null;
- }
+ const value = watch(permissionsKey);
+ const { data: tableConfig } = useMetadataTable(dataSourceName, table);
+ const tables = usePermissionTables({
+ dataSourceName,
+ tableCustomName: getMetadataTableCustomName(tableConfig),
+ });
+
+ const comparators = usePermissionComparators();
+
+ if (!tables) return <>Loading>;
return (
-
-
-
-
-
-
-
-
-
-
-
-
+ {
+ setValue(permissionsKey, permissions);
+ }}
+ table={table}
+ tables={tables}
+ permissions={value}
+ comparators={comparators}
+ />
);
};
diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Permissions/PermissionsForm/components/RowPermissionsBuilder/components/Builder.tsx b/frontend/libs/console/legacy-ce/src/lib/features/Permissions/PermissionsForm/components/RowPermissionsBuilder/components/Builder.tsx
deleted file mode 100644
index 8f6f4bc9040..00000000000
--- a/frontend/libs/console/legacy-ce/src/lib/features/Permissions/PermissionsForm/components/RowPermissionsBuilder/components/Builder.tsx
+++ /dev/null
@@ -1,232 +0,0 @@
-import React from 'react';
-import { useFormContext } from 'react-hook-form';
-import { GraphQLSchema } from 'graphql';
-import { Table } from '@/features/hasura-metadata-types';
-import { RenderFormElement } from './RenderFormElement';
-import { CustomField } from './Fields';
-import { JsonItem } from './Elements';
-import { getColumnOperators } from '../utils';
-
-import { useData } from '../hooks';
-
-const createKey = (inputs: string[]) => inputs.filter(Boolean).join('.');
-
-interface Args {
- value: string;
- data: ReturnType['data'];
-}
-
-/**
- * return value to be set for dropdown state
- */
-const getNewValues = ({ value, data }: Args) => {
- const allItemsArray = [
- ...data.boolOperators,
- ...data.columns,
- ...data.relationships,
- ];
- const selectedItem = allItemsArray.find(item => item.name === value);
-
- switch (selectedItem?.kind) {
- case 'boolOperator':
- return {
- name: selectedItem.name,
- typeName: selectedItem.name,
- type: 'boolOperator',
- columnOperator: '_eq',
- };
- case 'column':
- return {
- name: selectedItem.name,
- typeName: selectedItem.name,
- type: 'column',
- columnOperator: '_eq',
- };
- case 'relationship':
- return {
- name: selectedItem.name,
- // for relationships the type name will be different from the name
- // for example if the relationship name is things the type name will be thing
- // therefore we need both to
- // 1. correctly display the relationship name in the permission i.e. things
- // 2. find the information needed about the type from the schema using the type name i.e. thing
- typeName: selectedItem?.meta?.type?.type,
- type: 'relationship',
- columnOperator: '_eq',
- };
- default:
- throw new Error('Case not handled');
- }
-};
-
-interface RenderJsonDisplayProps {
- dropDownState: { name: string; type: string };
-}
-
-/**
- *
- * needed to render the next level of the form differently depending on which item is selected
- */
-const RenderJsonDisplay = (props: RenderJsonDisplayProps) => {
- const { dropDownState } = props;
-
- const isObjectType =
- dropDownState?.type === 'column' ||
- dropDownState?.type === 'relationship' ||
- dropDownState?.name === '_not';
-
- // if nothing is selected render a disabled input
- if (!dropDownState?.type) {
- return ;
- }
-
- if (isObjectType) {
- return (
- <>
-
- >
- );
- }
-
- if (dropDownState?.name === '_and' || dropDownState?.name === '_or') {
- return (
- <>
-
- >
- );
- }
-
- return null;
-};
-
-interface Props {
- tableName: string;
- /**
- * The builder is a recursive structure
- * the nesting describes the level of the structure
- * so react hook form can correctly register the fields
- * e.g. ['filter', 'Title', '_eq'] would be registered as 'filter.Title._eq'
- */
- nesting: string[];
- schema: GraphQLSchema;
- dataSourceName: string;
- table: Table;
-}
-
-export const Builder = (props: Props) => {
- const { tableName, nesting, schema, dataSourceName, table } = props;
-
- const { data, tableConfig } = useData({
- tableName,
- schema,
- // we have to pass in table like this because if it is a relationship if will
- // fetch the wrong table config otherwise
- table,
- dataSourceName,
- });
- const { unregister, setValue, getValues } = useFormContext();
- // the selections from the dropdowns are stored on the form state under the key "operators"
- // this will be removed for submitting the form
- // and is generated from the permissions object when rendering the form from existing data
- const operatorsKey = createKey(['operators', ...nesting]);
- const dropDownState = getValues(operatorsKey);
-
- const permissionsKey = createKey([...nesting, dropDownState?.name]);
- const columnKey = createKey([
- ...nesting,
- dropDownState?.name,
- dropDownState?.columnOperator || '_eq',
- ]);
-
- const columnOperators = React.useMemo(() => {
- if (dropDownState?.name && dropDownState?.type === 'column' && schema) {
- return getColumnOperators({
- tableName,
- columnName: dropDownState.name,
- schema,
- tableConfig,
- });
- }
-
- return [];
- }, [tableName, dropDownState, schema, tableConfig]);
-
- const handleDropdownChange: React.ChangeEventHandler<
- HTMLSelectElement
- > = e => {
- const value = e.target.value;
-
- // as the form is populated a json object is built up
- // when the dropdown changes at a specific level
- // everything below that level needs to be removed
- // set value undefined is necessary to remove field arrays
- if (dropDownState?.name === '_and' || dropDownState?.name === '_or') {
- setValue(permissionsKey, undefined);
- }
- // when the dropdown changes both the permissions object
- // and operators object need to be unregistered below this level
- unregister(permissionsKey);
- unregister(operatorsKey);
-
- const newValue = getNewValues({ value, data });
- return setValue(operatorsKey, newValue);
- };
-
- const handleColumnChange: React.ChangeEventHandler = e => {
- const target = e.target.value;
-
- // when the dropdown value changes the previous field needs to be unregistered
- // so it is removed from the form state
- unregister(columnKey);
- setValue(operatorsKey, {
- ...dropDownState,
- columnOperator: target,
- });
- };
-
- return (
-