@vegan-friendly/strapi-plugin-elasticsearch 0.0.11-alpha.6 → 0.1.0-alpha.0
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/.prettierrc +7 -0
- package/.vscode/settings.json +24 -0
- package/README.md +0 -4
- package/admin/src/components/Initializer/index.js +26 -0
- package/admin/src/components/PluginIcon/index.js +12 -0
- package/admin/src/components/SubNavigation/index.js +48 -0
- package/admin/src/index.js +63 -0
- package/admin/src/pages/App/index.js +29 -0
- package/admin/src/pages/ConfigureCollection/index.js +225 -0
- package/admin/src/pages/ConfigureCollectionList/index.js +266 -0
- package/admin/src/pages/Homepage/index.js +168 -0
- package/admin/src/pages/ViewIndexingRunLog/index.js +124 -0
- package/admin/src/pluginId.js +5 -0
- package/admin/src/translations/en.json +1 -0
- package/admin/src/translations/fr.json +1 -0
- package/admin/src/utils/apiUrls.js +14 -0
- package/admin/src/utils/axiosInstance.js +40 -0
- package/admin/src/utils/getTrad.js +5 -0
- package/package.json +40 -80
- package/server/bootstrap.js +142 -0
- package/server/config/index.js +6 -0
- package/server/content-types/index.js +9 -0
- package/server/content-types/indexing-logs.js +35 -0
- package/server/content-types/name-prefix.js +0 -0
- package/server/content-types/tasks.js +52 -0
- package/server/controllers/configure-indexing.js +66 -0
- package/server/controllers/index.js +15 -0
- package/server/controllers/log-indexing.js +11 -0
- package/server/controllers/perform-indexing.js +28 -0
- package/server/controllers/perform-search.js +31 -0
- package/server/controllers/setup-info.js +14 -0
- package/server/destroy.js +5 -0
- package/server/index.js +25 -0
- package/server/middlewares/index.js +3 -0
- package/server/policies/index.js +3 -0
- package/server/register.js +5 -0
- package/server/routes/configure-indexing.js +42 -0
- package/server/routes/index.js +13 -0
- package/server/routes/perform-indexing.js +24 -0
- package/server/routes/perform-search.js +14 -0
- package/server/routes/run-log.js +12 -0
- package/server/routes/setup-info.js +12 -0
- package/server/services/configure-indexing.js +184 -0
- package/server/services/es-interface.js +187 -0
- package/server/services/helper.js +305 -0
- package/server/services/index.js +21 -0
- package/server/services/log-indexing.js +26 -0
- package/server/services/perform-indexing.js +173 -0
- package/server/services/schedule-indexing.js +65 -0
- package/server/services/transform-content.js +22 -0
- package/server/services/virtual-collections-registry.js +445 -0
- package/strapi-admin.js +3 -0
- package/strapi-server.js +3 -0
- package/dist/_chunks/App-Br53NnT1.mjs +0 -17315
- package/dist/_chunks/App-C3jMSu4l.js +0 -17314
- package/dist/_chunks/en-B4KWt_jN.js +0 -4
- package/dist/_chunks/en-Byx4XI2L.mjs +0 -4
- package/dist/_chunks/index-BlmgBQo2.js +0 -71
- package/dist/_chunks/index-CRnRLV0T.mjs +0 -72
- package/dist/admin/index.js +0 -3
- package/dist/admin/index.mjs +0 -4
- package/dist/server/index.js +0 -7330
- package/dist/server/index.mjs +0 -7307
package/.prettierrc
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
3
|
+
"[javascript]": {
|
4
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
5
|
+
},
|
6
|
+
"[javascriptreact]": {
|
7
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
8
|
+
},
|
9
|
+
"[typescript]": {
|
10
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
11
|
+
},
|
12
|
+
"[typescriptreact]": {
|
13
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
14
|
+
},
|
15
|
+
"[jsonc]": {
|
16
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
17
|
+
},
|
18
|
+
"[json]": {
|
19
|
+
//redundant, but just in case
|
20
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
21
|
+
},
|
22
|
+
"editor.formatOnSaveMode": "modifications",
|
23
|
+
"editor.formatOnSave": true
|
24
|
+
}
|
package/README.md
CHANGED
@@ -16,10 +16,6 @@ via yarn:
|
|
16
16
|
yarn add @geeky-biz/strapi-plugin-elasticsearch
|
17
17
|
```
|
18
18
|
|
19
|
-
## Supported Strapi version
|
20
|
-
|
21
|
-
The latest version of this plugin works for Strapi v5. For Strapi v4, please install the version 0.0.8 of this plugin.
|
22
|
-
|
23
19
|
## Plugin Configuration
|
24
20
|
|
25
21
|
Within your Strapi project's `config/plugin.js`, enable the plugin and provide the configuration details:
|
@@ -0,0 +1,26 @@
|
|
1
|
+
/**
|
2
|
+
*
|
3
|
+
* Initializer
|
4
|
+
*
|
5
|
+
*/
|
6
|
+
|
7
|
+
import { useEffect, useRef } from 'react';
|
8
|
+
import PropTypes from 'prop-types';
|
9
|
+
import pluginId from '../../pluginId';
|
10
|
+
|
11
|
+
const Initializer = ({ setPlugin }) => {
|
12
|
+
const ref = useRef();
|
13
|
+
ref.current = setPlugin;
|
14
|
+
|
15
|
+
useEffect(() => {
|
16
|
+
ref.current(pluginId);
|
17
|
+
}, []);
|
18
|
+
|
19
|
+
return null;
|
20
|
+
};
|
21
|
+
|
22
|
+
Initializer.propTypes = {
|
23
|
+
setPlugin: PropTypes.func.isRequired,
|
24
|
+
};
|
25
|
+
|
26
|
+
export default Initializer;
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { Connector } from '@strapi/icons';
|
3
|
+
import { Box } from '@strapi/design-system';
|
4
|
+
import {
|
5
|
+
SubNav,
|
6
|
+
SubNavHeader,
|
7
|
+
SubNavSection,
|
8
|
+
SubNavSections,
|
9
|
+
SubNavLink,
|
10
|
+
} from '@strapi/design-system/v2';
|
11
|
+
import { NavLink } from 'react-router-dom';
|
12
|
+
import pluginId from "../../pluginId";
|
13
|
+
|
14
|
+
export const SubNavigation = ({activeUrl}) => {
|
15
|
+
const links = [ {
|
16
|
+
id: 1,
|
17
|
+
label : 'Setup Information',
|
18
|
+
icon : Connector,
|
19
|
+
to : `/plugins/${pluginId}/home`,
|
20
|
+
},
|
21
|
+
{
|
22
|
+
id: 2,
|
23
|
+
label : 'Configure Collections',
|
24
|
+
icon : Connector,
|
25
|
+
to : `/plugins/${pluginId}/configure-collections`,
|
26
|
+
},
|
27
|
+
{
|
28
|
+
id: 3,
|
29
|
+
label : 'Indexing Run Logs',
|
30
|
+
icon : Connector,
|
31
|
+
to : `/plugins/${pluginId}/view-indexing-logs`,
|
32
|
+
}];
|
33
|
+
return (<Box style={{
|
34
|
+
height: '100vh'
|
35
|
+
}} background="neutral200">
|
36
|
+
<SubNav ariaLabel="Settings sub nav">
|
37
|
+
<SubNavHeader label="Strapi Elasticsearch" />
|
38
|
+
<SubNavSections>
|
39
|
+
<SubNavSection>
|
40
|
+
{links.map(link => link.icon && <SubNavLink
|
41
|
+
as={NavLink} to={link.to} icon={link.icon} key={link.id} >
|
42
|
+
{link.label}
|
43
|
+
</SubNavLink>)}
|
44
|
+
</SubNavSection>
|
45
|
+
</SubNavSections>
|
46
|
+
</SubNav>
|
47
|
+
</Box>);
|
48
|
+
}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import { prefixPluginTranslations } from '@strapi/helper-plugin';
|
2
|
+
import pluginPkg from '../../package.json';
|
3
|
+
import pluginId from './pluginId';
|
4
|
+
import Initializer from './components/Initializer';
|
5
|
+
import PluginIcon from './components/PluginIcon';
|
6
|
+
|
7
|
+
const name = pluginPkg.strapi.name;
|
8
|
+
|
9
|
+
export default {
|
10
|
+
register(app) {
|
11
|
+
app.addMenuLink({
|
12
|
+
to: `/plugins/${pluginId}`,
|
13
|
+
icon: PluginIcon,
|
14
|
+
intlLabel: {
|
15
|
+
id: `${pluginId}.plugin.name`,
|
16
|
+
defaultMessage: 'Elasticsearch',
|
17
|
+
},
|
18
|
+
Component: async () => {
|
19
|
+
const component = await import(/* webpackChunkName: "[request]" */ './pages/App');
|
20
|
+
|
21
|
+
return component;
|
22
|
+
},
|
23
|
+
permissions: [
|
24
|
+
// Uncomment to set the permissions of the plugin here
|
25
|
+
// {
|
26
|
+
// action: '', // the action name should be plugin::plugin-name.actionType
|
27
|
+
// subject: null,
|
28
|
+
// },
|
29
|
+
],
|
30
|
+
});
|
31
|
+
app.registerPlugin({
|
32
|
+
id: pluginId,
|
33
|
+
initializer: Initializer,
|
34
|
+
isReady: false,
|
35
|
+
name,
|
36
|
+
});
|
37
|
+
},
|
38
|
+
|
39
|
+
bootstrap(app) {},
|
40
|
+
async registerTrads({ locales }) {
|
41
|
+
const importedTrads = await Promise.all(
|
42
|
+
locales.map((locale) => {
|
43
|
+
return import(
|
44
|
+
/* webpackChunkName: "translation-[request]" */ `./translations/${locale}.json`
|
45
|
+
)
|
46
|
+
.then(({ default: data }) => {
|
47
|
+
return {
|
48
|
+
data: prefixPluginTranslations(data, pluginId),
|
49
|
+
locale,
|
50
|
+
};
|
51
|
+
})
|
52
|
+
.catch(() => {
|
53
|
+
return {
|
54
|
+
data: {},
|
55
|
+
locale,
|
56
|
+
};
|
57
|
+
});
|
58
|
+
})
|
59
|
+
);
|
60
|
+
|
61
|
+
return Promise.resolve(importedTrads);
|
62
|
+
},
|
63
|
+
};
|
@@ -0,0 +1,29 @@
|
|
1
|
+
/**
|
2
|
+
*
|
3
|
+
* This component is the skeleton around the actual pages, and should only
|
4
|
+
* contain code that should be seen on all pages. (e.g. navigation bar)
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
|
8
|
+
import React from 'react';
|
9
|
+
import { Switch, Route, Redirect } from 'react-router-dom';
|
10
|
+
import { AnErrorOccurred } from '@strapi/helper-plugin';
|
11
|
+
import pluginId from '../../pluginId';
|
12
|
+
import ConfigureCollectionList from '../ConfigureCollectionList';
|
13
|
+
import ConfigureCollection from '../ConfigureCollection';
|
14
|
+
import ViewIndexingRunLog from '../ViewIndexingRunLog';
|
15
|
+
import Homepage from '../Homepage';
|
16
|
+
const App = () => {
|
17
|
+
return (
|
18
|
+
<Switch>
|
19
|
+
<Route path={`/plugins/${pluginId}`} render={() => (<Redirect to={`/plugins/${pluginId}/home`} />)} exact />
|
20
|
+
<Route path={`/plugins/${pluginId}/home`} component={Homepage} exact />
|
21
|
+
<Route path={`/plugins/${pluginId}/configure-collections`} component={ConfigureCollectionList} exact />
|
22
|
+
<Route path={`/plugins/${pluginId}/configure-collections/:collectionName`} component={ConfigureCollection} exact />
|
23
|
+
<Route path={`/plugins/${pluginId}/view-indexing-logs`} component={ViewIndexingRunLog} />
|
24
|
+
<Route component={AnErrorOccurred} />
|
25
|
+
</Switch>
|
26
|
+
);
|
27
|
+
};
|
28
|
+
|
29
|
+
export default App;
|
@@ -0,0 +1,225 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
* HomePage
|
4
|
+
*
|
5
|
+
*/
|
6
|
+
|
7
|
+
import React, { useState, useEffect } from 'react';
|
8
|
+
import { useParams, useHistory } from 'react-router-dom';
|
9
|
+
import axiosInstance from '../../utils/axiosInstance';
|
10
|
+
import { SubNavigation } from '../../components/SubNavigation';;
|
11
|
+
import { Box, Flex } from '@strapi/design-system';
|
12
|
+
import { ToggleInput } from '@strapi/design-system';
|
13
|
+
import { Link, useTracking } from '@strapi/helper-plugin';
|
14
|
+
import pluginId from '../../pluginId';
|
15
|
+
import { apiGetCollectionConfig, apiSaveCollectionConfig } from "../../utils/apiUrls";
|
16
|
+
import { Alert } from '@strapi/design-system';
|
17
|
+
import { Button } from '@strapi/design-system';
|
18
|
+
import { ArrowLeft } from '@strapi/icons';
|
19
|
+
import { Typography } from '@strapi/design-system';
|
20
|
+
import { Loader, Textarea, TextInput } from '@strapi/design-system';
|
21
|
+
import {LoadingIndicatorPage, useNotification} from '@strapi/helper-plugin';
|
22
|
+
|
23
|
+
const loadConfigForCollection = (collectionName) => {
|
24
|
+
return axiosInstance.get(apiGetCollectionConfig(collectionName))
|
25
|
+
.then((resp) => resp.data);
|
26
|
+
}
|
27
|
+
|
28
|
+
const saveConfigForCollection = (collectionName, data) => {
|
29
|
+
return axiosInstance.post(apiSaveCollectionConfig(collectionName), {
|
30
|
+
data
|
31
|
+
})
|
32
|
+
}
|
33
|
+
|
34
|
+
const ConfigureField = ({config, index, setFieldConfig}) => {
|
35
|
+
|
36
|
+
const validateSubfieldsConfig = (conf) => {
|
37
|
+
if (conf && conf.length > 0)
|
38
|
+
{
|
39
|
+
try {
|
40
|
+
JSON.parse(conf);
|
41
|
+
return true;
|
42
|
+
} catch (e) {
|
43
|
+
return false;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
else
|
47
|
+
return true;
|
48
|
+
}
|
49
|
+
|
50
|
+
const updateIndex = (checked) => {
|
51
|
+
setFieldConfig({index, config: {...config, index: checked}})
|
52
|
+
}
|
53
|
+
|
54
|
+
const updateSubfieldConfig = (subfields) => {
|
55
|
+
const subfieldsConfigValid = validateSubfieldsConfig(subfields);
|
56
|
+
setFieldConfig({index, config: {...config, subfields, subfieldsConfigValid}})
|
57
|
+
}
|
58
|
+
|
59
|
+
const updateMappedFieldName = (mappedName) => {
|
60
|
+
setFieldConfig({index, config: {...config, searchFieldName: mappedName}})
|
61
|
+
}
|
62
|
+
|
63
|
+
return (
|
64
|
+
<Box background="neutral100" borderColor="neutral200" hasRadius index={index}
|
65
|
+
padding={4}>
|
66
|
+
<Box paddingTop={2} paddingBottom={2}>
|
67
|
+
<Typography fontWeight="bold" textColor="neutral600">{config.name}</Typography>
|
68
|
+
</Box>
|
69
|
+
<Box paddingTop={2} paddingBottom={2}>
|
70
|
+
<ToggleInput label="Index" onLabel="Yes" offLabel="No"
|
71
|
+
checked={config.index} onChange={(e) => updateIndex(e.target.checked)} />
|
72
|
+
</Box>
|
73
|
+
<Box width="50%" paddingTop={2} paddingBottom={2}>
|
74
|
+
<TextInput label="Maps to search field" placeholder="Enter field name" name="Search field" onChange={e => updateMappedFieldName(e.target.value)} value={config.searchFieldName || ""} />
|
75
|
+
</Box>
|
76
|
+
{
|
77
|
+
config.index && config.type && config.type === "dynamiczone" ? (
|
78
|
+
<Box paddingTop={2} paddingBottom={2}>
|
79
|
+
<Textarea
|
80
|
+
label="Dynamic zone fields to index"
|
81
|
+
error={config.subfieldsConfigValid === false ? 'Invalid indexing configuration' : undefined}
|
82
|
+
onChange={e => updateSubfieldConfig(e.target.value)}
|
83
|
+
>{config.subfields || ""}</Textarea>
|
84
|
+
</Box>
|
85
|
+
) : null
|
86
|
+
}
|
87
|
+
{
|
88
|
+
config.index && config.type && config.type === "component" ? (
|
89
|
+
<Box paddingTop={2} paddingBottom={2}>
|
90
|
+
<Textarea
|
91
|
+
label="Component fields to index"
|
92
|
+
error={config.subfieldsConfigValid === false ? 'Invalid indexing configuration' : undefined}
|
93
|
+
onChange={e => updateSubfieldConfig(e.target.value)}
|
94
|
+
>{config.subfields || ""}</Textarea>
|
95
|
+
</Box>
|
96
|
+
) : null
|
97
|
+
}
|
98
|
+
</Box>
|
99
|
+
)
|
100
|
+
}
|
101
|
+
|
102
|
+
const ConfigureCollection = () => {
|
103
|
+
const [isInProgress, setIsInProgress] = useState(false);
|
104
|
+
const [selectedCollection, setSelectedCollection] = useState(null);
|
105
|
+
const [collectionConfig, setCollectionConfig] = useState(null);
|
106
|
+
|
107
|
+
const params = useParams();
|
108
|
+
const toggleNotification = useNotification();
|
109
|
+
const updateCollectionsConfig = ({index, config}) => {
|
110
|
+
setCollectionConfig({
|
111
|
+
collectionName: collectionConfig.collectionName,
|
112
|
+
attributes: collectionConfig.attributes.map((e, idx) => index === idx ? config : e)
|
113
|
+
});
|
114
|
+
}
|
115
|
+
|
116
|
+
const saveCollectionConfig = () => {
|
117
|
+
if (collectionConfig && collectionConfig.collectionName)
|
118
|
+
{
|
119
|
+
const data = {}
|
120
|
+
data[collectionConfig.collectionName] = {}
|
121
|
+
for (let k=0; k<collectionConfig.attributes.length; k++)
|
122
|
+
{
|
123
|
+
const {name, ...attribs} = collectionConfig.attributes[k]
|
124
|
+
data[collectionConfig.collectionName][name] = attribs
|
125
|
+
}
|
126
|
+
setIsInProgress(true);
|
127
|
+
saveConfigForCollection(collectionConfig.collectionName, data)
|
128
|
+
.then((resp) => {
|
129
|
+
toggleNotification({
|
130
|
+
type: "success", message: "The collection configuration is saved.", timeout: 5000
|
131
|
+
});
|
132
|
+
})
|
133
|
+
.catch((err) => {
|
134
|
+
toggleNotification({
|
135
|
+
type: "warning", message: err.message || "An error was encountered.", timeout: 5000
|
136
|
+
});
|
137
|
+
console.log(err);
|
138
|
+
})
|
139
|
+
.finally(() => setIsInProgress(false));
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
useEffect(() => {
|
144
|
+
if (params && params.collectionName)
|
145
|
+
setSelectedCollection(params.collectionName)
|
146
|
+
}, [params]);
|
147
|
+
|
148
|
+
useEffect(() => {
|
149
|
+
if (selectedCollection)
|
150
|
+
{
|
151
|
+
loadConfigForCollection(selectedCollection)
|
152
|
+
.then((resp) => {
|
153
|
+
if (Object.keys(resp).length === 0)
|
154
|
+
{
|
155
|
+
toggleNotification({
|
156
|
+
type: "warning", message: 'No collection with the selected name exists.', timeout: 5000
|
157
|
+
});
|
158
|
+
}
|
159
|
+
else
|
160
|
+
{
|
161
|
+
const collectionName = Object.keys(resp)[0];
|
162
|
+
const attributeNames = Object.keys(resp[collectionName]);
|
163
|
+
const attributes = [];
|
164
|
+
for (let s = 0; s<attributeNames.length; s++)
|
165
|
+
attributes.push({name: attributeNames[s], ...resp[collectionName][attributeNames[s]]})
|
166
|
+
const item = {collectionName, attributes};
|
167
|
+
setCollectionConfig(item);
|
168
|
+
}
|
169
|
+
})
|
170
|
+
.catch((err) => {
|
171
|
+
toggleNotification({
|
172
|
+
type: "warning", message: err.message || "An error was encountered.", timeout: 5000
|
173
|
+
});
|
174
|
+
console.log(err);
|
175
|
+
});
|
176
|
+
}
|
177
|
+
}, [selectedCollection]);
|
178
|
+
|
179
|
+
if (collectionConfig === null)
|
180
|
+
return <LoadingIndicatorPage />;
|
181
|
+
else
|
182
|
+
return (
|
183
|
+
<Flex alignItems="stretch" gap={4}>
|
184
|
+
<SubNavigation />
|
185
|
+
<Box padding={8} background="neutral100" width="100%">
|
186
|
+
<Box paddingBottom={4}>
|
187
|
+
<Link startIcon={<ArrowLeft />} to={`/plugins/${pluginId}/configure-collections/`}>
|
188
|
+
Back
|
189
|
+
</Link>
|
190
|
+
</Box>
|
191
|
+
{
|
192
|
+
selectedCollection && (
|
193
|
+
<Box paddingBottom={4}>
|
194
|
+
<Typography variant="alpha">{selectedCollection}</Typography>
|
195
|
+
</Box>
|
196
|
+
)
|
197
|
+
}
|
198
|
+
{
|
199
|
+
collectionConfig && (
|
200
|
+
<>
|
201
|
+
<Flex alignItems="stretch" gap={4} width="100%">
|
202
|
+
<Box padding={8} background="neutral0" width="100%">
|
203
|
+
<Box paddingBottom={2}>
|
204
|
+
<Typography variant="beta">Attributes</Typography>
|
205
|
+
{
|
206
|
+
collectionConfig.attributes.map((a, idx) => {
|
207
|
+
return <Box paddingTop={4} paddingBottom={4}><ConfigureField index={idx} config={a}
|
208
|
+
setFieldConfig={updateCollectionsConfig} /></Box>
|
209
|
+
})
|
210
|
+
}
|
211
|
+
</Box>
|
212
|
+
</Box>
|
213
|
+
</Flex>
|
214
|
+
<Box paddingTop={4}>
|
215
|
+
<Button loading={isInProgress} variant="default" onClick={saveCollectionConfig} >Save Configuration Changes</Button>
|
216
|
+
</Box>
|
217
|
+
</>
|
218
|
+
)
|
219
|
+
}
|
220
|
+
</Box>
|
221
|
+
</Flex>
|
222
|
+
);
|
223
|
+
};
|
224
|
+
|
225
|
+
export default ConfigureCollection;
|