Skip to content

Commit a393474

Browse files
author
ci-bot
committed
fix search to filter and filter by tag. fix order of components
1 parent e0bbc31 commit a393474

File tree

10 files changed

+167
-151
lines changed

10 files changed

+167
-151
lines changed

apps/remix-ide/src/app.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ class AppComponent {
269269
this.gistHandler = new GistHandler()
270270
// ----------------- theme service ---------------------------------
271271
this.themeModule = new ThemeModule()
272+
this.templateExplorerModal = new TemplateExplorerModalPlugin(this.themeModule)
272273
// ----------------- locale service ---------------------------------
273274
this.localeModule = new LocaleModule()
274275
Registry.getInstance().put({ api: this.themeModule, name: 'themeModule' })
@@ -403,7 +404,7 @@ class AppComponent {
403404

404405
const templateSelection = new TemplatesSelectionPlugin()
405406

406-
const templateExplorerModal = new TemplateExplorerModalPlugin()
407+
const templateExplorerModal = this.templateExplorerModal
407408

408409
const walletConnect = new WalletConnect()
409410

@@ -460,10 +461,10 @@ class AppComponent {
460461
pluginStateLogger,
461462
matomo,
462463
templateSelection,
463-
templateExplorerModal,
464464
scriptRunnerUI,
465465
remixAI,
466466
remixAiAssistant,
467+
templateExplorerModal,
467468
walletConnect
468469
])
469470

@@ -616,6 +617,7 @@ class AppComponent {
616617
await this.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
617618
await this.appManager.activatePlugin(['topbar'])
618619
await this.appManager.activatePlugin(['statusBar'])
620+
// await this.appManager.activatePlugin(['remix-template-explorer-modal'])
619621
await this.appManager.activatePlugin(['bottomBar'])
620622
await this.appManager.activatePlugin(['sidePanel']) // activating host plugin separately
621623
await this.appManager.activatePlugin(['pinnedPanel'])

apps/remix-ide/src/app/plugins/remix-template-explorer-modal.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { AppAction, AppState } from '@remix-ui/app'
44
import { PluginViewWrapper } from '@remix-ui/helper'
55
import { Plugin } from '@remixproject/engine'
66
import { EventEmitter } from 'events'
7-
import { RemixUiTemplateExplorerModal, RemixUiTemplateExplorerModalProps } from 'libs/remix-ui/template-explorer-modal/src/lib/remix-ui-template-explorer-modal'
7+
import { ThemeModule } from '../tabs/theme-module'
8+
import { TemplateExplorerProvider } from 'libs/remix-ui/template-explorer-modal/context/template-explorer-context'
89

910
const pluginProfile = {
1011
name: 'remix-template-explorer-modal',
@@ -18,16 +19,20 @@ export class TemplateExplorerModalPlugin extends Plugin {
1819
dispatch: React.Dispatch<any> = () => { }
1920
event: any
2021
appStateDispatch: any
21-
constructor() {
22+
theme: any = null
23+
constructor(theme: ThemeModule) {
2224
super(pluginProfile)
2325
this.element = document.createElement('div')
24-
this.element.setAttribute('id', 'remix-template-explorer-modal')
26+
this.element.setAttribute('id', 'template-explorer-modal')
2527
this.dispatch = () => { }
2628
this.event = new EventEmitter()
29+
this.theme = theme
2730
}
2831

2932
async onActivation(): Promise<void> {
30-
33+
this.on('theme', 'themeChanged', (theme: any) => {
34+
this.theme = theme
35+
})
3136
}
3237

3338
onDeactivation(): void {
@@ -53,17 +58,13 @@ export class TemplateExplorerModalPlugin extends Plugin {
5358

5459
renderComponent(): void {
5560
this.dispatch({
56-
element: this.element,
61+
plugins: this,
5762
})
5863
}
5964

60-
updateComponent(state: RemixUiTemplateExplorerModalProps, appState: AppState) {
65+
updateComponent() {
6166
return (
62-
<RemixUiTemplateExplorerModal
63-
appState={appState}
64-
dispatch={this.dispatch}
65-
plugin={this}
66-
/>
67+
<TemplateExplorerProvider plugin={this} />
6768
)
6869
}
6970
}

libs/remix-ui/app/src/lib/remix-app/remix-app.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { appInitialState } from './state/app'
1616
import isElectron from 'is-electron'
1717
import { desktopConnectionType } from '@remix-api'
1818
import { RemixUiTemplateExplorerModal } from 'libs/remix-ui/template-explorer-modal/src/lib/remix-ui-template-explorer-modal'
19+
import { TemplateExplorerProvider } from 'libs/remix-ui/template-explorer-modal/context/template-explorer-context'
1920

2021
declare global {
2122
interface Window {
@@ -233,7 +234,9 @@ const RemixApp = (props: IRemixAppUi) => {
233234
</div>
234235
<AppDialogs></AppDialogs>
235236
<DialogViewPlugin></DialogViewPlugin>
236-
{appState.genericModalState.showModal && <RemixUiTemplateExplorerModal appState={appState} dispatch={appStateDispatch} plugin={props.app.templateExplorerModal}></RemixUiTemplateExplorerModal>}
237+
{appState.genericModalState.showModal &&
238+
<TemplateExplorerProvider plugin={props.app.templateExplorerModal}></TemplateExplorerProvider>
239+
}
237240
</AppProvider>
238241
</onLineContext.Provider>
239242
</platformContext.Provider>

libs/remix-ui/template-explorer-modal/context/template-explorer-context.tsx

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
1+
/* eslint-disable @nrwl/nx/enforce-module-boundaries */
12
import React, { createContext, useContext, useEffect, useMemo, useReducer, useState } from 'react'
23
import { TemplateCategory, TemplateExplorerContextType, TemplateExplorerWizardAction, TemplateItem } from '../types/template-explorer-types'
34
import { initialState, templateExplorerReducer } from '../reducers/template-explorer-reducer'
45
import { metadata, templatesRepository } from '../src/utils/helpers'
56
import { AppContext } from '@remix-ui/app'
7+
import { TemplateExplorerModalPlugin } from 'apps/remix-ide/src/app/plugins/remix-template-explorer-modal'
8+
import { RemixUiTemplateExplorerModal } from '@remix-ui/template-explorer-modal'
69

710
export const TemplateExplorerContext = createContext<TemplateExplorerContextType>({} as any)
811

9-
export const TemplateExplorerProvider = ({ children }: { children: React.ReactNode }) => {
12+
export const TemplateExplorerProvider = (props: { plugin: TemplateExplorerModalPlugin }) => {
1013
// const [templateRepository, setTemplateRepository] = useState<TemplateCategory[]>([])
1114
// const [metadata, setMetadata] = useState<any[]>([])
1215
// const [selectedTag, setSelectedTag] = useState<string | null>(null)
1316
// const [recentBump, setRecentBump] = useState<number>(0)
1417
const [state, dispatch] = useReducer(templateExplorerReducer, initialState)
1518
const appContext = useContext(AppContext)
19+
const { plugin } = props
1620

1721
useEffect(() => {
18-
dispatch({ type: TemplateExplorerWizardAction.SET_METADATA, payload: metadata })
1922
dispatch({ type: TemplateExplorerWizardAction.SET_TEMPLATE_REPOSITORY, payload: templatesRepository })
23+
}, [])
2024

25+
useEffect(() => {
26+
dispatch({ type: TemplateExplorerWizardAction.SET_METADATA, payload: metadata })
2127
}, [])
2228

29+
const setSearchTerm = (term: string) => {
30+
console.log('setSearchTerm', { term, state })
31+
dispatch({ type: TemplateExplorerWizardAction.SET_SEARCH_TERM, payload: term })
32+
}
33+
2334
const allTags = useMemo((): string[] => {
2435
const tags: string[] = []
2536

@@ -42,7 +53,6 @@ export const TemplateExplorerProvider = ({ children }: { children: React.ReactNo
4253
return tags.sort()
4354
}, [])
4455

45-
// Recent templates (before filteredTemplates so it can be referenced later)
4656
const recentTemplates = useMemo((): TemplateItem[] => {
4757
try {
4858
const raw = typeof window !== 'undefined' ? window.localStorage.getItem(RECENT_KEY) : null
@@ -71,21 +81,33 @@ export const TemplateExplorerProvider = ({ children }: { children: React.ReactNo
7181
}
7282
}, [state.selectedTag, state.recentBump])
7383

74-
// Filter templates based on selected tag
7584
const filteredTemplates = useMemo((): TemplateCategory[] => {
76-
if (!state.selectedTag || !state.templateRepository || !Array.isArray(state.templateRepository)) {
77-
return state.templateRepository as TemplateCategory[] || []
78-
}
85+
const repo = (state.templateRepository as TemplateCategory[]) || []
86+
if (!Array.isArray(repo)) return []
87+
88+
const searchTerm = (state.searchTerm || '').trim().toLowerCase()
89+
const selectedTag = state.selectedTag
90+
91+
return repo
92+
.map((template: TemplateCategory) => ({
93+
...template,
94+
items: (template.items || []).filter((item: TemplateItem) => {
95+
// Filter by search term
96+
const matchesSearch = !searchTerm ||
97+
(item.displayName || item.value || '').toLowerCase().includes(searchTerm)
7998

80-
return (state.templateRepository as TemplateCategory[]).map((template: any) => ({
81-
...template,
82-
items: template.items.filter((item: any) =>
83-
item && item.tagList && Array.isArray(item.tagList) && item.tagList.includes(state.selectedTag)
99+
// Filter by selected tag
100+
const matchesTag = !selectedTag ||
101+
(item.tagList && item.tagList.includes(selectedTag))
102+
103+
return matchesSearch && matchesTag
104+
})
105+
}))
106+
.filter((template: TemplateCategory) =>
107+
template && template.items && template.items.length > 0
84108
)
85-
})).filter((template: any) => template && template.items && template.items.length > 0)
86-
}, [state.selectedTag])
109+
}, [state.selectedTag, state.searchTerm, state.templateRepository])
87110

88-
// Dedupe templates across the whole page and avoid showing ones already in recents
89111
const dedupedTemplates = useMemo((): TemplateCategory[] => {
90112
const recentSet = new Set<string>((recentTemplates || []).map((t: any) => t && t.value))
91113
const seen = new Set<string>()
@@ -131,9 +153,15 @@ export const TemplateExplorerProvider = ({ children }: { children: React.ReactNo
131153
}
132154
}
133155

156+
const contextValue = { templateRepository: state.templateRepository, metadata: state.metadata, selectedTag: state.selectedTag, recentTemplates, filteredTemplates, dedupedTemplates, handleTagClick, clearFilter, addRecentTemplate, RECENT_KEY, allTags, plugin, setSearchTerm }
157+
134158
return (
135-
<TemplateExplorerContext.Provider value={{ templateRepository: state.templateRepository, metadata: state.metadata, selectedTag: state.selectedTag, recentTemplates, filteredTemplates, dedupedTemplates, handleTagClick, clearFilter, addRecentTemplate, RECENT_KEY, allTags }}>
136-
{children}
159+
<TemplateExplorerContext.Provider value={contextValue}>
160+
<RemixUiTemplateExplorerModal
161+
appState={appContext.appState}
162+
dispatch={appContext.appStateDispatch}
163+
plugin={plugin}
164+
/>
137165
</TemplateExplorerContext.Provider>
138166
)
139167
}

libs/remix-ui/template-explorer-modal/reducers/template-explorer-reducer.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import React from 'react'
2-
import { MetadataType, TemplateExplorerWizardAction, TemplateExplorerWizardState, TemplateExplorerWizardSteps } from '../types/template-explorer-types'
2+
import { MetadataType, TemplateExplorerWizardAction, TemplateExplorerWizardState, TemplateRepository } from '../types/template-explorer-types'
33
import { metadata, templatesRepository } from '../src/utils/helpers'
44

55
export const initialState: TemplateExplorerWizardState = {
6-
steps: TemplateExplorerWizardSteps.SELECT_TEMPLATE,
76
workspaceTemplateChosen: '',
87
workspaceTemplateGroupChosen: '',
98
workspaceName: '',
@@ -13,15 +12,18 @@ export const initialState: TemplateExplorerWizardState = {
1312
workspaceGeneratedWithAi: false,
1413
searchTerm: '',
1514
metadata: metadata as MetadataType,
16-
templateRepository: templatesRepository,
17-
selectedTag: null
15+
templateRepository: templatesRepository as TemplateRepository || [],
16+
selectedTag: null,
17+
setSearchTerm: (term: string) => {}
1818
}
1919

2020
export const templateExplorerReducer = (state: TemplateExplorerWizardState, action: any) => {
2121
switch (action.type) {
22-
case TemplateExplorerWizardAction.SET_WORKSPACE_TEMPLATE:
23-
return action.payload
24-
case TemplateExplorerWizardAction.SET_WORKSPACE_TEMPLATE_WIZARD_STEP:
22+
case TemplateExplorerWizardAction.SET_TEMPLATE_REPOSITORY:
23+
return { ...state, templateRepository: action.payload }
24+
case TemplateExplorerWizardAction.SET_METADATA:
25+
return { ...state, metadata: action.payload }
26+
case TemplateExplorerWizardAction.SELECT_TEMPLATE:
2527
return action.payload
2628
case TemplateExplorerWizardAction.SET_WORKSPACE_TEMPLATE_GROUP:
2729
return action.payload
@@ -43,7 +45,19 @@ export const templateExplorerReducer = (state: TemplateExplorerWizardState, acti
4345
case TemplateExplorerWizardAction.CLEAR_SELECTED_TAG: {
4446
return { ...state, selectedTag: null }
4547
}
48+
case TemplateExplorerWizardAction.SET_SEARCH_TERM: {
49+
return { ...state, searchTerm: action.payload }
50+
}
4651
default:
4752
return state
4853
}
4954
}
55+
56+
function doTemplateSearch (searchTerm: string, repo: TemplateRepository) {
57+
if (!searchTerm) return repo
58+
return repo.filter(template => template.name.toLowerCase().includes(searchTerm.toLowerCase()))
59+
.map(template => ({
60+
...template,
61+
items: template.items.filter(item => item.displayName.toLowerCase().includes(searchTerm.toLowerCase()))
62+
}))
63+
}

libs/remix-ui/template-explorer-modal/src/components/template-explorer-body.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,49 @@
1-
import React from 'react'
1+
import React, { useContext } from 'react'
22
import { TopCard } from './topCard'
33
import { TopCardProps } from '../../types/template-explorer-types'
44
import { TemplateExplorer } from './template-explorer'
55
import { TopCards } from './topCards'
6+
import { TemplateExplorerContext } from '../../context/template-explorer-context'
67

78
export interface TemplateExplorerBodyProps {
8-
topCards: TopCardProps[]
99
plugin: any
1010
}
1111

12-
export function TemplateExplorerBody({ topCards, plugin }: TemplateExplorerBodyProps) {
12+
export function TemplateExplorerBody({ plugin }: TemplateExplorerBodyProps) {
13+
const { selectedTag, allTags, handleTagClick, clearFilter } = useContext(TemplateExplorerContext)
14+
15+
const filterTheseTags = tag => tag !== 'Circom' && tag !== 'All' && tag !== 'Noir' && tag !== 'AI'
1316
return (
1417
<section>
1518
<TopCards />
1619
<div className="body overflow-y-hidden">
1720
<label className="text-dark fs-5">Workspace Templates</label>
18-
<TemplateExplorer plugin={plugin} />
21+
{/* Tag Filter Row */}
22+
<div className="">
23+
<div className="d-flex flex-wrap align-items-center gap-2">
24+
25+
{allTags?.filter(filterTheseTags)?.reverse()?.map((tag: any) => (
26+
<span
27+
key={tag as any}
28+
className={`badge rounded-pill p-2 fw-light ${selectedTag === tag ? 'badge rounded-pill text-info p-2 fw-light' : 'badge rounded-pill text-bg-light p-2 fw-light'}`}
29+
onClick={() => handleTagClick(tag as any)}
30+
>
31+
{tag as any}
32+
</span>
33+
))}
34+
{selectedTag && (
35+
<small>
36+
<span
37+
className="p-0 ms-2 text-warning fw-light"
38+
onClick={clearFilter}
39+
>
40+
Clear filter
41+
</span>
42+
</small>
43+
)}
44+
</div>
45+
</div>
46+
<TemplateExplorer />
1947
</div>
2048
</section>
2149
)

0 commit comments

Comments
 (0)