From dd66ee3e7412cee0a16235854440a896cfcecb72 Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Mon, 11 Sep 2023 09:14:06 +0200 Subject: [PATCH 01/82] Issue #568: fix message filter horizontal and css --- .../src/components/FiltersHorizontal.tsx | 559 ++++++++++-------- .../src/components/FiltersMobile.tsx | 6 + .../search-frontend/src/embeddable/Main.tsx | 2 + 3 files changed, 307 insertions(+), 260 deletions(-) diff --git a/js-packages/search-frontend/src/components/FiltersHorizontal.tsx b/js-packages/search-frontend/src/components/FiltersHorizontal.tsx index b3ef763b0..57bea73be 100644 --- a/js-packages/search-frontend/src/components/FiltersHorizontal.tsx +++ b/js-packages/search-frontend/src/components/FiltersHorizontal.tsx @@ -69,6 +69,8 @@ function FiltersHorizontal({ const [filterSelect, setFilterSelect] = React.useState>(searchQuery); + const [haveValue, setHaveValue] = React.useState(false); + const handleCheckboxChange = (event: any, token: SearchToken) => { const isChecked = event.target.checked; const newFilter = { @@ -88,7 +90,6 @@ function FiltersHorizontal({ } }; const { t } = useTranslation(); - return (
-
- - -
+ align-items: center; + gap: 3px; + @media (max-width: 480px) { + background: white; + border: 1px solid #d6012e; + width: 100%; + height: auto; + margin-top: 20px; + color: black; + border-radius: 50px; + display: flex; + justify-content: center; + color: var(--red-tones-500, #c0272b); + text-align: center; + font-size: 16px; + font-style: normal; + font-weight: 700; + line-height: normal; + align-items: center; + } + `} + onClick={() => { + onConfigurationChange({ filterTokens: [] }); + onConfigurationChangeExt && onConfigurationChangeExt(); + }} + > +
{t("remove-filters")}
+ + + + + )}
); @@ -232,6 +241,8 @@ function FiltersHorizontal({ }, unknown >, + haveValue: boolean, + setHaveValue: any, ): JSX.Element { const [isOpen, setIsOpen] = React.useState(true); const resultValue = suggestions.data?.pages || []; @@ -241,176 +252,179 @@ function FiltersHorizontal({ searchQuery, suggestion.id, ); + if (filters.length === 0) return
; + React.useEffect(() => { + setHaveValue(true); + }, []); return ( - {index !== 0 && ( -
- )} -
-
- {suggestion.name} -
- -
- - {isOpen && - filters.map((token: any, index: number) => { - const asSearchToken = mapSuggestionToSearchToken(token, true); - const checked = filterSelect.some((element) => { - return ( - element.values && - element.values[0] === token.value && - "goToSuggestion" in element - ); - }); - return ( - -
- - handleCheckboxChange(event, asSearchToken) - } - css={css` - width: 14px; - appearance: none; - min-width: 15px; - min-height: 15px; - border-radius: 4px; - border: 2px solid #ccc; - background-color: ${checked - ? "var(--openk9-embeddable-search--secondary-active-color)" - : "#fff"}; - background-size: 100%; - background-position: center; - background-repeat: no-repeat; - cursor: pointer; - margin-right: 10px; - `} - /> - -
-
- ); - })} -
- {suggestions.hasNextPage && ( -
- -
+
+ {suggestion.name} +
+ + + + {isOpen && + filters.map((token: any, index: number) => { + const asSearchToken = mapSuggestionToSearchToken(token, true); + const checked = filterSelect.some((element) => { + return ( + element.values && + element.values[0] === token.value && + "goToSuggestion" in element + ); + }); + return ( + +
+ + handleCheckboxChange(event, asSearchToken) + } + css={css` + width: 14px; + appearance: none; + min-width: 15px; + min-height: 15px; + border-radius: 4px; + border: 2px solid #ccc; + background-color: ${checked + ? "var(--openk9-embeddable-search--secondary-active-color)" + : "#fff"}; + background-size: 100%; + background-position: center; + background-repeat: no-repeat; + cursor: pointer; + margin-right: 10px; + `} + /> + +
+
+ ); + })} +
+ {suggestions.hasNextPage && ( +
+ +
+ )} +
)} ); @@ -503,3 +517,28 @@ export function useInfiniteSuggestions( return suggestionCategories; } + +function NoFilters() { + const { t } = useTranslation(); + + return ( +
+
+ +

{t("no-filters")}

+
+
+ ); +} diff --git a/js-packages/search-frontend/src/components/FiltersMobile.tsx b/js-packages/search-frontend/src/components/FiltersMobile.tsx index 400c9ad37..81c8f6f1e 100644 --- a/js-packages/search-frontend/src/components/FiltersMobile.tsx +++ b/js-packages/search-frontend/src/components/FiltersMobile.tsx @@ -24,6 +24,8 @@ export type FiltersMobileProps = { setIsVisibleFilters: | React.Dispatch> | undefined; + language: string; + sortAfterKey: string; }; function FiltersMobile({ dynamicFilters, @@ -35,6 +37,8 @@ function FiltersMobile({ configuration, isVisibleFilters, setIsVisibleFilters, + language, + sortAfterKey, }: FiltersMobileProps) { const componet = ( @@ -116,6 +120,8 @@ function FiltersMobile({ filtersSelect={configuration.filterTokens} sort={sort} dynamicFilters={dynamicFilters} + language={language} + sortAfterKey={sortAfterKey} /> ); diff --git a/js-packages/search-frontend/src/embeddable/Main.tsx b/js-packages/search-frontend/src/embeddable/Main.tsx index 311464b8b..d29972792 100644 --- a/js-packages/search-frontend/src/embeddable/Main.tsx +++ b/js-packages/search-frontend/src/embeddable/Main.tsx @@ -325,6 +325,8 @@ export function Main({ configuration={configuration} isVisibleFilters={configuration.filtersMobile?.isVisible || false} setIsVisibleFilters={configuration.filtersMobile?.setIsVisible} + language={languageSelect} + sortAfterKey={sortAfterKey} /> , configuration.filtersMobile?.element !== undefined From 37ee7e0d8a2fe5b4dbe2c0bd4d851cf9122532ea Mon Sep 17 00:00:00 2001 From: Mirko Zizzari Date: Mon, 11 Sep 2023 11:46:59 +0200 Subject: [PATCH 02/82] Issue #571: load first level doctypes --- .../service/DocTypeFieldService.java | 151 ++++++++---------- 1 file changed, 67 insertions(+), 84 deletions(-) diff --git a/core/app/datasource/src/main/java/io/openk9/datasource/service/DocTypeFieldService.java b/core/app/datasource/src/main/java/io/openk9/datasource/service/DocTypeFieldService.java index 05611309e..aca847b20 100644 --- a/core/app/datasource/src/main/java/io/openk9/datasource/service/DocTypeFieldService.java +++ b/core/app/datasource/src/main/java/io/openk9/datasource/service/DocTypeFieldService.java @@ -18,7 +18,6 @@ package io.openk9.datasource.service; import io.openk9.common.graphql.util.relay.Connection; -import io.openk9.common.graphql.util.relay.GraphqlId; import io.openk9.common.util.SortBy; import io.openk9.datasource.mapper.DocTypeFieldMapper; import io.openk9.datasource.model.Analyzer; @@ -36,7 +35,6 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; -import javax.persistence.criteria.Predicate; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; @@ -170,25 +168,8 @@ public Uni> expandDocTypes(Collection docTypes) { .unis(docTypeField) .collectFailures() .combinedWith(e -> (List>) e) - .flatMap(list -> { - - Set>> innerDTFs = new LinkedHashSet<>(); - - for (Set docTypeFields : list) { - innerDTFs.add(expandDocTypeFields(docTypeFields)); - } - - return Uni - .combine() - .all() - .unis(innerDTFs) - .collectFailures() - .discardItems(); - - }) + .flatMap(this::loadAndExpandDocTypeFields) .replaceWith(docTypes); - - }); } else { @@ -197,7 +178,70 @@ public Uni> expandDocTypes(Collection docTypes) { } - public Uni> expandDocTypeFields(Collection docTypeFields) { + public Uni> findConnection( + long parentId, String after, String before, Integer first, Integer last, + String searchText, Set sortByList) { + + + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(); + + CriteriaQuery query = + criteriaBuilder.createQuery(getEntityClass()); + + Path root = query.from(getEntityClass()); + + Path parentField = root.get(DocTypeField_.parentDocTypeField); + + return findConnection( + query, root, + parentId > 0 + ? criteriaBuilder.equal(parentField.get(DocTypeField_.id), parentId) + : criteriaBuilder.isNull(parentField), + getSearchFields(), + after, before, first, last, searchText, sortByList + ); + } + + + private Uni> loadAndExpandDocTypeFields(List> list) { + + List> loadedDTFs = new LinkedList<>(); + + for (Set typeFields : list) { + loadedDTFs.add(loadDocTypeField(typeFields)); + } + + return Uni + .combine() + .all() + .unis(loadedDTFs) + .collectFailures() + .discardItems() + .chain(() -> { + + List>> inner = new LinkedList<>(); + + for (Set typeFields : list) { + inner.add(expandDocTypeFields(typeFields)); + } + + return Uni + .combine() + .all() + .unis(inner) + .collectFailures() + .combinedWith(e -> { + List> expandInner = (List>) e; + return expandInner.stream() + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + }); + + }); + + } + + private Uni> expandDocTypeFields(Collection docTypeFields) { if (docTypeFields == null || docTypeFields.isEmpty()) { return Uni.createFrom().item(Set.of()); @@ -220,74 +264,13 @@ public Uni> expandDocTypeFields(Collection docTy .unis(subDocTypeFieldUnis) .collectFailures() .combinedWith(e -> (List>)e) - .flatMap(list -> { - - List> loadedDTFs = new LinkedList<>(); - - for (Set typeFields : list) { - loadedDTFs.add(loadDocTypeField(typeFields)); - } - - return Uni - .combine() - .all() - .unis(loadedDTFs) - .collectFailures() - .discardItems() - .chain(() -> { - - List>> inner = new LinkedList<>(); - - for (Set typeFields : list) { - inner.add(expandDocTypeFields(typeFields)); - } - - return Uni - .combine() - .all() - .unis(inner) - .collectFailures() - .combinedWith(e -> { - List> expandInner = (List>) e; - return expandInner.stream() - .flatMap(Collection::stream) - .collect(Collectors.toSet()); - }); - - }); - - }); + .flatMap(this::loadAndExpandDocTypeFields); }); - } - public Uni> findConnection( - long parentId, String after, String before, Integer first, Integer last, - String searchText, Set sortByList) { - - - CriteriaBuilder criteriaBuilder = getCriteriaBuilder(); - - CriteriaQuery query = - criteriaBuilder.createQuery(getEntityClass()); - - Path root = query.from(getEntityClass()); - - Path parentField = root.get(DocTypeField_.parentDocTypeField); - - return findConnection( - query, root, - parentId > 0 - ? criteriaBuilder.equal(parentField.get(DocTypeField_.id), parentId) - : criteriaBuilder.isNull(parentField), - getSearchFields(), - after, before, first, last, searchText, sortByList - ); - } - - public Uni loadDocTypeField(Set typeFields) { + private Uni loadDocTypeField(Set typeFields) { return em.withTransaction(s -> { From 9f0627e51d6ec050fa73badaecaf0e8c87e6aabe Mon Sep 17 00:00:00 2001 From: Mirko Zizzari Date: Mon, 11 Sep 2023 15:19:31 +0200 Subject: [PATCH 03/82] Issue #572: persist datasource-events --- .../datasource/events/DatasourceEventBus.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/app/datasource/src/main/java/io/openk9/datasource/events/DatasourceEventBus.java b/core/app/datasource/src/main/java/io/openk9/datasource/events/DatasourceEventBus.java index af2fccb84..241ebddaf 100644 --- a/core/app/datasource/src/main/java/io/openk9/datasource/events/DatasourceEventBus.java +++ b/core/app/datasource/src/main/java/io/openk9/datasource/events/DatasourceEventBus.java @@ -1,8 +1,11 @@ package io.openk9.datasource.events; import io.quarkus.runtime.Startup; +import io.smallrye.reactive.messaging.rabbitmq.OutgoingRabbitMQMetadata; import org.eclipse.microprofile.reactive.messaging.Channel; import org.eclipse.microprofile.reactive.messaging.Emitter; +import org.eclipse.microprofile.reactive.messaging.Message; +import org.eclipse.microprofile.reactive.messaging.Metadata; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; @@ -12,7 +15,16 @@ public class DatasourceEventBus { public void sendEvent(DatasourceMessage datasourceMessage) { - quoteRequestEmitter.send(datasourceMessage); + quoteRequestEmitter.send( + Message.of( + datasourceMessage, + Metadata.of(OutgoingRabbitMQMetadata + .builder() + .withDeliveryMode(2) + .build() + ) + ) + ); } @Inject From 973357865fbd5fec65780750016cb7235353110a Mon Sep 17 00:00:00 2001 From: "N.Alivernini" Date: Mon, 11 Sep 2023 16:17:32 +0200 Subject: [PATCH 04/82] add button search component --- .../search-frontend/src/components/Search.tsx | 52 ++++++++++++++++--- .../search-frontend/src/embeddable/Main.tsx | 19 +++++++ .../search-frontend/src/embeddable/entry.tsx | 7 +++ 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/js-packages/search-frontend/src/components/Search.tsx b/js-packages/search-frontend/src/components/Search.tsx index ccaa1d5f8..93eab1e18 100644 --- a/js-packages/search-frontend/src/components/Search.tsx +++ b/js-packages/search-frontend/src/components/Search.tsx @@ -20,6 +20,7 @@ import { SearchDateRange } from "../embeddable/Main"; import { DeleteLogo } from "./DeleteLogo"; import { useTranslation } from "react-i18next"; import { ArrowLeftSvg } from "../svgElement/ArrowLeftSvg"; +import { divide } from "lodash"; type SearchProps = { configuration: Configuration; @@ -32,6 +33,7 @@ type SearchProps = { filtersSelect: SearchToken[]; isVisibleFilters: boolean; mobileVersion?: boolean; + btnSearch?: boolean; actionCloseMobileVersion?: | React.Dispatch> | undefined; @@ -45,6 +47,7 @@ export function Search({ showSyntax, isMobile, mobileVersion = false, + btnSearch = false, actionCloseMobileVersion, }: SearchProps) { const autoSelect = configuration.searchAutoselect; @@ -57,6 +60,7 @@ export function Search({ const clickAwayRef = React.useRef(null); useClickAway([clickAwayRef], () => setOpenedDropdown(null)); + const [textBtn, setTextBtn] = React.useState(""); const inputRef = React.useRef(null); const [adjustedSelection, setAdjustedSelection] = React.useState<{ selectionStart: number; @@ -228,14 +232,18 @@ export function Search({ } type="text" placeholder={t("search") || "search..."} - value={selectionsState.text} + value={btnSearch ? textBtn : selectionsState.text} onChange={(event) => { - selectionsDispatch({ - type: "set-text", - text: event.currentTarget.value, - }); - onDetail(null); - setOpenedDropdown(null); + if (!btnSearch) { + selectionsDispatch({ + type: "set-text", + text: event.currentTarget.value, + }); + onDetail(null); + setOpenedDropdown(null); + } else { + setTextBtn(event.currentTarget.value); + } }} css={css` position: relative; @@ -247,7 +255,11 @@ export function Search({ font-size: inherit; font-family: inherit; background-color: inherit; - color: ${showSyntax ? "transparent" : "inherit"}; + color: ${textBtn + ? "black" + : showSyntax + ? "transparent" + : "inherit"}; `} spellCheck="false" onSelect={(event) => { @@ -373,6 +385,30 @@ export function Search({ + {btnSearch && ( +
+ +
+ )} ); diff --git a/js-packages/search-frontend/src/embeddable/Main.tsx b/js-packages/search-frontend/src/embeddable/Main.tsx index d29972792..c8d1ce682 100644 --- a/js-packages/search-frontend/src/embeddable/Main.tsx +++ b/js-packages/search-frontend/src/embeddable/Main.tsx @@ -153,6 +153,25 @@ export function Main({ , configuration.search, )} + {renderPortal( + + + , + configuration.searchConfigurable + ? configuration.searchConfigurable.element + : null, + )} {renderPortal( Date: Mon, 11 Sep 2023 16:37:50 +0200 Subject: [PATCH 05/82] add collapsed filter element --- .../src/components/Filters.tsx | 4 ++++ .../search-frontend/src/components/Search.tsx | 4 ++-- .../search-frontend/src/embeddable/Main.tsx | 19 +++++++++++++++++++ .../search-frontend/src/embeddable/entry.tsx | 11 +++++++++-- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/js-packages/search-frontend/src/components/Filters.tsx b/js-packages/search-frontend/src/components/Filters.tsx index c7be21472..16031be76 100644 --- a/js-packages/search-frontend/src/components/Filters.tsx +++ b/js-packages/search-frontend/src/components/Filters.tsx @@ -24,6 +24,7 @@ type FiltersProps = { preFilters?: React.ReactNode; language: string; sortAfterKey: string; + isCollapsable?: boolean; }; function Filters({ searchQuery, @@ -36,6 +37,7 @@ function Filters({ preFilters, language, sortAfterKey, + isCollapsable = true, }: FiltersProps) { const suggestionCategories = useSuggestionCategories(); const { t } = useTranslation(); @@ -209,6 +211,7 @@ function Filters({ multiSelect={suggestionCategory?.multiSelect} searchQuery={searchQuery} language={language} + isCollapsable={isCollapsable} /> ) : ( ); })} diff --git a/js-packages/search-frontend/src/components/Search.tsx b/js-packages/search-frontend/src/components/Search.tsx index 93eab1e18..567b6eafc 100644 --- a/js-packages/search-frontend/src/components/Search.tsx +++ b/js-packages/search-frontend/src/components/Search.tsx @@ -389,8 +389,7 @@ export function Search({
+ + {Array.from({ length: numberOfPage }).map( + (_, index) => + index >= viewButton.start && + index < viewButton.end && ( + + ), + )} + + + + + + ) : ( + +
+
+ + + + + {t("result")} + +
+
+ +
+ )} + + ); +} + +function NoResults() { + const { t } = useTranslation(); + return ( +
+ +

{t("no-results-were-found")}

+
{t("try-with-another-query")}
+
+ ); +} + +export function useInfiniteResults( + searchQuery: Array, + sort: SortField[], + language: string, + sortAfterKey: string, + pagination: number, + numberOfResults: number, + elementForPage: number, + currentPage: number, +) { + const pageSize = elementForPage; + const client = useOpenK9Client(); + + const result = elementForPage * (currentPage + 1); + + return useInfiniteQuery( + ["results", searchQuery, sort, language, sortAfterKey, result] as const, + async ({ queryKey: [, searchQuery, sort], pageParam = 0 }) => { + const RangePage: [number, number] = + sortAfterKey === "" ? [result, pageSize] : [0, pageSize]; + return client.doSearch({ + range: RangePage, + language, + searchQuery, + sort, + sortAfterKey: sortAfterKey || "", + }); + }, + { + keepPreviousData: false, + getNextPageParam(lastPage, pages) { + const totalDownloaded = pages.reduce( + (total, page) => total + page.result.length, + 0, + ); + if (totalDownloaded < lastPage.total) { + return pages.length; + } + }, + suspense: true, + notifyOnChangeProps: ["isFetching"], + }, + ); +} From d67b2539707977172e4f9ce367cb874bb98b6889 Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Fri, 22 Sep 2023 10:46:35 +0200 Subject: [PATCH 57/82] Issue #590: fix pagination style --- .../src/components/ResultListPagination.tsx | 213 ++++++++---------- 1 file changed, 96 insertions(+), 117 deletions(-) diff --git a/js-packages/search-frontend/src/components/ResultListPagination.tsx b/js-packages/search-frontend/src/components/ResultListPagination.tsx index 288157bdc..4f7aae1a6 100644 --- a/js-packages/search-frontend/src/components/ResultListPagination.tsx +++ b/js-packages/search-frontend/src/components/ResultListPagination.tsx @@ -53,7 +53,7 @@ function ResultsPagination({ pagination, }: ResultsProps) { const renderers = useRenderers(); - const [currentPage, setCurrentPage] = React.useState(1); + const [currentPage, setCurrentPage] = React.useState(0); const changePage = (page: number) => { setCurrentPage(page); }; @@ -183,66 +183,6 @@ type ResulListProps = { setTotalResult: React.Dispatch>; }; -type FiniteResultsProps = ResulListProps & { sortAfterKey: string }; -// export function FiniteResults({ -// renderers, -// searchQuery, -// onDetail, -// setDetailMobile, -// sort, -// setSortResult, -// isMobile, -// overChangeCard = false, -// language, -// sortAfterKey, -// setTotalResult, -// }: FiniteResultsProps) { -// const results = useInfiniteResults( -// searchQuery, -// sort, -// language, -// sortAfterKey, -// ); - -// setTotalResult(results.data?.pages[0].total ?? null); - -// return ( -//
-// {results.data?.pages[0].total && results.data.pages[0].total > 0 ? ( -//
-// -// {results.data?.pages[0].total} -// -// {results.data?.pages[0].result.map((result, index) => { -// return ( -// -// renderers={renderers} -// key={index} -// result={result} -// onDetail={onDetail} -// setDetailMobile={setDetailMobile} -// isMobile={isMobile} -// overChangeCard={overChangeCard} -// /> -// ); -// })} -//
-// ) : ( -// -// )} -//
-// ); -// } - type InfiniteResultsProps = ResulListProps & { setSortAfterKey: React.Dispatch>; sortAfterKey: string; @@ -271,27 +211,26 @@ export function InfiniteResults({ elementForPage, setCurrentPage, }: InfiniteResultsProps) { + const result = currentPage * elementForPage; const results = useInfiniteResults( searchQuery, sort, language, sortAfterKey, - currentPage, - numberOfResults, elementForPage, - currentPage, + result, ); + const { t } = useTranslation(); const itemsPerPage = 3; // Numero di elementi per pagina const pagesToShow = 3; // Numero di pagine da mostrare per volta - + const partialResult = numberOfResults / elementForPage; + const numberOfPage = Math.ceil(partialResult); const [viewButton, setViewButton] = React.useState({ start: 0, end: itemsPerPage, }); - const numberOfPage = Math.ceil(numberOfResults / itemsPerPage); - const handlePrevClick = () => { setViewButton((view) => ({ ...view, @@ -323,9 +262,9 @@ export function InfiniteResults({ end: Math.min(view.end + pagesToShow, numberOfPage), })); }; - const { t } = useTranslation(); + setTotalResult(results.data?.pages[0].total ?? null); - const numberOfPageT = Math.ceil(numberOfResults / elementForPage); + return ( ({ ); })} - - - {Array.from({ length: numberOfPage }).map( - (_, index) => - index >= viewButton.start && - index < viewButton.end && ( - - ), - )} - - - + + + {Array.from({ length: numberOfPage }).map( + (_, index) => + index >= viewButton.start && + index < viewButton.end && ( + { + results.fetchNextPage(); + setCurrentPage(index); + }} + key={index} + value={"" + (index + 1)} + isCurrent={currentPage === index} + disable={viewButton.end >= numberOfPage} + ariaL={"clicca per vedere la " + (index + 1) + " pagina"} + /> + ), + )} + = numberOfPage} + ariaL="bottone per mostrare le tre pagine successive " + /> + resetEndClick(numberOfPage)} + value=">>" + disable={viewButton.end >= numberOfPage} + ariaL="bottone per mostrare le ultime tre pagine" + /> + ) : ( @@ -472,21 +428,17 @@ function NoResults() { ); } -export function useInfiniteResults( +function useInfiniteResults( searchQuery: Array, sort: SortField[], language: string, sortAfterKey: string, - pagination: number, - numberOfResults: number, elementForPage: number, - currentPage: number, + result: number, ) { const pageSize = elementForPage; const client = useOpenK9Client(); - const result = elementForPage * (currentPage + 1); - return useInfiniteQuery( ["results", searchQuery, sort, language, sortAfterKey, result] as const, async ({ queryKey: [, searchQuery, sort], pageParam = 0 }) => { @@ -502,17 +454,44 @@ export function useInfiniteResults( }, { keepPreviousData: false, - getNextPageParam(lastPage, pages) { - const totalDownloaded = pages.reduce( - (total, page) => total + page.result.length, - 0, - ); - if (totalDownloaded < lastPage.total) { - return pages.length; - } - }, suspense: true, notifyOnChangeProps: ["isFetching"], }, ); } + +function CreateButton({ + value, + action, + ariaL, + disable, + isCurrent = false, +}: { + value: string; + action: () => void; + ariaL: string; + disable: boolean; + isCurrent?: boolean; +}) { + return ( + + ); +} From 490e916280aafb9f518ad0ac8795fc1fdd82693e Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Fri, 22 Sep 2023 10:57:55 +0200 Subject: [PATCH 58/82] Issue #590: export component result pagination --- .../src/components/ResultListPagination.tsx | 1 + .../search-frontend/src/embeddable/Main.tsx | 26 ++++++++++++++++--- .../search-frontend/src/embeddable/entry.tsx | 2 ++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/js-packages/search-frontend/src/components/ResultListPagination.tsx b/js-packages/search-frontend/src/components/ResultListPagination.tsx index 4f7aae1a6..3d605adb1 100644 --- a/js-packages/search-frontend/src/components/ResultListPagination.tsx +++ b/js-packages/search-frontend/src/components/ResultListPagination.tsx @@ -312,6 +312,7 @@ export function InfiniteResults({ })}
- + , configuration.totalResult, )} @@ -309,6 +308,27 @@ export function Main({ , configuration.resultList ? configuration.resultList.element : null, )} + {renderPortal( + + + , + configuration.resultListPagination, + )} {renderPortal( diff --git a/js-packages/search-frontend/src/embeddable/entry.tsx b/js-packages/search-frontend/src/embeddable/entry.tsx index e3e7bced8..e64fa1f8c 100644 --- a/js-packages/search-frontend/src/embeddable/entry.tsx +++ b/js-packages/search-frontend/src/embeddable/entry.tsx @@ -251,6 +251,7 @@ export type Configuration = { filtersHorizontal: FiltersHorizontalConfiguration | null; sortable: Element | string | null; results: Element | string | null; + resultListPagination: Element | string | null; details: Element | string | null; calendar: Element | string | null; login: Element | string | null; @@ -294,6 +295,7 @@ const defaultConfiguration: Configuration = { changeLanguage: null, filtersHorizontal: null, results: null, + resultListPagination: null, details: null, sortResultConfigurable: null, login: null, From 7c02ae225ef318646cf79ad288701f8884fb8026 Mon Sep 17 00:00:00 2001 From: Mirko Zizzari Date: Fri, 22 Sep 2023 11:18:24 +0200 Subject: [PATCH 59/82] Issue #594: remove orphan DocTypeField --- .../src/main/java/io/openk9/datasource/model/DocType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/app/datasource/src/main/java/io/openk9/datasource/model/DocType.java b/core/app/datasource/src/main/java/io/openk9/datasource/model/DocType.java index 93dd5aa9e..f782908d9 100644 --- a/core/app/datasource/src/main/java/io/openk9/datasource/model/DocType.java +++ b/core/app/datasource/src/main/java/io/openk9/datasource/model/DocType.java @@ -57,7 +57,8 @@ public class DocType extends K9Entity { @OneToMany( mappedBy = "docType", cascade = javax.persistence.CascadeType.ALL, - fetch = FetchType.LAZY + fetch = FetchType.LAZY, + orphanRemoval = true ) @ToString.Exclude @JsonIgnore From 71bf7afd82b89ae16b900134804dc82ec1c03170 Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Fri, 22 Sep 2023 15:16:32 +0200 Subject: [PATCH 60/82] Issue #595: fix disabled button --- .../src/components/ResultListPagination.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/js-packages/search-frontend/src/components/ResultListPagination.tsx b/js-packages/search-frontend/src/components/ResultListPagination.tsx index 3d605adb1..9d042f9f2 100644 --- a/js-packages/search-frontend/src/components/ResultListPagination.tsx +++ b/js-packages/search-frontend/src/components/ResultListPagination.tsx @@ -345,7 +345,6 @@ export function InfiniteResults({ key={index} value={"" + (index + 1)} isCurrent={currentPage === index} - disable={viewButton.end >= numberOfPage} ariaL={"clicca per vedere la " + (index + 1) + " pagina"} /> ), @@ -465,21 +464,21 @@ function CreateButton({ value, action, ariaL, - disable, + disable = false, isCurrent = false, }: { value: string; action: () => void; ariaL: string; - disable: boolean; + disable?: boolean; isCurrent?: boolean; }) { return (
-
openk9.updateConfiguration({ results: element })} - css={css` - grid-area: result; - overflow-y: auto; - background-color: var( - --openk9-embeddable-search--primary-background-color - ); - border-radius: 8px; - border: 1px solid var(--openk9-embeddable-search--border-color); - `} - >
+
openk9.updateConfiguration({ resultList: {element:element, changeOnOver:true} })} + css={css` + grid-area: result; + overflow-y: auto; + background-color: var( + --openk9-embeddable-search--primary-background-color + ); + border-radius: 8px; + border: 1px solid var(--openk9-embeddable-search--border-color); + `} + >
diff --git a/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx b/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx new file mode 100644 index 000000000..ba2320681 --- /dev/null +++ b/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx @@ -0,0 +1,28 @@ +import React, { Children } from "react"; +import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +const { + DetailTitle, +} = rendererComponents; + +type DetailTitleExternalLinkProps = { href: string; children: React.ReactNode }; +export function DetailTitleExternalLink({ + href, + children, +}: DetailTitleExternalLinkProps) { + return ( + + ); +} \ No newline at end of file diff --git a/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx b/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx new file mode 100644 index 000000000..207b4a831 --- /dev/null +++ b/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx @@ -0,0 +1,29 @@ +import React, { Children } from "react"; +import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +const { + ResultTitle +} = rendererComponents; + +type ResultTitleExternalLinkProps = { href: string; children: React.ReactNode }; +export function ResultTitleExternalLink({ + href, + children, +}: ResultTitleExternalLinkProps) { + return ( + + ); +} \ No newline at end of file diff --git a/js-packages/search-frontend/src/renderer-components/index.ts b/js-packages/search-frontend/src/renderer-components/index.ts index db4fa39bd..7605a934a 100644 --- a/js-packages/search-frontend/src/renderer-components/index.ts +++ b/js-packages/search-frontend/src/renderer-components/index.ts @@ -30,3 +30,5 @@ export * from "./ResultLinkTwo"; export * from "./SanitizeHtml"; export * from "./SortResultList"; export * from "./WrapperContainer"; +export * from "./DetailTitleExternalLink" +export * from "./ResultTitleExternalLink" From 5fb783d50e2b6c0a8c423962c2b6a00214367dfe Mon Sep 17 00:00:00 2001 From: daniele caldarini Date: Sat, 23 Sep 2023 17:04:27 +0200 Subject: [PATCH 62/82] fixed ResultTitleExternalLink and DetailTitleExternalLink --- .../src/renderer-components/DetailTitleExternalLink.tsx | 3 --- .../src/renderer-components/ResultTitleExternalLink.tsx | 4 ---- 2 files changed, 7 deletions(-) diff --git a/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx b/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx index ba2320681..c17816e18 100644 --- a/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx +++ b/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx @@ -1,9 +1,6 @@ import React, { Children } from "react"; import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -const { - DetailTitle, -} = rendererComponents; type DetailTitleExternalLinkProps = { href: string; children: React.ReactNode }; export function DetailTitleExternalLink({ diff --git a/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx b/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx index 207b4a831..e690f61a2 100644 --- a/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx +++ b/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx @@ -2,10 +2,6 @@ import React, { Children } from "react"; import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -const { - ResultTitle -} = rendererComponents; - type ResultTitleExternalLinkProps = { href: string; children: React.ReactNode }; export function ResultTitleExternalLink({ href, From 3b1fee08def3e6df33a4455136bed28bcf689005 Mon Sep 17 00:00:00 2001 From: daniele caldarini Date: Sat, 23 Sep 2023 17:29:17 +0200 Subject: [PATCH 63/82] fixed ResultTitleExternalLink and DetailTitleExternalLink #2 --- .../src/renderer-components/DetailTitleExternalLink.tsx | 1 + .../src/renderer-components/ResultTitleExternalLink.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx b/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx index c17816e18..298bb3e99 100644 --- a/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx +++ b/js-packages/search-frontend/src/renderer-components/DetailTitleExternalLink.tsx @@ -1,6 +1,7 @@ import React, { Children } from "react"; import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { DetailTitle} from "./DetailTitle"; type DetailTitleExternalLinkProps = { href: string; children: React.ReactNode }; export function DetailTitleExternalLink({ diff --git a/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx b/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx index e690f61a2..0da8b1aa6 100644 --- a/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx +++ b/js-packages/search-frontend/src/renderer-components/ResultTitleExternalLink.tsx @@ -1,6 +1,7 @@ import React, { Children } from "react"; import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ResultTitle } from "./ResultTitle"; type ResultTitleExternalLinkProps = { href: string; children: React.ReactNode }; export function ResultTitleExternalLink({ From 0f212853be842a4144d772a563fee65043d78eb4 Mon Sep 17 00:00:00 2001 From: daniele caldarini Date: Mon, 25 Sep 2023 12:04:54 +0200 Subject: [PATCH 64/82] added CustomFontAwesomeIcon renderer component --- js-packages/search-frontend/package.json | 1 + .../CustomFontAwesomeIcon.tsx | 24 +++++++++++++++++++ .../src/renderer-components/index.ts | 1 + yarn.lock | 7 ++++++ 4 files changed, 33 insertions(+) create mode 100644 js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx diff --git a/js-packages/search-frontend/package.json b/js-packages/search-frontend/package.json index eecbcea9a..5ce03b800 100644 --- a/js-packages/search-frontend/package.json +++ b/js-packages/search-frontend/package.json @@ -53,6 +53,7 @@ "@fortawesome/fontawesome-svg-core": "6.2.0", "@fortawesome/free-solid-svg-icons": "6.2.0", "@fortawesome/react-fontawesome": "0.2.0", + "@fortawesome/free-brands-svg-icons": "6.2.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.1", "@types/keycloak-js": "^3.4.1", "@types/lodash": "^4.14.178", diff --git a/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx b/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx new file mode 100644 index 000000000..8edc5cfe4 --- /dev/null +++ b/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { GenericResultItem } from "../components/client"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faForumbee } from "@fortawesome/free-brands-svg-icons"; +import { faCalendar } from "@fortawesome/free-solid-svg-icons"; +import { faFileAlt } from "@fortawesome/free-solid-svg-icons/faFileAlt"; + +export function CustomFontAwesomeIcon({ + result, +}: { + result: GenericResultItem; +}) { + contentTypeSet.add(result.source.document.contentType); + if (result.source.documentTypes.includes("forum")) { + return ; + } + if (result.source.documentTypes.includes("calendar")) { + return ; + } + + return ; +} + +export const contentTypeSet = new Set(); diff --git a/js-packages/search-frontend/src/renderer-components/index.ts b/js-packages/search-frontend/src/renderer-components/index.ts index 7605a934a..407cfa41f 100644 --- a/js-packages/search-frontend/src/renderer-components/index.ts +++ b/js-packages/search-frontend/src/renderer-components/index.ts @@ -32,3 +32,4 @@ export * from "./SortResultList"; export * from "./WrapperContainer"; export * from "./DetailTitleExternalLink" export * from "./ResultTitleExternalLink" +export * from "./CustomFontAwesomeIcon)" diff --git a/yarn.lock b/yarn.lock index c18ebc4d0..9f0287818 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2588,6 +2588,13 @@ dependencies: "@fortawesome/fontawesome-common-types" "6.2.1" +"@fortawesome/free-brands-svg-icons@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.2.0.tgz#ce072179677f9b5d6767f918cfbf296f357cc1d0" + integrity sha512-fm1y4NyZ2qKYNmYhdMz9VAWRw1Et7PMHNunSw3W0SVAwKwv6o0qiJworLH3Y9SnmhHzAymXJwCX1op22FFvGiA== + dependencies: + "@fortawesome/fontawesome-common-types" "6.2.0" + "@fortawesome/free-solid-svg-icons@6.2.0": version "6.2.0" resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.0.tgz#8dcde48109354fd7a5ece8ea48d678bb91d4b5f0" From ca6d946b086676600f161c316fc86642242bc1f1 Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Mon, 25 Sep 2023 11:59:42 +0200 Subject: [PATCH 65/82] Issue #569: add chip component --- .../src/renderer-components/Chip.tsx | 28 +++++++++++++++++++ .../src/renderer-components/ResultFavicon.tsx | 12 +++++--- .../src/renderer-components/index.ts | 1 + 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 js-packages/search-frontend/src/renderer-components/Chip.tsx diff --git a/js-packages/search-frontend/src/renderer-components/Chip.tsx b/js-packages/search-frontend/src/renderer-components/Chip.tsx new file mode 100644 index 000000000..c1dcdc7e3 --- /dev/null +++ b/js-packages/search-frontend/src/renderer-components/Chip.tsx @@ -0,0 +1,28 @@ +import React from "react"; + +type ChipProps = { + title: string; +}; +export function Chip({ title }: ChipProps) { + return ( + + ); +} diff --git a/js-packages/search-frontend/src/renderer-components/ResultFavicon.tsx b/js-packages/search-frontend/src/renderer-components/ResultFavicon.tsx index 26535d231..4f2572262 100644 --- a/js-packages/search-frontend/src/renderer-components/ResultFavicon.tsx +++ b/js-packages/search-frontend/src/renderer-components/ResultFavicon.tsx @@ -1,16 +1,20 @@ import React from "react"; import { css } from "styled-components/macro"; -type ResultFaviconProps = { src: string }; -export function ResultFavicon({ src }: ResultFaviconProps) { +type ResultFaviconProps = { src: string; maxHei?: string; maxWid?: string }; +export function ResultFavicon({ + src, + maxHei = "30px", + maxWid = "30px", +}: ResultFaviconProps) { return ( ); diff --git a/js-packages/search-frontend/src/renderer-components/index.ts b/js-packages/search-frontend/src/renderer-components/index.ts index 407cfa41f..52da376cc 100644 --- a/js-packages/search-frontend/src/renderer-components/index.ts +++ b/js-packages/search-frontend/src/renderer-components/index.ts @@ -1,5 +1,6 @@ export * from "./Badge"; export * from "./BadgeContainer"; +export * from "./Chip"; export * from "./DateCard"; export * from "./DetailAttribute"; export * from "./DetailContainer"; From 1a6e2af2e0e91f8a43b35d38a96fd8a1ee53118f Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Mon, 25 Sep 2023 12:27:08 +0200 Subject: [PATCH 66/82] Issu #597: fix chip component --- .../src/renderer-components/Chip.tsx | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/js-packages/search-frontend/src/renderer-components/Chip.tsx b/js-packages/search-frontend/src/renderer-components/Chip.tsx index c1dcdc7e3..b7837b375 100644 --- a/js-packages/search-frontend/src/renderer-components/Chip.tsx +++ b/js-packages/search-frontend/src/renderer-components/Chip.tsx @@ -2,27 +2,37 @@ import React from "react"; type ChipProps = { title: string; + customStyles?: CustomStyles; }; -export function Chip({ title }: ChipProps) { + +type CustomStyles = { + button?: React.CSSProperties; + div?: React.CSSProperties; +}; + +export function Chip({ title, customStyles }: ChipProps) { + const buttonStyles = { + padding: "4px 10px", + borderRadius: "20px", + border: "1px solid #C0272B", + background: "white", + fontSize: "10px", + fontWeight: "700", + lineHeight: "12px", + ...(customStyles?.button || {}), + }; + + const divStyles = { + display: "flex", + alignItems: "baseline", + color: "#c0272b", + gap: "8px", + ...(customStyles?.div || {}), + }; + return ( - ); } From e4bd2c8f519831e269e29efa2e7c4a5bfca52ee1 Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Mon, 25 Sep 2023 15:01:17 +0200 Subject: [PATCH 67/82] Issue #597: fix scrollbar --- .../src/components/ResultListPagination.tsx | 291 ++++++++++-------- .../src/components/Scrollbar.css | 24 ++ 2 files changed, 182 insertions(+), 133 deletions(-) create mode 100644 js-packages/search-frontend/src/components/Scrollbar.css diff --git a/js-packages/search-frontend/src/components/ResultListPagination.tsx b/js-packages/search-frontend/src/components/ResultListPagination.tsx index 9d042f9f2..51e25c46e 100644 --- a/js-packages/search-frontend/src/components/ResultListPagination.tsx +++ b/js-packages/search-frontend/src/components/ResultListPagination.tsx @@ -13,6 +13,7 @@ import { ResultSvg } from "../svgElement/ResultSvg"; import { SortResultList } from "./SortResultList"; import { useTranslation } from "react-i18next"; import { result } from "lodash"; +import "../components/Scrollbar.css"; const OverlayScrollbarsComponentDockerFix = OverlayScrollbarsComponent as any; // for some reason this component breaks build inside docker export type ResultsDisplayMode = @@ -231,6 +232,17 @@ export function InfiniteResults({ end: itemsPerPage, }); + const overlayRef = React.useRef(null); + + function scrollToOverlay() { + if (overlayRef.current) { + overlayRef.current.scrollIntoView({ + behavior: "smooth", + block: "start", + }); + } + } + const handlePrevClick = () => { setViewButton((view) => ({ ...view, @@ -266,144 +278,157 @@ export function InfiniteResults({ setTotalResult(results.data?.pages[0].total ?? null); return ( - - {results?.data?.pages[0].total && results.data.pages[0].total > 0 ? ( -
- - {results.data?.pages[0].total} - - {results.data?.pages.map((page, pageIndex) => { - return ( - - {page.result.map((result, resultIndex) => { - return ( - - renderers={renderers} - key={resultIndex} - result={result} - onDetail={onDetail} - setDetailMobile={setDetailMobile} - isMobile={isMobile} - overChangeCard={overChangeCard} - /> - ); - })} - - ); - })} - -
- - - {Array.from({ length: numberOfPage }).map( - (_, index) => - index >= viewButton.start && - index < viewButton.end && ( - { - results.fetchNextPage(); - setCurrentPage(index); - }} - key={index} - value={"" + (index + 1)} - isCurrent={currentPage === index} - ariaL={"clicca per vedere la " + (index + 1) + " pagina"} - /> - ), - )} - = numberOfPage} - ariaL="bottone per mostrare le tre pagine successive " - /> - resetEndClick(numberOfPage)} - value=">>" - disable={viewButton.end >= numberOfPage} - ariaL="bottone per mostrare le ultime tre pagine" - /> -
-
-
- ) : ( - -
-
- - - - +
+ {results?.data?.pages[0].total && results.data.pages[0].total > 0 ? ( +
+ + {results.data?.pages[0].total} + + {results.data?.pages.map((page, pageIndex) => { + return ( + + {page.result.map((result, resultIndex) => { + return ( + + renderers={renderers} + key={resultIndex} + result={result} + onDetail={onDetail} + setDetailMobile={setDetailMobile} + isMobile={isMobile} + overChangeCard={overChangeCard} + /> + ); + })} + + ); + })} + +
- {t("result")} - -
+ + + {Array.from({ length: numberOfPage }).map( + (_, index) => + index >= viewButton.start && + index < viewButton.end && ( + { + results.fetchNextPage(); + setCurrentPage(index); + scrollToOverlay(); + }} + key={index} + value={"" + (index + 1)} + isCurrent={currentPage === index} + ariaL={ + "clicca per vedere la " + (index + 1) + " pagina" + } + /> + ), + )} + = numberOfPage} + ariaL="bottone per mostrare le tre pagine successive " + /> + resetEndClick(numberOfPage)} + value=">>" + disable={viewButton.end >= numberOfPage} + ariaL="bottone per mostrare le ultime tre pagine" + /> +
+
- - - )} - + ) : ( + +
+
+ + + + + {t("result")} + +
+
+ +
+ )} +
+ ); } diff --git a/js-packages/search-frontend/src/components/Scrollbar.css b/js-packages/search-frontend/src/components/Scrollbar.css new file mode 100644 index 000000000..2b4e0f9f0 --- /dev/null +++ b/js-packages/search-frontend/src/components/Scrollbar.css @@ -0,0 +1,24 @@ +::-webkit-scrollbar { + width: 6px; + } + + /* Track */ + ::-webkit-scrollbar-track { + background-color: transparent; + + + } + + /* Handle */ + ::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.4); + border-radius: 10px; + height:5px; + + } + + /* Handle on hover */ + ::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, .55); + height:5px; + } \ No newline at end of file From 9d29e0812f347fb90e90faf90c53101b2137bded Mon Sep 17 00:00:00 2001 From: daniele caldarini Date: Mon, 25 Sep 2023 15:31:32 +0200 Subject: [PATCH 68/82] fixed CustomFontAwesomeIcon result --- .../renderer-components/CustomFontAwesomeIcon.tsx | 12 +++++------- .../search-frontend/src/renderer-components/index.ts | 6 +++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx b/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx index 8edc5cfe4..f0f3b168c 100644 --- a/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx +++ b/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx @@ -5,20 +5,18 @@ import { faForumbee } from "@fortawesome/free-brands-svg-icons"; import { faCalendar } from "@fortawesome/free-solid-svg-icons"; import { faFileAlt } from "@fortawesome/free-solid-svg-icons/faFileAlt"; -export function CustomFontAwesomeIcon({ - result, +export function CustomFontAwesomeIcon({ + result }: { result: GenericResultItem; }) { - contentTypeSet.add(result.source.document.contentType); - if (result.source.documentTypes.includes("forum")) { + const realResult = result as any + if (realResult.source.documentTypes.includes("forum")) { return ; } - if (result.source.documentTypes.includes("calendar")) { + if (realResult.source.documentTypes.includes("calendar")) { return ; } return ; } - -export const contentTypeSet = new Set(); diff --git a/js-packages/search-frontend/src/renderer-components/index.ts b/js-packages/search-frontend/src/renderer-components/index.ts index 52da376cc..e6893ac49 100644 --- a/js-packages/search-frontend/src/renderer-components/index.ts +++ b/js-packages/search-frontend/src/renderer-components/index.ts @@ -31,6 +31,6 @@ export * from "./ResultLinkTwo"; export * from "./SanitizeHtml"; export * from "./SortResultList"; export * from "./WrapperContainer"; -export * from "./DetailTitleExternalLink" -export * from "./ResultTitleExternalLink" -export * from "./CustomFontAwesomeIcon)" +export * from "./DetailTitleExternalLink"; +export * from "./ResultTitleExternalLink"; +export * from "./CustomFontAwesomeIcon"; \ No newline at end of file From 758dcd2fc5acb36cf2f048e2f3389d619bf1f10f Mon Sep 17 00:00:00 2001 From: Mirko Zizzari Date: Mon, 25 Sep 2023 18:19:53 +0200 Subject: [PATCH 69/82] Issue #598: query docTypeField by docType and parent --- .../graphql/DocTypeGraphqlResource.java | 14 +++++++ .../datasource/service/DocTypeService.java | 20 +++++++++ .../graphql/util/service/GraphQLService.java | 42 ++++++++++++++++++- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/core/app/datasource/src/main/java/io/openk9/datasource/graphql/DocTypeGraphqlResource.java b/core/app/datasource/src/main/java/io/openk9/datasource/graphql/DocTypeGraphqlResource.java index e1a379c25..84307d32c 100644 --- a/core/app/datasource/src/main/java/io/openk9/datasource/graphql/DocTypeGraphqlResource.java +++ b/core/app/datasource/src/main/java/io/openk9/datasource/graphql/DocTypeGraphqlResource.java @@ -92,6 +92,20 @@ public Uni> getDocTypeFieldsFromDocType( docTypeId, after, before, first, last, searchText, sortByList, notEqual); } + @Query + public Uni> getDocTypeFieldsFromDocTypeByParent( + @Id long docTypeId, + @Description("id of the parent docTypeField (0 if root )") long parentId, + @Description("fetching only nodes after this node (exclusive)") String after, + @Description("fetching only nodes before this node (exclusive)") String before, + @Description("fetching only the first certain number of nodes") Integer first, + @Description("fetching only the last certain number of nodes") Integer last, + String searchText, Set sortByList, + @Description("if notEqual is true, it returns unbound entities") @DefaultValue("false") boolean notEqual) { + return docTypeService.getDocTypeFieldsConnectionByParent( + docTypeId, parentId, after, before, first, last, searchText, sortByList, notEqual); + } + @Query public Uni getDocType(@Id long id) { return docTypeService.findById(id); diff --git a/core/app/datasource/src/main/java/io/openk9/datasource/service/DocTypeService.java b/core/app/datasource/src/main/java/io/openk9/datasource/service/DocTypeService.java index 4e25cdd18..13a456ea2 100644 --- a/core/app/datasource/src/main/java/io/openk9/datasource/service/DocTypeService.java +++ b/core/app/datasource/src/main/java/io/openk9/datasource/service/DocTypeService.java @@ -23,6 +23,7 @@ import io.openk9.datasource.mapper.DocTypeMapper; import io.openk9.datasource.model.DocType; import io.openk9.datasource.model.DocTypeField; +import io.openk9.datasource.model.DocTypeField_; import io.openk9.datasource.model.DocTypeTemplate; import io.openk9.datasource.model.DocType_; import io.openk9.datasource.model.dto.DocTypeDTO; @@ -40,6 +41,7 @@ import javax.inject.Inject; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Path; import javax.persistence.criteria.Root; import java.util.Collection; import java.util.List; @@ -61,12 +63,30 @@ public String[] getSearchFields() { public Uni> getDocTypeFieldsConnection( Long id, String after, String before, Integer first, Integer last, String searchText, Set sortByList, boolean notEqual) { + return findJoinConnection( id, DocType_.DOC_TYPE_FIELDS, DocTypeField.class, docTypeFieldService.getSearchFields(), after, before, first, last, searchText, sortByList, notEqual); } + public Uni> getDocTypeFieldsConnectionByParent( + long docTypeId, long parentId, String after, String before, Integer first, Integer last, + String searchText, Set sortByList, boolean notEqual) { + + return findJoinConnection( + docTypeId, DocType_.DOC_TYPE_FIELDS, DocTypeField.class, + docTypeFieldService.getSearchFields(), after, before, first, last, + searchText, sortByList, notEqual, + (criteriaBuilder, join) -> { + Path parentField = join.get(DocTypeField_.parentDocTypeField); + + return parentId > 0 + ? criteriaBuilder.equal(parentField.get(DocTypeField_.id), parentId) + : criteriaBuilder.isNull(parentField); + }); + } + public Uni> getDocTypeFields( long docTypeId, Pageable pageable) { return getDocTypeFields(docTypeId, pageable, Filter.DEFAULT); diff --git a/core/common/graphql-util/src/main/java/io/openk9/common/graphql/util/service/GraphQLService.java b/core/common/graphql-util/src/main/java/io/openk9/common/graphql/util/service/GraphQLService.java index 6d69cdf3d..0bd7bb7dc 100644 --- a/core/common/graphql-util/src/main/java/io/openk9/common/graphql/util/service/GraphQLService.java +++ b/core/common/graphql-util/src/main/java/io/openk9/common/graphql/util/service/GraphQLService.java @@ -80,6 +80,22 @@ public Uni> findJoinConnection( } + public Uni> findJoinConnection( + long entityId, String joinField, Class joinType, + String[] searchFields, String after, + String before, Integer first, Integer last, String searchText, + Set sortByList, boolean not, + BiFunction, Predicate> whereFun) { + + return findJoinConnection( + entityId, joinField, joinType, searchFields, after, before, first, + last, searchText, sortByList, not, + entityRoot -> entityRoot.join(joinField), + (i1, i2) -> List.of(), + whereFun); + + } + public Uni> findJoinConnection( long entityId, String joinField, Class joinType, String[] searchFields, String after, @@ -88,6 +104,24 @@ public Uni> findJoinConnection( Function, Path> mapper, BiFunction, List> defaultOrderFun) { + return findJoinConnection( + entityId, joinField, joinType, searchFields, after, before, first, + last, searchText, sortByList, not, + mapper, + defaultOrderFun, + (criteriaBuilder, tPath) -> criteriaBuilder.conjunction()); + + } + + public Uni> findJoinConnection( + long entityId, String joinField, Class joinType, + String[] searchFields, String after, + String before, Integer first, Integer last, String searchText, + Set sortByList, boolean not, + Function, Path> mapper, + BiFunction, List> defaultOrderFun, + BiFunction, Predicate> whereFun) { + CriteriaBuilder builder = getCriteriaBuilder(); CriteriaQuery joinEntityQuery = builder.createQuery(joinType); @@ -110,7 +144,9 @@ public Uni> findJoinConnection( return findConnection( joinEntityQuery, upperRoot, - builder.in(upperRoot.get(getIdAttribute())).value(subquery).not(), + builder.and( + whereFun.apply(builder, subJoin), + builder.in(upperRoot.get(getIdAttribute())).value(subquery).not()), searchFields, after, before, first, last, searchText, sortByList); } @@ -124,7 +160,9 @@ public Uni> findJoinConnection( return findConnection( joinEntityQuery.select(join), join, - builder.equal(entityRoot.get(getIdAttribute()), entityId), + builder.and( + whereFun.apply(builder, join), + builder.equal(entityRoot.get(getIdAttribute()), entityId)), searchFields, after, before, first, last, searchText, sortByList); } From c5a3838ed7815c56aaca147df34373604b11cc70 Mon Sep 17 00:00:00 2001 From: daniele caldarini Date: Mon, 25 Sep 2023 21:42:41 +0200 Subject: [PATCH 70/82] added new icons in CustomFontAwesomeIcon.tsx --- .../renderer-components/CustomFontAwesomeIcon.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx b/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx index f0f3b168c..4ee6612cc 100644 --- a/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx +++ b/js-packages/search-frontend/src/renderer-components/CustomFontAwesomeIcon.tsx @@ -4,6 +4,9 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faForumbee } from "@fortawesome/free-brands-svg-icons"; import { faCalendar } from "@fortawesome/free-solid-svg-icons"; import { faFileAlt } from "@fortawesome/free-solid-svg-icons/faFileAlt"; +import { faUser } from "@fortawesome/free-solid-svg-icons"; +import { faSitemap } from "@fortawesome/free-solid-svg-icons"; +import { faWikipediaW } from "@fortawesome/free-brands-svg-icons"; export function CustomFontAwesomeIcon({ result @@ -17,6 +20,14 @@ export function CustomFontAwesomeIcon({ if (realResult.source.documentTypes.includes("calendar")) { return ; } - + if (realResult.source.documentTypes.includes("user")) { + return ; + } + if (realResult.source.documentTypes.includes("site")) { + return ; + } + if (realResult.source.documentTypes.includes("wiki")) { + return ; + } return ; } From 4a6de1f7c76d9bcf5983c40f633dbbfca951de4a Mon Sep 17 00:00:00 2001 From: "N.Alivernini" Date: Tue, 26 Sep 2023 17:44:04 +0200 Subject: [PATCH 71/82] fix query analysis --- js-packages/search-frontend/src/components/Search.tsx | 1 + js-packages/search-frontend/src/components/TokenSelect.tsx | 3 +++ 2 files changed, 4 insertions(+) diff --git a/js-packages/search-frontend/src/components/Search.tsx b/js-packages/search-frontend/src/components/Search.tsx index 8517e045d..9b8bb8cd2 100644 --- a/js-packages/search-frontend/src/components/Search.tsx +++ b/js-packages/search-frontend/src/components/Search.tsx @@ -233,6 +233,7 @@ export function Search({ setOpenedDropdown={setOpenedDropdown} selectionsDispatch={selectionsDispatch} isColorSearch={isSearchOnInputChange} + setTextBtn={setTextBtn} /> ); })} diff --git a/js-packages/search-frontend/src/components/TokenSelect.tsx b/js-packages/search-frontend/src/components/TokenSelect.tsx index 7a0dea193..3700fdeed 100644 --- a/js-packages/search-frontend/src/components/TokenSelect.tsx +++ b/js-packages/search-frontend/src/components/TokenSelect.tsx @@ -24,6 +24,7 @@ type TokenSelectProps = { optionPosition: number; } | null> >; + setTextBtn: React.Dispatch>; }; export function TokenSelect({ span, @@ -38,6 +39,7 @@ export function TokenSelect({ selectionsDispatch, saveSearchQuery, isColorSearch = true, + setTextBtn, }: TokenSelectProps) { const isInteractive = span.tokens.length > 0; const [subtitle, setSubtitle] = React.useState(false); @@ -191,6 +193,7 @@ export function TokenSelect({
{ + setTextBtn(getTokenLabel(option) || '') if (option.tokenType === "AUTOCOMPLETE") { onSelectText(option); } else { From f9c2d866e6898d2ec8c62f356a4715f6e34c8c7f Mon Sep 17 00:00:00 2001 From: "N.Alivernini" Date: Wed, 27 Sep 2023 14:35:27 +0200 Subject: [PATCH 72/82] fix autocomplete and btn search --- .../search-frontend/src/components/Search.tsx | 20 +++++++++++++------ .../src/components/TokenSelect.tsx | 5 ++++- .../src/components/useSelections.tsx | 10 +++++++++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/js-packages/search-frontend/src/components/Search.tsx b/js-packages/search-frontend/src/components/Search.tsx index 9b8bb8cd2..c2eda7054 100644 --- a/js-packages/search-frontend/src/components/Search.tsx +++ b/js-packages/search-frontend/src/components/Search.tsx @@ -69,7 +69,7 @@ export function Search({ const clickAwayRef = React.useRef(null); useClickAway([clickAwayRef], () => setOpenedDropdown(null)); - const [textBtn, setTextBtn] = React.useState(""); + const [textBtn, setTextBtn] = React.useState(); const inputRef = React.useRef(null); const [adjustedSelection, setAdjustedSelection] = React.useState<{ selectionStart: number; @@ -254,7 +254,7 @@ export function Search({ } type="text" placeholder={t("search") || "search..."} - value={btnSearch ? textBtn : selectionsState.text} + value={btnSearch ? textBtn ?? '' : selectionsState.text} onChange={(event) => { if (!btnSearch) { selectionsDispatch({ @@ -461,10 +461,18 @@ export function Search({ cursor: pointer; `} onClick={() => { - selectionsDispatch({ - type: "set-text", - text: textBtn, - }); + if(textBtn === '') { + selectionsDispatch({ + type: "reset-search" + }); + } else { + selectionsDispatch({ + type: "set-text", + text: textBtn, + textOnchange: textBtn, + }); + } + onDetail(null); setOpenedDropdown(null); }} diff --git a/js-packages/search-frontend/src/components/TokenSelect.tsx b/js-packages/search-frontend/src/components/TokenSelect.tsx index 3700fdeed..5d46442a8 100644 --- a/js-packages/search-frontend/src/components/TokenSelect.tsx +++ b/js-packages/search-frontend/src/components/TokenSelect.tsx @@ -24,7 +24,7 @@ type TokenSelectProps = { optionPosition: number; } | null> >; - setTextBtn: React.Dispatch>; + setTextBtn: React.Dispatch>; }; export function TokenSelect({ span, @@ -248,7 +248,10 @@ function getTokenLabel(token: AnalysisToken) { return token.entityName; case "TEXT": return token.value; + case "AUTOCOMPLETE": + return token.value; } + return token.value; } function FactoryTokenType({ diff --git a/js-packages/search-frontend/src/components/useSelections.tsx b/js-packages/search-frontend/src/components/useSelections.tsx index 726f28e23..24c5e3d73 100644 --- a/js-packages/search-frontend/src/components/useSelections.tsx +++ b/js-packages/search-frontend/src/components/useSelections.tsx @@ -65,6 +65,7 @@ const initial: SelectionsState = { export type SelectionsAction = | { type: "set-text"; text?: string; textOnchange?: string } + | { type: "reset-search" } | { type: "set-selection"; replaceText: boolean; @@ -116,12 +117,19 @@ function reducer( text: action.text || state.text || "", textOnChange: action.textOnchange || state.textOnChange || "", selection: shiftSelection( - state.textOnChange || "", + state.textOnChange ?? "", action.textOnchange || state.textOnChange || "", state.selection, ), }; } + case "reset-search" : { + return { + text: '', + textOnChange: '', + selection: [] + } + } case "set-selection": { const { text, selection } = (() => { if ( From 067c0c084a180c9074a6af0b18e08b7a234db78b Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Thu, 28 Sep 2023 10:49:41 +0200 Subject: [PATCH 73/82] Issue #610: fix navigation token select --- js-packages/search-frontend/src/components/Search.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js-packages/search-frontend/src/components/Search.tsx b/js-packages/search-frontend/src/components/Search.tsx index c2eda7054..82b65e59b 100644 --- a/js-packages/search-frontend/src/components/Search.tsx +++ b/js-packages/search-frontend/src/components/Search.tsx @@ -254,7 +254,7 @@ export function Search({ } type="text" placeholder={t("search") || "search..."} - value={btnSearch ? textBtn ?? '' : selectionsState.text} + value={btnSearch ? textBtn ?? "" : selectionsState.text} onChange={(event) => { if (!btnSearch) { selectionsDispatch({ @@ -341,6 +341,7 @@ export function Search({ } } else if (event.key === "Enter") { event.preventDefault(); + setTextBtn(option?.value); if (span) { if (isSearchOnInputChange) { selectionsDispatch({ @@ -461,9 +462,9 @@ export function Search({ cursor: pointer; `} onClick={() => { - if(textBtn === '') { + if (textBtn === "") { selectionsDispatch({ - type: "reset-search" + type: "reset-search", }); } else { selectionsDispatch({ @@ -472,7 +473,6 @@ export function Search({ textOnchange: textBtn, }); } - onDetail(null); setOpenedDropdown(null); }} From 298ae9ebe418095c497d815b5298317f33158f9a Mon Sep 17 00:00:00 2001 From: lorenzo venneri Date: Thu, 28 Sep 2023 11:32:56 +0200 Subject: [PATCH 74/82] Issue #611: fix Result list pagination with search --- .../src/components/ActiveFilters.tsx | 2 +- .../components/DateRangePickerVertical.tsx | 2 +- .../src/components/ResultListPagination.tsx | 19 +++++++++++++++---- .../search-frontend/src/embeddable/Main.tsx | 11 +++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/js-packages/search-frontend/src/components/ActiveFilters.tsx b/js-packages/search-frontend/src/components/ActiveFilters.tsx index 3489090e8..535d5fdf5 100644 --- a/js-packages/search-frontend/src/components/ActiveFilters.tsx +++ b/js-packages/search-frontend/src/components/ActiveFilters.tsx @@ -52,7 +52,7 @@ export function ActiveFilter({ > {searchQuery.map((selectToken, index) => { return ( - + {"goToSuggestion" in selectToken && (