mirror of
https://github.com/strapi/strapi.git
synced 2025-09-25 16:29:34 +00:00
Created providers list view
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
8575995080
commit
a1592c9626
@ -0,0 +1,8 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
// TODO : Temporary baseline alignment
|
||||
const ListBaselineAlignment = styled.div`
|
||||
padding-top: 3px;
|
||||
`;
|
||||
|
||||
export default ListBaselineAlignment;
|
@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import { CustomRow } from '@buffetjs/styles';
|
||||
import { IconLinks, Text } from '@buffetjs/core';
|
||||
import PropTypes from 'prop-types';
|
||||
import PrefixedIcon from '../PrefixedIcon';
|
||||
|
||||
const ListRow = ({ icon, name, onClick, links, children }) => {
|
||||
return (
|
||||
<CustomRow onClick={onClick}>
|
||||
<td>
|
||||
<PrefixedIcon icon={icon} name={name} />
|
||||
</td>
|
||||
{children}
|
||||
<td>
|
||||
<IconLinks links={links} />
|
||||
</td>
|
||||
</CustomRow>
|
||||
);
|
||||
};
|
||||
|
||||
ListRow.defaultProps = {
|
||||
children: null,
|
||||
onClick: () => {},
|
||||
links: [],
|
||||
};
|
||||
|
||||
ListRow.propTypes = {
|
||||
children: PropTypes.node,
|
||||
icon: PropTypes.array.isRequired,
|
||||
links: PropTypes.array,
|
||||
name: PropTypes.string.isRequired,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default ListRow;
|
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import { Flex, Padded, Text } from '@buffetjs/core';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { upperFirst } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const PrefixedIcon = ({ icon, name }) => {
|
||||
return (
|
||||
<Flex>
|
||||
<div>
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</div>
|
||||
<Padded left size="md">
|
||||
<Text fontWeight="semiBold" lineHeight="18px">
|
||||
{upperFirst(name)}
|
||||
</Text>
|
||||
</Padded>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
PrefixedIcon.propTypes = {
|
||||
icon: PropTypes.array.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default PrefixedIcon;
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Header } from '@buffetjs/custom';
|
||||
import { SettingsPageTitle } from 'strapi-helper-plugin';
|
||||
import getTrad from '../../utils/getTrad';
|
||||
|
||||
@ -10,7 +11,9 @@ const AdvancedSettingsPage = () => {
|
||||
return (
|
||||
<>
|
||||
<SettingsPageTitle name={pageTitle} />
|
||||
<div>Advanced settings</div>
|
||||
<div>
|
||||
<Header title={{ label: pageTitle }} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Header } from '@buffetjs/custom';
|
||||
import { SettingsPageTitle } from 'strapi-helper-plugin';
|
||||
import getTrad from '../../utils/getTrad';
|
||||
|
||||
@ -10,7 +11,9 @@ const EmailTemplatesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<SettingsPageTitle name={pageTitle} />
|
||||
<div>Email</div>
|
||||
<div>
|
||||
<Header title={{ label: pageTitle }} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,16 +1,122 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useMemo, useReducer } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { SettingsPageTitle } from 'strapi-helper-plugin';
|
||||
import getTrad from '../../utils/getTrad';
|
||||
import { Header, List } from '@buffetjs/custom';
|
||||
import { Text } from '@buffetjs/core';
|
||||
import { Pencil } from '@buffetjs/icons';
|
||||
import { SettingsPageTitle, useUserPermissions, request } from 'strapi-helper-plugin';
|
||||
import pluginPermissions from '../../permissions';
|
||||
import { getRequestURL, getTrad } from '../../utils';
|
||||
import ListBaselineAlignment from '../../components/ListBaselineAlignment';
|
||||
import ListRow from '../../components/ListRow';
|
||||
import reducer, { initialState } from './reducer';
|
||||
|
||||
const ProvidersPage = () => {
|
||||
const { formatMessage } = useIntl();
|
||||
const pageTitle = formatMessage({ id: getTrad('HeaderNav.link.providers') });
|
||||
const updatePermissions = useMemo(() => {
|
||||
return { update: pluginPermissions.updateProviders };
|
||||
}, [pluginPermissions]);
|
||||
const {
|
||||
isLoading: isLoadingForPermissions,
|
||||
allowedActions: { canUpdate },
|
||||
} = useUserPermissions(updatePermissions);
|
||||
const [{ isLoading, providers }, dispatch] = useReducer(reducer, initialState);
|
||||
const enabledProvidersCount = useMemo(
|
||||
() => providers.filter(provider => provider.enabled).length,
|
||||
[providers]
|
||||
);
|
||||
const disabledProvidersCount = useMemo(() => {
|
||||
return providers.length - enabledProvidersCount;
|
||||
}, [providers, enabledProvidersCount]);
|
||||
|
||||
const listTitle = useMemo(() => {
|
||||
const enabledMessage = formatMessage(
|
||||
{
|
||||
id: getTrad(
|
||||
`List.title.providers.enabled.${enabledProvidersCount > 1 ? 'plural' : 'singular'}`
|
||||
),
|
||||
},
|
||||
{ number: enabledProvidersCount }
|
||||
);
|
||||
const disabledMessage = formatMessage(
|
||||
{
|
||||
id: getTrad(
|
||||
`List.title.providers.disabled.${disabledProvidersCount > 1 ? 'plural' : 'singular'}`
|
||||
),
|
||||
},
|
||||
{ number: disabledProvidersCount }
|
||||
);
|
||||
|
||||
return `${enabledMessage} ${disabledMessage}`;
|
||||
}, [formatMessage, enabledProvidersCount]);
|
||||
|
||||
useEffect(() => {
|
||||
const getData = async () => {
|
||||
try {
|
||||
dispatch({
|
||||
type: 'GET_DATA',
|
||||
});
|
||||
|
||||
const data = await request(getRequestURL('providers'), { method: 'GET' });
|
||||
|
||||
console.log({ data });
|
||||
|
||||
dispatch({
|
||||
type: 'GET_DATA_SUCCEEDED',
|
||||
data,
|
||||
});
|
||||
} catch (err) {
|
||||
dispatch({
|
||||
type: 'GET_DATA_ERROR',
|
||||
});
|
||||
console.error(err);
|
||||
strapi.notification.error('notification.error');
|
||||
}
|
||||
};
|
||||
|
||||
if (!isLoadingForPermissions) {
|
||||
getData();
|
||||
}
|
||||
}, [isLoadingForPermissions]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsPageTitle name={pageTitle} />
|
||||
<div>Providers</div>
|
||||
<div>
|
||||
<Header title={{ label: pageTitle }} isLoading={isLoadingForPermissions || isLoading} />
|
||||
<ListBaselineAlignment />
|
||||
<List
|
||||
title={listTitle}
|
||||
items={providers}
|
||||
isLoading={isLoading}
|
||||
customRowComponent={provider => (
|
||||
<ListRow
|
||||
{...provider}
|
||||
onClick={() => {
|
||||
console.log(`Will edit ${provider.name}`);
|
||||
}}
|
||||
links={[
|
||||
{
|
||||
icon: canUpdate ? <Pencil fill="#0e1622" /> : null,
|
||||
onClick: () => {
|
||||
console.log(`Will edit ${provider.name}`);
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<td key="enabled">
|
||||
<Text
|
||||
fontWeight="semiBold"
|
||||
lineHeight="18px"
|
||||
color={provider.enabled ? 'green' : 'lightOrange'}
|
||||
>
|
||||
{provider.enabled ? 'Enabled' : 'Disabled'}
|
||||
</Text>
|
||||
</td>
|
||||
</ListRow>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,49 @@
|
||||
import produce from 'immer';
|
||||
import { sortBy } from 'lodash';
|
||||
|
||||
const initialState = {
|
||||
isLoading: true,
|
||||
data: {},
|
||||
providers: [],
|
||||
};
|
||||
|
||||
const reducer = (state, action) =>
|
||||
// eslint-disable-next-line consistent-return
|
||||
produce(state, draftState => {
|
||||
switch (action.type) {
|
||||
case 'GET_DATA': {
|
||||
draftState.isLoading = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'GET_DATA_SUCCEEDED': {
|
||||
draftState.isLoading = false;
|
||||
draftState.data = action.data;
|
||||
draftState.providers = sortBy(
|
||||
Object.keys(action.data).reduce((acc, current) => {
|
||||
const { icon: iconName, enabled } = action.data[current];
|
||||
const icon = iconName === 'envelope' ? ['fas', 'envelope'] : ['fab', iconName];
|
||||
|
||||
acc.push({ name: current, icon, enabled });
|
||||
|
||||
return acc;
|
||||
}, []),
|
||||
'name'
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
case 'GET_DATA_ERROR': {
|
||||
drafState.isLoading = true;
|
||||
break;
|
||||
}
|
||||
case 'RESET_PROPS':
|
||||
return initialState;
|
||||
default: {
|
||||
return draftState;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default reducer;
|
||||
export { initialState };
|
@ -44,10 +44,7 @@
|
||||
"List.button.roles": "Add New Role",
|
||||
"List.title.emailTemplates.plural": "{number} email templates are available",
|
||||
"List.title.emailTemplates.singular": "{number} email template is available",
|
||||
"List.title.providers.disabled.plural": "{number} are disabled",
|
||||
"List.title.providers.disabled.singular": "{number} is disabled",
|
||||
"List.title.providers.enabled.plural": "{number} providers are enabled and",
|
||||
"List.title.providers.enabled.singular": "{number} provider is enabled and",
|
||||
|
||||
"List.title.roles.plural": "{number} roles are available",
|
||||
"List.title.roles.singular": "{number} role is available",
|
||||
"ListRow.disabled": "Disabled",
|
||||
@ -113,6 +110,10 @@
|
||||
"HeaderNav.link.emailTemplates": "Email templates",
|
||||
"HeaderNav.link.providers": "Providers",
|
||||
"HeaderNav.link.roles": "Roles",
|
||||
"List.title.providers.disabled.plural": "{number} are disabled",
|
||||
"List.title.providers.disabled.singular": "{number} is disabled",
|
||||
"List.title.providers.enabled.plural": "{number} providers are enabled and",
|
||||
"List.title.providers.enabled.singular": "{number} provider is enabled and",
|
||||
"plugin.description.long": "Protect your API with a full authentication process based on JWT. This plugin comes also with an ACL strategy that allows you to manage the permissions between the groups of users.",
|
||||
"plugin.description.short": "Protect your API with a full authentication process based on JWT",
|
||||
"plugin.name": "Users & Permissions Plugin"
|
||||
|
@ -0,0 +1,5 @@
|
||||
import pluginId from '../pluginId';
|
||||
|
||||
const getRequestURL = endPoint => `/${pluginId}/${endPoint}`;
|
||||
|
||||
export default getRequestURL;
|
@ -0,0 +1,2 @@
|
||||
export { default as getRequestURL } from './getRequestURL';
|
||||
export { default as getTrad } from './getTrad';
|
Loading…
x
Reference in New Issue
Block a user