{"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":""}