From 6908ea38e43f4efeb8537c18cdb534e144f0ed48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Bj=C3=B6rk?= Date: Sat, 20 Dec 2025 17:26:23 +0100 Subject: [PATCH 1/5] Added search/filter in patterns tab Added pattern as dep to filter memo Format --- website/src/metadata_parser.js | 2 +- .../src/repl/components/panel/PatternsTab.jsx | 190 ++++++++++-------- 2 files changed, 106 insertions(+), 86 deletions(-) diff --git a/website/src/metadata_parser.js b/website/src/metadata_parser.js index fab943d66..f0a70babb 100644 --- a/website/src/metadata_parser.js +++ b/website/src/metadata_parser.js @@ -1,4 +1,4 @@ -const ALLOW_MANY = ['by', 'url', 'genre', 'license']; +const ALLOW_MANY = ['by', 'url', 'genre', 'license', 'tag']; export function getMetadata(raw_code) { if (raw_code == null) { diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 5e0d50e72..588f8f39e 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -18,6 +18,7 @@ import { Pagination } from '../pagination/Pagination.jsx'; import { useState } from 'react'; import { useDebounce } from '../usedebounce.jsx'; import cx from '@src/cx.mjs'; +import { Textbox } from '../textbox/Textbox.jsx'; export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) { const meta = useMemo(() => getMetadata(pattern.code), [pattern]); @@ -33,7 +34,7 @@ export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) { } const author = Array.isArray(meta.by) ? meta.by.join(',') : 'Anonymous'; - return <>{`${pattern.id}: ${title} by ${author.slice(0, 100)}`.slice(0, 60)}; + return <>{`${title} by ${author.slice(0, 100)}`.slice(0, 60)}; } function PatternButton({ showOutline, onClick, pattern, showHiglight }) { @@ -79,73 +80,117 @@ const updateCodeWindow = (context, patternData, reset = false) => { context.handleUpdate(patternData, reset); }; -function UserPatterns({ context }) { +export function PatternsTab({ context }) { + const [search, setSearch] = useState(''); const activePattern = useActivePattern(); const viewingPatternStore = useViewingPatternData(); const viewingPatternData = parseJSON(viewingPatternStore); - const { userPatterns, patternFilter, patternAutoStart } = useSettings(); + const { userPatterns, patternAutoStart } = useSettings(); const viewingPatternID = viewingPatternData?.id; - return ( -
-
- { - const { data } = userPattern.createAndAddToDB(); - updateCodeWindow(context, data); - }} - /> - { - const { data } = userPattern.duplicate(viewingPatternData); - updateCodeWindow(context, data); - }} - /> - { - const { data } = userPattern.delete(viewingPatternID); - updateCodeWindow(context, { ...data, collection: userPattern.collection }); - }} - /> - - - { - const { data } = userPattern.clearAll(); - updateCodeWindow(context, data); - }} - /> -
+ const visiblePatterns = useMemo(() => { + return Object.fromEntries( + Object.entries(userPatterns).filter(([_key, pattern]) => { + if (!search) { + return true; + } -
- {/* {patternFilter === patternFilterName.user && ( */} - { - updateCodeWindow(context, { ...userPatterns[id], collection: userPattern.collection }, patternAutoStart); + const meta = getMetadata(pattern.code); - if (context.started && activePattern === id) { - context.handleEvaluate(); + // Search for specific meta keys + const searchTrimmed = search.trim(); + if (searchTrimmed.includes(':')) { + const [metaKey, metaSearch] = searchTrimmed.split(':'); + if (metaKey !== undefined && metaSearch !== undefined && metaKey in meta) { + const metaValues = meta[metaKey]; + if (Array.isArray(metaValues)) { + return metaValues.some((metaValue) => metaValue.toLowerCase().includes(metaSearch.trim().toLowerCase())); + } else if (typeof metaValues === 'string') { + return metaValues.toLowerCase().includes(metaSearch.trim().toLowerCase()); + } else { + return false; } - }} - patterns={userPatterns} - started={context.started} - activePattern={activePattern} - viewingPatternID={viewingPatternID} - /> - {/* )} */} + } + } + const title = meta.title ? meta.title : 'unnamed'; + const authors = meta.by ? meta.by : ['anonymous']; + const tags = meta.tag ? meta.tag : []; + const lowerCaseSearch = search.toLowerCase(); + return ( + title.toLowerCase().includes(lowerCaseSearch) || + authors.some((author) => author.toLowerCase().includes(lowerCaseSearch)) || + tags.some((tag) => tag.toLowerCase().includes(lowerCaseSearch)) + ); + }), + ); + }, [search, viewingPatternStore]); + + return ( +
+
+ +
+
+
+ { + const { data } = userPattern.createAndAddToDB(); + updateCodeWindow(context, data); + }} + /> + { + const { data } = userPattern.duplicate(viewingPatternData); + updateCodeWindow(context, data); + }} + /> + { + const { data } = userPattern.delete(viewingPatternID); + updateCodeWindow(context, { ...data, collection: userPattern.collection }); + }} + /> + + + + { + const { data } = userPattern.clearAll(); + updateCodeWindow(context, data); + }} + /> +
+ +
+ {/* {patternFilter === patternFilterName.user && ( */} + { + updateCodeWindow(context, { ...userPatterns[id], collection: userPattern.collection }, patternAutoStart); + + if (context.started && activePattern === id) { + context.handleEvaluate(); + } + }} + patterns={visiblePatterns} + started={context.started} + activePattern={activePattern} + viewingPatternID={viewingPatternID} + /> + {/* )} */} +
); @@ -232,28 +277,3 @@ function PublicPatterns({ context }) { } return ; } - -export function PatternsTab({ context }) { - const { patternFilter } = useSettings(); - - return ( -
- -
- ); - /* return ( -
- settingsMap.setKey('patternFilter', value)} - items={patternFilterName} - > - - {patternFilter === patternFilterName.user ? ( - - ) : ( - - )} -
- ); */ -} From aa8209ad4c44e0d17a5185d3d3213269ef509229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Bj=C3=B6rk?= Date: Thu, 1 Jan 2026 12:22:52 +0100 Subject: [PATCH 2/5] Refactored handling of trim/lowercase based on PR comments --- .../src/repl/components/panel/PatternsTab.jsx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 588f8f39e..56f0b4cb8 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -98,15 +98,15 @@ export function PatternsTab({ context }) { const meta = getMetadata(pattern.code); // Search for specific meta keys - const searchTrimmed = search.trim(); - if (searchTrimmed.includes(':')) { - const [metaKey, metaSearch] = searchTrimmed.split(':'); + const searchLowercaseTrimmed = search.trim().toLowerCase(); + if (searchLowercaseTrimmed.includes(':')) { + const [metaKey, metaSearch] = searchLowercaseTrimmed.split(/:\s*/); if (metaKey !== undefined && metaSearch !== undefined && metaKey in meta) { const metaValues = meta[metaKey]; if (Array.isArray(metaValues)) { - return metaValues.some((metaValue) => metaValue.toLowerCase().includes(metaSearch.trim().toLowerCase())); + return metaValues.some((metaValue) => metaValue.toLowerCase().includes(metaSearch)); } else if (typeof metaValues === 'string') { - return metaValues.toLowerCase().includes(metaSearch.trim().toLowerCase()); + return metaValues.toLowerCase().includes(metaSearch); } else { return false; } @@ -115,11 +115,10 @@ export function PatternsTab({ context }) { const title = meta.title ? meta.title : 'unnamed'; const authors = meta.by ? meta.by : ['anonymous']; const tags = meta.tag ? meta.tag : []; - const lowerCaseSearch = search.toLowerCase(); return ( - title.toLowerCase().includes(lowerCaseSearch) || - authors.some((author) => author.toLowerCase().includes(lowerCaseSearch)) || - tags.some((tag) => tag.toLowerCase().includes(lowerCaseSearch)) + title.toLowerCase().includes(searchLowercaseTrimmed) || + authors.some((author) => author.toLowerCase().includes(searchLowercaseTrimmed)) || + tags.some((tag) => tag.toLowerCase().includes(searchLowercaseTrimmed)) ); }), ); From 8b1fb12388aa523224f8e7a93e5bca0e3368fbd0 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 13 Jan 2026 03:32:19 +0100 Subject: [PATCH 3/5] fix: class -> className --- website/src/repl/components/panel/PatternsTab.jsx | 2 +- website/src/repl/components/panel/Reference.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 56f0b4cb8..04f6452e5 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -126,7 +126,7 @@ export function PatternsTab({ context }) { return (
-
+
diff --git a/website/src/repl/components/panel/Reference.jsx b/website/src/repl/components/panel/Reference.jsx index 505cf50d2..c03ac0cf9 100644 --- a/website/src/repl/components/panel/Reference.jsx +++ b/website/src/repl/components/panel/Reference.jsx @@ -55,7 +55,7 @@ export function Reference() { return (
-
+
From e82bb6c4100e58b4a9f99e617745a74d1fb74b1c Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 13 Jan 2026 03:38:09 +0100 Subject: [PATCH 4/5] fix: use pattern.id as title fallback --- website/src/repl/components/panel/PatternsTab.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 04f6452e5..75c019438 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -29,7 +29,7 @@ export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) { if (!isNaN(date)) { title = date.toLocaleDateString(); } else { - title = 'unnamed'; + title = pattern.id || 'unnamed'; } } From e5ab6b3c93b35973e46607c45bb071b323177bbf Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 13 Jan 2026 03:47:33 +0100 Subject: [PATCH 5/5] fix: short circuit --- website/src/repl/components/panel/PatternsTab.jsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx index 75c019438..c72ebaa30 100644 --- a/website/src/repl/components/panel/PatternsTab.jsx +++ b/website/src/repl/components/panel/PatternsTab.jsx @@ -89,12 +89,11 @@ export function PatternsTab({ context }) { const viewingPatternID = viewingPatternData?.id; const visiblePatterns = useMemo(() => { + if (!search) { + return userPatterns; + } return Object.fromEntries( Object.entries(userPatterns).filter(([_key, pattern]) => { - if (!search) { - return true; - } - const meta = getMetadata(pattern.code); // Search for specific meta keys