Skip to content

Commit

Permalink
Merge pull request #61 from ScoopInstaller/distinct-manifests-filter
Browse files Browse the repository at this point in the history
Add a new "Distinct manifests only" filter
  • Loading branch information
gpailler committed May 17, 2023
2 parents ba3ba79 + a945ced commit 319de25
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 25 deletions.
42 changes: 31 additions & 11 deletions src/components/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const SEARCH_PARAM_PAGE = 'p';
const SEARCH_PARAM_SORT_INDEX = 's';
const SEARCH_PARAM_SORT_DIRECTION = 'd';
const SEARCH_PARAM_FILTER_OFFICIALONLY = 'o';
const SEARCH_PARAM_FILTER_DISTINCTONLY = 'dm';
const SEARCH_PARAM_OPTION_BUCKETNAME = 'n';
const SEARCH_PARAM_SELECTED_RESULT = 'id';
const SEARCH_DEBOUNCE_TIME_IN_MS = 500;
Expand Down Expand Up @@ -77,10 +78,14 @@ const Search = (): JSX.Element => {
[getSearchParam]
);

const getSearchOfficialOnlyFromSearchParams = useCallback((): boolean => {
const getOfficialOnlyFromSearchParams = useCallback((): boolean => {
return getSearchParam(SEARCH_PARAM_FILTER_OFFICIALONLY, true);
}, [getSearchParam]);

const getDistinctManifestsOnlyFromSearchParams = useCallback((): boolean => {
return getSearchParam(SEARCH_PARAM_FILTER_DISTINCTONLY, true);
}, [getSearchParam]);

const getInstallBucketNameFromSearchParams = useCallback((): boolean => {
return getSearchParam(SEARCH_PARAM_OPTION_BUCKETNAME, true);
}, [getSearchParam]);
Expand Down Expand Up @@ -114,9 +119,11 @@ const Search = (): JSX.Element => {
const [currentPage, setCurrentPage] = useState<number>(getCurrentPageFromSearchParams);
const [sortIndex, setSortIndex] = useState<number>(getSortIndexFromSearchParams);
const [sortDirection, setSortDirection] = useState<SortDirection>(getSortDirectionFromSearchParams(sortIndex));
const [searchOfficialOnly, setSearchOfficialOnly] = useState<boolean>(getSearchOfficialOnlyFromSearchParams);
const [officialOnly, setOfficialOnly] = useState<boolean>(getOfficialOnlyFromSearchParams);
const [distinctManifestsOnly, setDistinctManifestsOnly] = useState<boolean>(
getDistinctManifestsOnlyFromSearchParams()
);
const [installBucketName, setInstallBucketName] = useState<boolean>(getInstallBucketNameFromSearchParams());

const [searchResults, setSearchResults] = useState<SearchResultsJson>();
const [officialRepositories, setOfficialRepositories] = useState<{ [key: string]: string }>({});
const [selectedResult, setSelectedResult] = useState<ManifestJson | null>();
Expand All @@ -139,8 +146,11 @@ const Search = (): JSX.Element => {
if (getSortDirectionFromSearchParams(getSortIndexFromSearchParams()) !== sortDirection) {
setSortIndex(getSortDirectionFromSearchParams(getSortIndexFromSearchParams()));
}
if (getSearchOfficialOnlyFromSearchParams() !== searchOfficialOnly) {
setSearchOfficialOnly(getSearchOfficialOnlyFromSearchParams());
if (getOfficialOnlyFromSearchParams() !== officialOnly) {
setOfficialOnly(getOfficialOnlyFromSearchParams());
}
if (getDistinctManifestsOnlyFromSearchParams() !== distinctManifestsOnly) {
setDistinctManifestsOnly(getDistinctManifestsOnlyFromSearchParams());
}
if (getInstallBucketNameFromSearchParams() !== installBucketName) {
setInstallBucketName(getInstallBucketNameFromSearchParams());
Expand Down Expand Up @@ -213,10 +223,18 @@ const Search = (): JSX.Element => {
[updateSearchParams]
);

const handleSearchOfficialOnlyChange = useCallback(
(newSearchOfficialOnly: boolean): void => {
updateSearchParams(SEARCH_PARAM_FILTER_OFFICIALONLY, newSearchOfficialOnly.toString(), true);
setSearchOfficialOnly(newSearchOfficialOnly);
const handleOfficialOnlyChange = useCallback(
(newOfficialOnly: boolean): void => {
updateSearchParams(SEARCH_PARAM_FILTER_OFFICIALONLY, newOfficialOnly.toString(), true);
setOfficialOnly(newOfficialOnly);
},
[updateSearchParams]
);

const handleDistinctManifestsOnlyChange = useCallback(
(newDistinctManifestsOnly: boolean): void => {
updateSearchParams(SEARCH_PARAM_FILTER_DISTINCTONLY, newDistinctManifestsOnly.toString(), true);
setDistinctManifestsOnly(newDistinctManifestsOnly);
},
[updateSearchParams]
);
Expand Down Expand Up @@ -266,8 +284,10 @@ const Search = (): JSX.Element => {
query={debouncedQuery}
sortIndex={sortIndex}
sortDirection={sortDirection}
searchOfficialOnly={searchOfficialOnly}
onSearchOfficialOnlyChange={handleSearchOfficialOnlyChange}
officialOnly={officialOnly}
onOfficialOnlyChange={handleOfficialOnlyChange}
distinctManifestsOnly={distinctManifestsOnly}
onDistinctManifestsOnlyChange={handleDistinctManifestsOnlyChange}
onResultsChange={handleResultsChange}
onSortChange={handleSortChange}
installBucketName={installBucketName}
Expand Down
53 changes: 39 additions & 14 deletions src/components/SearchProcessor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ type SearchProcessorProps = {
query: string;
sortIndex: number;
sortDirection: SortDirection;
searchOfficialOnly: boolean;
onSearchOfficialOnlyChange: (searchOfficialOnly: boolean) => void;
officialOnly: boolean;
onOfficialOnlyChange: (officialOnly: boolean) => void;
distinctManifestsOnly: boolean;
onDistinctManifestsOnlyChange: (distinctManifestsOnly: boolean) => void;
installBucketName: boolean;
onInstallBucketName: (installBucketName: boolean) => void;

resultsPerPage: number;
onResultsChange: (value?: SearchResultsJson) => void;
onSortChange: (sortIndex: number, sortDirection: SortDirection) => void;
Expand Down Expand Up @@ -92,8 +93,10 @@ const SearchProcessor = (props: SearchProcessorProps): JSX.Element => {
resultsPerPage,
sortIndex,
sortDirection,
searchOfficialOnly,
onSearchOfficialOnlyChange,
officialOnly,
onOfficialOnlyChange,
distinctManifestsOnly,
onDistinctManifestsOnlyChange,
installBucketName,
onInstallBucketName,
onResultsChange,
Expand All @@ -107,12 +110,20 @@ const SearchProcessor = (props: SearchProcessorProps): JSX.Element => {
[onSortChange]
);

const toggleSearchOfficialOnly = useCallback(
const toggleOfficialOnly = useCallback(
(e: React.MouseEvent<HTMLElement>): void => {
e.currentTarget.blur();
onSearchOfficialOnlyChange(!searchOfficialOnly);
onOfficialOnlyChange(!officialOnly);
},
[searchOfficialOnly, onSearchOfficialOnlyChange]
[officialOnly, onOfficialOnlyChange]
);

const toggleDistinctManifestsOnly = useCallback(
(e: React.MouseEvent<HTMLElement>): void => {
e.currentTarget.blur();
onDistinctManifestsOnlyChange(!distinctManifestsOnly);
},
[distinctManifestsOnly, onDistinctManifestsOnlyChange]
);

const toggleInstallBucketName = useCallback(
Expand Down Expand Up @@ -151,14 +162,23 @@ const SearchProcessor = (props: SearchProcessorProps): JSX.Element => {
throw new Error('VITE_APP_AZURESEARCH_KEY is not defined');
}

const filters: string[] = [];
if (officialOnly) {
filters.push('Metadata/OfficialRepositoryNumber eq 1');
}

if (distinctManifestsOnly) {
filters.push('Metadata/DuplicateOf eq null');
}

const url = `${VITE_APP_AZURESEARCH_URL}/search?api-version=2020-06-30`;
fetch(url, {
method: 'POST',
body: JSON.stringify({
count: true,
search: query.trim(),
searchMode: 'all',
filter: searchOfficialOnly ? 'Metadata/OfficialRepositoryNumber eq 1' : '',
filter: filters.join(' and '),
orderby: sortModes[sortIndex].OrderBy[sortDirection].join(', '),
skip: (page - 1) * resultsPerPage,
top: resultsPerPage,
Expand Down Expand Up @@ -222,7 +242,7 @@ const SearchProcessor = (props: SearchProcessorProps): JSX.Element => {
fetchDataAsync(abortControllerRef.current.signal);

return () => abortControllerRef.current.abort();
}, [query, page, sortIndex, sortDirection, searchOfficialOnly, resultsPerPage, onResultsChange]);
}, [query, page, sortIndex, sortDirection, officialOnly, distinctManifestsOnly, resultsPerPage, onResultsChange]);

const SortIcon = (sortIconProps: { currentSortIndex: number } & IconBaseProps): JSX.Element => {
const { currentSortIndex, ...sortIconRest } = sortIconProps;
Expand All @@ -240,7 +260,7 @@ const SearchProcessor = (props: SearchProcessorProps): JSX.Element => {

const formatSortingAndFiltering = () => {
const currentSort = sortModes[sortIndex].DisplayName;
const currentFilter = searchOfficialOnly ? 'Official buckets only' : 'All buckets';
const currentFilter = officialOnly ? 'Official buckets only' : 'All buckets';
return `${currentSort}, ${currentFilter}`;
};

Expand Down Expand Up @@ -272,15 +292,20 @@ const SearchProcessor = (props: SearchProcessorProps): JSX.Element => {
))}
<Dropdown.Divider />
<Dropdown.Header>Filtering</Dropdown.Header>
<Dropdown.Item as={Button} onClick={(e) => toggleSearchOfficialOnly(e)}>
<Dropdown.Item as={Button} onClick={(e) => toggleOfficialOnly(e)}>
<Form.Switch className="form-switch-sm">
<Form.Switch.Input checked={searchOfficialOnly} />
<Form.Switch.Input checked={officialOnly} />
<Form.Switch.Label>
Official buckets only <BucketTypeIcon className="ms-1" official showTooltip={false} />
</Form.Switch.Label>
</Form.Switch>
</Dropdown.Item>

<Dropdown.Item as={Button} onClick={(e) => toggleDistinctManifestsOnly(e)}>
<Form.Switch className="form-switch-sm">
<Form.Switch.Input checked={distinctManifestsOnly} />
<Form.Switch.Label>Distinct manifests only</Form.Switch.Label>
</Form.Switch>
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Header>Option</Dropdown.Header>
<Dropdown.Item as={Button} onClick={(e) => toggleInstallBucketName(e)}>
Expand Down

0 comments on commit 319de25

Please sign in to comment.