From bb83a39267adfb544edd30d3b1164f1d62423998 Mon Sep 17 00:00:00 2001 From: Gabe Hamilton Date: Tue, 23 Apr 2024 09:39:10 -0600 Subject: [PATCH] feat: global tag filter uses properties instead of Storage, active global tag is (un)selected (#780) --- src/DIG/Tabs.jsx | 6 ++-- src/DIG/Tabs.metadata.json | 2 +- src/Entities/Template/EntityList.jsx | 29 ++++++++++++++----- src/Entities/Template/Forms/TagCloud.jsx | 10 +++++-- src/Entities/Template/GenericEntityConfig.jsx | 14 +++++++-- 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/DIG/Tabs.jsx b/src/DIG/Tabs.jsx index 071a30eb..a424dc71 100644 --- a/src/DIG/Tabs.jsx +++ b/src/DIG/Tabs.jsx @@ -1,4 +1,4 @@ -let { items, variant, size, ...forwardedProps } = props; +let { items, variant, size, contentProps, ...forwardedProps } = props; // this prop is just for preview const previewItems = [ @@ -221,7 +221,9 @@ return ( {items.map((item) => ( - {item.content} + + {typeof item.content === "function" ? item.content(contentProps) : item.content} + ))} ); diff --git a/src/DIG/Tabs.metadata.json b/src/DIG/Tabs.metadata.json index 5d0be644..cb5db832 100644 --- a/src/DIG/Tabs.metadata.json +++ b/src/DIG/Tabs.metadata.json @@ -1,5 +1,5 @@ { - "description": "This tabs component is built with the Radix primitive: https://www.radix-ui.com/docs/primitives/components/tabs\n\n### Example\n\n```jsx\n\n```\n\n### Props\n\n`variant`\n- one of `\"pill\"`, `\"line\"`, `toggle`\n- Default to `\"line\"`\n\n`size`\n- `\"small\"`, `\"default\"`, `\"large\"`\n- Default to `\"default\"`\n\n`items`\n- array of objects defining each tab with it's own content.\n- Each object requires a `value` (unique string), `name` (string) and `content` (string or JSX).\n- Also there is optional parameters:\n - `icon` - type: string (CSS Class). Example: `\"ph-bold ph-anchor-simple\"`. Adds an icon to the left of the `name`. Accepts classNames from https://phosphoricons.com and https://icons.getbootstrap.com.\n - `count` - type: string. Adds an counter label to the right of `name`.\n - `disabled` - type: `boolean`. When `true`, prevents the user from interacting with the tab. \n\nThis component also accepts all `Tabs.Root` props as outlined in the Radix documentation.", + "description": "This tabs component is built with the Radix primitive: https://www.radix-ui.com/docs/primitives/components/tabs\n\n### Example\n\n```jsx\n\n```\n\n### Props\n\n`variant`\n- one of `\"pill\"`, `\"line\"`, `toggle`\n- Default to `\"line\"`\n\n`size`\n- `\"small\"`, `\"default\"`, `\"large\"`\n- Default to `\"default\"`\n\n`items`\n- array of objects defining each tab with it's own content.\n- Each object requires a `value` (unique string), `name` (string) and `content` (string or JSX).\n- Also there is optional parameters:\n - `icon` - type: string (CSS Class). Example: `\"ph-bold ph-anchor-simple\"`. Adds an icon to the left of the `name`. Accepts classNames from https://phosphoricons.com and https://icons.getbootstrap.com.\n - `count` - type: string. Adds an counter label to the right of `name`.\n - `disabled` - type: `boolean`. When `true`, prevents the user from interacting with the tab.\n\n`contentProps`\n- type: `object`.\n- Properties to be passed to content if an item's `content` is a function. \n\nThis component also accepts all `Tabs.Root` props as outlined in the Radix documentation.", "name": "DIG.Tabs", "tags": { "dig": "" diff --git a/src/Entities/Template/EntityList.jsx b/src/Entities/Template/EntityList.jsx index 3e63dd28..7f9e8b3f 100644 --- a/src/Entities/Template/EntityList.jsx +++ b/src/Entities/Template/EntityList.jsx @@ -5,7 +5,18 @@ if (!loadItemsQueryApi) { const loadItems = props.loadItems ?? loadItemsQueryApi; const accountId = props.accountId || context.accountId; -const { schema, description, buildQueries, queryName, collection, renderItem, createWidget, createWidgetProps } = props; +const { + schema, + description, + buildQueries, + queryName, + collection, + renderItem, + createWidget, + createWidgetProps, + globalTagFilter, + setGlobalTagFilter, +} = props; const finalCreateWidget = createWidget ?? `${REPL_ACCOUNT}/widget/Entities.Template.EntityCreate`; @@ -20,13 +31,11 @@ const sortTypes = props.sortTypes ?? [ { text: "Oldest Updates", value: "{ updated_at: asc }" }, ]; -const initialTagFilter = Storage.get("global-tag-filter"); -if (initialTagFilter) { - Storage.set("global-tag-filter", null); -} const [searchKey, setSearchKey] = useState(""); const [sort, setSort] = useState(sortTypes[0].value); -const [tagsFilter, setTagsFilter] = useState(initialTagFilter); +const [tagsFilter, setTagsFilter] = useState( + Array.isArray(globalTagFilter) ? globalTagFilter.map((it) => it.tag) : null, +); const [items, setItems] = useState({ list: [], total: 0 }); const [showCreateModal, setShowCreateModal] = useState(false); const [activeItem, setActiveItem] = useState(null); @@ -55,6 +64,12 @@ const loadItemsUseState = (isResetOrPageNumber) => { const offset = isResetOrPageNumber === true ? 0 : items.list.length; return loadItems(buildQueries(searchKey, sort, { tags: tagsFilter }), queryName, offset, collection, loader); }; + +const onTagFilterChanged = (tags) => { + setTagsFilter(tags); + setGlobalTagFilter(tags.map((tag) => ({ entity_type: schema.entityType, tag }))); +}; + useEffect(() => { if (debounceTimer) clearTimeout(debounceTimer); const search = (searchKey ?? "").toLowerCase(); @@ -249,7 +264,7 @@ return ( props={{ placeholder: "Filter by Tag", value: tagsFilter, - setValue: setTagsFilter, + setValue: onTagFilterChanged, namespace: schema.namespace, entityType: schema.entityType, allowNew: false, diff --git a/src/Entities/Template/Forms/TagCloud.jsx b/src/Entities/Template/Forms/TagCloud.jsx index ca193847..1aecb982 100644 --- a/src/Entities/Template/Forms/TagCloud.jsx +++ b/src/Entities/Template/Forms/TagCloud.jsx @@ -3,11 +3,11 @@ if (!loadItems) { return

Loading modules...

; } -const { namespace, entityType, onSelect, limit } = props; +const { namespace, entityType, onSelect, limit, initialTags } = props; const tagLimit = limit ?? 100; const [items, setItems] = useState(null); -const [tags, setTags] = useState(value || []); +const [tags, setTags] = useState(initialTags); const user = "dataplatform_near"; const entityIndexer = "entities"; @@ -118,6 +118,7 @@ const TooltipTag = styled.span` `; const selectTag = (tag) => { + setTags([tag]); if (onSelect) { onSelect(tag); } @@ -127,6 +128,9 @@ const humanize = (str) => { return str.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase()); }; +const isSelected = (tag, tagList) => + tagList && tagList.find((t) => t.tag === tag.tag && t.entity_type === tag.entity_type); + return (

Filter by Tag

@@ -143,7 +147,7 @@ return ( ), trigger: ( - selectTag(tag)}> + selectTag(tag)} primary={isSelected(tag, props.initialTags)}> {tag.tag} {tag.count} ), diff --git a/src/Entities/Template/GenericEntityConfig.jsx b/src/Entities/Template/GenericEntityConfig.jsx index d20c2131..d659e6e3 100644 --- a/src/Entities/Template/GenericEntityConfig.jsx +++ b/src/Entities/Template/GenericEntityConfig.jsx @@ -4,7 +4,7 @@ if (!href) { } const { namespace, entityType, schemaFile } = props; // data props -const { title, homeLink } = props; // display props +const { title, homeLink, globalTagFilter, setGlobalTagFilter } = props; // display props const schemaLocation = schemaFile ? schemaFile : `${REPL_ACCOUNT}/widget/Entities.Template.GenericSchema`; const { genSchema } = VM.require(schemaLocation); @@ -302,7 +302,17 @@ return (
);