forked from hasura/graphql-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
console: fix regression in editing permissions manually (fix hasura#4683
) (hasura#4826)
- Loading branch information
1 parent
68f8cbd
commit 14fcd57
Showing
5 changed files
with
190 additions
and
104 deletions.
There are no files selected for viewing
68 changes: 68 additions & 0 deletions
68
console/src/components/Services/Data/TablePermissions/JSONEditor.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import React, { useState, useEffect, useCallback } from 'react'; | ||
import AceEditor, { IAnnotation } from 'react-ace'; | ||
import { isJsonString } from '../../../Common/utils/jsUtils'; | ||
import { usePrevious } from '../../../../hooks/usePrevious'; | ||
|
||
export interface JSONEditorProps { | ||
initData: string; | ||
onChange: (v: string) => void; | ||
data: string; | ||
} | ||
|
||
const JSONEditor: React.FC<JSONEditorProps> = ({ | ||
initData, | ||
onChange, | ||
data, | ||
}) => { | ||
const [value, setValue] = useState(initData || data || ''); | ||
const [annotations, setAnnotations] = useState<IAnnotation[]>([]); | ||
const prevData = usePrevious<string>(data); | ||
|
||
useEffect(() => { | ||
// if the data prop is changed do nothing | ||
if (prevData !== data) return; | ||
// when state gets new data, trigger parent callback | ||
if (value !== data) onChange(value); | ||
}, [value, data, prevData]); | ||
|
||
// check and set error message | ||
useEffect(() => { | ||
if (isJsonString(value)) { | ||
setAnnotations([]); | ||
} else { | ||
setAnnotations([ | ||
{ row: 0, column: 0, text: 'Invalid JSON', type: 'error' }, | ||
]); | ||
} | ||
return () => { | ||
setAnnotations([]); | ||
}; | ||
}, [value]); | ||
|
||
useEffect(() => { | ||
// set data to editor only if the prop has a valid json string | ||
// setting value from query editor will always have a valid json | ||
// any invalid json means, the value is set from this component so no need to set that again | ||
if (isJsonString(data)) setValue(data); | ||
}, [data]); | ||
|
||
const onEditorValueChange = useCallback(newVal => setValue(newVal), [ | ||
setValue, | ||
]); | ||
|
||
return ( | ||
<AceEditor | ||
mode="json" | ||
onChange={onEditorValueChange} | ||
theme="github" | ||
height="5em" | ||
maxLines={15} | ||
width="100%" | ||
showPrintMargin={false} | ||
value={value} | ||
annotations={annotations} | ||
/> | ||
); | ||
}; | ||
|
||
export default JSONEditor; |
94 changes: 94 additions & 0 deletions
94
console/src/components/Services/Data/TablePermissions/PermButtonsSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React, { useCallback } from 'react'; | ||
import { ThunkDispatch } from 'redux-thunk'; | ||
import { AnyAction } from 'redux'; | ||
import Button from '../../../Common/Button'; | ||
import { isJsonString, getConfirmation } from '../../../Common/utils/jsUtils'; | ||
import { FilterState } from './utils'; | ||
import { showErrorNotification } from '../../Common/Notification'; | ||
import { permChangePermissions, permChangeTypes } from './Actions'; | ||
import styles from '../../../Common/Permissions/PermissionStyles.scss'; | ||
|
||
interface PermButtonSectionProps { | ||
readOnlyMode: string; | ||
query: string; | ||
localFilterString: FilterState; | ||
dispatch: (d: ThunkDispatch<{}, {}, AnyAction>) => void; | ||
permissionsState: FilterState; | ||
permsChanged: string; | ||
currQueryPermissions: string; | ||
} | ||
|
||
const PermButtonSection: React.FC<PermButtonSectionProps> = ({ | ||
readOnlyMode, | ||
query, | ||
localFilterString, | ||
dispatch, | ||
permissionsState, | ||
permsChanged, | ||
currQueryPermissions, | ||
}) => { | ||
if (readOnlyMode) { | ||
return null; | ||
} | ||
|
||
const dispatchSavePermissions = useCallback(() => { | ||
const isInvalid = Object.values(localFilterString).some(val => { | ||
if (val && !isJsonString(val)) { | ||
return true; | ||
} | ||
return false; | ||
}); | ||
|
||
if (isInvalid) { | ||
dispatch( | ||
showErrorNotification( | ||
'Saving permissions failed', | ||
'Row permission is not a valid JSON' | ||
) | ||
); | ||
return; | ||
} | ||
|
||
dispatch(permChangePermissions(permChangeTypes.save)); | ||
}, [readOnlyMode, query, localFilterString, dispatch]); | ||
|
||
const dispatchRemoveAccess = useCallback(() => { | ||
const confirmMessage = | ||
'This will permanently delete the currently set permissions'; | ||
const isOk = getConfirmation(confirmMessage); | ||
if (isOk) { | ||
dispatch(permChangePermissions(permChangeTypes.delete)); | ||
} | ||
}, [dispatch]); | ||
|
||
return ( | ||
<div className={`${styles.add_mar_top} ${styles.add_pad_left}`}> | ||
<Button | ||
className={styles.add_mar_right} | ||
color="yellow" | ||
size="sm" | ||
onClick={dispatchSavePermissions} | ||
disabled={ | ||
permissionsState.applySamePermissions.length !== 0 || !permsChanged | ||
} | ||
title={!permsChanged ? 'No changes made' : ''} | ||
data-test="Save-Permissions-button" | ||
> | ||
Save Permissions | ||
</Button> | ||
<Button | ||
className={styles.add_mar_right} | ||
color="red" | ||
size="sm" | ||
onClick={dispatchRemoveAccess} | ||
disabled={!currQueryPermissions} | ||
title={!currQueryPermissions ? 'No permissions set' : ''} | ||
data-test="Delete-Permissions-button" | ||
> | ||
Delete Permissions | ||
</Button> | ||
</div> | ||
); | ||
}; | ||
|
||
export default PermButtonSection; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { useRef, useEffect } from 'react'; | ||
|
||
export const usePrevious = <T>(value: T) => { | ||
const ref = useRef<T>(); | ||
useEffect(() => { | ||
ref.current = value; | ||
}); | ||
return ref.current; | ||
}; |