Merge pull request #147 from pluginpal/feature/beta-fixes

Feature/beta fixes
pull/148/head
Boaz Poolman 2024-10-12 20:13:45 +02:00 committed by GitHub
commit 4f0ceccb85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 572 additions and 846 deletions

View File

@ -41,9 +41,13 @@ jobs:
node-version: ${{ matrix.node }}
cache: 'yarn'
- name: Install dependencies plugin
run: yarn --no-lockfile --unsafe-perm --production
run: yarn --no-lockfile --unsafe-perm
- name: Push the package to yalc
run: yarn build
- name: Add yalc package to the playground
run: yarn playground:yalc-add
- name: Install dependencies playground
run: yarn playground:install --unsafe-perm
run: cd playground && yarn install --unsafe-perm
- name: Build playground
run: yarn playground:build
- name: Run test

View File

@ -4,60 +4,55 @@ We want this community to be friendly and respectful to each other. Please follo
## Development Workflow
To get started with the project, make sure you have a local instance of Strapi running.
See the [Strapi docs](https://github.com/strapi/strapi#getting-started) on how to setup a Strapi project.
This plugin provides a local development instance of Strapi to develop it's features. We call this instance `playground` and it can be found in the playground folder in the root of the project. For that reason it is not needed to have your own Strapi instance running to work on this plugin. Just clone the repo and you're ready to go!
#### 1. Fork the [repository](https://github.com/boazpoolman/strapi-plugin-config-sync)
#### 1. Fork the [repository](https://github.com/pluginpal/strapi-plugin-config-sync)
[Go to the repository](https://github.com/boazpoolman/strapi-plugin-config-sync) and fork it to your own GitHub account.
[Go to the repository](https://github.com/pluginpal/strapi-plugin-config-sync) and fork it to your own GitHub account.
#### 2. Clone from your repository into the plugins folder
#### 2. Clone the forked repository
```bash
cd YOUR_STRAPI_PROJECT/src/plugins
git clone git@github.com:YOUR_USERNAME/strapi-plugin-config-sync.git config-sync
git clone git@github.com:YOUR_USERNAME/strapi-plugin-config-sync.git
```
#### 3. Install the dependencies
Go to the plugin and install it's dependencies.
Go to the folder and install the dependencies
```bash
cd YOUR_STRAPI_PROJECT/src/plugins/config-sync/ && yarn plugin:install
cd strapi-plugin-config-sync && yarn install
```
#### 4. Enable the plugin
#### 4. Install the playground dependencies
Add the following lines to the `config/plugins.js` file in your Strapi project.
```
const path = require('path');
// ...
{
'config-sync': {
enabled: true,
resolve: path.resolve(__dirname, '../src/plugins/config-sync'),
},
}
```
#### 5. Rebuild your Strapi project
Rebuild your strapi project to build the admin part of the plugin.
Run this in the root of the repository
```bash
cd YOUR_STRAPI_PROJECT && yarn build
yarn playground:install
```
#### 6. Running the administration panel in development mode
#### 5. Run the compiler of the plugin
**Start the administration panel server for development**
We use `yalc` to publish the package to a local registry. Run the following command o watch for changes and push to `yalc` every time a change is made:
```bash
cd YOUR_STRAPI_PROJECT && yarn develop --watch-admin
yarn develop
```
The administration panel will be available at http://localhost:8080/admin
#### 6. Start the playground instance
Leave the watcher running, open up a new terminal window and browse back to the root of the plugin repo. Run the following command:
```bash
yarn playground:develop
```
This will start the playground instance that will have the plugin installed from the `yalc` registry. Browse to http://localhost:1337 and create a test admin user to log in to the playground.
#### 7. Start your contribution!
You can now start working on your contribution. If you had trouble setting up this testing environment please feel free to report an issue on Github.
### Commit message convention
@ -82,12 +77,10 @@ The `package.json` file contains various scripts for common tasks:
- `yarn eslint`: lint files with ESLint.
- `yarn eslint:fix`: auto-fix ESLint issues.
- `yarn test:unit`: run unit tests with Jest.
- `yarn test:integration`: run integration tests with Jest.
### Sending a pull request
> **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
When you're sending a pull request:
- Prefer small pull requests focused on one change.

View File

@ -1,8 +1,8 @@
import React, { useState } from 'react';
import React from 'react';
import styled from 'styled-components';
import { useDispatch, useSelector } from 'react-redux';
import { isEmpty } from 'lodash';
import { Button } from '@strapi/design-system';
import { Button, Typography } from '@strapi/design-system';
import { Map } from 'immutable';
import { getFetchClient, useNotification } from '@strapi/strapi/admin';
import { useIntl } from 'react-intl';
@ -14,38 +14,32 @@ const ActionButtons = () => {
const { post, get } = getFetchClient();
const dispatch = useDispatch();
const { toggleNotification } = useNotification();
const [modalIsOpen, setModalIsOpen] = useState(false);
const [actionType, setActionType] = useState('');
const partialDiff = useSelector((state) => state.getIn(['config', 'partialDiff'], Map({}))).toJS();
const { formatMessage } = useIntl();
const closeModal = () => {
setActionType('');
setModalIsOpen(false);
};
const openModal = (type) => {
setActionType(type);
setModalIsOpen(true);
};
return (
<ActionButtonsStyling>
<Button disabled={isEmpty(partialDiff)} onClick={() => openModal('import')}>
{formatMessage({ id: 'config-sync.Buttons.Import' })}
</Button>
<Button disabled={isEmpty(partialDiff)} onClick={() => openModal('export')}>
{formatMessage({ id: 'config-sync.Buttons.Export' })}
</Button>
{!isEmpty(partialDiff) && (
<h4 style={{ display: 'inline' }}>{Object.keys(partialDiff).length} {Object.keys(partialDiff).length === 1 ? "config change" : "config changes"}</h4>
)}
<ConfirmModal
isOpen={modalIsOpen}
onClose={closeModal}
type={actionType}
onSubmit={(force) => actionType === 'import' ? dispatch(importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get)) : dispatch(exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get))}
type="import"
trigger={(
<Button disabled={isEmpty(partialDiff)}>
{formatMessage({ id: 'config-sync.Buttons.Import' })}
</Button>
)}
onSubmit={(force) => dispatch(importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get))}
/>
<ConfirmModal
type="export"
trigger={(
<Button disabled={isEmpty(partialDiff)}>
{formatMessage({ id: 'config-sync.Buttons.Export' })}
</Button>
)}
onSubmit={(force) => dispatch(exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get))}
/>
{!isEmpty(partialDiff) && (
<Typography variant="epsilon">{Object.keys(partialDiff).length} {Object.keys(partialDiff).length === 1 ? "config change" : "config changes"}</Typography>
)}
</ActionButtonsStyling>
);
};

