@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.
- package/CHANGELOG.md +345 -0
- package/LICENSE +674 -0
- package/README.md +45 -0
- package/babel.config.js +3 -0
- package/jest.config.js +5 -0
- package/lib/application/query/index.js +32 -0
- package/lib/application/query/index.js.map +1 -0
- package/lib/components/SearchAdmin/RecentSearches/RecentSearches.js +62 -0
- package/lib/components/SearchAdmin/RecentSearches/RecentSearches.js.map +1 -0
- package/lib/components/SearchAdmin/RecentSearches/index.js +16 -0
- package/lib/components/SearchAdmin/RecentSearches/index.js.map +1 -0
- package/lib/components/SearchAdmin/SearchAdmin.js +191 -0
- package/lib/components/SearchAdmin/SearchAdmin.js.map +1 -0
- package/lib/components/SearchAdmin/SearchBar/SearchBar.js +72 -0
- package/lib/components/SearchAdmin/SearchBar/SearchBar.js.map +1 -0
- package/lib/components/SearchAdmin/SearchBar/index.js +16 -0
- package/lib/components/SearchAdmin/SearchBar/index.js.map +1 -0
- package/lib/components/SearchAdmin/SearchResults/SearchResults.js +200 -0
- package/lib/components/SearchAdmin/SearchResults/SearchResults.js.map +1 -0
- package/lib/components/SearchAdmin/SearchResults/index.js +16 -0
- package/lib/components/SearchAdmin/SearchResults/index.js.map +1 -0
- package/lib/components/SearchAdmin/TriggerModal/TriggerModal.js +30 -0
- package/lib/components/SearchAdmin/TriggerModal/TriggerModal.js.map +1 -0
- package/lib/components/SearchAdmin/TriggerModal/index.js +16 -0
- package/lib/components/SearchAdmin/TriggerModal/index.js.map +1 -0
- package/lib/components/SearchAdmin/index.js +16 -0
- package/lib/components/SearchAdmin/index.js.map +1 -0
- package/lib/components/SearchPublishedContent/SearchPublishedContent.js +216 -0
- package/lib/components/SearchPublishedContent/SearchPublishedContent.js.map +1 -0
- package/lib/components/SearchPublishedContent/index.js +16 -0
- package/lib/components/SearchPublishedContent/index.js.map +1 -0
- package/lib/components/useLocalStorage/index.js +16 -0
- package/lib/components/useLocalStorage/index.js.map +1 -0
- package/lib/components/useLocalStorage/useLocalStorage.js +36 -0
- package/lib/components/useLocalStorage/useLocalStorage.js.map +1 -0
- package/lib/components/useSearch/index.js +16 -0
- package/lib/components/useSearch/index.js.map +1 -0
- package/lib/components/useSearch/useSearch.js +154 -0
- package/lib/components/useSearch/useSearch.js.map +1 -0
- package/lib/components/useSearchResults/index.js +16 -0
- package/lib/components/useSearchResults/index.js.map +1 -0
- package/lib/components/useSearchResults/useSearchResults.js +102 -0
- package/lib/components/useSearchResults/useSearchResults.js.map +1 -0
- package/lib/constants.js +25 -0
- package/lib/constants.js.map +1 -0
- package/lib/index.js +34 -0
- package/lib/index.js.map +1 -0
- package/lib-es/application/query/index.js +34 -0
- package/lib-es/application/query/index.js.map +1 -0
- package/lib-es/components/SearchAdmin/RecentSearches/RecentSearches.js +40 -0
- package/lib-es/components/SearchAdmin/RecentSearches/RecentSearches.js.map +1 -0
- package/lib-es/components/SearchAdmin/RecentSearches/index.js +3 -0
- package/lib-es/components/SearchAdmin/RecentSearches/index.js.map +1 -0
- package/lib-es/components/SearchAdmin/SearchAdmin.js +126 -0
- package/lib-es/components/SearchAdmin/SearchAdmin.js.map +1 -0
- package/lib-es/components/SearchAdmin/SearchBar/SearchBar.js +54 -0
- package/lib-es/components/SearchAdmin/SearchBar/SearchBar.js.map +1 -0
- package/lib-es/components/SearchAdmin/SearchBar/index.js +3 -0
- package/lib-es/components/SearchAdmin/SearchBar/index.js.map +1 -0
- package/lib-es/components/SearchAdmin/SearchResults/SearchResults.js +120 -0
- package/lib-es/components/SearchAdmin/SearchResults/SearchResults.js.map +1 -0
- package/lib-es/components/SearchAdmin/SearchResults/index.js +3 -0
- package/lib-es/components/SearchAdmin/SearchResults/index.js.map +1 -0
- package/lib-es/components/SearchAdmin/TriggerModal/TriggerModal.js +16 -0
- package/lib-es/components/SearchAdmin/TriggerModal/TriggerModal.js.map +1 -0
- package/lib-es/components/SearchAdmin/TriggerModal/index.js +3 -0
- package/lib-es/components/SearchAdmin/TriggerModal/index.js.map +1 -0
- package/lib-es/components/SearchAdmin/index.js +3 -0
- package/lib-es/components/SearchAdmin/index.js.map +1 -0
- package/lib-es/components/SearchPublishedContent/SearchPublishedContent.js +157 -0
- package/lib-es/components/SearchPublishedContent/SearchPublishedContent.js.map +1 -0
- package/lib-es/components/SearchPublishedContent/index.js +3 -0
- package/lib-es/components/SearchPublishedContent/index.js.map +1 -0
- package/lib-es/components/useLocalStorage/index.js +3 -0
- package/lib-es/components/useLocalStorage/index.js.map +1 -0
- package/lib-es/components/useLocalStorage/useLocalStorage.js +19 -0
- package/lib-es/components/useLocalStorage/useLocalStorage.js.map +1 -0
- package/lib-es/components/useSearch/index.js +3 -0
- package/lib-es/components/useSearch/index.js.map +1 -0
- package/lib-es/components/useSearch/useSearch.js +100 -0
- package/lib-es/components/useSearch/useSearch.js.map +1 -0
- package/lib-es/components/useSearchResults/index.js +3 -0
- package/lib-es/components/useSearchResults/index.js.map +1 -0
- package/lib-es/components/useSearchResults/useSearchResults.js +57 -0
- package/lib-es/components/useSearchResults/useSearchResults.js.map +1 -0
- package/lib-es/constants.js +10 -0
- package/lib-es/constants.js.map +1 -0
- package/lib-es/index.js +5 -0
- package/lib-es/index.js.map +1 -0
- package/package.json +56 -0
- package/src/application/query/index.js +28 -0
- package/src/components/SearchAdmin/RecentSearches/RecentSearches.js +33 -0
- package/src/components/SearchAdmin/RecentSearches/index.js +3 -0
- package/src/components/SearchAdmin/SearchAdmin.js +129 -0
- package/src/components/SearchAdmin/SearchBar/SearchBar.js +58 -0
- package/src/components/SearchAdmin/SearchBar/index.js +3 -0
- package/src/components/SearchAdmin/SearchResults/SearchResults.js +112 -0
- package/src/components/SearchAdmin/SearchResults/index.js +3 -0
- package/src/components/SearchAdmin/TriggerModal/TriggerModal.js +17 -0
- package/src/components/SearchAdmin/TriggerModal/index.js +3 -0
- package/src/components/SearchAdmin/index.js +3 -0
- package/src/components/SearchPublishedContent/SearchPublishedContent.js +157 -0
- package/src/components/SearchPublishedContent/index.js +3 -0
- package/src/components/useLocalStorage/index.js +3 -0
- package/src/components/useLocalStorage/useLocalStorage.js +18 -0
- package/src/components/useSearch/index.js +3 -0
- package/src/components/useSearch/useSearch.js +85 -0
- package/src/components/useSearchResults/index.js +3 -0
- package/src/components/useSearchResults/useSearchResults.js +38 -0
- package/src/constants.js +19 -0
- 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"}
|
package/lib-es/index.js
ADDED
|
@@ -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,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,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,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;
|