diff --git a/server/application/application.go b/server/application/application.go index 09fe4a4adb628..a5198765b0318 100644 --- a/server/application/application.go +++ b/server/application/application.go @@ -2817,6 +2817,7 @@ func (s *Server) getAppFilter(ctx context.Context, q *application.ApplicationQue } if len(q.GetClusters()) > 0 { + matched := false for _, item := range q.GetClusters() { url := "" name := "" @@ -2828,12 +2829,17 @@ func (s *Server) getAppFilter(ctx context.Context, q *application.ApplicationQue } else { name = item } - if app.Spec.Destination.Server != "" && app.Spec.Destination.Server != url { - return false - } else if app.Spec.Destination.Name != "" && app.Spec.Destination.Name != name { - return false + if app.Spec.Destination.Server != "" && app.Spec.Destination.Server == url { + matched = true + break + } else if app.Spec.Destination.Name != "" && app.Spec.Destination.Name == name { + matched = true + break } } + if !matched { + return false + } } if len(q.GetNamespaces()) > 0 && !sets.NewString(q.GetNamespaces()...).Has(app.Spec.Destination.Namespace) { diff --git a/ui/src/app/applications/components/application-details/application-details-app-dropdown.tsx b/ui/src/app/applications/components/application-details/application-details-app-dropdown.tsx index eea0388f21b6d..f7d78f6ed5713 100644 --- a/ui/src/app/applications/components/application-details/application-details-app-dropdown.tsx +++ b/ui/src/app/applications/components/application-details/application-details-app-dropdown.tsx @@ -35,13 +35,9 @@ export const ApplicationsDetailsAppDropdown = (props: {appName: string}) => { } /> - services.applications.list({fields: ['items.metadata.name', 'items.metadata.namespace']})}> + services.applications.list({fields: ['items.metadata.name', 'items.metadata.namespace'], search: appFilter, limit: 100})}> {apps => apps.items - .filter(app => { - return appFilter.length === 0 || app.metadata.name.toLowerCase().includes(appFilter.toLowerCase()); - }) - .slice(0, 100) // take top 100 results after filtering to avoid performance issues .map(app => (
  • ctx.navigation.goto(getAppUrl(app))}> {app.metadata.name} {app.metadata.name === props.appName && ' (current)'} diff --git a/ui/src/app/applications/components/applications-list/applications-list.tsx b/ui/src/app/applications/components/applications-list/applications-list.tsx index 608bbad6b8494..88537112dc9ef 100644 --- a/ui/src/app/applications/components/applications-list/applications-list.tsx +++ b/ui/src/app/applications/components/applications-list/applications-list.tsx @@ -110,7 +110,7 @@ function loadApplications(q: AppsQuery): Observable<{applications: models.Applic ); } -const ViewPref = ({children}: {children: (pref: AppsListPreferences & {page: number; pageSize: number; search: string}) => React.ReactNode}) => ( +const ViewPref = ({children}: {children: (data: {pref: AppsListPreferences & {page: number; pageSize: number; search: string}, healthBarPrefs: HealthStatusBarPreferences}) => React.ReactNode}) => ( {q => ( - {pref => children(pref)} + {pref => children({pref, healthBarPrefs: pref.statusBarView || ({} as HealthStatusBarPreferences)})} )} @@ -191,8 +191,8 @@ function tryJsonParse(input: string) { } } -const SearchBar = (props: {content: string; ctx: ContextApis; apps: models.Application[]}) => { - const {content, ctx, apps} = {...props}; +const SearchBar = (props: {content: string; ctx: ContextApis}) => { + const {content, ctx} = {...props}; const searchBar = React.useRef(null); @@ -236,48 +236,52 @@ const SearchBar = (props: {content: string; ctx: ContextApis; apps: models.Appli }); return ( - ( -
    - { - if (searchBar.current) { - searchBar.current.querySelector('input').focus(); - } - }} - /> - { - e.target.select(); - if (inputProps.onFocus) { - inputProps.onFocus(e); - } - }} - style={{fontSize: '14px'}} - className='argo-field' - placeholder='Search applications...' - /> -
    /
    - {content && setValue(null)} style={{cursor: 'pointer', marginLeft: '5px'}} />} -
    - )} - wrapperProps={{className: 'applications-list__search-wrapper'}} - renderItem={item => ( - - {item.label} - + services.applications.list({fields: ['items.metadata.name'], search: value, limit: 100}).then(res => res.items)}> + {apps => ( + ( +
    + { + if (searchBar.current) { + searchBar.current.querySelector('input').focus(); + } + }} + /> + { + e.target.select(); + if (inputProps.onFocus) { + inputProps.onFocus(e); + } + }} + style={{fontSize: '14px'}} + className='argo-field' + placeholder='Search applications...' + /> +
    /
    + {content && setValue(null)} style={{cursor: 'pointer', marginLeft: '5px'}} />} +
    + )} + wrapperProps={{className: 'applications-list__search-wrapper'}} + renderItem={item => ( + + {item.label} + + )} + onSelect={val => { + ctx.navigation.goto(`./${val}`); + }} + onChange={e => setValue(e.target.value)} + value={value || ''} + items={apps.map(app => AppUtils.appQualifiedName(app, useAuthSettingsCtx?.appsInAnyNamespaceEnabled))} + /> )} - onSelect={val => { - ctx.navigation.goto(`./${val}`); - }} - onChange={e => setValue(e.target.value)} - value={value || ''} - items={apps.map(app => AppUtils.appQualifiedName(app, useAuthSettingsCtx?.appsInAnyNamespaceEnabled))} - /> +
    ); }; @@ -413,13 +417,89 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => { {ctx => ( - {pref => ( + {({pref, healthBarPrefs}) => ( + + {q => } + + + +
    + { + ctx.navigation.goto('.', {view: Tiles}); + services.viewPreferences.updatePreferences({appList: {...pref, view: Tiles}}); + }} + /> + { + ctx.navigation.goto('.', {view: List}); + services.viewPreferences.updatePreferences({appList: {...pref, view: List}}); + }} + /> + { + ctx.navigation.goto('.', {view: Summary}); + services.viewPreferences.updatePreferences({appList: {...pref, view: Summary}}); + }} + /> +
    + + ), + actionMenu: { + items: [ + { + title: 'New App', + iconClassName: 'fa fa-plus', + qeId: 'applications-list-button-new-app', + action: () => ctx.navigation.goto('.', {new: '{}'}, {replace: true}) + }, + { + title: 'Sync Apps', + iconClassName: 'fa fa-sync', + action: () => ctx.navigation.goto('.', {syncApps: true}, {replace: true}) + }, + { + title: 'Refresh Apps', + iconClassName: 'fa fa-redo', + action: () => ctx.navigation.goto('.', {refreshApps: true}, {replace: true}) + } + ] + } + }} + /> ) => { const healthBarPrefs = pref.statusBarView || ({} as HealthStatusBarPreferences); return ( - - {q => } - - - -
    - { - ctx.navigation.goto('.', {view: Tiles}); - services.viewPreferences.updatePreferences({appList: {...pref, view: Tiles}}); - }} - /> - { - ctx.navigation.goto('.', {view: List}); - services.viewPreferences.updatePreferences({appList: {...pref, view: List}}); - }} - /> - { - ctx.navigation.goto('.', {view: Summary}); - services.viewPreferences.updatePreferences({appList: {...pref, view: Summary}}); - }} - /> -
    -
    - ), - actionMenu: { - items: [ - { - title: 'New App', - iconClassName: 'fa fa-plus', - qeId: 'applications-list-button-new-app', - action: () => ctx.navigation.goto('.', {new: '{}'}, {replace: true}) - }, - { - title: 'Sync Apps', - iconClassName: 'fa fa-sync', - action: () => ctx.navigation.goto('.', {syncApps: true}, {replace: true}) - }, - { - title: 'Refresh Apps', - iconClassName: 'fa fa-redo', - action: () => ctx.navigation.goto('.', {refreshApps: true}, {replace: true}) - } - ] - } - }} - />
    {stats.total === 0 && !isFiltered(pref) ? (