View File

@ -8,36 +8,39 @@ import {
Typography,
} from '@strapi/design-system';
const ConfigDiff = ({ isOpen, onClose, oldValue, newValue, configName }) => {
const ConfigDiff = ({ oldValue, newValue, configName, trigger }) => {
const { formatMessage } = useIntl();
if (!isOpen) return null;
return (
<Modal.Root
onClose={onClose}
labelledBy="title"
>
<Modal.Header>
<Typography variant="omega" fontWeight="bold" textColor="neutral800">
{formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName}
</Typography>
</Modal.Header>
<Modal.Body>
<Grid.Root paddingBottom={4} style={{ textAlign: 'center' }}>
<Grid.Item col={6}>
<Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography>
</Grid.Item>
<Grid.Item col={6}>
<Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography>
</Grid.Item>
</Grid.Root>
<ReactDiffViewer
oldValue={JSON.stringify(oldValue, null, 2)}
newValue={JSON.stringify(newValue, null, 2)}
splitView
compareMethod={DiffMethod.WORDS}
/>
</Modal.Body>
<Modal.Root>
<Modal.Trigger>
{trigger}
</Modal.Trigger>
<Modal.Content>
<Modal.Header>
<Typography variant="omega" fontWeight="bold" textColor="neutral800">
{formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName}
</Typography>
</Modal.Header>
<Modal.Body>
<Grid.Root paddingBottom={4} style={{ textAlign: 'center' }}>
<Grid.Item col={6}>
<Typography variant="delta" style={{ width: '100%' }}>{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography>
</Grid.Item>
<Grid.Item col={6}>
<Typography variant="delta" style={{ width: '100%' }}>{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography>
</Grid.Item>
</Grid.Root>
<Typography variant="pi">
<ReactDiffViewer
oldValue={JSON.stringify(oldValue, null, 2)}
newValue={JSON.stringify(newValue, null, 2)}
splitView
compareMethod={DiffMethod.WORDS}
/>
</Typography>
</Modal.Body>
</Modal.Content>
</Modal.Root>
);
};

View File

@ -1,7 +1,7 @@
import React from 'react';
import { Tr, Td, Checkbox } from '@strapi/design-system';
import { Tr, Td, Checkbox, Typography } from '@strapi/design-system';
const CustomRow = ({ row, checked, updateValue }) => {
const CustomRow = ({ row, checked, updateValue, ...props }) => {
const { configName, configType, state, onClick } = row;
const stateStyle = (stateStr) => {
@ -34,6 +34,7 @@ const CustomRow = ({ row, checked, updateValue }) => {
return (
<Tr
{...props}
onClick={(e) => {
if (e.target.type !== 'checkbox') {
onClick(configType, configName);
@ -44,18 +45,18 @@ const CustomRow = ({ row, checked, updateValue }) => {
<Td>
<Checkbox
aria-label={`Select ${configName}`}
value={checked}
onValueChange={updateValue}
checked={checked}
onCheckedChange={updateValue}
/>
</Td>
<Td>
<p>{configName}</p>
<Td onClick={(e) => props.onClick(e)}>
<Typography variant="omega">{configName}</Typography>
</Td>
<Td>
<p>{configType}</p>
<Td onClick={(e) => props.onClick(e)}>
<Typography variant="omega">{configType}</Typography>
</Td>
<Td>
<p style={stateStyle(state)}>{state}</p>
<Td onClick={(e) => props.onClick(e)}>
<Typography variant="omega" style={stateStyle(state)}>{state}</Typography>
</Td>
</Tr>
);

View File

@ -22,7 +22,6 @@ import { setConfigPartialDiffInState } from '../../state/actions/Config';
const ConfigList = ({ diff, isLoading }) => {
const [openModal, setOpenModal] = useState(false);
const [originalConfig, setOriginalConfig] = useState({});
const [newConfig, setNewConfig] = useState({});
const [cName, setCname] = useState('');
@ -72,7 +71,6 @@ const ConfigList = ({ diff, isLoading }) => {
setOriginalConfig(diff.fileConfig[`${configType}.${configName}`]);
setNewConfig(diff.databaseConfig[`${configType}.${configName}`]);
setCname(`${configType}.${configName}`);
setOpenModal(true);
},
});
});
@ -89,13 +87,6 @@ const ConfigList = ({ diff, isLoading }) => {
dispatch(setConfigPartialDiffInState(newPartialDiff));
}, [checkedItems]);
const closeModal = () => {
setOriginalConfig({});
setNewConfig({});
setCname('');
setOpenModal(false);
};
if (isLoading) {
return (
<div style={{ textAlign: 'center', marginTop: 40 }}>
@ -117,22 +108,14 @@ const ConfigList = ({ diff, isLoading }) => {
return (
<div>
<ConfigDiff
isOpen={openModal}
oldValue={originalConfig}
newValue={newConfig}
onClose={closeModal}
configName={cName}
/>
<Table colCount={4} rowCount={rows.length + 1}>
<Thead>
<Tr>
<Th>
<Checkbox
aria-label={formatMessage({ id: 'config-sync.ConfigList.SelectAll' })}
indeterminate={isIndeterminate}
onValueChange={(value) => setCheckedItems(checkedItems.map(() => value))}
value={allChecked}
checked={isIndeterminate ? "indeterminate" : allChecked}
onCheckedChange={(value) => setCheckedItems(checkedItems.map(() => value))}
/>
</Th>
<Th>
@ -148,14 +131,21 @@ const ConfigList = ({ diff, isLoading }) => {
</Thead>
<Tbody>
{rows.map((row, index) => (
<ConfigListRow
<ConfigDiff
key={row.configName}
row={row}
checked={checkedItems[index]}
updateValue={() => {
checkedItems[index] = !checkedItems[index];
setCheckedItems([...checkedItems]);
}}
oldValue={originalConfig}
newValue={newConfig}
configName={cName}
trigger={(
<ConfigListRow
row={row}
checked={checkedItems[index]}
updateValue={() => {
checkedItems[index] = !checkedItems[index];
setCheckedItems([...checkedItems]);
}}
/>
)}
/>
))}
</Tbody>

View File

@ -10,69 +10,69 @@ import {
Checkbox,
Divider,
Box,
Field,
} from '@strapi/design-system';
import { WarningCircle } from '@strapi/icons';
const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => {
const ConfirmModal = ({ onClose, onSubmit, type, trigger }) => {
const soft = useSelector((state) => state.getIn(['config', 'appEnv', 'config', 'soft'], false));
const [force, setForce] = useState(false);
const { formatMessage } = useIntl();
if (!isOpen) return null;
return (
<Dialog.Root
onClose={onClose}
title={formatMessage({ id: "config-sync.popUpWarning.Confirmation" })}
isOpen={isOpen}
>
<Dialog.Body icon={<WarningCircle />}>
<Flex size={2}>
<Flex justifyContent="center">
<Typography variant="omega" id="confirm-description" style={{ textAlign: 'center' }}>
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_1` })}<br />
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_2` })}
</Typography>
<Dialog.Root>
<Dialog.Trigger>
{trigger}
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>{formatMessage({ id: "config-sync.popUpWarning.Confirmation" })}</Dialog.Header>
<Dialog.Body>
<WarningCircle fill="danger600" width="32px" height="32px" />
<Flex size={2}>
<Flex justifyContent="center">
<Typography variant="omega" id="confirm-description" style={{ textAlign: 'center' }}>
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_1` })}<br />
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_2` })}
</Typography>
</Flex>
</Flex>
</Flex>
</Dialog.Body>
{(soft && type === 'import') && (
<React.Fragment>
<Divider />
<Box padding={4}>
<Checkbox
onValueChange={(value) => setForce(value)}
value={force}
name="force"
hint="Check this to ignore the soft setting."
{(soft && type === 'import') && (
<Box width="100%">
<Divider marginTop={4} />
<Box paddingTop={6}>
<Field.Root hint="Check this to ignore the soft setting.">
<Checkbox
onValueChange={(value) => setForce(value)}
value={force}
name="force"
>
{formatMessage({ id: 'config-sync.popUpWarning.force' })}
</Checkbox>
<Field.Hint />
</Field.Root>
</Box>
</Box>
)}
</Dialog.Body>
<Dialog.Footer>
<Dialog.Cancel>
<Button fullWidth variant="tertiary">
{formatMessage({ id: 'config-sync.popUpWarning.button.cancel' })}
</Button>
</Dialog.Cancel>
<Dialog.Action>
<Button
fullWidth
variant="secondary"
onClick={() => {
onSubmit(force);
}}
>
{formatMessage({ id: 'config-sync.popUpWarning.force' })}
</Checkbox>
</Box>
</React.Fragment>
)}
<Dialog.Footer
startAction={(
<Button
onClick={() => {
onClose();
}}
variant="tertiary"
>
{formatMessage({ id: 'config-sync.popUpWarning.button.cancel' })}
</Button>
)}
endAction={(
<Button
variant="secondary"
onClick={() => {
onClose();
onSubmit(force);
}}
>
{formatMessage({ id: `config-sync.popUpWarning.button.${type}` })}
</Button>
)} />
{formatMessage({ id: `config-sync.popUpWarning.button.${type}` })}
</Button>
</Dialog.Action>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
);
};

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React from 'react';
import { useIntl } from 'react-intl';
import { useDispatch } from 'react-redux';
import { getFetchClient, useNotification } from '@strapi/strapi/admin';
@ -13,20 +13,21 @@ const FirstExport = () => {
const { post, get } = getFetchClient();
const { toggleNotification } = useNotification();
const dispatch = useDispatch();
const [modalIsOpen, setModalIsOpen] = useState(false);
const { formatMessage } = useIntl();
return (
<div>
<ConfirmModal
isOpen={modalIsOpen}
onClose={() => setModalIsOpen(false)}
type="export"
onSubmit={() => dispatch(exportAllConfig([], toggleNotification, formatMessage, post, get))}
/>
<EmptyStateLayout
content={formatMessage({ id: 'config-sync.FirstExport.Message' })}
action={<Button onClick={() => setModalIsOpen(true)}>{formatMessage({ id: 'config-sync.FirstExport.Button' })}</Button>}
action={(
<ConfirmModal
type="export"
onSubmit={() => dispatch(exportAllConfig([], toggleNotification, formatMessage, post, get))}
trigger={(
<Button>{formatMessage({ id: 'config-sync.FirstExport.Button' })}</Button>
)}
/>
)}
icon={<EmptyDocuments width={160} />}
/>
</div>

View File

@ -14,12 +14,15 @@
"config-sync": "./bin/config-sync"
},
"scripts": {
"develop": "nodemon -e js,jsx --ignore playground --exec \"yalc publish && yalc push\"",
"build": "yalc push --publish",
"eslint": "eslint --max-warnings=0 './**/*.{js,jsx}'",
"eslint:fix": "eslint --fix './**/*.{js,jsx}'",
"test:unit": "jest --verbose",
"test:integration": "cd playground && node_modules/.bin/jest --verbose --forceExit --detectOpenHandles",
"plugin:install": "yarn install && rm -rf node_modules/@strapi/helper-plugin",
"playground:install": "cd playground && yarn install",
"playground:install": "yarn playground:yalc-add-link && cd playground && yarn install",
"playground:yalc-add": "cd playground && yalc add strapi-plugin-config-sync",
"playground:yalc-add-link": "cd playground && yalc add --link strapi-plugin-config-sync",
"playground:build": "cd playground && yarn build",
"playground:develop": "cd playground && yarn develop"
},
@ -55,13 +58,13 @@
"strapi-server.js"
],
"peerDependencies": {
"@strapi/strapi": "^5.0.0-rc.2"
"@strapi/strapi": "^5.0.0"
},
"devDependencies": {
"@strapi/design-system": "2.0.0-rc.7",
"@strapi/icons": "2.0.0-rc.7",
"@strapi/strapi": "5.0.0-rc.2",
"@strapi/utils": "5.0.0-rc.2",
"@strapi/design-system": "2.0.0-rc.11",
"@strapi/icons": "2.0.0-rc.11",
"@strapi/strapi": "5.0.4",
"@strapi/utils": "5.0.4",
"babel-eslint": "9.0.0",
"eslint": "^7.32.0",
"eslint-config-airbnb": "^18.2.1",
@ -78,10 +81,12 @@
"jest-cli": "^29.3.1",
"jest-styled-components": "^7.0.2",
"lodash": "^4.17.11",
"nodemon": "^3.1.7",
"react": "^17.0.2",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"styled-components": "^5.2.3"
"styled-components": "^5.2.3",
"yalc": "^1.0.0-pre.53"
},
"bugs": {
"url": "https://github.com/pluginpal/strapi-plugin-config-sync/issues"

View File

@ -114,3 +114,7 @@ exports
*.cache
build
.strapi-updater.json
# yalc
.yalc
yalc.lock

View File

@ -2,15 +2,15 @@
* This file was automatically generated by Strapi.
* Any modifications made will be discarded.
*/
import usersPermissions from "@strapi/plugin-users-permissions/strapi-admin";
import strapiCloud from "@strapi/plugin-cloud/strapi-admin";
import usersPermissions from "@strapi/plugin-users-permissions/strapi-admin";
import configSync from "strapi-plugin-config-sync/strapi-admin";
import { renderAdmin } from "@strapi/strapi/admin";
renderAdmin(document.getElementById("strapi"), {
plugins: {
"users-permissions": usersPermissions,
"strapi-cloud": strapiCloud,
"users-permissions": usersPermissions,
"config-sync": configSync,
},
});

View File

@ -14,4 +14,7 @@ module.exports = ({ env }) => ({
nps: env.bool('FLAG_NPS', true),
promoteEE: env.bool('FLAG_PROMOTE_EE', true),
},
watchIgnoreFiles: [
'!**/.yalc/**/server/**',
]
});

View File

@ -13,17 +13,18 @@
"devDependencies": {
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
"supertest": "^6.3.3"
"supertest": "^6.3.3",
"yalc": "^1.0.0-pre.53"
},
"dependencies": {
"@strapi/strapi": "5.0.0-rc.2",
"@strapi/plugin-users-permissions": "5.0.0-rc.2",
"@strapi/plugin-cloud": "5.0.0-rc.2",
"@strapi/plugin-cloud": "5.0.4",
"@strapi/plugin-users-permissions": "5.0.4",
"@strapi/strapi": "5.0.4",
"better-sqlite3": "9.4.3",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.0.0",
"strapi-plugin-config-sync": "./..",
"strapi-plugin-config-sync": "link:.yalc/strapi-plugin-config-sync",
"styled-components": "^6.0.0"
},
"author": {

View File

@ -1,5 +1,3 @@
import type { Struct, Schema } from '@strapi/strapi';
declare module '@strapi/strapi' {
export module Public {}
}
/*
* The app doesn't have any components yet.
*/

View File

@ -22,6 +22,7 @@ export interface ApiHomeHome extends Struct.SingleTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<'oneToMany', 'api::home.home'>;
};
}
@ -45,6 +46,7 @@ export interface ApiPagePage extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<'oneToMany', 'api::page.page'>;
};
}
@ -99,6 +101,10 @@ export interface PluginUploadFile extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::upload.file'
>;
};
}
@ -145,6 +151,10 @@ export interface PluginUploadFolder extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::upload.folder'
>;
};
}
@ -186,6 +196,10 @@ export interface PluginI18NLocale extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::i18n.locale'
>;
};
}
@ -229,6 +243,10 @@ export interface PluginContentReleasesRelease
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::content-releases.release'
>;
};
}
@ -269,6 +287,10 @@ export interface PluginContentReleasesReleaseAction
Schema.Attribute.Private;
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::content-releases.release-action'
>;
};
}
@ -312,6 +334,10 @@ export interface PluginReviewWorkflowsWorkflow
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::review-workflows.workflow'
>;
};
}
@ -353,6 +379,10 @@ export interface PluginReviewWorkflowsWorkflowStage
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::review-workflows.workflow-stage'
>;
};
}
@ -391,6 +421,10 @@ export interface PluginUsersPermissionsPermission
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::users-permissions.permission'
>;
};
}
@ -439,6 +473,10 @@ export interface PluginUsersPermissionsRole
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::users-permissions.role'
>;
};
}
@ -490,6 +528,10 @@ export interface PluginUsersPermissionsUser
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'plugin::users-permissions.user'
>;
};
}
@ -535,6 +577,7 @@ export interface AdminPermission extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::permission'>;
};
}
@ -599,6 +642,7 @@ export interface AdminUser extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::user'>;
};
}
@ -646,6 +690,7 @@ export interface AdminRole extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::role'>;
};
}
@ -704,6 +749,7 @@ export interface AdminApiToken extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<'oneToMany', 'admin::api-token'>;
};
}
@ -742,6 +788,10 @@ export interface AdminApiTokenPermission extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'admin::api-token-permission'
>;
};
}
@ -797,6 +847,10 @@ export interface AdminTransferToken extends Struct.CollectionTypeSchema {
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'admin::transfer-token'
>;
};
}
@ -836,6 +890,10 @@ export interface AdminTransferTokenPermission
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
locale: Schema.Attribute.String;
localizations: Schema.Attribute.Relation<
'oneToMany',
'admin::transfer-token-permission'
>;
};
}

947
yarn.lock

File diff suppressed because it is too large Load Diff