@blaze-cms/plugin-search-ui 0.110.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +345 -0
  2. package/LICENSE +674 -0
  3. package/README.md +45 -0
  4. package/babel.config.js +3 -0
  5. package/jest.config.js +5 -0
  6. package/lib/application/query/index.js +32 -0
  7. package/lib/application/query/index.js.map +1 -0
  8. package/lib/components/SearchAdmin/RecentSearches/RecentSearches.js +62 -0
  9. package/lib/components/SearchAdmin/RecentSearches/RecentSearches.js.map +1 -0
  10. package/lib/components/SearchAdmin/RecentSearches/index.js +16 -0
  11. package/lib/components/SearchAdmin/RecentSearches/index.js.map +1 -0
  12. package/lib/components/SearchAdmin/SearchAdmin.js +191 -0
  13. package/lib/components/SearchAdmin/SearchAdmin.js.map +1 -0
  14. package/lib/components/SearchAdmin/SearchBar/SearchBar.js +72 -0
  15. package/lib/components/SearchAdmin/SearchBar/SearchBar.js.map +1 -0
  16. package/lib/components/SearchAdmin/SearchBar/index.js +16 -0
  17. package/lib/components/SearchAdmin/SearchBar/index.js.map +1 -0
  18. package/lib/components/SearchAdmin/SearchResults/SearchResults.js +200 -0
  19. package/lib/components/SearchAdmin/SearchResults/SearchResults.js.map +1 -0
  20. package/lib/components/SearchAdmin/SearchResults/index.js +16 -0
  21. package/lib/components/SearchAdmin/SearchResults/index.js.map +1 -0
  22. package/lib/components/SearchAdmin/TriggerModal/TriggerModal.js +30 -0
  23. package/lib/components/SearchAdmin/TriggerModal/TriggerModal.js.map +1 -0
  24. package/lib/components/SearchAdmin/TriggerModal/index.js +16 -0
  25. package/lib/components/SearchAdmin/TriggerModal/index.js.map +1 -0
  26. package/lib/components/SearchAdmin/index.js +16 -0
  27. package/lib/components/SearchAdmin/index.js.map +1 -0
  28. package/lib/components/SearchPublishedContent/SearchPublishedContent.js +216 -0
  29. package/lib/components/SearchPublishedContent/SearchPublishedContent.js.map +1 -0
  30. package/lib/components/SearchPublishedContent/index.js +16 -0
  31. package/lib/components/SearchPublishedContent/index.js.map +1 -0
  32. package/lib/components/useLocalStorage/index.js +16 -0
  33. package/lib/components/useLocalStorage/index.js.map +1 -0
  34. package/lib/components/useLocalStorage/useLocalStorage.js +36 -0
  35. package/lib/components/useLocalStorage/useLocalStorage.js.map +1 -0
  36. package/lib/components/useSearch/index.js +16 -0
  37. package/lib/components/useSearch/index.js.map +1 -0
  38. package/lib/components/useSearch/useSearch.js +154 -0
  39. package/lib/components/useSearch/useSearch.js.map +1 -0
  40. package/lib/components/useSearchResults/index.js +16 -0
  41. package/lib/components/useSearchResults/index.js.map +1 -0
  42. package/lib/components/useSearchResults/useSearchResults.js +102 -0
  43. package/lib/components/useSearchResults/useSearchResults.js.map +1 -0
  44. package/lib/constants.js +25 -0
  45. package/lib/constants.js.map +1 -0
  46. package/lib/index.js +34 -0
  47. package/lib/index.js.map +1 -0
  48. package/lib-es/application/query/index.js +34 -0
  49. package/lib-es/application/query/index.js.map +1 -0
  50. package/lib-es/components/SearchAdmin/RecentSearches/RecentSearches.js +40 -0
  51. package/lib-es/components/SearchAdmin/RecentSearches/RecentSearches.js.map +1 -0
  52. package/lib-es/components/SearchAdmin/RecentSearches/index.js +3 -0
  53. package/lib-es/components/SearchAdmin/RecentSearches/index.js.map +1 -0
  54. package/lib-es/components/SearchAdmin/SearchAdmin.js +126 -0
  55. package/lib-es/components/SearchAdmin/SearchAdmin.js.map +1 -0
  56. package/lib-es/components/SearchAdmin/SearchBar/SearchBar.js +54 -0
  57. package/lib-es/components/SearchAdmin/SearchBar/SearchBar.js.map +1 -0
  58. package/lib-es/components/SearchAdmin/SearchBar/index.js +3 -0
  59. package/lib-es/components/SearchAdmin/SearchBar/index.js.map +1 -0
  60. package/lib-es/components/SearchAdmin/SearchResults/SearchResults.js +120 -0
  61. package/lib-es/components/SearchAdmin/SearchResults/SearchResults.js.map +1 -0
  62. package/lib-es/components/SearchAdmin/SearchResults/index.js +3 -0
  63. package/lib-es/components/SearchAdmin/SearchResults/index.js.map +1 -0
  64. package/lib-es/components/SearchAdmin/TriggerModal/TriggerModal.js +16 -0
  65. package/lib-es/components/SearchAdmin/TriggerModal/TriggerModal.js.map +1 -0
  66. package/lib-es/components/SearchAdmin/TriggerModal/index.js +3 -0
  67. package/lib-es/components/SearchAdmin/TriggerModal/index.js.map +1 -0
  68. package/lib-es/components/SearchAdmin/index.js +3 -0
  69. package/lib-es/components/SearchAdmin/index.js.map +1 -0
  70. package/lib-es/components/SearchPublishedContent/SearchPublishedContent.js +157 -0
  71. package/lib-es/components/SearchPublishedContent/SearchPublishedContent.js.map +1 -0
  72. package/lib-es/components/SearchPublishedContent/index.js +3 -0
  73. package/lib-es/components/SearchPublishedContent/index.js.map +1 -0
  74. package/lib-es/components/useLocalStorage/index.js +3 -0
  75. package/lib-es/components/useLocalStorage/index.js.map +1 -0
  76. package/lib-es/components/useLocalStorage/useLocalStorage.js +19 -0
  77. package/lib-es/components/useLocalStorage/useLocalStorage.js.map +1 -0
  78. package/lib-es/components/useSearch/index.js +3 -0
  79. package/lib-es/components/useSearch/index.js.map +1 -0
  80. package/lib-es/components/useSearch/useSearch.js +100 -0
  81. package/lib-es/components/useSearch/useSearch.js.map +1 -0
  82. package/lib-es/components/useSearchResults/index.js +3 -0
  83. package/lib-es/components/useSearchResults/index.js.map +1 -0
  84. package/lib-es/components/useSearchResults/useSearchResults.js +57 -0
  85. package/lib-es/components/useSearchResults/useSearchResults.js.map +1 -0
  86. package/lib-es/constants.js +10 -0
  87. package/lib-es/constants.js.map +1 -0
  88. package/lib-es/index.js +5 -0
  89. package/lib-es/index.js.map +1 -0
  90. package/package.json +56 -0
  91. package/src/application/query/index.js +28 -0
  92. package/src/components/SearchAdmin/RecentSearches/RecentSearches.js +33 -0
  93. package/src/components/SearchAdmin/RecentSearches/index.js +3 -0
  94. package/src/components/SearchAdmin/SearchAdmin.js +129 -0
  95. package/src/components/SearchAdmin/SearchBar/SearchBar.js +58 -0
  96. package/src/components/SearchAdmin/SearchBar/index.js +3 -0
  97. package/src/components/SearchAdmin/SearchResults/SearchResults.js +112 -0
  98. package/src/components/SearchAdmin/SearchResults/index.js +3 -0
  99. package/src/components/SearchAdmin/TriggerModal/TriggerModal.js +17 -0
  100. package/src/components/SearchAdmin/TriggerModal/index.js +3 -0
  101. package/src/components/SearchAdmin/index.js +3 -0
  102. package/src/components/SearchPublishedContent/SearchPublishedContent.js +157 -0
  103. package/src/components/SearchPublishedContent/index.js +3 -0
  104. package/src/components/useLocalStorage/index.js +3 -0
  105. package/src/components/useLocalStorage/useLocalStorage.js +18 -0
  106. package/src/components/useSearch/index.js +3 -0
  107. package/src/components/useSearch/useSearch.js +85 -0
  108. package/src/components/useSearchResults/index.js +3 -0
  109. package/src/components/useSearchResults/useSearchResults.js +38 -0
  110. package/src/constants.js +19 -0
  111. package/src/index.js +5 -0
