Skip to content

Commit

Permalink
Merge pull request #161 from vespa-engine/laura/VESPANG-597
Browse files Browse the repository at this point in the history
convert the namespaces in search to tabs and add an all option
  • Loading branch information
lperry25 authored Nov 22, 2024
2 parents 41ff4a9 + 8fabb14 commit 978d614
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 32 deletions.
1 change: 1 addition & 0 deletions src/App/libs/provider/namespaces.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const ALL_NAMESPACES = Object.freeze([
{ id: 'all', name: 'All', icon: 'check' },
{ id: 'open-p', name: 'Documentation', icon: 'book' },
{ id: 'cloud-p', name: 'Cloud Documentation', icon: 'cloud' },
{ id: 'vespaapps-p', name: 'Sample Apps', icon: 'vial' },
Expand Down
17 changes: 6 additions & 11 deletions src/App/libs/provider/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ export function createStore(set) {
};
}

function toggleOption(allOptions, current, item) {
return allOptions
.map(({ id }) => id)
.filter((id) => (id === item) !== current.includes(id));
}

function setFilters(state, filters) {
return Object.entries(filters).reduce((result, [key, value]) => {
switch (key) {
Expand All @@ -51,12 +45,13 @@ function setNamespaces(state, namespaces) {
}

function toggleNamespace(state, namespace) {
let namespaces = toggleOption(ALL_NAMESPACES, state.namespaces, namespace);
if (namespaces.length === 0)
namespaces = ALL_NAMESPACES.map(({ id }) => id).filter(
(id) => id !== namespace,
if (namespace === 'all') {
return setNamespaces(
state,
ALL_NAMESPACES.map(({ id }) => id),
);
return setNamespaces(state, namespaces);
}
return setNamespaces(state, [namespace]);
}

function summaryAppend(state, summary) {
Expand Down
10 changes: 8 additions & 2 deletions src/App/libs/provider/url-params.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { isEqual } from 'lodash';
import { NAMESPACES_BY_ID } from 'App/libs/provider/namespaces';

const DEFAULT_NAMESPACES = Object.freeze(Object.keys(NAMESPACES_BY_ID));
const DEFAULT_NAMESPACES = Object.freeze(Object.keys(NAMESPACES_BY_ID)).filter(
(id) => id !== 'all',
);

const qpQuery = 'query';
const qpNamespace = 'namespace';
Expand All @@ -18,7 +20,11 @@ export function createUrlParams({ query, namespaces }) {
const queryParts = [];
if (query.length > 0)
queryParts.push(`${qpQuery}=${encodeURIComponent(query)}`);
if (namespaces.length > 0 && !isEqual(namespaces, DEFAULT_NAMESPACES))
if (namespaces.length > 0 && !isEqual(namespaces, DEFAULT_NAMESPACES)) {
if (namespaces.includes('all')) {
namespaces = namespaces.filter((id) => id !== 'all');
}
queryParts.push(`${qpNamespace}=` + namespaces.join(','));
}
return queryParts.length > 0 ? '?' + queryParts.join('&') : '';
}
58 changes: 39 additions & 19 deletions src/App/pages/search/search-sources.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,54 @@
import React from 'react';
import { Button, Group } from '@mantine/core';
import React, { useEffect, useRef } from 'react';
import { ScrollArea, Tabs } from '@mantine/core';
import { useLocation } from 'react-router-dom';
import { ALL_NAMESPACES, useSearchContext } from 'App/libs/provider';
import { Icon } from 'App/components';
import { useMobile } from 'App/hooks';
import { parseUrlParams } from 'App/libs/provider/url-params';

function Source({ id, icon, name }) {
function Source({ id, icon, name, selectedTab }) {
const toggleNamespace = useSearchContext((ctx) => ctx.toggleNamespace);
const selected = useSearchContext((ctx) => ctx.namespaces.includes(id));
const isMobile = useMobile();
const tabRef = useRef(null);

useEffect(() => {
if (selectedTab === id) {
tabRef?.current?.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
}
}, [id, selectedTab]);

return (
<Button
leftSection={<Icon name={icon} />}
color={selected ? 'green' : 'gray'}
variant={selected ? 'filled' : 'subtle'}
<Tabs.Tab
value={id}
onClick={() => toggleNamespace(id)}
size={isMobile ? 'compact-xs' : 'xs'}
radius="xl"
leftSection={<Icon name={icon} />}
ref={tabRef}
>
{name}
</Button>
</Tabs.Tab>
);
}

export function SearchSources() {
const isMobile = useMobile();
const location = useLocation();
const { namespaces } = parseUrlParams(location.search);
const defaultValue = namespaces?.length === 1 ? namespaces[0] : 'all';
return (
<Group justify="center" gap={isMobile ? 'xs' : 'md'}>
{ALL_NAMESPACES.map(({ id, name, icon }) => (
<Source key={id} id={id} name={name} icon={icon} />
))}
</Group>
<ScrollArea h="40">
<Tabs defaultValue={defaultValue}>
<Tabs.List style={{ flexWrap: 'nowrap' }}>
{ALL_NAMESPACES.map(({ id, name, icon }) => (
<Source
key={id}
id={id}
name={name}
icon={icon}
selectedTab={defaultValue}
/>
))}
</Tabs.List>
</Tabs>
</ScrollArea>
);
}
1 change: 1 addition & 0 deletions src/App/styles/icons/fa-icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export {
faExternalLink,
faExternalLinkSquare,
faCode,
faCheck,
} from '@fortawesome/free-solid-svg-icons';
export {
faClipboard,
Expand Down

0 comments on commit 978d614

Please sign in to comment.