{"version":3,"sources":["datatypes/Pages.ts","datatypes/Common.ts","datatypes/Libraries.ts","datatypes/RequirementsSearch.ts","components/RequirementsSearchFilter.tsx","components/RequirementsSearch.tsx","pagetypes/HomePage.tsx"],"names":["buildPageUrl","pageId","sanitizeId","getPage","id","locale","url","fetchServerUrl","then","response","json","page","navbarIcon","iconId","iconStringToIdConversions","transformIconLocatorStringId","catch","reason","console","log","link","faLink","question","faQuestion","industry","faIndustry","faClipboardCheck","getSectionNameForContentType","contentType","key","toLowerCase","i18n","exists","t","getTooltipForContentType","toString","getPageTitleForContentType","getContentTypeSectionIndex","getIconForContentType","iconType","IconType","FontAwesome","faTasks","faInfoCircle","faFileAlt","faBook","replace","getLibraryFilterNames","libraries","length","map","l","lib","filtersDict","LibraryFilter","libraryName","filter","join","getLibraryFilters","filters","getLibrarySortOrder","sortOrder","getLibraryFiltersDictionary","allLibrariesUnchecked","toLibraryFilterList","items","result","forEach","i","LibraryFilterGroup","selected","concat","children","c","push","libraryId","libraryNameKey","isDefault","parentGroup","this","setSelected","groupId","groupNameKey","f","suggestionsRunning","getSearchSuggestions","searchString","maxCount","a","trim","preparedSearchString","encodeURIComponent","suggestions","error","getRequirementsSearchResults","preparedLibrariesString","getStatsKey","err","results","fulltextResults","selectedLibraries","buildRequirementsSearchUrl","groupPageResults","groups","distinct","r","pages","p","reverseSortByMember","grp","summaryContentTypes","groupSummary","group","groupedCounts","ct","count","otherResults","sum","RadioButton","props","isChecked","onToggle","isEnabled","buttonGroup","className","type","value","disabled","radioGroup","checked","onChange","Checkbox","Filter","useTranslation","FilterGroup","groupName","RequirementsSearchFilter","useState","isOpen","setIsOpen","onBoxCollapseToggle","e","preventDefault","onFilterToggle","target","filterIds","setLibraries","title","onClick","icon","faMinusSquare","faPlusSquare","href","Collapse","SearchBoxStyle","noSuggestionsBox","element","noData","style","fontSize","textTransform","React","cloneElement","IsReportableSearchBox","onSubmit","suggest","ContentMarkdown","source","InputGroup","InputGroupAddon","addonType","InputGroupText","name","data","placeholder","popupSettings","height","listNoDataRender","Button","color","UncontrolledTooltip","BasicSearchBox","onClose","RequirementsSearch","language","setSearchString","lastPostedSearchString","setLastPostedSearchString","setSuggestions","autocompleteSuggest","setAutocompleteSuggest","wasLoaded","setWasLoaded","useEffect","autoFocus","document","querySelector","focus","runSearch","useCallback","str","history","nativeEvent","state","focusedItem","onLibraryChange","wasChanged","suggestion","userInput","sug","isBusy","Loading","boxStyle","is_reportable","HomePage","setPageTitle","useDDHPageContext"],"mappings":"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","file":"static/js/5.92b7e86d.chunk.js","sourcesContent":["import { sanitizeId } from \"./Common\";\r\nimport { i18n } from \"../ddh-translations\";\r\nimport { fetchServerUrl } from \"../util\";\r\nimport { IconLocator, IconType } from \"../components/IconRenderer\";\r\nimport {\r\n faTasks,\r\n faInfoCircle,\r\n faBook,\r\n faFileAlt,\r\n faLink,\r\n faQuestion,\r\n faIndustry,\r\n faClipboardCheck,\r\n} from \"@fortawesome/free-solid-svg-icons\";\r\nimport { IconProp } from \"@fortawesome/fontawesome-svg-core\";\r\n\r\nexport function buildPageUrl(pageId: string): string {\r\n return `/page/${sanitizeId(pageId)}`;\r\n}\r\n\r\n/**\r\n * Defines the header data and content for a page in the system.\r\n */\r\nexport interface DDHPage {\r\n /** The unique content ID used to retrieve this page. */\r\n id: string;\r\n\r\n /** The title of the page. Should be displayed at the top of the page and in link text to this page. */\r\n title: string;\r\n\r\n /** The type of page. Used to style and group links to this page. */\r\n contentType: string;\r\n\r\n navbarText?: string | undefined;\r\n\r\n navbarIcon?: IconLocator | undefined;\r\n\r\n /** The content of the page in markdown. */\r\n contentMarkdown: string;\r\n\r\n keywords: string[];\r\n\r\n libraries: string[] | null;\r\n\r\n collapseSectionsByDefault: boolean;\r\n}\r\n\r\n/**\r\n * Retrieves the complete contents of the page by doing a GET request to the API and returning the\r\n * resulting JSON. Returns a promise that resolves when the request is complete.\r\n * @param id The unique page content ID to retrieve.\r\n */\r\nexport function getPage(id: string, locale: string): Promise<DDHPage | null> {\r\n var url = `/api/page/${sanitizeId(id)}?locale=${locale}`;\r\n return fetchServerUrl(url)\r\n .then((response) => response.json())\r\n .then((page) => transformIconLocatorStringId(page))\r\n .catch((reason) => {\r\n console.log(`Error retrieving page ${url}`);\r\n console.log(reason);\r\n return null;\r\n });\r\n}\r\n\r\nconst iconStringToIdConversions: { [id: string]: IconProp } = {\r\n link: faLink,\r\n question: faQuestion,\r\n industry: faIndustry,\r\n \"clipboard-check\": faClipboardCheck,\r\n};\r\n\r\nfunction transformIconLocatorStringId(page: DDHPage | null) {\r\n if (\r\n page &&\r\n page.navbarIcon &&\r\n typeof page.navbarIcon.iconId === \"string\" &&\r\n iconStringToIdConversions[page.navbarIcon.iconId]\r\n ) {\r\n page.navbarIcon.iconId =\r\n iconStringToIdConversions[page.navbarIcon.iconId];\r\n }\r\n return page;\r\n}\r\n\r\n/**\r\n * Converts a page content type ID into a friendly name to show the user.\r\n * @param contentType The ID of the content type.\r\n */\r\nexport function getSectionNameForContentType(contentType: string): string {\r\n const key = `ContentTypeSectionName_${contentType.toLowerCase()}`;\r\n if (i18n.exists(key)) {\r\n return i18n.t(key);\r\n } else {\r\n return i18n.t(`ContentTypeSectionName_(default)`);\r\n }\r\n}\r\n\r\nexport function getTooltipForContentType(contentType: string): string | null {\r\n const key = `ContentTypeTooltip_${contentType.toLowerCase()}`;\r\n if (i18n.exists(key)) {\r\n return i18n.t(key).toString();\r\n } else {\r\n return null;\r\n }\r\n}\r\n\r\nexport function getPageTitleForContentType(contentType: string): string {\r\n const key = `ContentTypePageTitle_${contentType.toLowerCase()}`;\r\n if (i18n.exists(key)) {\r\n return i18n.t(key);\r\n } else {\r\n return i18n.t(`ContentTypePageTitle_(default)`);\r\n }\r\n}\r\n\r\n/** Defines the order in which contentTypes should be displayed in results. Higher weights are displayed first. */\r\nexport function getContentTypeSectionIndex(contentType: string): number {\r\n switch (contentType.toLowerCase()) {\r\n case \"requirement\":\r\n return 1000;\r\n case \"citation\":\r\n return 999;\r\n case \"document\":\r\n return 998;\r\n default:\r\n return 0;\r\n }\r\n}\r\n\r\nexport function getIconForContentType(contentType: string) {\r\n switch (contentType) {\r\n case \"requirement\":\r\n return {\r\n iconType: IconType.FontAwesome,\r\n iconId: faTasks,\r\n };\r\n case \"guidance\":\r\n return {\r\n iconType: IconType.FontAwesome,\r\n iconId: faInfoCircle,\r\n };\r\n case \"document\":\r\n return {\r\n iconType: IconType.FontAwesome,\r\n iconId: faFileAlt,\r\n };\r\n case \"glossary\":\r\n return {\r\n iconType: IconType.FontAwesome,\r\n iconId: faBook,\r\n };\r\n default:\r\n return null;\r\n }\r\n}\r\n","/**\r\n * Strips all characters other than a-z, A-Z, 0-9, and dashes (-) from a string.\r\n * @param id The ID to be sanitized.\r\n */\r\nexport function sanitizeId(id: string) {\r\n return id.replace(/[^a-zA-Z0-9-]/g, \"-\");\r\n}\r\n","import { TFunction } from \"i18next\";\r\n\r\n/**\r\n * Defines an item in the library filters list; either a container group of library filters, or a single library filter.\r\n */\r\nexport interface LibraryFilterItem {\r\n id: string;\r\n selected: boolean;\r\n sortOrder: number;\r\n setSelected: (selected: boolean) => void;\r\n}\r\n\r\n/**\r\n * Returns the full display names (separated by commas) for a list of library IDs.\r\n * @param libraries A list of library filter IDs.\r\n */\r\nexport function getLibraryFilterNames(\r\n libraries: string[] | null,\r\n t: TFunction\r\n) {\r\n if (libraries === null || libraries.length === 0) {\r\n return null;\r\n }\r\n\r\n return libraries\r\n .map((l) => {\r\n var lib = filtersDict[l];\r\n if (lib && lib instanceof LibraryFilter) {\r\n return lib.libraryName(t);\r\n }\r\n return null;\r\n })\r\n .filter((l) => l)\r\n .join(\", \");\r\n}\r\n\r\n/**\r\n * Returns all library filter IDs in the system.\r\n */\r\nexport function getLibraryFilterIDs() {\r\n return Object.keys(filtersDict);\r\n}\r\n\r\n/**\r\n * Returns all library filter objects in the system, as a tree.\r\n */\r\nexport function getLibraryFilters() {\r\n return filters;\r\n}\r\n\r\nexport function getLibrarySortOrder(id: string): number {\r\n return (filtersDict[id] && filtersDict[id].sortOrder) || 0;\r\n}\r\n\r\n/**\r\n * Returns a flattened dictionary of all library filter objects in the system, which\r\n * can be used to convert a library filter ID into a library filter object.\r\n */\r\nexport function getLibraryFiltersDictionary() {\r\n return filtersDict;\r\n}\r\n\r\nexport function allLibrariesUnchecked() {\r\n return toLibraryFilterList(filters).length === 0;\r\n}\r\n\r\n/**\r\n * Returns a list of the IDs of all checked LibraryFilter objects in the given set of LibraryFilterItems.\r\n * @param items A list of library filter objects representing both filters and container groups\r\n */\r\nexport function toLibraryFilterList(items: LibraryFilterItem[]): string[] {\r\n var result: string[] = [];\r\n\r\n items.forEach((i) => {\r\n if (i instanceof LibraryFilterGroup) {\r\n if (i.selected) {\r\n result = result.concat(\r\n i.children.filter((c) => c.selected).map((c) => c.id)\r\n );\r\n }\r\n } else if (i instanceof LibraryFilter) {\r\n if (i.selected) {\r\n result.push(i.id);\r\n }\r\n }\r\n });\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Represents a single library filter in the system.\r\n *\r\n * If contained in a LibraryFilterGroup, it is mutually exclusive with other items in the group.\r\n */\r\nexport class LibraryFilter implements LibraryFilterItem {\r\n /**\r\n * The library filter ID. Used to keep track of which library filters are selected\r\n * by the user and tagged to specific pages and answers.\r\n */\r\n id: string;\r\n // libraryName: string;\r\n libraryNameKey: string;\r\n selected: boolean;\r\n sortOrder: number;\r\n parentGroup: LibraryFilterGroup | null;\r\n\r\n constructor(\r\n libraryId: string,\r\n libraryNameKey: string,\r\n sortOrder: number,\r\n isDefault: boolean\r\n ) {\r\n this.id = libraryId;\r\n this.libraryNameKey = libraryNameKey;\r\n this.selected = isDefault;\r\n this.parentGroup = null;\r\n this.sortOrder = sortOrder;\r\n }\r\n\r\n libraryName(t: TFunction) {\r\n return t(this.libraryNameKey);\r\n }\r\n\r\n setSelected(selected: boolean) {\r\n this.selected = selected;\r\n\r\n if (selected && this.parentGroup) {\r\n this.parentGroup.children\r\n .filter((c) => c.id !== this.id)\r\n .forEach((c) => c.setSelected(false));\r\n }\r\n }\r\n}\r\n\r\nexport class LibraryFilterGroup implements LibraryFilterItem {\r\n id: string;\r\n // groupName: string;\r\n groupNameKey: string;\r\n selected: boolean;\r\n sortOrder: number;\r\n children: LibraryFilter[];\r\n\r\n constructor(\r\n groupId: string,\r\n groupNameKey: string,\r\n isDefault: boolean,\r\n children: LibraryFilter[]\r\n ) {\r\n this.id = groupId;\r\n this.groupNameKey = groupNameKey;\r\n this.selected = isDefault;\r\n this.children = children;\r\n this.sortOrder = 0;\r\n\r\n this.children.forEach((c) => (c.parentGroup = this));\r\n }\r\n\r\n groupName(t: TFunction) {\r\n return t(this.groupNameKey);\r\n }\r\n\r\n setSelected(selected: boolean) {\r\n this.selected = selected;\r\n }\r\n}\r\n\r\nvar filters: LibraryFilterItem[] = [\r\n new LibraryFilterGroup(\"csa-group\", \"CSAFull\", true, [\r\n new LibraryFilter(\"csa\", \"CSAOnly\", 30, true),\r\n new LibraryFilter(\"msqp\", \"CSAWithMSQP\", 20, false),\r\n ]),\r\n new LibraryFilter(\"ap\", \"AdditionalProtocol\", 10, true),\r\n];\r\n\r\nvar filtersDict: { [id: string]: LibraryFilterItem } = {};\r\nfilters.forEach((f) => {\r\n filtersDict[f.id] = f;\r\n if (f instanceof LibraryFilterGroup) {\r\n f.children.forEach((c) => (filtersDict[c.id] = c));\r\n }\r\n});\r\n","import { TFunction } from \"i18next\";\r\nimport {\r\n distinct,\r\n fetchServerUrl,\r\n getStatsKey,\r\n reverseSortByMember,\r\n sum,\r\n} from \"../util\";\r\nimport { getContentTypeSectionIndex } from \"./Pages\";\r\n\r\nconst minSuggestionLength: number = 3;\r\nvar suggestionsRunning: boolean = false;\r\nexport async function getSearchSuggestions(\r\n searchString: string | null,\r\n locale: string,\r\n maxCount: number\r\n): Promise<string[]> {\r\n if (\r\n !searchString ||\r\n searchString.trim().length < minSuggestionLength ||\r\n suggestionsRunning\r\n )\r\n return [\"\"];\r\n\r\n var preparedSearchString = encodeURIComponent(searchString);\r\n suggestionsRunning = true;\r\n\r\n try {\r\n var response = await fetchServerUrl(\r\n `/api/suggestions/${preparedSearchString}?maxCount=${encodeURIComponent(\r\n maxCount\r\n )}&locale=${locale}`\r\n );\r\n suggestionsRunning = false;\r\n var json = await response.json();\r\n return json.suggestions;\r\n } catch (err) {\r\n console.error(err);\r\n return [\"\"];\r\n }\r\n}\r\n\r\nexport interface DDHRequirementsSearchResult {\r\n results: DDHAnswerGrouping[];\r\n fulltextResults: DDHFulltextResult[];\r\n selectedLibraries: string[] | null;\r\n}\r\n\r\nexport interface DDHFulltextResult {\r\n id: string;\r\n objectType: string;\r\n url: string | null;\r\n score: number;\r\n contentType: string;\r\n highlightedTitle: string;\r\n highlightedContentMarkdown: string;\r\n}\r\n\r\nexport interface DDHAnswerGrouping {\r\n answer: DDHAnswerSearchResult | null;\r\n searchTerms: DDHKeywordGrouping[];\r\n matchingLibraries: string[] | null;\r\n pages: DDHPageSearchResult[];\r\n}\r\n\r\nexport interface DDHPageSearchResult {\r\n id: string;\r\n searchTerms: DDHKeywordGrouping[];\r\n libraries: string[] | null;\r\n counts: number;\r\n title: string;\r\n contentType: string;\r\n}\r\n\r\nexport interface DDHPageResultsGrouping {\r\n contentType: string;\r\n pages: DDHPageSearchResult[];\r\n}\r\n\r\nexport interface DDHKeywordGrouping {\r\n canonical: string;\r\n searchTerms: string[];\r\n}\r\n\r\n/**\r\n * Defines a mapping between a search keyword and a colloquial answer, as returned from a search.\r\n */\r\nexport interface DDHAnswerSearchResult {\r\n id: string;\r\n answerType: string;\r\n searchTerms: DDHKeywordGrouping[];\r\n libraries: string[] | null;\r\n relationshipText: string;\r\n contentMarkdown: string;\r\n}\r\n\r\n/**\r\n * Returns results for a requirements search.\r\n * @param searchString The search string input by the user.\r\n */\r\nexport function getRequirementsSearchResults(\r\n searchString: string,\r\n locale: string,\r\n libraries: string[] | null\r\n): Promise<DDHRequirementsSearchResult> {\r\n if (libraries && libraries.length === 0) libraries = null;\r\n\r\n console.log(\r\n `Running requirements search for ${searchString} in libraries ${\r\n (libraries && libraries.join(\", \")) || \"(null)\"\r\n }`\r\n );\r\n\r\n var preparedSearchString = encodeURIComponent(searchString);\r\n var preparedLibrariesString = libraries\r\n ? `libraries=${libraries.map((l) => encodeURIComponent(l)).join(\",\")}&`\r\n : \"\";\r\n\r\n return fetchServerUrl(\r\n `/api/search/${preparedSearchString}?${preparedLibrariesString}statsKey=${encodeURIComponent(\r\n getStatsKey()\r\n )}&locale=${locale}`\r\n )\r\n .then((response: any) => response.json())\r\n .catch((err) => {\r\n console.error(err);\r\n return {\r\n results: [],\r\n fulltextResults: [],\r\n selectedLibraries: null,\r\n };\r\n });\r\n}\r\n\r\nexport function buildRequirementsSearchUrl(\r\n searchString: string | null\r\n): string {\r\n return `/requirements-search/${\r\n searchString == null ? \"\" : encodeURIComponent(searchString)\r\n }`;\r\n}\r\n\r\nexport function groupPageResults(results: DDHPageSearchResult[]) {\r\n var groups: DDHPageResultsGrouping[] = distinct(\r\n results.map((r) => r.contentType)\r\n ).map((contentType) => {\r\n var pages = results.filter((p) => p.contentType === contentType);\r\n return {\r\n contentType: contentType,\r\n pages: pages,\r\n };\r\n });\r\n\r\n reverseSortByMember(groups, (grp: DDHPageResultsGrouping) =>\r\n getContentTypeSectionIndex(grp.contentType)\r\n );\r\n return groups;\r\n}\r\n\r\nconst summaryContentTypes = [\"requirement\", \"guidance\", \"glossary\", \"document\"];\r\nexport function groupSummary(t: TFunction, group: DDHAnswerGrouping): string[] {\r\n var results: string[] = [];\r\n\r\n const groupedCounts = summaryContentTypes.map(\r\n (ct) => group.pages.filter((p) => p.contentType === ct).length\r\n );\r\n\r\n for (var i = 0; i < groupedCounts.length; i++) {\r\n const count = groupedCounts[i];\r\n if (count > 0) {\r\n results.push(\r\n `${count} ${t(\r\n `SearchResultSummary_${summaryContentTypes[i]}${\r\n count === 1 ? \"\" : \"s\"\r\n }`\r\n )}`\r\n );\r\n }\r\n }\r\n\r\n const otherResults = group.pages.length - sum(groupedCounts);\r\n if (otherResults > 0) {\r\n results.push(\r\n `${otherResults} ${t(\r\n `SearchResultSummary_(${\r\n group.pages.length === otherResults ? \"keyword\" : \"other\"\r\n }${otherResults === 1 ? \"\" : \"s\"})`\r\n )}`\r\n );\r\n }\r\n\r\n if (results.length === 0) {\r\n results.push(t(\"SearchResultSummary_(none)\"));\r\n }\r\n\r\n return results;\r\n}\r\n","import React, { useState } from \"react\";\r\nimport {\r\n getLibraryFilters,\r\n LibraryFilter,\r\n getLibraryFiltersDictionary,\r\n toLibraryFilterList,\r\n LibraryFilterGroup,\r\n allLibrariesUnchecked,\r\n} from \"../datatypes/Libraries\";\r\nimport { Collapse } from \"reactstrap\";\r\nimport { faPlusSquare, faMinusSquare } from \"@fortawesome/free-solid-svg-icons\";\r\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\r\nimport { useTranslation } from \"react-i18next\";\r\n\r\ninterface RequirementsSearchFilterProps {\r\n setLibraries: (libraries: string[] | null) => void;\r\n}\r\n\r\nfunction RadioButton(props: {\r\n libraryId: string;\r\n libraryName: string;\r\n isChecked: boolean;\r\n onToggle: any;\r\n isEnabled: boolean;\r\n buttonGroup: string;\r\n}) {\r\n const {\r\n libraryId,\r\n libraryName,\r\n isChecked,\r\n onToggle,\r\n isEnabled,\r\n buttonGroup,\r\n } = props;\r\n\r\n return (\r\n <div className=\"form-check\" key={libraryId}>\r\n <label className=\"form-check-label\">\r\n <input\r\n type=\"radio\"\r\n className=\"form-check-input\"\r\n value={libraryId}\r\n disabled={!isEnabled}\r\n radioGroup={buttonGroup}\r\n checked={isChecked}\r\n onChange={onToggle}\r\n />{\" \"}\r\n {libraryName}\r\n </label>\r\n </div>\r\n );\r\n}\r\n\r\nfunction Checkbox(props: {\r\n libraryId: string;\r\n libraryName: string;\r\n isChecked: boolean;\r\n onToggle: any;\r\n}) {\r\n const { libraryId, libraryName, isChecked, onToggle } = props;\r\n\r\n return (\r\n <div className=\"form-check\" key={libraryId}>\r\n <label className=\"form-check-label\">\r\n <input\r\n type=\"checkbox\"\r\n className=\"form-check-input\"\r\n value={libraryId}\r\n checked={isChecked}\r\n onChange={onToggle}\r\n />{\" \"}\r\n {libraryName}\r\n </label>\r\n </div>\r\n );\r\n}\r\n\r\nfunction Filter(props: { filter: LibraryFilter; onToggle: any }) {\r\n const { filter, onToggle } = props;\r\n const { t } = useTranslation();\r\n return (\r\n <Checkbox\r\n libraryId={filter.id}\r\n libraryName={filter.libraryName(t)}\r\n isChecked={filter.selected}\r\n onToggle={onToggle}\r\n />\r\n );\r\n}\r\n\r\nfunction FilterGroup(props: { grp: LibraryFilterGroup; onToggle: any }) {\r\n const { grp, onToggle } = props;\r\n const { t } = useTranslation();\r\n\r\n return (\r\n <div key={grp.id}>\r\n <Checkbox\r\n libraryId={grp.id}\r\n libraryName={grp.groupName(t)}\r\n isChecked={grp.selected}\r\n onToggle={onToggle}\r\n />\r\n <div className=\"pl-4\">\r\n {grp.children.map((c) => (\r\n <RadioButton\r\n key={c.libraryName(t)}\r\n libraryId={c.id}\r\n libraryName={c.libraryName(t)}\r\n isChecked={c.selected}\r\n onToggle={onToggle}\r\n isEnabled={grp.selected}\r\n buttonGroup={grp.id}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nconst filters = getLibraryFilters();\r\nconst filtersDict = getLibraryFiltersDictionary();\r\n\r\nexport default function RequirementsSearchFilter(\r\n props: RequirementsSearchFilterProps\r\n) {\r\n const { t } = useTranslation();\r\n const [isOpen, setIsOpen] = useState<boolean>(true);\r\n\r\n const onBoxCollapseToggle = function (e: any) {\r\n setIsOpen(!isOpen);\r\n e.preventDefault();\r\n return false;\r\n };\r\n\r\n const onFilterToggle = function (e: any) {\r\n var id = e.target.value;\r\n if (filtersDict[id]) {\r\n filtersDict[id].setSelected(e.target.checked);\r\n // Don't deselect the last checkbox\r\n if (allLibrariesUnchecked()) filtersDict[id].setSelected(true);\r\n }\r\n\r\n var filterIds = toLibraryFilterList(filters);\r\n props.setLibraries(filterIds.length > 0 ? filterIds : null);\r\n };\r\n\r\n return (\r\n <div className=\"card filter-box mb-2\">\r\n <div className=\"card-header bg-secondary\">\r\n <button\r\n className=\"btn btn-link m-0 p-0 mr-2\"\r\n title={isOpen ? t(\"CollapseFilters\") : t(\"ExpandFilters\")}\r\n onClick={onBoxCollapseToggle}\r\n >\r\n <FontAwesomeIcon\r\n title={\r\n isOpen ? t(\"CollapseFilters\") : t(\"ExpandFilters\")\r\n }\r\n icon={isOpen ? faMinusSquare : faPlusSquare}\r\n />\r\n </button>\r\n <a\r\n href=\"#\"\r\n title={isOpen ? \"Collapse Filters\" : \"Expand Filters\"}\r\n onClick={onBoxCollapseToggle}\r\n >\r\n {t(\"SearchFilterTitle\")}\r\n </a>\r\n </div>\r\n <Collapse isOpen={isOpen} className=\"form-group p-2 mb-0 card-body\">\r\n <small className=\"font-italic mt-2 mb-2\">\r\n {t(\"SearchFilterOneMustBeSelected\")}\r\n </small>\r\n {filters.map((f) => {\r\n if (f instanceof LibraryFilterGroup) {\r\n return (\r\n <FilterGroup\r\n key={f.groupName(t)}\r\n grp={f}\r\n onToggle={onFilterToggle}\r\n />\r\n );\r\n } else if (f instanceof LibraryFilter) {\r\n return (\r\n <Filter\r\n key={f.libraryName(t)}\r\n filter={f}\r\n onToggle={onFilterToggle}\r\n />\r\n );\r\n } else {\r\n return null;\r\n }\r\n })}\r\n </Collapse>\r\n </div>\r\n );\r\n}\r\n","import { AutoComplete } from \"@progress/kendo-react-dropdowns\";\r\nimport React, { useCallback, useEffect, useState } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport {\r\n Button,\r\n InputGroup,\r\n InputGroupAddon,\r\n InputGroupText,\r\n UncontrolledTooltip,\r\n} from \"reactstrap\";\r\nimport {\r\n buildRequirementsSearchUrl,\r\n getSearchSuggestions,\r\n} from \"../datatypes/RequirementsSearch\";\r\nimport ContentMarkdown from \"./ContentMarkdown\";\r\nimport Loading from \"./Loading\";\r\nimport RequirementsSearchFilter from \"./RequirementsSearchFilter\";\r\nimport { i18n } from \"../ddh-translations\";\r\n\r\ninterface RequirementsSearchProps {\r\n searchString: string;\r\n history: any;\r\n boxStyle?: SearchBoxStyle | null | undefined;\r\n setLibraries?:\r\n | ((searchString: string, libraries: string[] | null) => void)\r\n | undefined;\r\n autoFocus: boolean;\r\n isBusy: boolean;\r\n}\r\n\r\nexport enum SearchBoxStyle {\r\n basic,\r\n is_reportable,\r\n}\r\n\r\nfunction noSuggestionsBox(element: React.ReactElement<HTMLDivElement>) {\r\n const noData = (\r\n <h3 style={{ fontSize: \"1em\", textTransform: \"none\" }}>\r\n {i18n.t(\"NoSuggestions\")}\r\n </h3>\r\n );\r\n\r\n return React.cloneElement(element, { ...element.props }, noData);\r\n}\r\n\r\nfunction IsReportableSearchBox(props: {\r\n searchString: string;\r\n onSubmit: any;\r\n onChange: any;\r\n suggest: string;\r\n suggestions: string[];\r\n}) {\r\n const { searchString, onSubmit, onChange, suggest, suggestions } = props;\r\n const { t } = useTranslation();\r\n\r\n return (\r\n <form onSubmit={onSubmit}>\r\n <ContentMarkdown source={t(\"RequirementsSearchIntroText\")} />\r\n <div\r\n id=\"requirements-search\"\r\n className=\"d-flex flex-wrap search-controls\"\r\n >\r\n <div>\r\n <InputGroup className=\"mb-3\">\r\n <InputGroupAddon addonType=\"prepend\">\r\n <InputGroupText className=\"font-weight-bold\">\r\n {t(\"IsReportablePrefix\")}\r\n </InputGroupText>\r\n </InputGroupAddon>\r\n <AutoComplete\r\n name=\"requirements-search-input\"\r\n className=\"search-box\"\r\n data={suggestions}\r\n placeholder={t(\"SearchPlaceholder\")}\r\n value={searchString}\r\n onChange={onChange}\r\n suggest={suggest}\r\n aria-label=\"Search\"\r\n popupSettings={{ height: \"300px\" }}\r\n listNoDataRender={noSuggestionsBox}\r\n />\r\n <InputGroupAddon addonType=\"append\">\r\n <InputGroupText className=\"font-weight-bold\">\r\n {t(\"IsReportableSuffix\")}\r\n </InputGroupText>\r\n </InputGroupAddon>\r\n </InputGroup>\r\n </div>\r\n <div className=\"pl-2 pr-2\">\r\n <Button color=\"primary\" id=\"requirements-search-button\">\r\n {t(\"SearchButton\")}\r\n </Button>\r\n </div>\r\n </div>\r\n {searchString ? (\r\n <UncontrolledTooltip target=\"requirements-search\">\r\n {t(\"SearchFor\")} \"{searchString}\"\r\n </UncontrolledTooltip>\r\n ) : (\r\n <></>\r\n )}\r\n </form>\r\n );\r\n}\r\n\r\nfunction BasicSearchBox(props: {\r\n searchString: string;\r\n onSubmit: any;\r\n onChange: any;\r\n onClose: any;\r\n suggest: string;\r\n suggestions: string[];\r\n setLibraries: ((libraries: string[] | null) => void) | null;\r\n}) {\r\n const {\r\n searchString,\r\n onSubmit,\r\n onChange,\r\n onClose,\r\n suggest,\r\n suggestions,\r\n setLibraries,\r\n } = props;\r\n\r\n const { t } = useTranslation();\r\n\r\n return (\r\n <form onSubmit={onSubmit}>\r\n <ContentMarkdown source={t(\"RequirementsSearchIntroText\")} />\r\n <div\r\n id=\"requirements-search\"\r\n className=\"d-flex flex-wrap search-controls\"\r\n >\r\n <div className=\"flex-shrink-1 align-baseline\">\r\n <AutoComplete\r\n name=\"requirements-search-input\"\r\n className=\"search-box\"\r\n data={suggestions}\r\n placeholder={t(\"SearchPlaceholder\")}\r\n value={searchString}\r\n onChange={onChange}\r\n onClose={onClose}\r\n suggest={suggest}\r\n aria-label=\"Search\"\r\n popupSettings={{ height: \"300px\" }}\r\n listNoDataRender={noSuggestionsBox}\r\n />\r\n </div>\r\n <div className=\"pl-2 align-baseline\">\r\n <button\r\n className=\"btn btn-primary\"\r\n id=\"requirements-search-button\"\r\n >\r\n {t(\"SearchButton\")}\r\n </button>\r\n </div>\r\n </div>\r\n {searchString ? (\r\n <UncontrolledTooltip target=\"requirements-search\">\r\n {t(\"SearchFor\")} \"{searchString}\"\r\n </UncontrolledTooltip>\r\n ) : (\r\n <></>\r\n )}\r\n {setLibraries ? (\r\n <RequirementsSearchFilter setLibraries={setLibraries} />\r\n ) : (\r\n <></>\r\n )}\r\n </form>\r\n );\r\n}\r\n\r\nexport default function RequirementsSearch(props: RequirementsSearchProps) {\r\n const {\r\n i18n: { language: locale },\r\n } = useTranslation();\r\n const [searchString, setSearchString] = useState<string>(\r\n props.searchString\r\n );\r\n const [lastPostedSearchString, setLastPostedSearchString] =\r\n useState<string>(props.searchString);\r\n\r\n const [suggestions, setSuggestions] = useState<string[]>([]);\r\n const [autocompleteSuggest, setAutocompleteSuggest] = useState<string>(\"\");\r\n\r\n // Auto focus the search box\r\n const [wasLoaded, setWasLoaded] = useState<boolean>(false);\r\n useEffect(() => {\r\n if (!wasLoaded) {\r\n setWasLoaded(true);\r\n if (props.autoFocus) {\r\n (\r\n document.querySelector(\r\n \".search-box input\"\r\n ) as HTMLInputElement\r\n )?.focus();\r\n }\r\n }\r\n }, [wasLoaded, props.autoFocus]);\r\n\r\n useEffect(() => {\r\n // Keeps track of changes to searchString pushed down from the parent page\r\n // This allows us to change the text in the search box when navigating with back/foward in browser\r\n if (props.searchString !== lastPostedSearchString) {\r\n setLastPostedSearchString(props.searchString);\r\n setSearchString(props.searchString);\r\n }\r\n }, [lastPostedSearchString, props.searchString]);\r\n\r\n const runSearch = useCallback(\r\n (str: string) => {\r\n console.log(`RequirementsSearch component got search \"${str}\"`);\r\n props.history.push(buildRequirementsSearchUrl(str));\r\n },\r\n [props.history]\r\n );\r\n\r\n // On form submit, change the URL\r\n const onSubmit = useCallback(\r\n (e: any) => {\r\n e.preventDefault();\r\n runSearch(searchString);\r\n },\r\n [runSearch, searchString]\r\n );\r\n\r\n // On autocomplete close, trigger search depending on how it occurred\r\n const onClose = useCallback(\r\n (e: any) => {\r\n if (\r\n e.nativeEvent &&\r\n e.nativeEvent.key &&\r\n e.nativeEvent.key === \"Enter\"\r\n ) {\r\n if (\r\n e.target &&\r\n e.target.state &&\r\n e.target.state.focusedItem &&\r\n e.target.state.focusedItem !== \"\" &&\r\n e.target.state.focusedItem !== searchString\r\n ) {\r\n runSearch(e.target.state.focusedItem);\r\n } else {\r\n onSubmit(e.nativeEvent);\r\n }\r\n return;\r\n }\r\n },\r\n [onSubmit, runSearch, searchString]\r\n );\r\n\r\n // On library change, also trigger search update\r\n const onLibraryChange = useCallback(\r\n (libraries: string[] | null) => {\r\n if (props.setLibraries) props.setLibraries(searchString, libraries);\r\n },\r\n [props, searchString]\r\n );\r\n\r\n // On text box change, update the current search string\r\n const onChange = useCallback(\r\n (e: any) => {\r\n var wasChanged = e.target.value !== searchString;\r\n setSearchString(e.target.value);\r\n\r\n if (\r\n e.nativeEvent &&\r\n e.nativeEvent.key &&\r\n e.nativeEvent.key === \"Enter\"\r\n ) {\r\n return;\r\n }\r\n\r\n setAutocompleteSuggest(e.suggestion ? e.suggestion.value : \"\");\r\n if (\r\n wasChanged &&\r\n e.target.value !== null &&\r\n e.target.value.trim() !== \"\"\r\n ) {\r\n getSearchSuggestions(\r\n e.suggestion ? e.suggestion.userInput : \"\",\r\n locale,\r\n 20\r\n ).then((sug) => setSuggestions(sug));\r\n }\r\n },\r\n [locale, searchString]\r\n );\r\n\r\n if (props.isBusy) {\r\n return <Loading />;\r\n }\r\n\r\n switch (props.boxStyle) {\r\n case SearchBoxStyle.is_reportable:\r\n return (\r\n <IsReportableSearchBox\r\n searchString={searchString}\r\n onSubmit={onSubmit}\r\n onChange={onChange}\r\n suggest={autocompleteSuggest}\r\n suggestions={suggestions}\r\n />\r\n );\r\n\r\n default:\r\n return (\r\n <BasicSearchBox\r\n searchString={searchString}\r\n onSubmit={onSubmit}\r\n onChange={onChange}\r\n onClose={onClose}\r\n suggest={autocompleteSuggest}\r\n suggestions={suggestions}\r\n setLibraries={onLibraryChange}\r\n />\r\n );\r\n }\r\n}\r\n","import React, { useEffect } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport ContentMarkdown from \"../components/ContentMarkdown\";\r\nimport { useDDHPageContext } from \"../components/DDHPageContext\";\r\nimport RequirementsSearch, {\r\n SearchBoxStyle,\r\n} from \"../components/RequirementsSearch\";\r\n\r\nexport default function HomePage(props: any) {\r\n const { t } = useTranslation();\r\n\r\n const { setPageTitle } = useDDHPageContext();\r\n\r\n useEffect(() => {\r\n setPageTitle(t(\"HomePageNavBar\"), \"\");\r\n }, [setPageTitle, t]);\r\n\r\n return (\r\n <div id=\"content\">\r\n <ContentMarkdown source={t(\"HomePageContentUpper\")} />\r\n <RequirementsSearch\r\n autoFocus={false}\r\n isBusy={false}\r\n searchString=\"\"\r\n history={props.history}\r\n boxStyle={SearchBoxStyle.is_reportable}\r\n />\r\n <ContentMarkdown source={t(\"HomePageContentLower\")} />\r\n </div>\r\n );\r\n}\r\n"],"sourceRoot":""}