@@ -0,0 +1,57 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
4
+
5
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6
+
7
+ import { useState, useEffect } from 'react';
8
+ import useSearch from '../useSearch';
9
+
10
+ function useSearchResults({
11
+ queryKey,
12
+ resultKeys,
13
+ entities,
14
+ fields
15
+ }) {
16
+ const [{
17
+ searchedValue,
18
+ loading,
19
+ data: {
20
+ results,
21
+ total
22
+ }
23
+ }, setParams] = useSearch({
24
+ queryKey,
25
+ resultKeys,
26
+ entities,
27
+ fields
28
+ });
29
+ const [currentResults, setCurrentResults] = useState([]);
30
+ const [allResults, setAllResults] = useState([]);
31
+ useEffect(() => {
32
+ if (currentResults.length !== results.length) {
33
+ setAllResults([...allResults, ...results]);
34
+ setCurrentResults(results);
35
+ }
36
+ }, [allResults, currentResults, currentResults.length, results]);
37
+
38
+ const clearList = params => {
39
+ setAllResults([]);
40
+ setParams(_objectSpread(_objectSpread({}, params), {}, {
41
+ offset: 0
42
+ }));
43
+ };
44
+
45
+ const setQueryParams = params => {
46
+ params.value !== searchedValue ? clearList(params) : setParams(params);
47
+ };
48
+
49
+ return [{
50
+ loading,
51
+ results: allResults,
52
+ total
53
+ }, setQueryParams];
54
+ }
55
+
56
+ export default useSearchResults;
57
+ //# sourceMappingURL=useSearchResults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/useSearchResults/useSearchResults.js"],"names":["useState","useEffect","useSearch","useSearchResults","queryKey","resultKeys","entities","fields","searchedValue","loading","data","results","total","setParams","currentResults","setCurrentResults","allResults","setAllResults","length","clearList","params","offset","setQueryParams","value"],"mappings":";;;;;;AAAA,SAASA,QAAT,EAAmBC,SAAnB,QAAoC,OAApC;AACA,OAAOC,SAAP,MAAsB,cAAtB;;AAEA,SAASC,gBAAT,CAA0B;AAAEC,EAAAA,QAAF;AAAYC,EAAAA,UAAZ;AAAwBC,EAAAA,QAAxB;AAAkCC,EAAAA;AAAlC,CAA1B,EAAsE;AACpE,QAAM,CACJ;AACEC,IAAAA,aADF;AAEEC,IAAAA,OAFF;AAGEC,IAAAA,IAAI,EAAE;AAAEC,MAAAA,OAAF;AAAWC,MAAAA;AAAX;AAHR,GADI,EAMJC,SANI,IAOFX,SAAS,CAAC;AAAEE,IAAAA,QAAF;AAAYC,IAAAA,UAAZ;AAAwBC,IAAAA,QAAxB;AAAkCC,IAAAA;AAAlC,GAAD,CAPb;AAQA,QAAM,CAACO,cAAD,EAAiBC,iBAAjB,IAAsCf,QAAQ,CAAC,EAAD,CAApD;AACA,QAAM,CAACgB,UAAD,EAAaC,aAAb,IAA8BjB,QAAQ,CAAC,EAAD,CAA5C;AAEAC,EAAAA,SAAS,CACP,MAAM;AACJ,QAAIa,cAAc,CAACI,MAAf,KAA0BP,OAAO,CAACO,MAAtC,EAA8C;AAC5CD,MAAAA,aAAa,CAAC,CAAC,GAAGD,UAAJ,EAAgB,GAAGL,OAAnB,CAAD,CAAb;AACAI,MAAAA,iBAAiB,CAACJ,OAAD,CAAjB;AACD;AACF,GANM,EAOP,CAACK,UAAD,EAAaF,cAAb,EAA6BA,cAAc,CAACI,MAA5C,EAAoDP,OAApD,CAPO,CAAT;;AAUA,QAAMQ,SAAS,GAAGC,MAAM,IAAI;AAC1BH,IAAAA,aAAa,CAAC,EAAD,CAAb;AACAJ,IAAAA,SAAS,iCAAMO,MAAN;AAAcC,MAAAA,MAAM,EAAE;AAAtB,OAAT;AACD,GAHD;;AAKA,QAAMC,cAAc,GAAGF,MAAM,IAAI;AAC/BA,IAAAA,MAAM,CAACG,KAAP,KAAiBf,aAAjB,GAAiCW,SAAS,CAACC,MAAD,CAA1C,GAAqDP,SAAS,CAACO,MAAD,CAA9D;AACD,GAFD;;AAIA,SAAO,CAAC;AAAEX,IAAAA,OAAF;AAAWE,IAAAA,OAAO,EAAEK,UAApB;AAAgCJ,IAAAA;AAAhC,GAAD,EAA0CU,cAA1C,CAAP;AACD;;AAED,eAAenB,gBAAf","sourcesContent":["import { useState, useEffect } from 'react';\nimport useSearch from '../useSearch';\n\nfunction useSearchResults({ queryKey, resultKeys, entities, fields }) {\n const [\n {\n searchedValue,\n loading,\n data: { results, total }\n },\n setParams\n ] = useSearch({ queryKey, resultKeys, entities, fields });\n const [currentResults, setCurrentResults] = useState([]);\n const [allResults, setAllResults] = useState([]);\n\n useEffect(\n () => {\n if (currentResults.length !== results.length) {\n setAllResults([...allResults, ...results]);\n setCurrentResults(results);\n }\n },\n [allResults, currentResults, currentResults.length, results]\n );\n\n const clearList = params => {\n setAllResults([]);\n setParams({ ...params, offset: 0 });\n };\n\n const setQueryParams = params => {\n params.value !== searchedValue ? clearList(params) : setParams(params);\n };\n\n return [{ loading, results: allResults, total }, setQueryParams];\n}\n\nexport default useSearchResults;\n"],"file":"useSearchResults.js"}
@@ -0,0 +1,10 @@
1
+ const SEARCH_ADMIN = 'SEARCH_ADMIN';
2
+ const SEARCH_PUBLISHED = 'SEARCH_PUBLISHED';
3
+ const SEARCH_RESULTS_OVER_SCAN_BUFFER = 0;
4
+ const SEARCH_RESULTS_ELEMETS_HEIGHT_ABOVE_LIST = 186;
5
+ const SEARCH_RESULTS_ITEM_SIZE = 105;
6
+ const DEFAULT_RESULTS_KEYS = 'name, url';
7
+ const SEARCH_BUTTON = 'search-button';
8
+ const FILE = 'file';
9
+ export { SEARCH_ADMIN, SEARCH_PUBLISHED, SEARCH_RESULTS_OVER_SCAN_BUFFER, SEARCH_RESULTS_ELEMETS_HEIGHT_ABOVE_LIST, SEARCH_RESULTS_ITEM_SIZE, DEFAULT_RESULTS_KEYS, SEARCH_BUTTON, FILE };
10
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.js"],"names":["SEARCH_ADMIN","SEARCH_PUBLISHED","SEARCH_RESULTS_OVER_SCAN_BUFFER","SEARCH_RESULTS_ELEMETS_HEIGHT_ABOVE_LIST","SEARCH_RESULTS_ITEM_SIZE","DEFAULT_RESULTS_KEYS","SEARCH_BUTTON","FILE"],"mappings":"AAAA,MAAMA,YAAY,GAAG,cAArB;AACA,MAAMC,gBAAgB,GAAG,kBAAzB;AACA,MAAMC,+BAA+B,GAAG,CAAxC;AACA,MAAMC,wCAAwC,GAAG,GAAjD;AACA,MAAMC,wBAAwB,GAAG,GAAjC;AACA,MAAMC,oBAAoB,GAAG,WAA7B;AACA,MAAMC,aAAa,GAAG,eAAtB;AACA,MAAMC,IAAI,GAAG,MAAb;AAEA,SACEP,YADF,EAEEC,gBAFF,EAGEC,+BAHF,EAIEC,wCAJF,EAKEC,wBALF,EAMEC,oBANF,EAOEC,aAPF,EAQEC,IARF","sourcesContent":["const SEARCH_ADMIN = 'SEARCH_ADMIN';\nconst SEARCH_PUBLISHED = 'SEARCH_PUBLISHED';\nconst SEARCH_RESULTS_OVER_SCAN_BUFFER = 0;\nconst SEARCH_RESULTS_ELEMETS_HEIGHT_ABOVE_LIST = 186;\nconst SEARCH_RESULTS_ITEM_SIZE = 105;\nconst DEFAULT_RESULTS_KEYS = 'name, url';\nconst SEARCH_BUTTON = 'search-button';\nconst FILE = 'file';\n\nexport {\n SEARCH_ADMIN,\n SEARCH_PUBLISHED,\n SEARCH_RESULTS_OVER_SCAN_BUFFER,\n SEARCH_RESULTS_ELEMETS_HEIGHT_ABOVE_LIST,\n SEARCH_RESULTS_ITEM_SIZE,\n DEFAULT_RESULTS_KEYS,\n SEARCH_BUTTON,\n FILE\n};\n"],"file":"constants.js"}
@@ -0,0 +1,5 @@
1
+ import SearchAdmin from './components/SearchAdmin';
2
+ import SearchPublishedContent from './components/SearchPublishedContent';
3
+ import SearchBar from './components/SearchAdmin/SearchBar';
4
+ export { SearchAdmin, SearchPublishedContent, SearchBar };
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.js"],"names":["SearchAdmin","SearchPublishedContent","SearchBar"],"mappings":"AAAA,OAAOA,WAAP,MAAwB,0BAAxB;AACA,OAAOC,sBAAP,MAAmC,qCAAnC;AACA,OAAOC,SAAP,MAAsB,oCAAtB;AAEA,SAASF,WAAT,EAAsBC,sBAAtB,EAA8CC,SAA9C","sourcesContent":["import SearchAdmin from './components/SearchAdmin';\nimport SearchPublishedContent from './components/SearchPublishedContent';\nimport SearchBar from './components/SearchAdmin/SearchBar';\n\nexport { SearchAdmin, SearchPublishedContent, SearchBar };\n"],"file":"index.js"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@blaze-cms/plugin-search-ui",
3
+ "version": "0.110.0-alpha.1",
4
+ "description": "Blaze plugin search ui",
5
+ "main": "lib/index.js",
6
+ "module": "lib-es/index.js",
7
+ "sideEffects": false,
8
+ "directories": {
9
+ "src": "src/"
10
+ },
11
+ "scripts": {
12
+ "test": "jest",
13
+ "lint": "yarn run lint:js",
14
+ "lint:js": "eslint .",
15
+ "clean": "rm -Rf ./lib/ && rm -Rf ./lib-es/",
16
+ "build:cjs": "BABEL_ENV=cjs ../../node_modules/.bin/babel ./src --out-dir ./lib --source-maps --root-mode upward",
17
+ "build:esm": "BABEL_ENV=esm ../../node_modules/.bin/babel ./src --out-dir ./lib-es --source-maps --root-mode upward",
18
+ "build": "yarn run build:cjs && yarn run build:esm",
19
+ "build:clean": "yarn run clean && yarn run build",
20
+ "prepublishOnly": "yarn run build:clean",
21
+ "postpublish": "yarn run clean"
22
+ },
23
+ "author": {
24
+ "email": "hello@thebyte9.com",
25
+ "name": "Byte9",
26
+ "url": "https://thebyte9.com"
27
+ },
28
+ "license": "GPL-3.0",
29
+ "dependencies": {
30
+ "@blaze-cms/admin-ui-utils": "^0.102.0",
31
+ "@blaze-cms/core-errors": "^0.102.0",
32
+ "@blaze-cms/setup-ui": "^0.92.0",
33
+ "@blaze-react/button": "0.5.19",
34
+ "@blaze-react/input": "0.5.30",
35
+ "@blaze-react/utils": "0.5.15",
36
+ "classnames": "^2.2.6",
37
+ "core-js": "^3.2.1",
38
+ "graphql-tag": "^2.10.1",
39
+ "react-router-dom": "^5.0.1",
40
+ "react-tiny-virtual-list": "2.2.0"
41
+ },
42
+ "devDependencies": {
43
+ "@blaze-cms/core-ui": "^0.110.0-alpha.1"
44
+ },
45
+ "peerDependencies": {
46
+ "@blaze-cms/admin": "^0.97.2",
47
+ "prop-types": "^15.7.2",
48
+ "react": "^16.13.1",
49
+ "react-apollo": "^3.1.1"
50
+ },
51
+ "eslintIgnore": [
52
+ "lib/*",
53
+ "lib-es/*"
54
+ ],
55
+ "gitHead": "35f5b02ddd0690ef295f6a2881a1b217eaceee4c"
56
+ }
@@ -0,0 +1,28 @@
1
+ import gql from 'graphql-tag';
2
+
3
+ const SEARCH_ADMIN = () => gql`
4
+ query searchAdmin($limit: Int, $offset: Int, $sort: String, $rawQuery: JSON!) {
5
+ search: searchAdmin(limit: $limit, offset: $offset, sort: $sort, rawQuery: $rawQuery) {
6
+ jsonResults
7
+ total
8
+ }
9
+ }
10
+ `;
11
+
12
+ const SEARCH_PUBLISHED = ({ resultKeys }) => gql`
13
+ query searchPublishedContent($limit: Int, $offset: Int, $sort: String, $rawQuery: JSON!) {
14
+ search: searchPublishedContent(
15
+ limit: $limit
16
+ offset: $offset
17
+ sort: $sort
18
+ rawQuery: $rawQuery
19
+ ) {
20
+ results {
21
+ ${resultKeys}
22
+ }
23
+ total
24
+ }
25
+ }
26
+ `;
27
+
28
+ export default { SEARCH_ADMIN, SEARCH_PUBLISHED };
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ const RecentSearches = ({ recentSearches, handleSearchTerm, search }) => (
5
+ <div className="list list--search">
6
+ <div className="header header--list">
7
+ <h2>Recent searches</h2>
8
+ </div>
9
+ {recentSearches.map(searchedTerm => (
10
+ <div
11
+ key={searchedTerm}
12
+ role="button"
13
+ className="list__item list__item--search"
14
+ onClick={() => {
15
+ handleSearchTerm({ target: { value: searchedTerm } });
16
+ search({ value: searchedTerm });
17
+ }}>
18
+ <div className="list__item-row list__item-row--search">
19
+ <i className="material-icons">search</i>
20
+ <div className="list__item-text list__item-text--search">{searchedTerm}</div>
21
+ </div>
22
+ </div>
23
+ ))}
24
+ </div>
25
+ );
26
+
27
+ RecentSearches.propTypes = {
28
+ recentSearches: PropTypes.array.isRequired,
29
+ handleSearchTerm: PropTypes.func.isRequired,
30
+ search: PropTypes.func.isRequired
31
+ };
32
+
33
+ export default RecentSearches;
@@ -0,0 +1,3 @@
1
+ import RecentSearches from './RecentSearches';
2
+
3
+ export default RecentSearches;
@@ -0,0 +1,129 @@
1
+ import React, { useState, useRef, useEffect } from 'react';
2
+ import classnames from 'classnames';
3
+ import useLocalStorage from '../useLocalStorage';
4
+ import SearchBar from './SearchBar';
5
+ import RecentSearches from './RecentSearches';
6
+ import SearchResults from './SearchResults';
7
+ import TriggerModal from './TriggerModal';
8
+ import useSearchResults from '../useSearchResults';
9
+ import { SEARCH_ADMIN } from '../../constants';
10
+
11
+ const SearchAdmin = () => {
12
+ const [searchTerm, setSearchTerm] = useState('');
13
+ const [recentSearches, setRecentSearches] = useLocalStorage('recentSearches', []);
14
+ const [displaySearchModalFrame, setDisplaySearchModalFrame] = useState(false);
15
+ const [enableResults, setEnableResults] = useState(true);
16
+ const searchInputRef = useRef(null);
17
+ const [{ loading, results, total }, setQueryParams] = useSearchResults({
18
+ queryKey: SEARCH_ADMIN
19
+ });
20
+
21
+ useEffect(
22
+ () => {
23
+ if (searchInputRef && searchInputRef.current) {
24
+ searchInputRef.current.focus();
25
+ }
26
+ },
27
+ [displaySearchModalFrame]
28
+ );
29
+
30
+ const handleSearchTerm = ({ target: { value } }) => {
31
+ setSearchTerm(value);
32
+ };
33
+ const toggleSearchModal = () => {
34
+ setSearchTerm(null);
35
+ setEnableResults(false);
36
+ setDisplaySearchModalFrame(!displaySearchModalFrame);
37
+ };
38
+ const search = ({ value }) => {
39
+ if (!value) return;
40
+ !enableResults && setEnableResults(true);
41
+ const MAX_RECENT_SEARCHES = 5;
42
+ const recentSearchesCopy = recentSearches.slice();
43
+
44
+ if (!recentSearchesCopy.includes(value)) {
45
+ recentSearchesCopy.push(value);
46
+ if (recentSearchesCopy.length > MAX_RECENT_SEARCHES) {
47
+ recentSearchesCopy.shift();
48
+ }
49
+ }
50
+
51
+ setRecentSearches(recentSearchesCopy);
52
+ setQueryParams({ value });
53
+ };
54
+
55
+ const handleKeyDown = ({ key }) => {
56
+ if (key === 'Enter') {
57
+ if (!searchTerm) return clear();
58
+ search({ value: searchTerm });
59
+ }
60
+ };
61
+
62
+ const clear = () => {
63
+ setSearchTerm('');
64
+ setEnableResults(false);
65
+ };
66
+
67
+ const searchModalResultsClassName = classnames('modal modal--full-screen modal--search', {
68
+ 'modal--show': displaySearchModalFrame
69
+ });
70
+
71
+ const isEmptySearchTermAndData = !searchTerm && !results.length;
72
+ const isEmptySearchTermnAndDisabledResults = !searchTerm && !enableResults;
73
+ const shouldDisplayRecentSearches =
74
+ isEmptySearchTermAndData || isEmptySearchTermnAndDisabledResults;
75
+
76
+ const showResults = enableResults && results.length;
77
+
78
+ return (
79
+ <div className="search search--header">
80
+ <TriggerModal toggleSearchModal={toggleSearchModal} />
81
+ <div className={searchModalResultsClassName}>
82
+ {displaySearchModalFrame && (
83
+ <>
84
+ <div className="modal__header modal__header--search">
85
+ <SearchBar
86
+ toggleSearchModal={toggleSearchModal}
87
+ handleKeyDown={handleKeyDown}
88
+ searchInputRef={searchInputRef}
89
+ handleSearchTerm={handleSearchTerm}
90
+ searchTerm={searchTerm}
91
+ search={() => search({ value: searchTerm })}
92
+ />
93
+ </div>
94
+ {shouldDisplayRecentSearches ? (
95
+ <RecentSearches
96
+ recentSearches={recentSearches}
97
+ handleSearchTerm={handleSearchTerm}
98
+ search={search}
99
+ />
100
+ ) : (
101
+ <>
102
+ {!showResults && (
103
+ <div className="list list--search">
104
+ <div className="header header--list">
105
+ <h2>No Results</h2>
106
+ </div>
107
+ </div>
108
+ )}
109
+ </>
110
+ )}
111
+ {showResults && (
112
+ <SearchResults
113
+ currentValue={searchTerm}
114
+ searchTerm={searchTerm}
115
+ loading={loading}
116
+ results={results}
117
+ total={total}
118
+ setQueryParams={setQueryParams}
119
+ closeModal={toggleSearchModal}
120
+ />
121
+ )}
122
+ </>
123
+ )}
124
+ </div>
125
+ </div>
126
+ );
127
+ };
128
+
129
+ export default SearchAdmin;
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ const SearchBar = ({
5
+ handleKeyDown,
6
+ searchInputRef,
7
+ handleSearchTerm,
8
+ searchTerm,
9
+ toggleSearchModal,
10
+ close,
11
+ search,
12
+ placeholder
13
+ }) => (
14
+ <div className="search__wrapper">
15
+ <input
16
+ onKeyDown={handleKeyDown}
17
+ ref={searchInputRef}
18
+ placeholder={placeholder}
19
+ type="text"
20
+ onChange={handleSearchTerm}
21
+ value={searchTerm}
22
+ />
23
+ <span
24
+ onClick={search}
25
+ role="button"
26
+ className="icon-button icon-button--search icon-button--toggle">
27
+ <i className="material-icons">search</i>
28
+ </span>
29
+ {close && (
30
+ <div className="modal__close">
31
+ <i className="material-icons" onClick={toggleSearchModal} role="button">
32
+ close
33
+ </i>
34
+ </div>
35
+ )}
36
+ </div>
37
+ );
38
+
39
+ SearchBar.propTypes = {
40
+ close: PropTypes.bool,
41
+ handleKeyDown: PropTypes.func.isRequired,
42
+ searchInputRef: PropTypes.object,
43
+ handleSearchTerm: PropTypes.func.isRequired,
44
+ searchTerm: PropTypes.string,
45
+ toggleSearchModal: PropTypes.func,
46
+ search: PropTypes.func.isRequired,
47
+ placeholder: PropTypes.string
48
+ };
49
+
50
+ SearchBar.defaultProps = {
51
+ searchTerm: '',
52
+ close: true,
53
+ placeholder: 'Search...',
54
+ toggleSearchModal: null,
55
+ searchInputRef: null
56
+ };
57
+
58
+ export default SearchBar;
@@ -0,0 +1,3 @@
1
+ import SearchBar from './SearchBar';
2
+
3
+ export default SearchBar;
@@ -0,0 +1,112 @@
1
+ /* eslint-disable jsx-a11y/anchor-is-valid */
2
+ /* eslint-disable jsx-a11y/no-static-element-interactions */
3
+ import React, { useState } from 'react';
4
+ import PropTypes from 'prop-types';
5
+ import VirtualList from 'react-tiny-virtual-list';
6
+ import { withRouter } from 'react-router-dom';
7
+ import {
8
+ SEARCH_RESULTS_OVER_SCAN_BUFFER,
9
+ SEARCH_RESULTS_ELEMETS_HEIGHT_ABOVE_LIST,
10
+ SEARCH_RESULTS_ITEM_SIZE,
11
+ FILE
12
+ } from '../../../constants';
13
+
14
+ const SearchResults = ({
15
+ currentValue,
16
+ loading,
17
+ results,
18
+ total,
19
+ setQueryParams,
20
+ closeModal,
21
+ history
22
+ }) => {
23
+ const [verifiedRanges, setVerifiedRanges] = useState([]);
24
+ const [currentIndex, setCurrentIndex] = useState(0);
25
+
26
+ const handleRenderedItems = async ({ startIndex }) => {
27
+ const rowsLength = results.length;
28
+ const loadIndex = Math.floor(rowsLength / 2) - SEARCH_RESULTS_OVER_SCAN_BUFFER;
29
+ if (loadIndex > 0 && loadIndex < startIndex && !verifiedRanges.includes(loadIndex)) {
30
+ setQueryParams({ value: currentValue, offset: results.length });
31
+ setVerifiedRanges([...verifiedRanges, loadIndex]);
32
+ setCurrentIndex(startIndex + SEARCH_RESULTS_OVER_SCAN_BUFFER);
33
+ }
34
+ };
35
+
36
+ const getNavigationRoute = ({ id, docType }) =>
37
+ docType === FILE ? `/media/edit/${id}` : `/data-listing/${docType}/update/${id}`;
38
+
39
+ const navigate = ({ id, docType }) => {
40
+ history.push(getNavigationRoute({ id, docType }));
41
+ closeModal();
42
+ };
43
+
44
+ const getDateFormat = date => {
45
+ const newDate = new Date(date);
46
+ const day = `0${newDate.getDate()}`.slice(-2);
47
+ const month = `0${newDate.getMonth() + 1}`.slice(-2);
48
+ const year = String(newDate.getYear()).slice(-2);
49
+ return `${day}.${month}.${year}`;
50
+ };
51
+
52
+ return (
53
+ <>
54
+ {loading && <span>Loading...</span>}
55
+ <div className="modal__content modal__content--search">
56
+ <div className="header header--list">
57
+ <h2>{total} results</h2>
58
+ </div>
59
+ <VirtualList
60
+ width="100%"
61
+ height={window.innerHeight - SEARCH_RESULTS_ELEMETS_HEIGHT_ABOVE_LIST}
62
+ itemCount={results.length}
63
+ itemSize={SEARCH_RESULTS_ITEM_SIZE}
64
+ overscanCount={SEARCH_RESULTS_OVER_SCAN_BUFFER}
65
+ scrollToIndex={currentIndex}
66
+ onItemsRendered={handleRenderedItems}
67
+ renderItem={({ index, style }) => {
68
+ const { id, docType, updated, name } = results[index];
69
+ const updatedDate = updated ? getDateFormat(updated) : null;
70
+ return (
71
+ <div key={index} style={style} className="list__item--resultWrapper">
72
+ <div className="list__item list__item--result">
73
+ <div className="list__item-row list__item-row--result">
74
+ <span className="badge badge--primary">
75
+ {docType} {updatedDate}
76
+ </span>
77
+ <a
78
+ href={getNavigationRoute({
79
+ id,
80
+ docType
81
+ })}
82
+ onClick={() =>
83
+ navigate({
84
+ id,
85
+ docType
86
+ })
87
+ }
88
+ className="list__item-text list__item-text--result">
89
+ {name}
90
+ </a>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ );
95
+ }}
96
+ />
97
+ </div>
98
+ </>
99
+ );
100
+ };
101
+
102
+ SearchResults.propTypes = {
103
+ loading: PropTypes.bool.isRequired,
104
+ results: PropTypes.array.isRequired,
105
+ total: PropTypes.number.isRequired,
106
+ setQueryParams: PropTypes.func.isRequired,
107
+ closeModal: PropTypes.func.isRequired,
108
+ history: PropTypes.object.isRequired,
109
+ currentValue: PropTypes.string.isRequired
110
+ };
111
+
112
+ export default withRouter(SearchResults);
@@ -0,0 +1,3 @@
1
+ import SearchResults from './SearchResults';
2
+
3
+ export default SearchResults;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ const TriggerModal = ({ toggleSearchModal }) => (
5
+ <span
6
+ role="button"
7
+ className="material-icons searchModal-search-icon"
8
+ onClick={toggleSearchModal}>
9
+ search
10
+ </span>
11
+ );
12
+
13
+ TriggerModal.propTypes = {
14
+ toggleSearchModal: PropTypes.func.isRequired
15
+ };
16
+
17
+ export default TriggerModal;
@@ -0,0 +1,3 @@
1
+ import TriggerModal from './TriggerModal';
2
+
3
+ export default TriggerModal;
@@ -0,0 +1,3 @@
1
+ import SearchAdmin from './SearchAdmin';
2
+
3
+ export default SearchAdmin;