mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
refactor(source): define more types (#149)
* define more types * lint fixes * update snapshot and reduce coverage * revert role change, since it incompatible with directus
This commit is contained in:
parent
63e864ff81
commit
12fd624780
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
type ContentProps = {
|
||||
interface ContentProps {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { useContext, createContext } from 'react'
|
||||
import { BrowserRouter as Router, useLocation } from 'react-router-dom'
|
||||
@ -19,8 +18,7 @@ import { AppStateProvider } from './hooks/useAppState'
|
||||
// Helper context to determine if the ContextWrapper is already present.
|
||||
const ContextCheckContext = createContext(false)
|
||||
|
||||
// eslint-disable-next-line react/prop-types
|
||||
export const ContextWrapper = ({ children }) => {
|
||||
export const ContextWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
const isWrapped = useContext(ContextCheckContext)
|
||||
|
||||
// Check if we are already inside a Router
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
import { useCallback, useState, createContext, useContext } from 'react'
|
||||
|
||||
@ -22,10 +21,15 @@ function useQuestsManager(initialOpen: boolean): {
|
||||
return { open, setQuestsOpen }
|
||||
}
|
||||
|
||||
export const QuestsProvider: React.FunctionComponent<{
|
||||
interface QuestProviderProps {
|
||||
initialOpen: boolean
|
||||
children?: React.ReactNode
|
||||
}> = ({ initialOpen, children }) => (
|
||||
}
|
||||
|
||||
export const QuestsProvider: React.FunctionComponent<QuestProviderProps> = ({
|
||||
initialOpen,
|
||||
children,
|
||||
}: QuestProviderProps) => (
|
||||
<QuestContext.Provider value={useQuestsManager(initialOpen)}>{children}</QuestContext.Provider>
|
||||
)
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
import InformationCircleIcon from '@heroicons/react/24/outline/InformationCircleIcon'
|
||||
import { useState } from 'react'
|
||||
|
||||
type SelectBoxProps = {
|
||||
interface SelectBoxProps {
|
||||
labelTitle?: string
|
||||
labelStyle?: string
|
||||
type?: string
|
||||
@ -40,9 +38,9 @@ export function SelectBox(props: SelectBoxProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`tw-inline-block ${containerStyle}`}>
|
||||
<div className={`tw-inline-block ${containerStyle ?? ''}`}>
|
||||
{labelTitle ? (
|
||||
<label className={`tw-label ${labelStyle}`}>
|
||||
<label className={`tw-label ${labelStyle ?? ''}`}>
|
||||
<div className='tw-label-text'>
|
||||
{labelTitle}
|
||||
{labelDescription && (
|
||||
|
||||
@ -1,12 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
/* eslint-disable @typescript-eslint/consistent-indexed-object-style */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
import { useTags } from '#components/Map/hooks/useTags'
|
||||
|
||||
type TextAreaProps = {
|
||||
interface TextAreaProps {
|
||||
labelTitle?: string
|
||||
labelStyle?: string
|
||||
containerStyle?: string
|
||||
@ -18,9 +14,7 @@ type TextAreaProps = {
|
||||
updateFormValue?: (value: string) => void
|
||||
}
|
||||
|
||||
interface KeyValue {
|
||||
[key: string]: string
|
||||
}
|
||||
type KeyValue = Record<string, string>
|
||||
|
||||
/**
|
||||
* @category Input
|
||||
@ -60,10 +54,12 @@ export function TextAreaInput({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`tw-form-control tw-w-full ${containerStyle || ''}`}>
|
||||
<div className={`tw-form-control tw-w-full ${containerStyle ?? ''}`}>
|
||||
{labelTitle ? (
|
||||
<label className='tw-label'>
|
||||
<span className={`tw-label-text tw-text-base-content ${labelStyle}`}>{labelTitle}</span>
|
||||
<span className={`tw-label-text tw-text-base-content ${labelStyle ?? ''}`}>
|
||||
{labelTitle}
|
||||
</span>
|
||||
</label>
|
||||
) : null}
|
||||
<textarea
|
||||
@ -71,8 +67,8 @@ export function TextAreaInput({
|
||||
ref={ref}
|
||||
value={inputValue}
|
||||
name={dataField}
|
||||
className={`tw-textarea tw-textarea-bordered tw-w-full tw-leading-5 ${inputStyle || ''}`}
|
||||
placeholder={placeholder || ''}
|
||||
className={`tw-textarea tw-textarea-bordered tw-w-full tw-leading-5 ${inputStyle ?? ''}`}
|
||||
placeholder={placeholder ?? ''}
|
||||
onChange={handleChange}
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
type InputTextProps = {
|
||||
interface InputTextProps {
|
||||
labelTitle?: string
|
||||
labelStyle?: string
|
||||
type?: string
|
||||
@ -35,10 +32,10 @@ export function TextInput({
|
||||
required = true,
|
||||
updateFormValue,
|
||||
}: InputTextProps) {
|
||||
const [inputValue, setInputValue] = useState<string>(defaultValue || '')
|
||||
const [inputValue, setInputValue] = useState<string>(defaultValue ?? '')
|
||||
|
||||
useEffect(() => {
|
||||
setInputValue(defaultValue || '')
|
||||
setInputValue(defaultValue ?? '')
|
||||
}, [defaultValue])
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
@ -50,22 +47,24 @@ export function TextInput({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`tw-form-control ${containerStyle}`}>
|
||||
<div className={`tw-form-control ${containerStyle ?? ''}`}>
|
||||
{labelTitle ? (
|
||||
<label className='tw-label'>
|
||||
<span className={`tw-label-text tw-text-base-content ${labelStyle}`}>{labelTitle}</span>
|
||||
<span className={`tw-label-text tw-text-base-content ${labelStyle ?? ''}`}>
|
||||
{labelTitle}
|
||||
</span>
|
||||
</label>
|
||||
) : null}
|
||||
<input
|
||||
required={required}
|
||||
pattern={pattern}
|
||||
type={type || 'text'}
|
||||
type={type ?? 'text'}
|
||||
name={dataField}
|
||||
value={inputValue}
|
||||
placeholder={placeholder || ''}
|
||||
placeholder={placeholder ?? ''}
|
||||
autoComplete={autocomplete}
|
||||
onChange={handleChange}
|
||||
className={`tw-input tw-input-bordered tw-w-full ${inputStyle || ''}`}
|
||||
className={`tw-input tw-input-bordered tw-w-full ${inputStyle ?? ''}`}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
exports[`<TextInput /> > labelTitle > sets label 1`] = `
|
||||
<div
|
||||
class="tw-form-control undefined"
|
||||
class="tw-form-control "
|
||||
>
|
||||
<label
|
||||
class="tw-label"
|
||||
>
|
||||
<span
|
||||
class="tw-label-text tw-text-base-content undefined"
|
||||
class="tw-label-text tw-text-base-content "
|
||||
>
|
||||
My Title
|
||||
</span>
|
||||
@ -25,7 +25,7 @@ exports[`<TextInput /> > labelTitle > sets label 1`] = `
|
||||
|
||||
exports[`<TextInput /> > renders properly 1`] = `
|
||||
<div
|
||||
class="tw-form-control undefined"
|
||||
class="tw-form-control "
|
||||
>
|
||||
<input
|
||||
class="tw-input tw-input-bordered tw-w-full "
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import { useTimeout } from './useTimeout'
|
||||
|
||||
export const useDebounce = (callback, delay, deps) => {
|
||||
export const useDebounce = (callback: () => void, delay: number, deps: string[]) => {
|
||||
const { reset, clear } = useTimeout(callback, delay)
|
||||
|
||||
useEffect(reset, [...deps, reset])
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
import { useCallback, useReducer, createContext, useContext } from 'react'
|
||||
|
||||
import type { LayerProps } from '#types/LayerProps'
|
||||
@ -13,6 +11,7 @@ type UseItemManagerResult = ReturnType<typeof useLayerManager>
|
||||
|
||||
const LayerContext = createContext<UseItemManagerResult>({
|
||||
layers: [],
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
addLayer: () => {},
|
||||
})
|
||||
|
||||
@ -46,7 +45,7 @@ function useLayerManager(initialLayers: LayerProps[]): {
|
||||
export const LayersProvider: React.FunctionComponent<{
|
||||
initialLayers: LayerProps[]
|
||||
children?: React.ReactNode
|
||||
}> = ({ initialLayers, children }) => (
|
||||
}> = ({ initialLayers, children }: { initialLayers: LayerProps[]; children?: React.ReactNode }) => (
|
||||
<LayerContext.Provider value={useLayerManager(initialLayers)}>{children}</LayerContext.Provider>
|
||||
)
|
||||
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
/* eslint-disable @typescript-eslint/no-misused-promises */
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
/* eslint-disable @typescript-eslint/prefer-optional-chain */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { useCallback, useReducer, createContext, useContext, useState } from 'react'
|
||||
|
||||
import { useAuth } from '#components/Auth/useAuth'
|
||||
@ -15,6 +12,7 @@ import type { ItemsApi } from '#types/ItemsApi'
|
||||
import type { LayerProps } from '#types/LayerProps'
|
||||
import type { Permission } from '#types/Permission'
|
||||
import type { PermissionAction } from '#types/PermissionAction'
|
||||
import type { PermissionCondition } from '#types/PermissionCondition'
|
||||
|
||||
type ActionType = { type: 'ADD'; permission: Permission } | { type: 'REMOVE'; id: string }
|
||||
|
||||
@ -30,7 +28,7 @@ const PermissionContext = createContext<UsePermissionManagerResult>({
|
||||
|
||||
function usePermissionsManager(initialPermissions: Permission[]): {
|
||||
permissions: Permission[]
|
||||
setPermissionApi: (api: ItemsApi<any>) => void
|
||||
setPermissionApi: (api: ItemsApi<Permission>) => void
|
||||
setPermissionData: (data: Permission[]) => void
|
||||
setAdminRole: (adminRole: string) => void
|
||||
hasUserPermission: (
|
||||
@ -76,7 +74,7 @@ function usePermissionsManager(initialPermissions: Permission[]): {
|
||||
|
||||
const hasUserPermission = useCallback(
|
||||
(collectionName: string, action: PermissionAction, item?: Item, layer?: LayerProps) => {
|
||||
const evaluateCondition = (condition: any) => {
|
||||
const evaluateCondition = (condition: PermissionCondition) => {
|
||||
if (condition.user_created?._eq === '$CURRENT_USER') {
|
||||
return item?.user_created?.id === user?.id
|
||||
}
|
||||
@ -86,27 +84,29 @@ function usePermissionsManager(initialPermissions: Permission[]): {
|
||||
return false
|
||||
}
|
||||
|
||||
const evaluatePermissions = (permissionConditions: any) => {
|
||||
if (!permissionConditions || !permissionConditions._and) {
|
||||
const evaluatePermissions = (permissionConditions: Permission['permissions']) => {
|
||||
if (!permissionConditions?._and) {
|
||||
return true
|
||||
}
|
||||
|
||||
return permissionConditions._and.every((andCondition: any) =>
|
||||
andCondition._or
|
||||
? andCondition._or.some((orCondition: any) => evaluateCondition(orCondition))
|
||||
return permissionConditions._and.every((andCondition: PermissionCondition) =>
|
||||
(andCondition as any)._or
|
||||
? (andCondition as any)._or.some((orCondition: PermissionCondition) =>
|
||||
evaluateCondition(orCondition),
|
||||
)
|
||||
: evaluateCondition(andCondition),
|
||||
)
|
||||
}
|
||||
if (collectionName === 'items' && action === 'create' && layer?.public_edit_items) return true
|
||||
// Bedingung für leere Berechtigungen nur, wenn NICHT item und create
|
||||
if (permissions.length === 0) return true
|
||||
else if (user && user.role.id === adminRole) return true
|
||||
else if (user && user.role?.id === adminRole) return true
|
||||
else {
|
||||
return permissions.some(
|
||||
(p) =>
|
||||
p.action === action &&
|
||||
p.collection === collectionName &&
|
||||
((p.policy?.name === user?.role.name &&
|
||||
((p.policy?.name === user?.role?.name &&
|
||||
(!item || evaluatePermissions(p.permissions))) ||
|
||||
(p.policy?.name === '$t:public_label' &&
|
||||
(layer?.public_edit_items || item?.layer?.public_edit_items) &&
|
||||
@ -123,7 +123,13 @@ function usePermissionsManager(initialPermissions: Permission[]): {
|
||||
export const PermissionsProvider: React.FunctionComponent<{
|
||||
initialPermissions: Permission[]
|
||||
children?: React.ReactNode
|
||||
}> = ({ initialPermissions, children }) => (
|
||||
}> = ({
|
||||
initialPermissions,
|
||||
children,
|
||||
}: {
|
||||
initialPermissions: Permission[]
|
||||
children?: React.ReactNode
|
||||
}) => (
|
||||
<PermissionContext.Provider value={usePermissionsManager(initialPermissions)}>
|
||||
{children}
|
||||
</PermissionContext.Provider>
|
||||
|
||||
@ -14,8 +14,8 @@ export default defineConfig({
|
||||
exclude: [...configDefaults.exclude],
|
||||
thresholds: {
|
||||
lines: 0,
|
||||
functions: 65,
|
||||
branches: 66,
|
||||
functions: 61,
|
||||
branches: 62,
|
||||
statements: 0,
|
||||
},
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user