From 2362f88e9e1b443569dfd9133de7f760f97e96df Mon Sep 17 00:00:00 2001 From: Mate Kiss Date: Wed, 15 May 2024 10:11:02 +0200 Subject: [PATCH 1/2] feat: set custom icon from relative path --- apps/sensenet/src/components/Icon.tsx | 13 ++++- apps/sensenet/src/components/IconFromPath.tsx | 48 +++++++++++++++++++ .../src/Repository/Repository.ts | 2 + 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 apps/sensenet/src/components/IconFromPath.tsx diff --git a/apps/sensenet/src/components/Icon.tsx b/apps/sensenet/src/components/Icon.tsx index 441af78e4..4f4b86428 100644 --- a/apps/sensenet/src/components/Icon.tsx +++ b/apps/sensenet/src/components/Icon.tsx @@ -60,6 +60,7 @@ import travisCi from '@iconify-icons/logos/travis-ci' import vercelIcon from '@iconify-icons/logos/vercel-icon' import React, { CSSProperties, FunctionComponent } from 'react' import { EventLogEntry } from '../services/EventService' +import { IconFromPath } from './IconFromPath' import { UserAvatar } from './UserAvatar' export interface IconOptions { @@ -183,9 +184,19 @@ const getIconByName = (name: string | undefined, options: IconOptions) => { } } -/* eslint-disable react/display-name */ +const getIconByPath = (icon: string | undefined, options: IconOptions) => { + if (!icon || !icon.startsWith('/')) { + return null + } + + return +} +/* eslint-disable react/display-name */ export const defaultContentResolvers: Array> = [ + { + get: (item, options) => getIconByPath(item.Icon, options), + }, { get: (item, options) => options.repo.schemas.isContentFromType(item, 'User') ? ( diff --git a/apps/sensenet/src/components/IconFromPath.tsx b/apps/sensenet/src/components/IconFromPath.tsx new file mode 100644 index 000000000..d28448607 --- /dev/null +++ b/apps/sensenet/src/components/IconFromPath.tsx @@ -0,0 +1,48 @@ +import { PathHelper } from '@sensenet/client-utils' +import React, { memo, useEffect, useState } from 'react' +import { IconOptions } from './Icon' + +const IconFromPath = ({ path, options }: { path: string; options: IconOptions }) => { + const [icon, setIcon] = useState(null) + + useEffect(() => { + async function fetchData() { + if (options.repo.iconCache.has(path)) { + const cachedData = options.repo.iconCache.get(path) ?? '' + setIcon(cachedData) + return + } + + const imageUrl = PathHelper.joinPaths(options.repo.configuration.repositoryUrl, path) + + if (path.endsWith('.svg')) { + const fetchedSvg = await options.repo.fetch(imageUrl, { cache: 'force-cache' }) + if (!fetchedSvg.ok) { + return + } + const svg = await fetchedSvg.text().catch(() => '') + options.repo.iconCache.set(path, svg) + setIcon(svg) + return + } + + options.repo.iconCache.set(path, imageUrl) + setIcon(imageUrl) + } + fetchData() + }, [options.repo, path]) + + if (!icon) { + return null + } + + if (path.endsWith('.svg')) { + return + } + + return icon +} + +const memoIzedIconFromPath = memo(IconFromPath) + +export { memoIzedIconFromPath as IconFromPath } diff --git a/packages/sn-client-core/src/Repository/Repository.ts b/packages/sn-client-core/src/Repository/Repository.ts index 6020ab1f6..a5f4a5038 100644 --- a/packages/sn-client-core/src/Repository/Repository.ts +++ b/packages/sn-client-core/src/Repository/Repository.ts @@ -500,6 +500,8 @@ export class Repository implements Disposable { this.schemas.setSchemas(schemas) } + public iconCache = new Map() + constructor( config?: RepositoryConfiguration, private fetchMethod: WindowOrWorkerGlobalScope['fetch'] = window && window.fetch && window.fetch.bind(window), From c53df2e9533662efb7fd98331901bf0459bab52e Mon Sep 17 00:00:00 2001 From: Mate Kiss Date: Wed, 15 May 2024 15:04:36 +0200 Subject: [PATCH 2/2] fix: add style to svg custom icon --- apps/sensenet/src/components/IconFromPath.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sensenet/src/components/IconFromPath.tsx b/apps/sensenet/src/components/IconFromPath.tsx index d28448607..641e1a4d8 100644 --- a/apps/sensenet/src/components/IconFromPath.tsx +++ b/apps/sensenet/src/components/IconFromPath.tsx @@ -37,7 +37,7 @@ const IconFromPath = ({ path, options }: { path: string; options: IconOptions }) } if (path.endsWith('.svg')) { - return + return } return icon