replace custom hook implementation for permissions

pull/1344/head
joseph izang 3 years ago
parent d72b8526a2
commit b51c8c1fa4
  1. 85
      libs/remix-ui/plugin-manager/src/lib/components/permissionsSettings.tsx
  2. 123
      libs/remix-ui/plugin-manager/src/lib/custom-hooks/useLocalStorage.ts
  3. 3
      libs/remix-ui/plugin-manager/tsconfig.json
  4. 4
      libs/remix-ui/plugin-manager/tsconfig.lib.json
  5. 15
      libs/remix-ui/plugin-manager/tsconfig.spec.json

@ -2,7 +2,8 @@
import React, { Fragment, useEffect, useState } from 'react'
/* eslint-disable-line */
import { ModalDialog } from '@remix-ui/modal-dialog'
import { useLocalStorage } from '../custom-hooks/useLocalStorage'
import useLocalStorage from '../custom-hooks/useLocalStorage'
import { PluginPermissions } from '../../types'
// import { PluginManagerSettings, PluginPermissions } from '../../types'
interface PermissionSettingsProps {
@ -14,7 +15,7 @@ function PermisssionsSettings ({ pluginSettings }: PermissionSettingsProps) {
* Declare component local state
*/
const [modalVisibility, setModalVisibility] = useState<boolean>(true)
const [permissions, setPermissions] = useLocalStorage('plugins/permissions', '{}')
const [permissions, setPermissions] = useLocalStorage<PluginPermissions>('plugins/permissions', {} as PluginPermissions)
const closeModal = () => setModalVisibility(true)
function ShowPluginHeading ({ headingName }) {
@ -23,7 +24,6 @@ function PermisssionsSettings ({ pluginSettings }: PermissionSettingsProps) {
<h3>{headingName} permissions:</h3>
<i
onClick={() => {
console.log(`${headingName}`)
clearPersmission(headingName)
}}
className="far fa-trash-alt"
@ -41,45 +41,48 @@ function PermisssionsSettings ({ pluginSettings }: PermissionSettingsProps) {
topLevelPluginName: string
}) {
const [checkBoxState, setCheckBoxState] = useState(allow)
const [showPermissions, setShowPermissions] = useLocalStorage<PluginPermissions>('plugins/permissions', {} as PluginPermissions)
useEffect(() => {
window.addEventListener('storage', () => setPermissions(showPermissions))
return () => window.removeEventListener('storage', () => setPermissions(showPermissions))
}, [checkBoxState])
const handleCheckboxClick = () => {
const copyPermissions = permissions
const copyPermissions = showPermissions
copyPermissions[pluginName][functionName][topLevelPluginName].allow = !checkBoxState
setCheckBoxState(!checkBoxState)
setPermissions(copyPermissions)
setShowPermissions(copyPermissions)
}
console.log('showPermissions', showPermissions)
return (
<div className="form-group remixui_permissionKey">
<div className="remixui_checkbox">
<span className="mr-2">
<input
type="checkbox"
onChange={handleCheckboxClick}
checked={checkBoxState}
id={`permission-checkbox-${topLevelPluginName}-${functionName}-${pluginName}`}
aria-describedby={`module ${pluginName} asks permission for ${functionName}`}
/>
<label
className="ml-4"
htmlFor={`permission-checkbox-${topLevelPluginName}-${functionName}-${topLevelPluginName}`}
data-id={`permission-label-${topLevelPluginName}-${functionName}-${topLevelPluginName}`}
>
Allow <u>{pluginName}</u> to call <u>{functionName}</u>
</label>
</span>
</div>
<i
onClick={() => {
console.log(`${pluginName}'s trash icon was clicked!`)
clearAllPersmissions(pluginName, topLevelPluginName, functionName)
}}
className="fa fa-trash-alt"
data-id={`pluginManagerSettingsRemovePermission-${topLevelPluginName}-${functionName}-${topLevelPluginName}`}
/>
{ showPermissions && Object.keys(showPermissions).length > 0
? (
<><div className="remixui_checkbox">
<span className="mr-2">
<input
type="checkbox"
onChange={handleCheckboxClick}
checked={checkBoxState}
id={`permission-checkbox-${topLevelPluginName}-${functionName}-${pluginName}`}
aria-describedby={`module ${pluginName} asks permission for ${functionName}`} />
<label
className="ml-4"
htmlFor={`permission-checkbox-${topLevelPluginName}-${functionName}-${topLevelPluginName}`}
data-id={`permission-label-${topLevelPluginName}-${functionName}-${topLevelPluginName}`}
>
Allow <u>{pluginName}</u> to call <u>{functionName}</u>
</label>
</span>
</div><i
onClick={() => {
clearAllPersmissions(pluginName, topLevelPluginName, functionName)
} }
className="fa fa-trash-alt"
data-id={`pluginManagerSettingsRemovePermission-${topLevelPluginName}-${functionName}-${topLevelPluginName}`} /></>
) : null
}
</div>
)
}
@ -95,9 +98,7 @@ function PermisssionsSettings ({ pluginSettings }: PermissionSettingsProps) {
delete permissionsCopy[topLevelPluginName]
}
}
// eslint-disable-next-line no-debugger
debugger
setPermissions({ ...permissionsCopy })
setPermissions(permissionsCopy)
}
function clearPersmission (topLevelPluginName: string) {
@ -105,7 +106,7 @@ function PermisssionsSettings ({ pluginSettings }: PermissionSettingsProps) {
if (permissionsCopy[topLevelPluginName]) {
delete permissionsCopy[topLevelPluginName]
}
setPermissions({})
setPermissions({} as PluginPermissions)
}
return (
@ -117,23 +118,23 @@ function PermisssionsSettings ({ pluginSettings }: PermissionSettingsProps) {
okLabel="OK"
cancelLabel="Cancel"
>
{JSON.parse(localStorage.getItem('plugins/permissions')) && Object.keys(JSON.parse(localStorage.getItem('plugins/permissions'))).length > 0
{permissions && Object.keys(permissions).length > 0
? (<h4 className="text-center">Current Permission Settings</h4>)
: (<h4 className="text-center">No Permission requested yet.</h4>)
}
<form className="remixui_permissionForm" data-id="pluginManagerSettingsPermissionForm">
<div className="p-2">
{
Object.keys(JSON.parse(localStorage.getItem('plugins/permissions'))).map(toplevelName => (
Object.keys(permissions).map(toplevelName => (
<ShowPluginHeading key={toplevelName} headingName={toplevelName} />
))
}
{
Object.keys(JSON.parse(localStorage.getItem('plugins/permissions'))).map(topName => {
return Object.keys(JSON.parse(localStorage.getItem('plugins/permissions'))[topName]).map(funcName => {
return Object.keys(JSON.parse(localStorage.getItem('plugins/permissions'))[topName][funcName]).map(pluginName => (
Object.keys(permissions).map(topName => {
return Object.keys(permissions[topName]).map(funcName => {
return Object.keys(permissions[topName][funcName]).map(pluginName => (
<ShowCheckBox
allow={JSON.parse(localStorage.getItem('plugins/permissions'))[topName][funcName][pluginName].allow}
allow={permissions[topName][funcName][pluginName].allow}
functionName={funcName}
pluginName={pluginName}
topLevelPluginName={topName}

@ -1,36 +1,115 @@
import { useState } from 'react'
// import { useState } from 'react'
// // Hook
// export const useLocalStorage = (key: string, initialValue: any) => {
// // State to store our value
// // Pass initial state function to useState so logic is only executed once
// const [storedValue, setStoredValue] = useState<any>(() => {
// try {
// // Get from local storage by key
// const item = window.localStorage.getItem(key)
// // Parse stored json or if none return initialValue
// return item ? JSON.parse(item) : initialValue
// } catch (error) {
// // If error also return initialValue
// console.log(error)
// return initialValue
// }
// })
// // Return a wrapped version of useState's setter function that ...
// // ... persists the new value to localStorage.
// const setValue = (value: any | ((val: any) => any)) => {
// try {
// // Allow value to be a function so we have same API as useState
// const valueToStore =
// value instanceof Function ? value(storedValue) : value
// // Save state
// setStoredValue(valueToStore)
// // Save to local storage
// window.localStorage.setItem(key, JSON.stringify(valueToStore))
// } catch (error) {
// // A more advanced implementation would handle the error case
// console.log(error)
// }
// }
// return [storedValue, setValue] as const
// }
import { Dispatch, SetStateAction, useEffect, useState } from 'react'
type SetValue<T> = Dispatch<SetStateAction<T>>
function useLocalStorage<T> (key: string, initialValue: T): [T, SetValue<T>] {
// Get from local storage then
// parse stored json or return initialValue
const readValue = (): T => {
// Prevent build error "window is undefined" but keep keep working
if (typeof window === 'undefined') {
return initialValue
}
// Hook
export const useLocalStorage = (key: string, initialValue: any) => {
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = useState<any>(() => {
try {
// Get from local storage by key
const item = window.localStorage.getItem(key)
// Parse stored json or if none return initialValue
return item ? JSON.parse(item) : initialValue
return item ? (JSON.parse(item) as T) : initialValue
} catch (error) {
// If error also return initialValue
console.log(error)
console.warn(`Error reading localStorage key “${key}”:`, error)
return initialValue
}
})
}
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = useState<T>(readValue)
// Return a wrapped version of useState's setter function that ...
// ... persists the new value to localStorage.
const setValue = (value: any | ((val: any) => any)) => {
const setValue: SetValue<T> = value => {
// Prevent build error "window is undefined" but keeps working
if (typeof window === 'undefined') {
console.warn(
`Tried setting localStorage key “${key}” even though environment is not a client`
)
}
try {
// Allow value to be a function so we have same API as useState
const valueToStore =
value instanceof Function ? value(storedValue) : value
// Save state
setStoredValue(valueToStore)
// Allow value to be a function so we have the same API as useState
const newValue = value instanceof Function ? value(storedValue) : value
// Save to local storage
window.localStorage.setItem(key, JSON.stringify(valueToStore))
window.localStorage.setItem(key, JSON.stringify(newValue))
// Save state
setStoredValue(newValue)
// We dispatch a custom event so every useLocalStorage hook are notified
window.dispatchEvent(new Event('local-storage'))
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error)
console.warn(`Error setting localStorage key “${key}”:`, error)
}
}
return [storedValue, setValue] as const
useEffect(() => {
setStoredValue(readValue())
}, [])
useEffect(() => {
const handleStorageChange = () => {
setStoredValue(readValue())
}
// this only works for other documents, not the current one
window.addEventListener('storage', handleStorageChange)
// this is a custom event, triggered in writeValueToLocalStorage
window.addEventListener('local-storage', handleStorageChange)
return () => {
window.removeEventListener('storage', handleStorageChange)
window.removeEventListener('local-storage', handleStorageChange)
}
}, [])
return [storedValue, setValue]
}
export default useLocalStorage

@ -12,9 +12,6 @@
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

@ -5,8 +5,8 @@
"types": ["node"]
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/react/typings/image.d.ts"
"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]

@ -1,15 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.spec.ts",
"**/*.spec.tsx",
"**/*.spec.js",
"**/*.spec.jsx",
"**/*.d.ts"
]
}
Loading…
Cancel
Save