filter-button 0.1.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/README.md +95 -0
- package/admin/src/components/ButtonComponent/ButtonComponent.js +37 -0
- package/admin/src/components/Initializer/index.js +26 -0
- package/admin/src/components/PluginIcon/index.js +26 -0
- package/admin/src/index.js +64 -0
- package/admin/src/pages/App/index.js +25 -0
- package/admin/src/pages/HomePage/index.js +20 -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/axiosInstance.js +42 -0
- package/admin/src/utils/getTrad.js +5 -0
- package/assets/demo.gif +0 -0
- package/package.json +25 -0
- package/server/bootstrap.js +5 -0
- package/server/index.js +7 -0
- package/server/register.js +9 -0
- package/strapi-admin.js +3 -0
- package/strapi-server.js +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
|
|
2
|
+
# Filter Button
|
|
3
|
+
|
|
4
|
+
## About
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
This package provides a custom field for Strapi that lets you add a filter button in no time.
|
|
9
|
+
|
|
10
|
+
Custom fields are supported since Strapi 4.4+ and offer powerful API to create highly customizable fields.
|
|
11
|
+
|
|
12
|
+
This plugin lets you view filtered data according to your configurations.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Installation
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
To install this plugin, you need to add an NPM dependency to your Strapi application:
|
|
20
|
+
#### For NPM:
|
|
21
|
+
```bash
|
|
22
|
+
npm i filter-button
|
|
23
|
+
```
|
|
24
|
+
#### For Yarn:
|
|
25
|
+
```bash
|
|
26
|
+
yarn add filter-button
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Now we need to register plugin so strapi can use it. In order to do that we need to create (if not already created) ./config/plugins.js file and add entry to it.
|
|
30
|
+
```bash
|
|
31
|
+
'filter-button': {
|
|
32
|
+
enabled: true,
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
#### create relations first for filter button to work
|
|
38
|
+
if relation is many to many then add boolean ```manyToMany:true``` in configuration
|
|
39
|
+
|
|
40
|
+
Add webpack.config.js file into src/admin and paste this content there.
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
'use strict';
|
|
45
|
+
|
|
46
|
+
/* eslint-disable no-unused-vars */
|
|
47
|
+
module.exports = (config, webpack) => {
|
|
48
|
+
config.plugins.push(
|
|
49
|
+
new webpack.DefinePlugin({
|
|
50
|
+
CONTENT_TYPES: JSON.stringify(
|
|
51
|
+
[
|
|
52
|
+
{
|
|
53
|
+
from: 'api::topic.topic', // collection where button will be added
|
|
54
|
+
to: 'api::card.card', // which collection you want to filter
|
|
55
|
+
filterBy: 'title', // field name by which you want to filter
|
|
56
|
+
attributeName: 'viewCards', //attribute name added while adding button
|
|
57
|
+
buttonTitle: 'View Cards', // title of button
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
from: 'api::category.category',
|
|
61
|
+
to: 'api::topic.topic',
|
|
62
|
+
filterBy: 'title',
|
|
63
|
+
attributeName: 'viewTopics',
|
|
64
|
+
buttonTitle: 'View Topics',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
from: 'api::category.category', //adding multiple buttons for same collection
|
|
68
|
+
to: 'api::card.card',
|
|
69
|
+
filterBy: 'title',
|
|
70
|
+
attributeName: 'viewCards',
|
|
71
|
+
buttonTitle: 'View Cards',
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
),
|
|
75
|
+
})
|
|
76
|
+
)
|
|
77
|
+
return config;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Then Run build:
|
|
83
|
+
#### For NPM:
|
|
84
|
+
```bash
|
|
85
|
+
npm run bild
|
|
86
|
+
```
|
|
87
|
+
#### For Yarn:
|
|
88
|
+
```bash
|
|
89
|
+
yarn bild
|
|
90
|
+
```
|
|
91
|
+
## How To Use
|
|
92
|
+
|
|
93
|
+
1. Once all necessary configuration is done, create a elation between ```from``` and ```to``` collections.
|
|
94
|
+
2. Add button from custom fields
|
|
95
|
+
3. make sure ```attributeName``` is matching with configurations while creating custom field
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* HomePage
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
import { Box, Button } from '@strapi/design-system';
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { useHistory } from "react-router-dom";
|
|
9
|
+
import { useCMEditViewDataManager } from '@strapi/helper-plugin';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const ButtonComponent = ({ name }) => {
|
|
13
|
+
const history = useHistory();
|
|
14
|
+
const {
|
|
15
|
+
allLayoutData,
|
|
16
|
+
modifiedData
|
|
17
|
+
} = useCMEditViewDataManager();
|
|
18
|
+
|
|
19
|
+
const { uid } = allLayoutData.contentType;
|
|
20
|
+
const currentCollection = CONTENT_TYPES?.filter(data => { if (data?.from === uid && data?.attributeName === name) return data })[0]
|
|
21
|
+
console.log(currentCollection)
|
|
22
|
+
const filterCards = () => {
|
|
23
|
+
history.push(`/content-manager/collectionType/${currentCollection?.to}?page=1&pageSize=10&sort=${currentCollection?.filterBy}:ASC&filters[$and][0][${currentCollection?.manyToMany ? currentCollection?.from?.split('.')[1] + 's' : currentCollection?.from?.split('.')[1]}][${currentCollection?.filterBy}][$eq]=${modifiedData?.title}`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<Box paddingTop={5} style={{ width: '100%' }}>
|
|
29
|
+
<Button style={{ margin: 'auto' }} size="L" variant="default" onClick={filterCards}>
|
|
30
|
+
{currentCollection?.buttonTitle || "View"}
|
|
31
|
+
</Button>
|
|
32
|
+
</Box>
|
|
33
|
+
</>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default ButtonComponent;
|
|
@@ -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,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { Icon } from '@strapi/design-system/Icon';
|
|
4
|
+
import { Flex } from '@strapi/design-system/Flex';
|
|
5
|
+
import Filter from '@strapi/icons/Filter';
|
|
6
|
+
|
|
7
|
+
const IconBox = styled(Flex)`
|
|
8
|
+
/* Hard code color values */
|
|
9
|
+
/* to stay consistent between themes */
|
|
10
|
+
background-color: #f0f0ff; /* primary100 */
|
|
11
|
+
border: 1px solid #d9d8ff; /* primary200 */
|
|
12
|
+
|
|
13
|
+
svg > path {
|
|
14
|
+
fill: #4945ff; /* primary600 */
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
const PluginIcon = () => {
|
|
19
|
+
return (
|
|
20
|
+
<IconBox justifyContent="center" alignItems="center" width={7} height={6} hasRadius aria-hidden>
|
|
21
|
+
<Icon as={Filter} />
|
|
22
|
+
</IconBox>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default PluginIcon;
|
|
@@ -0,0 +1,64 @@
|
|
|
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.customFields.register({
|
|
12
|
+
name: "filterButton",
|
|
13
|
+
pluginId: pluginId, // the custom field is created by a color-picker plugin
|
|
14
|
+
type: "string", // the color will be stored as a string
|
|
15
|
+
|
|
16
|
+
intlLabel: {
|
|
17
|
+
id: "filter-button-button-label",
|
|
18
|
+
defaultMessage: "Filter Button",
|
|
19
|
+
},
|
|
20
|
+
intlDescription: {
|
|
21
|
+
id: "filter-button-button-description",
|
|
22
|
+
defaultMessage: "Filter Data",
|
|
23
|
+
},
|
|
24
|
+
icon: PluginIcon, // don't forget to create/import your icon component
|
|
25
|
+
components: {
|
|
26
|
+
Input: async () => import(/* webpackChunkName: "input-component" */ "./components/ButtonComponent/ButtonComponent.js"),
|
|
27
|
+
},
|
|
28
|
+
options: {
|
|
29
|
+
// declare options here
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
app.registerPlugin({
|
|
33
|
+
id: pluginId,
|
|
34
|
+
initializer: Initializer,
|
|
35
|
+
isReady: false,
|
|
36
|
+
name,
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
bootstrap(app) { },
|
|
41
|
+
async registerTrads({ locales }) {
|
|
42
|
+
const importedTrads = await Promise.all(
|
|
43
|
+
locales.map((locale) => {
|
|
44
|
+
return import(
|
|
45
|
+
/* webpackChunkName: "translation-[request]" */ `./translations/${locale}.json`
|
|
46
|
+
)
|
|
47
|
+
.then(({ default: data }) => {
|
|
48
|
+
return {
|
|
49
|
+
data: prefixPluginTranslations(data, pluginId),
|
|
50
|
+
locale,
|
|
51
|
+
};
|
|
52
|
+
})
|
|
53
|
+
.catch(() => {
|
|
54
|
+
return {
|
|
55
|
+
data: {},
|
|
56
|
+
locale,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
return Promise.resolve(importedTrads);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
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 } from 'react-router-dom';
|
|
10
|
+
import { NotFound } from '@strapi/helper-plugin';
|
|
11
|
+
import pluginId from '../../pluginId';
|
|
12
|
+
import HomePage from '../HomePage';
|
|
13
|
+
|
|
14
|
+
const App = () => {
|
|
15
|
+
return (
|
|
16
|
+
<div>
|
|
17
|
+
<Switch>
|
|
18
|
+
<Route path={`/plugins/${pluginId}`} component={HomePage} exact />
|
|
19
|
+
<Route component={NotFound} />
|
|
20
|
+
</Switch>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default App;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* HomePage
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
// import PropTypes from 'prop-types';
|
|
9
|
+
import pluginId from '../../pluginId';
|
|
10
|
+
|
|
11
|
+
const HomePage = () => {
|
|
12
|
+
return (
|
|
13
|
+
<div>
|
|
14
|
+
<h1>{pluginId}'s HomePage</h1>
|
|
15
|
+
<p>Happy coding</p>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default HomePage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* axios with a custom config.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import axios from 'axios';
|
|
6
|
+
import { auth, wrapAxiosInstance } from '@strapi/helper-plugin';
|
|
7
|
+
|
|
8
|
+
const instance = axios.create({
|
|
9
|
+
baseURL: process.env.STRAPI_ADMIN_BACKEND_URL,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
instance.interceptors.request.use(
|
|
13
|
+
async (config) => {
|
|
14
|
+
config.headers = {
|
|
15
|
+
Authorization: `Bearer ${auth.getToken()}`,
|
|
16
|
+
Accept: 'application/json',
|
|
17
|
+
'Content-Type': 'application/json',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return config;
|
|
21
|
+
},
|
|
22
|
+
(error) => {
|
|
23
|
+
Promise.reject(error);
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
instance.interceptors.response.use(
|
|
28
|
+
(response) => response,
|
|
29
|
+
(error) => {
|
|
30
|
+
// whatever you want to do with the error
|
|
31
|
+
if (error.response?.status === 401) {
|
|
32
|
+
auth.clearAppStorage();
|
|
33
|
+
window.location.reload();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const wrapper = wrapAxiosInstance(instance);
|
|
41
|
+
|
|
42
|
+
export default wrapper;
|
package/assets/demo.gif
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "filter-button",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "This is the description of the plugin.",
|
|
5
|
+
"strapi": {
|
|
6
|
+
"name": "filter-button",
|
|
7
|
+
"description": "Description of Filter Button plugin",
|
|
8
|
+
"kind": "plugin",
|
|
9
|
+
"displayName": "Filter Button"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {},
|
|
12
|
+
"author": {
|
|
13
|
+
"name": "A Strapi developer"
|
|
14
|
+
},
|
|
15
|
+
"maintainers": [
|
|
16
|
+
{
|
|
17
|
+
"name": "A Strapi developer"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=14.19.1 <=18.x.x",
|
|
22
|
+
"npm": ">=6.0.0"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT"
|
|
25
|
+
}
|
package/server/index.js
ADDED
package/strapi-admin.js
ADDED
package/strapi-server.js
ADDED