mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
linting: fix auto-fixable issues
This commit is contained in:
parent
3735f0c0c4
commit
0c618a2afd
@ -11,4 +11,4 @@
|
||||
"bracketSameLine": false,
|
||||
"arrowParens": "always",
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,11 +56,11 @@ export default tseslint.config(
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'react': react,
|
||||
react: react,
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
'import-x': importXPlugin,
|
||||
'promise': promisePlugin,
|
||||
promise: promisePlugin,
|
||||
'no-catch-all': noCatchAllPlugin,
|
||||
},
|
||||
settings: {
|
||||
@ -81,11 +81,11 @@ export default tseslint.config(
|
||||
// Basic rules
|
||||
'no-console': 'error',
|
||||
'no-debugger': 'error',
|
||||
'camelcase': 'error',
|
||||
camelcase: 'error',
|
||||
|
||||
// Standard JS rules (replacing eslint-config-standard)
|
||||
'semi': ['error', 'never'],
|
||||
'quotes': ['error', 'single', { avoidEscape: true }],
|
||||
semi: ['error', 'never'],
|
||||
quotes: ['error', 'single', { avoidEscape: true }],
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
// Disabled: conflicts with common TypeScript/React patterns
|
||||
// 'space-before-function-paren': ['error', 'always'],
|
||||
@ -102,7 +102,7 @@ export default tseslint.config(
|
||||
'linebreak-style': ['error', 'unix'],
|
||||
|
||||
// Additional standard rules that were missing
|
||||
'eqeqeq': ['error', 'always', { null: 'ignore' }],
|
||||
eqeqeq: ['error', 'always', { null: 'ignore' }],
|
||||
'new-cap': ['error', { newIsCap: true, capIsNew: false, properties: true }],
|
||||
'array-callback-return': ['error', { allowImplicit: false, checkForEach: false }],
|
||||
|
||||
@ -151,7 +151,16 @@ export default tseslint.config(
|
||||
'import-x/order': [
|
||||
'error',
|
||||
{
|
||||
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
|
||||
groups: [
|
||||
'builtin',
|
||||
'external',
|
||||
'internal',
|
||||
'parent',
|
||||
'sibling',
|
||||
'index',
|
||||
'object',
|
||||
'type',
|
||||
],
|
||||
'newlines-between': 'always',
|
||||
alphabetize: {
|
||||
order: 'asc',
|
||||
@ -222,10 +231,13 @@ export default tseslint.config(
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
|
||||
// Configure no-unused-expressions to allow logical AND and ternary patterns
|
||||
'@typescript-eslint/no-unused-expressions': ['error', {
|
||||
allowShortCircuit: true,
|
||||
allowTernary: true,
|
||||
}],
|
||||
'@typescript-eslint/no-unused-expressions': [
|
||||
'error',
|
||||
{
|
||||
allowShortCircuit: true,
|
||||
allowTernary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@ -22,7 +22,9 @@ export function Welcome1({ clickAction1, map }: ChapterProps) {
|
||||
<div className='tw:grid'>
|
||||
<label
|
||||
className='tw:btn tw:btn-primary tw:place-self-end tw:mt-4'
|
||||
onClick={() => clickAction1()}
|
||||
onClick={() => {
|
||||
clickAction1()
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</label>
|
||||
@ -45,7 +47,9 @@ export function Welcome1({ clickAction1, map }: ChapterProps) {
|
||||
<div className='tw:grid'>
|
||||
<label
|
||||
className='tw:btn tw:btn-primary tw:place-self-end tw:mt-4'
|
||||
onClick={() => clickAction1()}
|
||||
onClick={() => {
|
||||
clickAction1()
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</label>
|
||||
|
||||
@ -86,9 +86,10 @@ export const authLocalStorage = (mainKey = 'directus_storage') =>
|
||||
// implementation of set, here set the value at mainKey in localStorage, or remove it if value is null
|
||||
set: async (value: AuthenticationData | null) => {
|
||||
if (!value) {
|
||||
return window.localStorage.removeItem(mainKey)
|
||||
window.localStorage.removeItem(mainKey)
|
||||
return
|
||||
}
|
||||
return window.localStorage.setItem(mainKey, JSON.stringify(value))
|
||||
window.localStorage.setItem(mainKey, JSON.stringify(value))
|
||||
},
|
||||
}) as AuthenticationStorage
|
||||
|
||||
|
||||
@ -20,8 +20,8 @@ export class itemsApi<T> implements ItemsApi<T> {
|
||||
|
||||
constructor(
|
||||
collectionName: keyof MyCollections,
|
||||
layerId?: string | undefined,
|
||||
mapId?: string | undefined,
|
||||
layerId?: string,
|
||||
mapId?: string,
|
||||
filter?: any,
|
||||
customParameter?: any,
|
||||
) {
|
||||
|
||||
@ -53,7 +53,8 @@ export class UserApi {
|
||||
|
||||
async logout(): Promise<any> {
|
||||
try {
|
||||
return await directusClient.logout()
|
||||
await directusClient.logout()
|
||||
return
|
||||
} catch (error: any) {
|
||||
console.log(error)
|
||||
if (error.errors[0].message) throw error.errors[0].message
|
||||
@ -97,7 +98,8 @@ export class UserApi {
|
||||
|
||||
async requestPasswordReset(email: string, reset_url?: string): Promise<any> {
|
||||
try {
|
||||
return await directusClient.request(passwordRequest(email, reset_url))
|
||||
await directusClient.request(passwordRequest(email, reset_url))
|
||||
return
|
||||
} catch (error: any) {
|
||||
console.log(error)
|
||||
if (error.errors[0].message) throw error.errors[0].message
|
||||
@ -107,7 +109,8 @@ export class UserApi {
|
||||
|
||||
async passwordReset(reset_token: string, new_password: string): Promise<any> {
|
||||
try {
|
||||
return await directusClient.request(passwordReset(reset_token, new_password))
|
||||
await directusClient.request(passwordReset(reset_token, new_password))
|
||||
return
|
||||
} catch (error: any) {
|
||||
console.log(error)
|
||||
if (error.errors[0].message) throw error.errors[0].message
|
||||
|
||||
@ -12,35 +12,17 @@
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
],
|
||||
"utopia-ui": [
|
||||
"../lib/src"
|
||||
],
|
||||
"#components/*": [
|
||||
"../lib/src/Components/*"
|
||||
],
|
||||
"#utils/*": [
|
||||
"../lib/src/Utils/*"
|
||||
],
|
||||
"#types/*": [
|
||||
"../lib/src/types/*"
|
||||
],
|
||||
"#assets/*": [
|
||||
"../lib/src/assets/*"
|
||||
],
|
||||
"#src/*": [
|
||||
"../lib/src/*"
|
||||
],
|
||||
"#root/*": [
|
||||
"../lib/*"
|
||||
]
|
||||
"@/*": ["src/*"],
|
||||
"utopia-ui": ["../lib/src"],
|
||||
"#components/*": ["../lib/src/Components/*"],
|
||||
"#utils/*": ["../lib/src/Utils/*"],
|
||||
"#types/*": ["../lib/src/types/*"],
|
||||
"#assets/*": ["../lib/src/assets/*"],
|
||||
"#src/*": ["../lib/src/*"],
|
||||
"#root/*": ["../lib/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
|
||||
@ -11,4 +11,4 @@
|
||||
"bracketSameLine": false,
|
||||
"arrowParens": "always",
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,11 +56,11 @@ export default tseslint.config(
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'react': react,
|
||||
react: react,
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
'import-x': importXPlugin,
|
||||
'promise': promisePlugin,
|
||||
promise: promisePlugin,
|
||||
'no-catch-all': noCatchAllPlugin,
|
||||
},
|
||||
settings: {
|
||||
@ -81,11 +81,11 @@ export default tseslint.config(
|
||||
// Basic rules
|
||||
'no-console': 'error',
|
||||
'no-debugger': 'error',
|
||||
'camelcase': 'error',
|
||||
camelcase: 'error',
|
||||
|
||||
// Standard JS rules
|
||||
'semi': ['error', 'never'],
|
||||
'quotes': ['error', 'single', { avoidEscape: true }],
|
||||
semi: ['error', 'never'],
|
||||
quotes: ['error', 'single', { avoidEscape: true }],
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'keyword-spacing': ['error', { before: true, after: true }],
|
||||
'space-infix-ops': 'error',
|
||||
@ -95,9 +95,9 @@ export default tseslint.config(
|
||||
'array-bracket-spacing': ['error', 'never'],
|
||||
'computed-property-spacing': ['error', 'never'],
|
||||
'no-multiple-empty-lines': ['error', { max: 1, maxEOF: 0 }],
|
||||
'indent': ['error', 2],
|
||||
indent: ['error', 2],
|
||||
'linebreak-style': ['error', 'unix'],
|
||||
'eqeqeq': ['error', 'always', { null: 'ignore' }],
|
||||
eqeqeq: ['error', 'always', { null: 'ignore' }],
|
||||
'new-cap': ['error', { newIsCap: true, capIsNew: false, properties: true }],
|
||||
'array-callback-return': ['error', { allowImplicit: false, checkForEach: false }],
|
||||
|
||||
@ -145,7 +145,16 @@ export default tseslint.config(
|
||||
'import-x/order': [
|
||||
'error',
|
||||
{
|
||||
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
|
||||
groups: [
|
||||
'builtin',
|
||||
'external',
|
||||
'internal',
|
||||
'parent',
|
||||
'sibling',
|
||||
'index',
|
||||
'object',
|
||||
'type',
|
||||
],
|
||||
'newlines-between': 'always',
|
||||
alphabetize: { order: 'asc', caseInsensitive: true },
|
||||
distinctGroup: true,
|
||||
@ -155,7 +164,10 @@ export default tseslint.config(
|
||||
'import-x/no-unused-modules': 'error',
|
||||
'import-x/no-import-module-exports': 'error',
|
||||
'import-x/unambiguous': 'off',
|
||||
'import-x/no-relative-parent-imports': ['error', { ignore: ['#[src,types,root,components,utils,assets]/*'] }],
|
||||
'import-x/no-relative-parent-imports': [
|
||||
'error',
|
||||
{ ignore: ['#[src,types,root,components,utils,assets]/*'] },
|
||||
],
|
||||
|
||||
// Promise rules
|
||||
'promise/catch-or-return': 'error',
|
||||
@ -175,7 +187,6 @@ export default tseslint.config(
|
||||
|
||||
// Security and other rules
|
||||
'no-catch-all/no-catch-all': 'error',
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
@ -207,10 +218,13 @@ export default tseslint.config(
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
|
||||
// Configure no-unused-expressions to allow logical AND and ternary patterns
|
||||
'@typescript-eslint/no-unused-expressions': ['error', {
|
||||
allowShortCircuit: true,
|
||||
allowTernary: true,
|
||||
}],
|
||||
'@typescript-eslint/no-unused-expressions': [
|
||||
'error',
|
||||
{
|
||||
allowShortCircuit: true,
|
||||
allowTernary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@ -244,4 +258,3 @@ export default tseslint.config(
|
||||
// Prettier recommended config (should be last to override other formatting rules)
|
||||
eslintPluginPrettierRecommended,
|
||||
)
|
||||
|
||||
|
||||
@ -31,7 +31,9 @@ export default function NavBar({ appName }: { appName: string }) {
|
||||
className='tw:btn tw:btn-square tw:btn-ghost tw:ml-3'
|
||||
aria-controls='#sidenav'
|
||||
aria-haspopup='true'
|
||||
onClick={() => toggleSidebar()}
|
||||
onClick={() => {
|
||||
toggleSidebar()
|
||||
}}
|
||||
>
|
||||
<Bars3Icon className='tw:inline-block tw:w-5 tw:h-5' />
|
||||
</button>
|
||||
@ -50,7 +52,9 @@ export default function NavBar({ appName }: { appName: string }) {
|
||||
</Link>
|
||||
<button
|
||||
className='tw:btn tw:px-2 tw:btn-ghost'
|
||||
onClick={() => window.my_modal_3.showModal()}
|
||||
onClick={() => {
|
||||
window.my_modal_3.showModal()
|
||||
}}
|
||||
>
|
||||
<QuestionMarkIcon className='tw:h-5 tw:w-5' />
|
||||
</button>
|
||||
|
||||
@ -57,7 +57,9 @@ export function SideBar({ routes, bottomRoutes }: { routes: Route[]; bottomRoute
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
to={`${route.path}${params && '?' + params.toString()}`}
|
||||
className={({ isActive }) =>
|
||||
`${isActive ? 'tw:font-semibold tw:bg-base-200 tw:rounded-none!' : 'tw:font-normal tw:rounded-none!'}`
|
||||
isActive
|
||||
? 'tw:font-semibold tw:bg-base-200 tw:rounded-none!'
|
||||
: 'tw:font-normal tw:rounded-none!'
|
||||
}
|
||||
onClick={() => {
|
||||
if (screen.width < 640 && !appState.sideBarSlim) toggleSidebarOpen()
|
||||
@ -70,7 +72,7 @@ export function SideBar({ routes, bottomRoutes }: { routes: Route[]; bottomRoute
|
||||
{route.icon}
|
||||
</div>
|
||||
<span
|
||||
className={`${appState.sideBarSlim ? 'tw:hidden' : ''}`}
|
||||
className={appState.sideBarSlim ? 'tw:hidden' : ''}
|
||||
data-te-sidenav-slim='false'
|
||||
>
|
||||
{route.name}
|
||||
@ -119,7 +121,7 @@ export function SideBar({ routes, bottomRoutes }: { routes: Route[]; bottomRoute
|
||||
>
|
||||
{route.icon}
|
||||
<span
|
||||
className={`${appState.sideBarSlim ? 'tw:hidden' : ''}`}
|
||||
className={appState.sideBarSlim ? 'tw:hidden' : ''}
|
||||
data-te-sidenav-slim='false'
|
||||
>
|
||||
{route.name}
|
||||
@ -143,7 +145,9 @@ export function SideBar({ routes, bottomRoutes }: { routes: Route[]; bottomRoute
|
||||
'tw:w-5 tw:h-5 tw:mb-4 tw:mr-5 tw:mt-2 tw:cursor-pointer tw:float-right tw:delay-400 tw:duration-500 tw:transition-all ' +
|
||||
(!appState.sideBarSlim ? 'tw:rotate-180' : '')
|
||||
}
|
||||
onClick={() => toggleSidebarSlim()}
|
||||
onClick={() => {
|
||||
toggleSidebarSlim()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -31,7 +31,12 @@ function SidebarSubmenu({
|
||||
return (
|
||||
<div className='flex-col'>
|
||||
{/** Route header */}
|
||||
<div className='w-full' onClick={() => setIsExpanded(!isExpanded)}>
|
||||
<div
|
||||
className='w-full'
|
||||
onClick={() => {
|
||||
setIsExpanded(!isExpanded)
|
||||
}}
|
||||
>
|
||||
{icon} <span>{name} </span>
|
||||
<ChevronDownIcon
|
||||
className={
|
||||
|
||||
@ -68,7 +68,7 @@ export function LoginPage({ inviteApi, showRequestPassword }: Props) {
|
||||
},
|
||||
error: {
|
||||
render({ data }) {
|
||||
return `${data as string}`
|
||||
return data as string
|
||||
},
|
||||
autoClose: 10000,
|
||||
},
|
||||
@ -97,13 +97,17 @@ export function LoginPage({ inviteApi, showRequestPassword }: Props) {
|
||||
type='email'
|
||||
placeholder='E-Mail'
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setEmail(e.target.value)
|
||||
}}
|
||||
className='tw:input tw:input-bordered tw:w-full tw:max-w-xs'
|
||||
/>
|
||||
<input
|
||||
type='password'
|
||||
placeholder='Password'
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setPassword(e.target.value)
|
||||
}}
|
||||
className='tw:input tw:input-bordered tw:w-full tw:max-w-xs'
|
||||
/>
|
||||
<div className='tw:text-right tw:text-primary'>
|
||||
|
||||
@ -28,7 +28,7 @@ export function RequestPasswordPage({ resetUrl }: { resetUrl: string }) {
|
||||
},
|
||||
error: {
|
||||
render({ data }) {
|
||||
return `${data as string}`
|
||||
return data as string
|
||||
},
|
||||
},
|
||||
pending: 'sending email ...',
|
||||
@ -42,7 +42,9 @@ export function RequestPasswordPage({ resetUrl }: { resetUrl: string }) {
|
||||
type='email'
|
||||
placeholder='E-Mail'
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setEmail(e.target.value)
|
||||
}}
|
||||
className='tw:input tw:input-bordered tw:w-full tw:max-w-xs'
|
||||
/>
|
||||
<div className='tw:card-actions tw:mt-4'>
|
||||
|
||||
@ -28,7 +28,7 @@ export function SetNewPasswordPage() {
|
||||
},
|
||||
error: {
|
||||
render({ data }) {
|
||||
return `${data as string}`
|
||||
return data as string
|
||||
},
|
||||
},
|
||||
pending: 'setting password ...',
|
||||
@ -41,7 +41,9 @@ export function SetNewPasswordPage() {
|
||||
<input
|
||||
type='password'
|
||||
placeholder='Password'
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setPassword(e.target.value)
|
||||
}}
|
||||
className='tw:input tw:input-bordered tw:w-full tw:max-w-xs'
|
||||
/>
|
||||
<div className='tw:card-actions tw:mt-4'>
|
||||
|
||||
@ -32,7 +32,7 @@ export function SignupPage() {
|
||||
},
|
||||
error: {
|
||||
render({ data }) {
|
||||
return `${data as string}`
|
||||
return data as string
|
||||
},
|
||||
autoClose: 10000,
|
||||
},
|
||||
@ -61,20 +61,26 @@ export function SignupPage() {
|
||||
type='text'
|
||||
placeholder='Name'
|
||||
value={userName}
|
||||
onChange={(e) => setUserName(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setUserName(e.target.value)
|
||||
}}
|
||||
className='tw:input tw:input-bordered tw:w-full tw:max-w-xs'
|
||||
/>
|
||||
<input
|
||||
type='email'
|
||||
placeholder='E-Mail'
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setEmail(e.target.value)
|
||||
}}
|
||||
className='tw:input tw:input-bordered tw:w-full tw:max-w-xs'
|
||||
/>
|
||||
<input
|
||||
type='password'
|
||||
placeholder='Password'
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setPassword(e.target.value)
|
||||
}}
|
||||
className='tw:input tw:input-bordered tw:w-full tw:max-w-xs'
|
||||
/>
|
||||
<div className='tw:card-actions tw:mt-4'>
|
||||
|
||||
@ -135,7 +135,8 @@ export const AuthProvider = ({ userApi, children }: AuthProviderProps) => {
|
||||
setLoading(true)
|
||||
try {
|
||||
await userApi.requestPasswordReset(email, resetUrl)
|
||||
return setLoading(false)
|
||||
setLoading(false)
|
||||
return
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
throw error
|
||||
@ -146,7 +147,8 @@ export const AuthProvider = ({ userApi, children }: AuthProviderProps) => {
|
||||
setLoading(true)
|
||||
try {
|
||||
await userApi.passwordReset(token, newPassword)
|
||||
return setLoading(false)
|
||||
setLoading(false)
|
||||
return
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
throw error
|
||||
|
||||
@ -44,7 +44,9 @@ export function Quests() {
|
||||
<div className='tw:card-actions tw:justify-end'>
|
||||
<label
|
||||
className='tw:btn tw:btn-sm tw:btn-circle tw:btn-ghost tw:absolute tw:right-1 tw:top-1'
|
||||
onClick={() => setQuestsOpen(false)}
|
||||
onClick={() => {
|
||||
setQuestsOpen(false)
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</label>
|
||||
|
||||
@ -85,7 +85,9 @@ export const Autocomplete = ({
|
||||
ref={inputRef}
|
||||
{...inputProps}
|
||||
type='text'
|
||||
onChange={(e) => handleChange(e)}
|
||||
onChange={(e) => {
|
||||
handleChange(e)
|
||||
}}
|
||||
tabIndex='-1'
|
||||
onKeyDown={handleKeyDown}
|
||||
className='tw:border-none tw:focus:outline-none tw:focus:ring-0 tw:mt-5'
|
||||
@ -94,7 +96,12 @@ export const Autocomplete = ({
|
||||
className={`tw:absolute tw:z-4000 ${filteredSuggestions.length > 0 && 'tw:bg-base-100 tw:rounded-xl tw:p-2'}`}
|
||||
>
|
||||
{filteredSuggestions.map((suggestion, index) => (
|
||||
<li key={index} onClick={() => handleSuggestionClick(suggestion)}>
|
||||
<li
|
||||
key={index}
|
||||
onClick={() => {
|
||||
handleSuggestionClick(suggestion)
|
||||
}}
|
||||
>
|
||||
<TagView heighlight={index === heighlightedSuggestion} tag={suggestion}></TagView>
|
||||
</li>
|
||||
))}
|
||||
|
||||
@ -89,7 +89,9 @@ export default function AddButton({
|
||||
tabIndex={0}
|
||||
className='tw:z-500 tw:border-0 tw:p-0 tw:w-10 tw:h-10 tw:cursor-pointer tw:rounded-full tw:mouse tw:drop-shadow-md tw:transition tw:ease-in tw:duration-200 tw:focus:outline-hidden tw:flex tw:items-center tw:justify-center'
|
||||
style={{ backgroundColor: layer.menuColor || '#777' }}
|
||||
onClick={() => handleLayerClick(layer)}
|
||||
onClick={() => {
|
||||
handleLayerClick(layer)
|
||||
}}
|
||||
onTouchEnd={(e) => {
|
||||
handleLayerClick(layer)
|
||||
e.preventDefault()
|
||||
|
||||
@ -18,7 +18,9 @@ export function FilterControl() {
|
||||
]
|
||||
|
||||
useEffect(() => {
|
||||
groupTypes.map((layer) => addVisibleGroupType(layer.value))
|
||||
groupTypes.map((layer) => {
|
||||
addVisibleGroupType(layer.value)
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
@ -48,7 +50,9 @@ export function FilterControl() {
|
||||
>
|
||||
<input
|
||||
id={groupType.value}
|
||||
onChange={() => toggleVisibleGroupType(groupType.value)}
|
||||
onChange={() => {
|
||||
toggleVisibleGroupType(groupType.value)
|
||||
}}
|
||||
type='checkbox'
|
||||
className='tw:checkbox tw:checkbox-xs tw:checkbox-success'
|
||||
checked={isGroupTypeVisible(groupType.value)}
|
||||
|
||||
@ -36,7 +36,9 @@ export function LayerControl({ expandLayerControl = false }: { expandLayerContro
|
||||
>
|
||||
<input
|
||||
id={layer.name}
|
||||
onChange={() => toggleVisibleLayer(layer)}
|
||||
onChange={() => {
|
||||
toggleVisibleLayer(layer)
|
||||
}}
|
||||
type='checkbox'
|
||||
className='tw:checkbox tw:checkbox-xs tw:checkbox-success tw:text-white'
|
||||
checked={isLayerVisible(layer)}
|
||||
|
||||
@ -206,7 +206,9 @@ export const LocateControl = (): JSX.Element => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
if (lc) lc.stop()
|
||||
// Reset flag after a delay to allow future updates
|
||||
setTimeout(() => setHasUpdatedPosition(false), 5000)
|
||||
setTimeout(() => {
|
||||
setHasUpdatedPosition(false)
|
||||
}, 5000)
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
toast.update(toastId, {
|
||||
@ -278,7 +280,9 @@ export const LocateControl = (): JSX.Element => {
|
||||
<label
|
||||
className='tw:btn tw:mt-4 tw:btn-primary'
|
||||
onClick={() => {
|
||||
void itemUpdatePosition().then(() => setShowLocationModal(false))
|
||||
void itemUpdatePosition().then(() => {
|
||||
setShowLocationModal(false)
|
||||
})
|
||||
}}
|
||||
>
|
||||
Yes
|
||||
|
||||
@ -12,11 +12,15 @@ export function QuestControl() {
|
||||
) : (
|
||||
<div
|
||||
className='tw:card tw:bg-base-100 tw:shadow-xl tw:my-2 tw:w-10'
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className='tw:card-body tw:hover:bg-slate-300 tw:rounded-2xl tw:p-2 tw:h-10 tw:w-10 tw:transition-all tw:duration-300 tw:hover:cursor-pointer'
|
||||
onClick={() => setQuestsOpen(true)}
|
||||
onClick={() => {
|
||||
setQuestsOpen(true)
|
||||
}}
|
||||
>
|
||||
<img src={FistSVG} alt='Quests' className='tw:h-[2em]' />
|
||||
</div>
|
||||
|
||||
@ -115,7 +115,9 @@ export const SearchControl = () => {
|
||||
className='tw:input tw:input-bordered tw:h-12 tw:grow tw:shadow-xl tw:rounded-box tw:pr-12 tw:w-full'
|
||||
data-cy='search-input'
|
||||
ref={searchInput}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value)
|
||||
}}
|
||||
onFocus={() => {
|
||||
setHideSuggestions(false)
|
||||
if (windowDimensions.width < 500) map.closePopup()
|
||||
@ -126,7 +128,9 @@ export const SearchControl = () => {
|
||||
<button
|
||||
className='tw:btn tw:btn-sm tw:btn-circle tw:absolute tw:right-2 tw:top-2'
|
||||
data-cy='search-clear-button'
|
||||
onClick={() => setValue('')}
|
||||
onClick={() => {
|
||||
setValue('')
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
@ -13,7 +13,9 @@ export const SidebarControl = () => {
|
||||
<>
|
||||
<div
|
||||
className='tw:card tw:justify-center tw:items-center tw:bg-base-100 tw:flex-none tw:shadow-xl tw:px-0 tw:hover:bg-slate-300 tw:hover:cursor-pointer tw:transition-all tw:duration-300 tw:mr-2 tw:h-12 tw:w-12 '
|
||||
onClick={() => toggleSidebar()}
|
||||
onClick={() => {
|
||||
toggleSidebar()
|
||||
}}
|
||||
>
|
||||
<Bars3Icon className='tw:inline-block tw:w-5 tw:h-5' />
|
||||
</div>
|
||||
|
||||
@ -16,7 +16,9 @@ export const TagsControl = () => {
|
||||
<div className='tw:card-actions tw:justify-end'>
|
||||
<label
|
||||
className='tw:btn tw:btn-xs tw:btn-circle tw:absolute tw:-right-2 tw:-top-2 tw:bg-white tw:text-gray-600'
|
||||
onClick={() => removeFilterTag(tag.name)}
|
||||
onClick={() => {
|
||||
removeFilterTag(tag.name)
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</label>
|
||||
|
||||
@ -235,8 +235,7 @@ export function ItemFormPopup(props: Props) {
|
||||
}, [popupForm?.position])
|
||||
|
||||
return (
|
||||
popupForm &&
|
||||
popupForm.layer.name === activeLayerName && (
|
||||
popupForm?.layer.name === activeLayerName && (
|
||||
<LeafletPopup
|
||||
minWidth={275}
|
||||
maxWidth={275}
|
||||
|
||||
@ -35,7 +35,8 @@ export function ConnectionStatus({ item }: ConnectionStatusProps) {
|
||||
return (
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: `${item.color ?? (tags[0]?.color ? tags[0].color : item.layer.markerDefaultColor || '#000')}`,
|
||||
backgroundColor:
|
||||
item.color ?? (tags[0]?.color ? tags[0].color : item.layer.markerDefaultColor || '#000'),
|
||||
}}
|
||||
className='tw:btn tw:text-white tw:mr-2 tw:tooltip tw:tooltip-top '
|
||||
data-tip={'Connect'}
|
||||
|
||||
@ -17,7 +17,11 @@ export function DeleteModal({ item, isOpen, onClose, onConfirm }: DeleteModalPro
|
||||
|
||||
return (
|
||||
<DialogModal isOpened={isOpen} title='Are you sure?' showCloseButton={false} onClose={onClose}>
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<div
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
Do you want to delete <b>{item.name}</b>?
|
||||
</span>
|
||||
|
||||
@ -53,7 +53,12 @@ export function EditMenu({
|
||||
if (!hasDeletePermission && !hasUpdatePermission) return null
|
||||
|
||||
return (
|
||||
<div onClick={(e) => e.stopPropagation()} className={`${big ? 'tw:mt-5' : 'tw:mt-1'}`}>
|
||||
<div
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
className={big ? 'tw:mt-5' : 'tw:mt-1'}
|
||||
>
|
||||
<div className='tw:dropdown tw:dropdown-bottom tw:dropdown-center'>
|
||||
<label tabIndex={0} className='tw:btn tw:btn-ghost tw:px-2.5'>
|
||||
<EllipsisVerticalIcon className='tw:h-5 tw:w-5' />
|
||||
@ -67,13 +72,13 @@ export function EditMenu({
|
||||
<a
|
||||
className='tw:text-base-content! tw:tooltip tw:tooltip-top tw:cursor-pointer'
|
||||
data-tip='Edit'
|
||||
onClick={(e) =>
|
||||
onClick={(e) => {
|
||||
item.layer?.customEditLink
|
||||
? navigate(
|
||||
`${item.layer.customEditLink}${item.layer.customEditParameter ? `/${item.id}${params.toString() ? '?' + params.toString() : ''}` : ''}`,
|
||||
)
|
||||
: editCallback(e)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<PencilIcon className='tw:h-5 tw:w-5' />
|
||||
</a>
|
||||
|
||||
@ -53,8 +53,12 @@ export function ItemAvatar({
|
||||
className='tw:w-full tw:h-full tw:object-cover tw:rounded-full tw:border-white'
|
||||
src={avatar}
|
||||
alt={(item.name ?? '') + ' logo'}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
onError={() => setImageLoaded(false)}
|
||||
onLoad={() => {
|
||||
setImageLoaded(true)
|
||||
}}
|
||||
onError={() => {
|
||||
setImageLoaded(false)
|
||||
}}
|
||||
style={{ display: imageLoaded ? 'block' : 'none' }}
|
||||
/>
|
||||
{!imageLoaded && <div className='tw:w-full tw:h-full tw:bg-gray-200 tw:rounded-full' />}
|
||||
|
||||
@ -24,7 +24,12 @@ export function QRModal({ item, isOpen, onClose }: QRModalProps) {
|
||||
onClose={onClose}
|
||||
className='tw:w-[calc(100vw-2rem)] tw:!max-w-96'
|
||||
>
|
||||
<div onClick={(e) => e.stopPropagation()} className='tw:text-center tw:p-4'>
|
||||
<div
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
className='tw:text-center tw:p-4'
|
||||
>
|
||||
<p className='tw:text-xl tw:font-bold'>Share your Profile to expand your Network!</p>
|
||||
|
||||
<div className='tw:flex tw:flex-col tw:items-center tw:gap-4 tw:my-8'>
|
||||
|
||||
@ -44,7 +44,9 @@ export function HeaderView({
|
||||
item={item}
|
||||
big={big}
|
||||
showQrButton={showQrButton}
|
||||
onQrClick={() => setQrModalOpen(true)}
|
||||
onQrClick={() => {
|
||||
setQrModalOpen(true)
|
||||
}}
|
||||
/>
|
||||
<ItemTitle
|
||||
item={item}
|
||||
@ -64,7 +66,9 @@ export function HeaderView({
|
||||
loading={loading}
|
||||
hideMenu={hideMenu}
|
||||
big={big}
|
||||
onDeleteModalOpen={() => setModalOpen(true)}
|
||||
onDeleteModalOpen={() => {
|
||||
setModalOpen(true)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -81,12 +85,20 @@ export function HeaderView({
|
||||
<DeleteModal
|
||||
item={item}
|
||||
isOpen={modalOpen}
|
||||
onClose={() => setModalOpen(false)}
|
||||
onClose={() => {
|
||||
setModalOpen(false)
|
||||
}}
|
||||
onConfirm={deleteCallback ?? (() => undefined)}
|
||||
/>
|
||||
|
||||
{showQrButton && (
|
||||
<QRModal item={item} isOpen={qrModalOpen} onClose={() => setQrModalOpen(false)} />
|
||||
<QRModal
|
||||
item={item}
|
||||
isOpen={qrModalOpen}
|
||||
onClose={() => {
|
||||
setQrModalOpen(false)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
@ -114,7 +114,9 @@ export const ItemViewPopup = forwardRef((props: ItemViewPopupProps, ref: any) =>
|
||||
) : (
|
||||
<p
|
||||
className='tw:my-0! tw:min-h-[21px] tw:font-bold tw:cursor-pointer tw:text-gray-500'
|
||||
onClick={() => setInfoExpanded(true)}
|
||||
onClick={() => {
|
||||
setInfoExpanded(true)
|
||||
}}
|
||||
>
|
||||
ⓘ
|
||||
</p>
|
||||
|
||||
@ -34,7 +34,9 @@ export const SelectPositionToast = ({
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', handleEscape)
|
||||
return () => window.removeEventListener('keydown', handleEscape)
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleEscape)
|
||||
}
|
||||
}, [selectNewItemPosition, setSelectNewItemPosition])
|
||||
|
||||
const toastContent = useMemo(() => {
|
||||
|
||||
@ -103,7 +103,9 @@ export function UtopiaMapInner({
|
||||
useTheme(defaultTheme)
|
||||
|
||||
useEffect(() => {
|
||||
layers.forEach((layer) => addVisibleLayer(layer))
|
||||
layers.forEach((layer) => {
|
||||
addVisibleLayer(layer)
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [layers])
|
||||
|
||||
@ -301,7 +303,7 @@ export function UtopiaMapInner({
|
||||
<Outlet />
|
||||
<Control position='topLeft' zIndex='1000' absolute>
|
||||
<SearchControl />
|
||||
<div className={`${showZoomControl ? 'tw:pl-14' : ''}`}>
|
||||
<div className={showZoomControl ? 'tw:pl-14' : ''}>
|
||||
<TagsControl />
|
||||
</div>
|
||||
</Control>
|
||||
@ -326,7 +328,9 @@ export function UtopiaMapInner({
|
||||
<MapLibreLayer styleUrl={maplibreStyle} attribution={tileServerAttribution} />
|
||||
)}
|
||||
<MarkerClusterGroup
|
||||
ref={(r) => setClusterRef(r as any)}
|
||||
ref={(r) => {
|
||||
setClusterRef(r as any)
|
||||
}}
|
||||
showCoverageOnHover
|
||||
chunkedLoading
|
||||
maxClusterRadius={50}
|
||||
|
||||
@ -152,8 +152,8 @@ function useFilterManager(initialTags: Tag[]): {
|
||||
params.set('tags', `${urlTags || ''}${urlTags ? ';' : ''}${tag.name}`)
|
||||
}
|
||||
if (windowDimensions.width < 786 && location.pathname.split('/').length > 2)
|
||||
navigate('/' + `${params ? `?${params}` : ''}`)
|
||||
else navigate(location.pathname + `${params ? `?${params}` : ''}`)
|
||||
navigate('/' + (params ? `?${params}` : ''))
|
||||
else navigate(location.pathname + (params ? `?${params}` : ''))
|
||||
|
||||
dispatchTags({
|
||||
type: 'ADD_TAG',
|
||||
@ -171,16 +171,16 @@ function useFilterManager(initialTags: Tag[]): {
|
||||
if (tags?.length === 0 && urlTags?.length && urlTags.length > 0) tags[0] = urlTags
|
||||
tags?.map((urlTag) => {
|
||||
if (!(urlTag.toLocaleLowerCase() === name.toLocaleLowerCase())) {
|
||||
newUrlTags = newUrlTags + `${newUrlTags === '' ? urlTag : `;${urlTag}`}`
|
||||
newUrlTags = newUrlTags + (newUrlTags === '' ? urlTag : `;${urlTag}`)
|
||||
}
|
||||
return null
|
||||
})
|
||||
if (newUrlTags !== '') {
|
||||
params.set('tags', `${newUrlTags}`)
|
||||
navigate(location.pathname + `${params ? `?${params}` : ''}`)
|
||||
params.set('tags', newUrlTags)
|
||||
navigate(location.pathname + (params ? `?${params}` : ''))
|
||||
} else {
|
||||
params.delete('tags')
|
||||
navigate(location.pathname + `${params ? `?${params}` : ''}`)
|
||||
navigate(location.pathname + (params ? `?${params}` : ''))
|
||||
}
|
||||
|
||||
dispatchTags({
|
||||
|
||||
@ -17,7 +17,9 @@ export default function useWindowDimensions() {
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize)
|
||||
return () => window.removeEventListener('resize', handleResize)
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return windowDimensions
|
||||
|
||||
@ -12,10 +12,16 @@ const toastUpdateMock: (id: number, options: any) => void = vi.fn()
|
||||
|
||||
vi.mock('react-toastify', () => ({
|
||||
toast: {
|
||||
error: (t: string) => toastErrorMock(t),
|
||||
success: (t: string) => toastSuccessMock(t),
|
||||
error: (t: string) => {
|
||||
toastErrorMock(t)
|
||||
},
|
||||
success: (t: string) => {
|
||||
toastSuccessMock(t)
|
||||
},
|
||||
loading: (t: string) => toastLoadingMock(t),
|
||||
update: (id: number, options: any) => toastUpdateMock(id, options),
|
||||
update: (id: number, options: any) => {
|
||||
toastUpdateMock(id, options)
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
|
||||
@ -186,7 +186,9 @@ export function ProfileView({ attestationApi }: { attestationApi?: ItemsApi<any>
|
||||
// Error handling is already in handleDelete
|
||||
})
|
||||
}}
|
||||
editCallback={() => navigate('/edit-item/' + item.id)}
|
||||
editCallback={() => {
|
||||
navigate('/edit-item/' + item.id)
|
||||
}}
|
||||
setPositionCallback={() => {
|
||||
map.closePopup()
|
||||
setSelectPosition(item)
|
||||
|
||||
@ -89,7 +89,9 @@ export function ActionButton({
|
||||
<DialogModal
|
||||
title={'Select'}
|
||||
isOpened={modalOpen}
|
||||
onClose={() => setModalOpen(false)}
|
||||
onClose={() => {
|
||||
setModalOpen(false)
|
||||
}}
|
||||
className='tw:w-xl tw:sm:w-2xl tw:min-h-80 tw:bg-base-200'
|
||||
>
|
||||
<TextInput
|
||||
|
||||
@ -201,7 +201,13 @@ export const AvatarWidget: React.FC<AvatarWidgetProps> = ({ avatar, setAvatar, i
|
||||
}}
|
||||
closeOnClickOutside={false}
|
||||
>
|
||||
<ReactCrop crop={crop} onChange={(c) => setCrop(c)} aspect={1}>
|
||||
<ReactCrop
|
||||
crop={crop}
|
||||
onChange={(c) => {
|
||||
setCrop(c)
|
||||
}}
|
||||
aspect={1}
|
||||
>
|
||||
<img src={image} ref={imgRef} onLoad={onImageLoad} />
|
||||
</ReactCrop>
|
||||
<button
|
||||
|
||||
@ -11,7 +11,9 @@ export const ColorPicker = ({ color, onChange, className }) => {
|
||||
const popover = useRef<HTMLDivElement>(null)
|
||||
const [isOpen, toggle] = useState(false)
|
||||
|
||||
const close = useCallback(() => toggle(false), [])
|
||||
const close = useCallback(() => {
|
||||
toggle(false)
|
||||
}, [])
|
||||
useClickOutside(popover, close)
|
||||
|
||||
const colorPickerRef = useRef<HTMLDivElement>(null)
|
||||
@ -34,11 +36,23 @@ export const ColorPicker = ({ color, onChange, className }) => {
|
||||
|
||||
return (
|
||||
<div ref={colorPickerRef} className={`picker ${className}`}>
|
||||
<div className='swatch' style={{ backgroundColor: color }} onClick={() => toggle(true)} />
|
||||
<div
|
||||
className='swatch'
|
||||
style={{ backgroundColor: color }}
|
||||
onClick={() => {
|
||||
toggle(true)
|
||||
}}
|
||||
/>
|
||||
|
||||
{isOpen && (
|
||||
<div className='popover tw:z-10000' ref={popover}>
|
||||
<HexColorPicker color={color} onChange={onChange} onClick={() => toggle(false)} />
|
||||
<HexColorPicker
|
||||
color={color}
|
||||
onChange={onChange}
|
||||
onClick={() => {
|
||||
toggle(false)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -18,12 +18,12 @@ export const ContactInfoForm = ({
|
||||
type='email'
|
||||
required={false}
|
||||
defaultValue={state.contact}
|
||||
updateFormValue={(v) =>
|
||||
updateFormValue={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
contact: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -35,12 +35,12 @@ export const ContactInfoForm = ({
|
||||
required={false}
|
||||
pattern='^\+?[0-9\s\-]{7,15}$'
|
||||
defaultValue={state.telephone}
|
||||
updateFormValue={(v) =>
|
||||
updateFormValue={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
telephone: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -18,12 +18,12 @@ export const CrowdfundingForm = ({
|
||||
type='text'
|
||||
required={false}
|
||||
defaultValue={state.openCollectiveSlug}
|
||||
updateFormValue={(v) =>
|
||||
updateFormValue={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
openCollectiveSlug: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -20,22 +20,22 @@ export const FormHeader = ({ item, state, setState }: Props) => {
|
||||
<div className='tw:flex'>
|
||||
<AvatarWidget
|
||||
avatar={state.image}
|
||||
setAvatar={(i) =>
|
||||
setAvatar={(i) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
image: i,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
item={item}
|
||||
/>
|
||||
<ColorPicker
|
||||
color={state.color}
|
||||
onChange={(c) =>
|
||||
onChange={(c) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
color: c,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
className={'tw:-left-6 tw:top-14 tw:-mr-6'}
|
||||
/>
|
||||
<div
|
||||
@ -44,12 +44,12 @@ export const FormHeader = ({ item, state, setState }: Props) => {
|
||||
<TextInput
|
||||
placeholder='Name'
|
||||
defaultValue={item.name ? item.name : ''}
|
||||
updateFormValue={(v) =>
|
||||
updateFormValue={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
name: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
containerStyle='tw:grow tw:px-4'
|
||||
inputStyle='tw:input-md'
|
||||
/>
|
||||
@ -58,12 +58,12 @@ export const FormHeader = ({ item, state, setState }: Props) => {
|
||||
placeholder={item.layer.itemType.subtitle_label}
|
||||
required={false}
|
||||
defaultValue={item.subname ? item.subname : ''}
|
||||
updateFormValue={(v) =>
|
||||
updateFormValue={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
subname: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
containerStyle='tw:grow tw:px-4 tw:mt-1'
|
||||
inputStyle='tw:input-sm'
|
||||
/>
|
||||
|
||||
@ -28,7 +28,9 @@ export const GalleryForm = ({ state, setState, hideInputLabel = false }: Props)
|
||||
|
||||
const [imageSelectedToDelete, setImageSelectedToDelete] = useState<number | null>(null)
|
||||
|
||||
const closeModal = () => setImageSelectedToDelete(null)
|
||||
const closeModal = () => {
|
||||
setImageSelectedToDelete(null)
|
||||
}
|
||||
|
||||
const upload = async (acceptedFiles: File[]) => {
|
||||
setState((prevState) => ({
|
||||
@ -116,7 +118,9 @@ export const GalleryForm = ({ state, setState, hideInputLabel = false }: Props)
|
||||
{image.state === 'uploaded' && (
|
||||
<button
|
||||
className='tw:m-2 tw:bg-red-500 tw:text-white tw:p-2 tw:rounded-full tw:absolute tw:top-0 tw:right-0 tw:hover:bg-red-600 tw:cursor-pointer'
|
||||
onClick={() => setImageSelectedToDelete(index)}
|
||||
onClick={() => {
|
||||
setImageSelectedToDelete(index)
|
||||
}}
|
||||
type='button'
|
||||
>
|
||||
<TrashIcon className='tw:h-5 tw:w-5' data-testid='trash' />
|
||||
@ -142,7 +146,11 @@ export const GalleryForm = ({ state, setState, hideInputLabel = false }: Props)
|
||||
showCloseButton={false}
|
||||
onClose={closeModal}
|
||||
>
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<div
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
<span>Do you want to delete this image?</span>
|
||||
<div className='tw:grid'>
|
||||
<div className='tw:flex tw:justify-between'>
|
||||
|
||||
@ -44,10 +44,19 @@ export const GalleryView = ({ item }: { item: Item }) => {
|
||||
<RowsPhotoAlbum
|
||||
photos={images}
|
||||
targetRowHeight={150}
|
||||
onClick={({ index: current }) => setIndex(current)}
|
||||
onClick={({ index: current }) => {
|
||||
setIndex(current)
|
||||
}}
|
||||
/>
|
||||
|
||||
<ReactLightbox index={index} slides={images} open={index >= 0} close={() => setIndex(-1)} />
|
||||
<ReactLightbox
|
||||
index={index}
|
||||
slides={images}
|
||||
open={index >= 0}
|
||||
close={() => {
|
||||
setIndex(-1)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
else return <></>
|
||||
|
||||
@ -57,12 +57,12 @@ export const GroupSubheaderForm = ({
|
||||
id='status'
|
||||
options={groupStates || []}
|
||||
value={state.status}
|
||||
onValueChange={(v) =>
|
||||
onValueChange={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
status: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
@ -71,12 +71,12 @@ export const GroupSubheaderForm = ({
|
||||
id='groupType'
|
||||
options={groupTypes?.map((gt) => gt.groupTypes_id.name) || []}
|
||||
value={state.group_type}
|
||||
onValueChange={(v) =>
|
||||
onValueChange={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
group_type: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -50,7 +50,12 @@ export function LinkedItemsHeaderView({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='tw:col-span-1' onClick={(e) => e.stopPropagation()}>
|
||||
<div
|
||||
className='tw:col-span-1'
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
{unlinkPermission && (
|
||||
<div className='tw:dropdown tw:dropdown-bottom'>
|
||||
<label
|
||||
|
||||
@ -6,7 +6,9 @@ export const MarkdownHint = () => {
|
||||
const [expended, setExpended] = useState<boolean>(false)
|
||||
return (
|
||||
<div
|
||||
onClick={() => setExpended(true)}
|
||||
onClick={() => {
|
||||
setExpended(true)
|
||||
}}
|
||||
title='Markdown is supported'
|
||||
className='flex tw:flex-row tw:text-gray-400 tw:cursor-pointer tw:items-center'
|
||||
>
|
||||
|
||||
@ -14,18 +14,18 @@ export const ProfileStartEndForm = ({
|
||||
<PopupStartEndInput
|
||||
item={item}
|
||||
showLabels={false}
|
||||
updateEndValue={(e) =>
|
||||
updateEndValue={(e) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
end: e,
|
||||
}))
|
||||
}
|
||||
updateStartValue={(s) =>
|
||||
}}
|
||||
updateStartValue={(s) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
start: s,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
></PopupStartEndInput>
|
||||
)
|
||||
}
|
||||
|
||||
@ -44,12 +44,12 @@ export const ProfileTextForm = ({
|
||||
placeholder={'...'}
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
defaultValue={state[field]}
|
||||
updateFormValue={(v) =>
|
||||
updateFormValue={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
[field]: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
showMenu={size === 'full'}
|
||||
containerStyle={size === 'full' ? 'tw:flex-1' : 'tw:h-24 tw:flex-none'}
|
||||
/>
|
||||
|
||||
@ -41,7 +41,9 @@ const SocialShareBar = ({
|
||||
color: 'white',
|
||||
backgroundColor: '#444',
|
||||
}}
|
||||
onClick={() => copyLink()}
|
||||
onClick={() => {
|
||||
copyLink()
|
||||
}}
|
||||
title='share link via email'
|
||||
>
|
||||
<img src={ChevronSVG} alt='\/' className='tw:h-4 tw:w-4' />
|
||||
@ -55,7 +57,9 @@ const SocialShareBar = ({
|
||||
color: 'white',
|
||||
backgroundColor: '#888',
|
||||
}}
|
||||
onClick={() => copyLink()}
|
||||
onClick={() => {
|
||||
copyLink()
|
||||
}}
|
||||
title='copy Link'
|
||||
>
|
||||
<img src={ClipboardSVG} className='tw:w-5' />
|
||||
|
||||
@ -121,7 +121,9 @@ export const TagsWidget = ({ placeholder, containerStyle, defaultTags, onUpdate
|
||||
<div className='tw:card-actions tw:justify-end'>
|
||||
<label
|
||||
className='tw:btn tw:btn-xs tw:btn-circle tw:absolute tw:-right-2 tw:-top-2 tw:bg-white tw:text-gray-600'
|
||||
onClick={() => deleteTag(tag)}
|
||||
onClick={() => {
|
||||
deleteTag(tag)
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</label>
|
||||
@ -134,7 +136,9 @@ export const TagsWidget = ({ placeholder, containerStyle, defaultTags, onUpdate
|
||||
pushFilteredSuggestions={pushFilteredSuggestions}
|
||||
setFocus={focusInput}
|
||||
inputProps={inputProps}
|
||||
onSelected={(tag) => onSelected(tag)}
|
||||
onSelected={(tag) => {
|
||||
onSelected(tag)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -29,12 +29,12 @@ export const OnepagerForm = ({
|
||||
<TextAreaInput
|
||||
placeholder='Beschreibung'
|
||||
defaultValue={state.text || ''}
|
||||
updateFormValue={(v) =>
|
||||
updateFormValue={(v) => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
text: v,
|
||||
}))
|
||||
}
|
||||
}}
|
||||
inputStyle='tw:h-48'
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -131,7 +131,9 @@ export const TabsForm = ({
|
||||
<div
|
||||
key={i.id}
|
||||
className='tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:mx-4 tw:p-6 tw:mb-4'
|
||||
onClick={() => navigate('/item/' + i.id)}
|
||||
onClick={() => {
|
||||
navigate('/item/' + i.id)
|
||||
}}
|
||||
>
|
||||
<LinkedItemsHeaderView
|
||||
unlinkPermission={updatePermission}
|
||||
|
||||
@ -88,9 +88,11 @@ export const TabsView = ({
|
||||
name='my_tabs_2'
|
||||
role='tab'
|
||||
className={'tw:tab tw:font-bold tw:ps-2! tw:pe-2! '}
|
||||
aria-label={`${item.layer?.itemType.icon_as_labels && activeTab !== 0 ? '📝' : '📝\u00A0Info'}`}
|
||||
aria-label={item.layer?.itemType.icon_as_labels && activeTab !== 0 ? '📝' : '📝\u00A0Info'}
|
||||
checked={activeTab === 0 && true}
|
||||
onChange={() => updateActiveTab(0)}
|
||||
onChange={() => {
|
||||
updateActiveTab(0)
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
role='tabpanel'
|
||||
@ -112,9 +114,13 @@ export const TabsView = ({
|
||||
name='my_tabs_2'
|
||||
role='tab'
|
||||
className={'tw:tab tw:font-bold tw:ps-2! tw:pe-2!'}
|
||||
aria-label={`${item.layer.itemType.icon_as_labels && activeTab !== 3 ? '❤️' : '❤️\u00A0Trust'}`}
|
||||
aria-label={
|
||||
item.layer.itemType.icon_as_labels && activeTab !== 3 ? '❤️' : '❤️\u00A0Trust'
|
||||
}
|
||||
checked={activeTab === 3 && true}
|
||||
onChange={() => updateActiveTab(3)}
|
||||
onChange={() => {
|
||||
updateActiveTab(3)
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
role='tabpanel'
|
||||
@ -195,9 +201,15 @@ export const TabsView = ({
|
||||
name='my_tabs_2'
|
||||
role='tab'
|
||||
className={`tw:tab tw:font-bold tw:ps-2! tw:pe-2! ${!(item.layer.itemType.icon_as_labels && activeTab !== 1) && 'tw:min-w-[10.4em]'} `}
|
||||
aria-label={`${item.layer.itemType.icon_as_labels && activeTab !== 1 ? '♻️' : '♻️\u00A0Offers & Needs'}`}
|
||||
aria-label={
|
||||
item.layer.itemType.icon_as_labels && activeTab !== 1
|
||||
? '♻️'
|
||||
: '♻️\u00A0Offers & Needs'
|
||||
}
|
||||
checked={activeTab === 1 && true}
|
||||
onChange={() => updateActiveTab(1)}
|
||||
onChange={() => {
|
||||
updateActiveTab(1)
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
role='tabpanel'
|
||||
@ -228,7 +240,13 @@ export const TabsView = ({
|
||||
<h3 className='tw:-mb-2 tw:col-span-1'>Needs</h3>
|
||||
<div className='tw:flex tw:flex-wrap tw:mb-4'>
|
||||
{needs.map((n) => (
|
||||
<TagView key={n.id} tag={n} onClick={() => addFilterTag(n)} />
|
||||
<TagView
|
||||
key={n.id}
|
||||
tag={n}
|
||||
onClick={() => {
|
||||
addFilterTag(n)
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@ -248,9 +266,13 @@ export const TabsView = ({
|
||||
name='my_tabs_2'
|
||||
role='tab'
|
||||
className='tw:tab tw:font-bold tw:ps-2! tw:pe-2! '
|
||||
aria-label={`${item.layer.itemType.icon_as_labels && activeTab !== 2 ? '🔗' : '🔗\u00A0Links'}`}
|
||||
aria-label={
|
||||
item.layer.itemType.icon_as_labels && activeTab !== 2 ? '🔗' : '🔗\u00A0Links'
|
||||
}
|
||||
checked={activeTab === 2 && true}
|
||||
onChange={() => updateActiveTab(2)}
|
||||
onChange={() => {
|
||||
updateActiveTab(2)
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
role='tabpanel'
|
||||
@ -263,7 +285,9 @@ export const TabsView = ({
|
||||
<div
|
||||
key={i.id}
|
||||
className='tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:p-6 tw:mr-4 tw:mb-4'
|
||||
onClick={() => navigate('/item/' + i.id)}
|
||||
onClick={() => {
|
||||
navigate('/item/' + i.id)
|
||||
}}
|
||||
>
|
||||
<LinkedItemsHeaderView
|
||||
unlinkPermission={updatePermission}
|
||||
|
||||
@ -44,7 +44,9 @@ export function UserSettings() {
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(() => navigate('/'))
|
||||
.then(() => {
|
||||
navigate('/')
|
||||
})
|
||||
.catch((e) => {
|
||||
throw e
|
||||
})
|
||||
@ -62,7 +64,9 @@ export function UserSettings() {
|
||||
type='email'
|
||||
placeholder='new E-Mail'
|
||||
defaultValue={user?.email ? user.email : ''}
|
||||
updateFormValue={(v) => setEmail(v)}
|
||||
updateFormValue={(v) => {
|
||||
setEmail(v)
|
||||
}}
|
||||
/>
|
||||
<TextInput
|
||||
type='password'
|
||||
@ -83,7 +87,9 @@ export function UserSettings() {
|
||||
? ' tw:loading tw:btn-disabled tw:btn tw:btn-primary tw:float-right'
|
||||
: 'tw:btn tw:btn-primary tw:float-right'
|
||||
}
|
||||
onClick={() => onUpdateUser()}
|
||||
onClick={() => {
|
||||
onUpdateUser()
|
||||
}}
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
|
||||
@ -68,7 +68,7 @@ export const AttestationForm = ({ api }: { api?: ItemsApi<unknown> }) => {
|
||||
},
|
||||
},
|
||||
)
|
||||
.then(() =>
|
||||
.then(() => {
|
||||
navigate(
|
||||
'/item/' +
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||
@ -79,8 +79,8 @@ export const AttestationForm = ({ api }: { api?: ItemsApi<unknown> }) => {
|
||||
i.layer?.userProfileLayer === true,
|
||||
)?.id +
|
||||
'?tab=2',
|
||||
),
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const [selectedEmoji, setSelectedEmoji] = useState('select badge')
|
||||
|
||||
@ -9,18 +9,24 @@ export const DateUserInfo = ({ item }: { item: Item }) => {
|
||||
return (
|
||||
<div
|
||||
className='tw:flex tw:-mb-1 tw:flex-row tw:mr-2 tw:-mt-2'
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
{infoExpanded ? (
|
||||
<p
|
||||
className={'tw:italic tw:min-h-[21px] tw:my-0! tw:text-gray-500'}
|
||||
onClick={() => setInfoExpanded(false)}
|
||||
onClick={() => {
|
||||
setInfoExpanded(false)
|
||||
}}
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
>{`${item.date_updated && item.date_updated !== item.date_created ? 'updated' : 'posted'} ${item.user_created?.first_name ? `by ${item.user_created.first_name}` : ''} ${item.date_updated ? timeAgo(item.date_updated) : timeAgo(item.date_created!)}`}</p>
|
||||
) : (
|
||||
<p
|
||||
className='tw:my-0! tw:min-h-[21px] tw:font-bold tw:cursor-pointer tw:text-gray-500'
|
||||
onClick={() => setInfoExpanded(true)}
|
||||
onClick={() => {
|
||||
setInfoExpanded(true)
|
||||
}}
|
||||
>
|
||||
ⓘ
|
||||
</p>
|
||||
|
||||
@ -109,7 +109,9 @@ export const EmojiPicker = ({
|
||||
{emojis.map((emoji) => (
|
||||
<button
|
||||
key={emoji}
|
||||
onClick={() => selectEmoji(emoji)}
|
||||
onClick={() => {
|
||||
selectEmoji(emoji)
|
||||
}}
|
||||
className={`tw:cursor-pointer tw:text-2xl tw:p-2 tw:hover:bg-base-200 tw:rounded-md ${emoji === selectedEmoji ? 'tw:bg-base-300' : ''}`}
|
||||
>
|
||||
{emoji}
|
||||
@ -122,7 +124,9 @@ export const EmojiPicker = ({
|
||||
<div
|
||||
key={shape}
|
||||
className={`tw:cursor-pointer tw:hover:bg-base-200 tw:rounded-md tw:p-2 ${shape === selectedShape ? 'tw:bg-base-300' : ''}`}
|
||||
onClick={() => selectShape(shape)}
|
||||
onClick={() => {
|
||||
selectShape(shape)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`tw:h-12 tw:w-full tw:mask ${shape === 'squircle' ? 'tw:mask-squircle' : shape === 'circle' ? 'tw:mask-circle' : 'tw:mask-hexagon-2'} tw:bg-neutral-content`}
|
||||
@ -136,7 +140,9 @@ export const EmojiPicker = ({
|
||||
<div
|
||||
key={color}
|
||||
className={`tw:cursor-pointer tw:hover:bg-base-200 tw:rounded-md tw:p-2 tw:flex tw:justify-center tw:items-center ${color === selectedColor ? 'tw:bg-base-300' : ''}`}
|
||||
onClick={() => selectColor(color)}
|
||||
onClick={() => {
|
||||
selectColor(color)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`tw:h-8 tw:w-8 tw:rounded-full`}
|
||||
|
||||
@ -60,21 +60,25 @@ export const ItemCard = ({
|
||||
// We could have an onClick callback instead
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
if (windowDimensions.width < 786 && i.position)
|
||||
navigate('/' + i.id + `${params.size > 0 ? `?${params.toString()}` : ''}`)
|
||||
else navigate(url + i.id + `${params.size > 0 ? `?${params.toString()}` : ''}`)
|
||||
navigate('/' + i.id + (params.size > 0 ? `?${params.toString()}` : ''))
|
||||
else navigate(url + i.id + (params.size > 0 ? `?${params.toString()}` : ''))
|
||||
}}
|
||||
>
|
||||
<HeaderView
|
||||
loading={loading}
|
||||
item={i}
|
||||
api={i.layer?.api}
|
||||
editCallback={() => handleEdit()}
|
||||
editCallback={() => {
|
||||
handleEdit()
|
||||
}}
|
||||
setPositionCallback={() => {
|
||||
map.closePopup()
|
||||
setSelectPosition(i)
|
||||
navigate('/')
|
||||
}}
|
||||
deleteCallback={() => deleteCallback(i)}
|
||||
deleteCallback={() => {
|
||||
deleteCallback(i)
|
||||
}}
|
||||
></HeaderView>
|
||||
<div className='tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade'>
|
||||
{i.layer?.itemType.show_start_end && <StartEndView item={i}></StartEndView>}
|
||||
|
||||
@ -50,7 +50,9 @@ export function MapOverlayPage({
|
||||
{children}
|
||||
<button
|
||||
className='tw:btn tw:btn-sm tw:btn-circle tw:btn-ghost tw:absolute tw:right-2 tw:top-2'
|
||||
onClick={() => closeScreen()}
|
||||
onClick={() => {
|
||||
closeScreen()
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
@ -68,7 +68,9 @@ export const MarketView = () => {
|
||||
<div className='tw:flex tw:flex-wrap'>
|
||||
{groupAndCount(offers).map((o) => (
|
||||
<TagView
|
||||
onClick={() => navigate(`/?tags=${o.object.name}`)}
|
||||
onClick={() => {
|
||||
navigate(`/?tags=${o.object.name}`)
|
||||
}}
|
||||
key={o.object.id}
|
||||
tag={o.object}
|
||||
count={o.count}
|
||||
@ -81,7 +83,9 @@ export const MarketView = () => {
|
||||
<div className='tw:flex tw:flex-wrap'>
|
||||
{groupAndCount(needs).map((o) => (
|
||||
<TagView
|
||||
onClick={() => navigate(`/?tags=${o.object.name}`)}
|
||||
onClick={() => {
|
||||
navigate(`/?tags=${o.object.name}`)
|
||||
}}
|
||||
key={o.object.id}
|
||||
tag={o.object}
|
||||
count={o.count}
|
||||
|
||||
@ -172,7 +172,9 @@ export const OverlayItemsIndexPage = ({
|
||||
<div className='tw:cursor-pointer tw:break-inside-avoid card tw:border-[1px] tw:border-base-300 card-body tw:shadow-xl tw:bg-base-100 tw:text-base-content tw:p-6 tw:mb-10'>
|
||||
<label
|
||||
className='tw:btn tw:btn-sm tw:rounded-2xl tw:btn-circle tw:btn-ghost tw:hover:bg-transparent tw:absolute tw:right-0 tw:top-0 tw:text-gray-600'
|
||||
onClick={() => setAddItemPopupOpen(false)}
|
||||
onClick={() => {
|
||||
setAddItemPopupOpen(false)
|
||||
}}
|
||||
>
|
||||
<p className='tw:text-center'>✕</p>
|
||||
</label>
|
||||
|
||||
@ -31,7 +31,9 @@ export const SelectUser = () => {
|
||||
<td>
|
||||
<input
|
||||
type='checkbox'
|
||||
onChange={() => setSelectedUsers((prev) => [...prev, u.id])}
|
||||
onChange={() => {
|
||||
setSelectedUsers((prev) => [...prev, u.id])
|
||||
}}
|
||||
className='checkbox checkbox-sm'
|
||||
/>
|
||||
</td>
|
||||
|
||||
@ -51,7 +51,9 @@ export const Tabs: React.FC<TabsProps> = ({ items, setUrlParams }: TabsProps) =>
|
||||
key={index}
|
||||
role='tab'
|
||||
className={`tw:tab ${index === activeIndex ? 'tw:tab-active' : ''}`}
|
||||
onClick={() => updateActiveTab(index)}
|
||||
onClick={() => {
|
||||
updateActiveTab(index)
|
||||
}}
|
||||
>
|
||||
{item.title}
|
||||
</div>
|
||||
|
||||
@ -52,7 +52,9 @@ export const ThemeControl = () => {
|
||||
name='theme'
|
||||
value={t}
|
||||
checked={theme === t}
|
||||
onChange={() => setTheme(t)}
|
||||
onChange={() => {
|
||||
setTheme(t)
|
||||
}}
|
||||
aria-label={t.toLowerCase()}
|
||||
/>
|
||||
</li>
|
||||
|
||||
@ -40,7 +40,7 @@ const MarkerIconFactory = (
|
||||
) => {
|
||||
if (icon)
|
||||
return divIcon({
|
||||
html: `<div class="svg-container">${createSvg(shape, color1, color2)}<img class="overlay-svg" style="width: ${icon.size ? icon.size : '12.5'}px; height: ${icon.size ? icon.size : '12.5'}px; filter: invert(1) brightness(2);" src="${`${assetsURL ?? ''}` + icon.image}"></div>`,
|
||||
html: `<div class="svg-container">${createSvg(shape, color1, color2)}<img class="overlay-svg" style="width: ${icon.size ? icon.size : '12.5'}px; height: ${icon.size ? icon.size : '12.5'}px; filter: invert(1) brightness(2);" src="${(assetsURL ?? '') + icon.image}"></div>`,
|
||||
iconAnchor: [17, 40],
|
||||
popupAnchor: [0, -40],
|
||||
iconSize: new Point(40, 46),
|
||||
|
||||
@ -7,7 +7,7 @@ export function fixUrls(message: string): string {
|
||||
message = message.replace(urlRegex, function (url) {
|
||||
let hyperlink = url.replace(' ', '')
|
||||
|
||||
if (!hyperlink.match('^https?://')) {
|
||||
if (!/^https?:\/\//.exec(hyperlink)) {
|
||||
hyperlink = 'https://' + hyperlink
|
||||
}
|
||||
return hyperlink
|
||||
|
||||
@ -13,7 +13,9 @@ export const getImageDimensions = (
|
||||
try {
|
||||
const img = new Image()
|
||||
|
||||
img.onload = () => resolve({ width: img.width, height: img.height })
|
||||
img.onload = () => {
|
||||
resolve({ width: img.width, height: img.height })
|
||||
}
|
||||
|
||||
img.src = fileReader.result as string // is the data URL because called with readAsDataURL
|
||||
} catch (error) {
|
||||
|
||||
@ -1,32 +1,36 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
"declarationDir": "dist/types", // 🔹 Muss innerhalb von dist/ liegen
|
||||
"emitDeclarationOnly": true, // Nur `.d.ts` generieren, kein JavaScript
|
||||
"sourceMap": false,
|
||||
"allowJs": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"paths": {
|
||||
"#assets/*": ["./src/assets/*"],
|
||||
"#components/*": ["./src/Components/*"],
|
||||
"#utils/*": ["./src/Utils/*"],
|
||||
"#types/*": ["./src/types/*"],
|
||||
"#src/*": ["./src/*"],
|
||||
"#root/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "vite.config.ts", "setupTest.ts", "cypress.config.ts", "cypress/support/commands.ts", "cypress/support/component.ts"],
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
"declarationDir": "dist/types", // 🔹 Muss innerhalb von dist/ liegen
|
||||
"emitDeclarationOnly": true, // Nur `.d.ts` generieren, kein JavaScript
|
||||
"sourceMap": false,
|
||||
"allowJs": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"paths": {
|
||||
"#assets/*": ["./src/assets/*"],
|
||||
"#components/*": ["./src/Components/*"],
|
||||
"#utils/*": ["./src/Utils/*"],
|
||||
"#types/*": ["./src/types/*"],
|
||||
"#src/*": ["./src/*"],
|
||||
"#root/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
"vite.config.ts",
|
||||
"setupTest.ts",
|
||||
"cypress.config.ts",
|
||||
"cypress/support/commands.ts",
|
||||
"cypress/support/component.ts"
|
||||
],
|
||||
"exclude": ["node_modules", "dist", "example"],
|
||||
"typeRoots": [
|
||||
"./src/types",
|
||||
"./node_modules/@types/"
|
||||
]
|
||||
"typeRoots": ["./src/types", "./node_modules/@types/"]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user