mirror of
https://github.com/strapi/strapi.git
synced 2025-09-15 03:27:19 +00:00
Merge branch 'master' into repo/issueTemplateLinks
This commit is contained in:
commit
a5cf340e15
2
.github/actions/check-pr-status/package.json
vendored
2
.github/actions/check-pr-status/package.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "check-pr-status",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"main": "dist/index.js",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "getstarted",
|
||||
"private": true,
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "A Strapi application.",
|
||||
"scripts": {
|
||||
"develop": "strapi develop",
|
||||
@ -12,17 +12,17 @@
|
||||
"strapi": "strapi"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/admin": "4.1.3",
|
||||
"@strapi/plugin-documentation": "4.1.3",
|
||||
"@strapi/plugin-graphql": "4.1.3",
|
||||
"@strapi/plugin-i18n": "4.1.3",
|
||||
"@strapi/plugin-sentry": "4.1.3",
|
||||
"@strapi/plugin-users-permissions": "4.1.3",
|
||||
"@strapi/provider-email-mailgun": "4.1.3",
|
||||
"@strapi/provider-upload-aws-s3": "4.1.3",
|
||||
"@strapi/provider-upload-cloudinary": "4.1.3",
|
||||
"@strapi/strapi": "4.1.3",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/admin": "4.1.5",
|
||||
"@strapi/plugin-documentation": "4.1.5",
|
||||
"@strapi/plugin-graphql": "4.1.5",
|
||||
"@strapi/plugin-i18n": "4.1.5",
|
||||
"@strapi/plugin-sentry": "4.1.5",
|
||||
"@strapi/plugin-users-permissions": "4.1.5",
|
||||
"@strapi/provider-email-mailgun": "4.1.5",
|
||||
"@strapi/provider-upload-aws-s3": "4.1.5",
|
||||
"@strapi/provider-upload-cloudinary": "4.1.5",
|
||||
"@strapi/strapi": "4.1.5",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"lodash": "4.17.21",
|
||||
"mysql": "2.18.1",
|
||||
"passport-google-oauth2": "0.2.0",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "kitchensink",
|
||||
"private": true,
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "A Strapi application.",
|
||||
"scripts": {
|
||||
"develop": "strapi develop",
|
||||
@ -12,12 +12,12 @@
|
||||
"strapi": "strapi"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/admin": "4.1.3",
|
||||
"@strapi/provider-email-mailgun": "4.1.3",
|
||||
"@strapi/provider-upload-aws-s3": "4.1.3",
|
||||
"@strapi/provider-upload-cloudinary": "4.1.3",
|
||||
"@strapi/strapi": "4.1.3",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/admin": "4.1.5",
|
||||
"@strapi/provider-email-mailgun": "4.1.5",
|
||||
"@strapi/provider-upload-aws-s3": "4.1.5",
|
||||
"@strapi/provider-upload-cloudinary": "4.1.5",
|
||||
"@strapi/strapi": "4.1.5",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"lodash": "4.17.21",
|
||||
"mysql": "2.18.1",
|
||||
"passport-google-oauth2": "0.2.0",
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"packages": [
|
||||
"packages/*",
|
||||
"examples/*"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/admin-test-utils",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"private": true,
|
||||
"description": "Test utilities for the Strapi administration panel",
|
||||
"license": "MIT",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-strapi-app",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Generate a new Strapi application.",
|
||||
"keywords": [
|
||||
"create-strapi-app",
|
||||
@ -38,7 +38,7 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/generate-new": "4.1.3",
|
||||
"@strapi/generate-new": "4.1.5",
|
||||
"commander": "6.1.0",
|
||||
"inquirer": "8.2.0"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-strapi-starter",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Generate a new Strapi application.",
|
||||
"keywords": [
|
||||
"create-strapi-starter",
|
||||
@ -38,7 +38,7 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/generate-new": "4.1.3",
|
||||
"@strapi/generate-new": "4.1.5",
|
||||
"chalk": "4.1.1",
|
||||
"ci-info": "3.1.1",
|
||||
"commander": "7.1.0",
|
||||
|
@ -57,10 +57,13 @@ const ComponentInitializer = ({ error, isReadOnly, onClick }) => {
|
||||
</Box>
|
||||
{error?.id && (
|
||||
<Typography textColor="danger600" variant="pi">
|
||||
{formatMessage({
|
||||
id: error.id,
|
||||
defaultMessage: error.id,
|
||||
})}
|
||||
{formatMessage(
|
||||
{
|
||||
id: error.id,
|
||||
defaultMessage: error.id,
|
||||
},
|
||||
{ ...error.values }
|
||||
)}
|
||||
</Typography>
|
||||
)}
|
||||
</>
|
||||
@ -75,6 +78,8 @@ ComponentInitializer.defaultProps = {
|
||||
ComponentInitializer.propTypes = {
|
||||
error: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
defaultMessage: PropTypes.string.isRequired,
|
||||
values: PropTypes.object,
|
||||
}),
|
||||
isReadOnly: PropTypes.bool,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
|
@ -92,7 +92,7 @@ const AccordionGroupCustom = ({ children, footer, label, labelAction, error }) =
|
||||
{error && (
|
||||
<Box paddingTop={1}>
|
||||
<Typography variant="pi" textColor="danger600">
|
||||
{formatMessage({ id: error.id, defaultMessage: error.id })}
|
||||
{formatMessage({ id: error.id, defaultMessage: error.id }, { ...error.values })}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
@ -111,6 +111,8 @@ AccordionGroupCustom.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
error: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
defaultMessage: PropTypes.string.isRequired,
|
||||
values: PropTypes.object,
|
||||
}),
|
||||
footer: PropTypes.node,
|
||||
label: PropTypes.string,
|
||||
|
@ -242,9 +242,14 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => {
|
||||
};
|
||||
|
||||
const redirectToPreviousLocation = () => {
|
||||
const locationBeforeAuthenticated = decodeURIComponent(query.get('redirectTo'));
|
||||
const redirectUrl = locationBeforeAuthenticated || '/';
|
||||
push(redirectUrl);
|
||||
if (authType === 'login') {
|
||||
const redirectTo = query.get('redirectTo');
|
||||
const redirectUrl = redirectTo ? decodeURIComponent(redirectTo) : '/';
|
||||
|
||||
push(redirectUrl);
|
||||
} else {
|
||||
push('/');
|
||||
}
|
||||
};
|
||||
|
||||
// Redirect the user to the login page if
|
||||
|
@ -30,9 +30,6 @@ const StyledReddit = styled(Reddit)`
|
||||
> path:first-child {
|
||||
fill: #ff4500;
|
||||
}
|
||||
> path:last-child {
|
||||
fill: ${({ theme }) => theme.colors.neutral0};
|
||||
}
|
||||
`;
|
||||
const StyledStrapi = styled(Strapi)`
|
||||
> path:first-child {
|
||||
|
@ -633,10 +633,6 @@ describe('Homepage', () => {
|
||||
fill: #ff4500;
|
||||
}
|
||||
|
||||
.c52 > path:last-child {
|
||||
fill: #ffffff;
|
||||
}
|
||||
|
||||
.c55 > path:first-child {
|
||||
fill: #8e75ff;
|
||||
}
|
||||
|
@ -1,15 +1,24 @@
|
||||
{
|
||||
"Analytics": "Phân Tích",
|
||||
"Auth.components.Oops.text": "Tài khoản của bạn đã bị khoá",
|
||||
"Auth.components.Oops.text.admin": "Nếu có sự nhầm lẫn, hãy liên hệ người quản trị",
|
||||
"Auth.form.button.forgot-password": "Gửi Email",
|
||||
"Auth.form.button.go-home": "QUAY VỀ TRANG CHỦ",
|
||||
"Auth.form.button.login": "Đăng nhập",
|
||||
"Auth.form.button.login.providers.error": "Không thể kết nối bạn với dịch vụ đã chọn.",
|
||||
"Auth.form.button.login.providers.see-more": "Xem thêm",
|
||||
"Auth.form.button.login.strapi": "Đăng nhập với Strapi",
|
||||
"Auth.form.button.password-recovery": "Khôi phục mật khẩu",
|
||||
"Auth.form.button.register": "Sẵn sàng để bắt đầu",
|
||||
"Auth.form.button.reset-password": "Đổi mật khẩu",
|
||||
"Auth.form.confirmPassword.label": "Nhập lại mật khẩu",
|
||||
"Auth.form.currentPassword.label": "Mật khẩu hiện tại",
|
||||
"Auth.form.email.label": "Email",
|
||||
"Auth.form.email.placeholder": "kai@doe.com",
|
||||
"Auth.form.error.blocked": "Tài khoản của bạn bị khóa bởi người quản trị",
|
||||
"Auth.form.error.blocked": "Tài khoản của bạn bị khóa bởi người quản trị.",
|
||||
"Auth.form.error.code.provide": "Mã sai đã được cung cấp.",
|
||||
"Auth.form.error.confirmed": "Email của tài khoản của bạn chưa được xác nhận.",
|
||||
"Auth.form.error.email.invalid": "Eemail sai.",
|
||||
"Auth.form.error.email.invalid": "Email sai.",
|
||||
"Auth.form.error.email.provide": "Vui lòng cung cấp tên đăng nhập hoặc email.",
|
||||
"Auth.form.error.email.taken": "Email đã được dùng.",
|
||||
"Auth.form.error.invalid": "Định danh hoặc mật khẩu sai.",
|
||||
@ -21,18 +30,35 @@
|
||||
"Auth.form.error.ratelimit": "Thử quá nhiều lần, vui lòng thử lại trong một phút",
|
||||
"Auth.form.error.user.not-exist": "Email này chưa tồn tại.",
|
||||
"Auth.form.error.username.taken": "Tên đăng nhập đã bị lấy.",
|
||||
"Auth.form.firstname.label": "Họ",
|
||||
"Auth.form.firstname.placeholder": "v.d. Kai",
|
||||
"Auth.form.forgot-password.email.label": "Nhập email của bạn",
|
||||
"Auth.form.forgot-password.email.label.success": "Email đã gửi thành công đến",
|
||||
"Auth.form.lastname.label": "Tên",
|
||||
"Auth.form.lastname.placeholder": "v.d. Doe",
|
||||
"Auth.form.password.hide-password": "Ẩn mật khẩu",
|
||||
"Auth.form.password.hint": "Mật khẩu phải chứa ít nhất 8 ký tự, 1 viết hoa, 1 viết thường, và 1 số",
|
||||
"Auth.form.password.label": "Mật khẩu",
|
||||
"Auth.form.password.show-password": "Hiển thị password",
|
||||
"Auth.form.register.news.label": "Cập nhật cho tôi về chức năng mới và những cải thiện sắp tới (thông qua việc này bạn đã chấp nhận {terms} và {policy}).",
|
||||
"Auth.form.register.subtitle": "Thông tin của bạn chỉ được sử dụng để đăng nhập vào trang quản trị. Tất cả các dữ liệu được lưu ở cơ sở dữ liệu của bạn.",
|
||||
"Auth.form.rememberMe.label": "Nhớ tôi",
|
||||
"Auth.form.username.label": "Tên đăng nhập",
|
||||
"Auth.form.username.placeholder": "Kai Doe",
|
||||
"Auth.link.forgot-password": "Quên mật khẩu của bạn?",
|
||||
"Auth.form.welcome.subtitle": "Đăng nhập vào tài khoản Strapi của bạn",
|
||||
"Auth.form.welcome.title": "Chào mừng!",
|
||||
"Auth.link.forgot-password": "Quên mật khẩu?",
|
||||
"Auth.link.ready": "Sẵn sàng đăng nhập?",
|
||||
"Auth.link.signin": "Đăng nhập",
|
||||
"Auth.link.signin.account": "Đã có tài khoản?",
|
||||
"Auth.login.sso.divider": "Hoặc đăng nhập với",
|
||||
"Auth.login.sso.loading": "Đang tải các dịch vụ cung cấp...",
|
||||
"Auth.login.sso.subtitle": "Đăng nhập qua SSO",
|
||||
"Auth.privacy-policy-agreement.policy": "chính sách bảo mật",
|
||||
"Auth.privacy-policy-agreement.terms": "các điều khoản",
|
||||
"Auth.reset-password.title": "Đặt lại mật khẩu",
|
||||
"Content Manager": "Quản Lý Nội Dung",
|
||||
"Documentation": "Tài liệu",
|
||||
"Email": "Email",
|
||||
"Files Upload": "Tải Tâp Tin Lên",
|
||||
"HomePage.helmet.title": "Trang chủ",
|
||||
@ -257,4 +283,4 @@
|
||||
"notification.error.layout": "Không thể khôi phục",
|
||||
"notification.form.error.fields": "Bảng nhập liệu có vài lỗi",
|
||||
"request.error.model.unknown": "Cấu trúc này không tồn tại"
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/admin",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Strapi Admin",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -52,11 +52,11 @@
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.3",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
||||
"@fortawesome/react-fontawesome": "^0.1.14",
|
||||
"@strapi/babel-plugin-switch-ee-ce": "4.1.3",
|
||||
"@strapi/babel-plugin-switch-ee-ce": "4.1.5",
|
||||
"@strapi/design-system": "0.0.1-alpha.79",
|
||||
"@strapi/helper-plugin": "4.1.3",
|
||||
"@strapi/helper-plugin": "4.1.5",
|
||||
"@strapi/icons": "0.0.1-alpha.79",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"axios": "0.24.0",
|
||||
"babel-loader": "8.2.3",
|
||||
"babel-plugin-styled-components": "2.0.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-content-manager",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "A powerful UI to easily manage your data.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -24,7 +24,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sindresorhus/slugify": "1.1.0",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"lodash": "4.17.21"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -107,7 +107,8 @@ const baseForm = {
|
||||
metadatas: {
|
||||
intlLabel: {
|
||||
id: getTrad('form.attribute.item.date.type.date'),
|
||||
defaultMessage: 'date',
|
||||
defaultMessage: 'date (ex: 01/01/{currentYear})',
|
||||
values: { currentYear: new Date().getFullYear() },
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -117,7 +118,8 @@ const baseForm = {
|
||||
metadatas: {
|
||||
intlLabel: {
|
||||
id: getTrad('form.attribute.item.date.type.datetime'),
|
||||
defaultMessage: 'datetime',
|
||||
defaultMessage: 'datetime (ex: 01/01/{currentYear} 00:00 AM)',
|
||||
values: { currentYear: new Date().getFullYear() },
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -127,7 +129,7 @@ const baseForm = {
|
||||
metadatas: {
|
||||
intlLabel: {
|
||||
id: getTrad('form.attribute.item.date.type.time'),
|
||||
defaultMessage: 'time',
|
||||
defaultMessage: 'time (ex: 00:00 AM)',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -56,12 +56,12 @@ function List({
|
||||
<Tr>
|
||||
<Th>
|
||||
<Typography variant="sigma" textColor="neutral600">
|
||||
{formatMessage({ id: 'table.headers.name', defaultMessage: 'Name' })}
|
||||
{formatMessage({ id: getTrad('table.headers.name'), defaultMessage: 'Name' })}
|
||||
</Typography>
|
||||
</Th>
|
||||
<Th>
|
||||
<Typography variant="sigma" textColor="neutral600">
|
||||
{formatMessage({ id: 'table.headers.type', defaultMessage: 'Type' })}
|
||||
{formatMessage({ id: getTrad('table.headers.type'), defaultMessage: 'Type' })}
|
||||
</Typography>
|
||||
</Th>
|
||||
</Tr>
|
||||
@ -84,12 +84,12 @@ function List({
|
||||
<Tr>
|
||||
<Th>
|
||||
<Typography variant="sigma" textColor="neutral600">
|
||||
{formatMessage({ id: 'table.headers.name', defaultMessage: 'Name' })}
|
||||
{formatMessage({ id: getTrad('table.headers.name'), defaultMessage: 'Name' })}
|
||||
</Typography>
|
||||
</Th>
|
||||
<Th>
|
||||
<Typography variant="sigma" textColor="neutral600">
|
||||
{formatMessage({ id: 'table.headers.type', defaultMessage: 'Type' })}
|
||||
{formatMessage({ id: getTrad('table.headers.type'), defaultMessage: 'Type' })}
|
||||
</Typography>
|
||||
</Th>
|
||||
</Tr>
|
||||
@ -134,12 +134,12 @@ function List({
|
||||
<tr>
|
||||
<th>
|
||||
<Typography variant="sigma" textColor="neutral600">
|
||||
{formatMessage({ id: 'table.headers.name', defaultMessage: 'Name' })}
|
||||
{formatMessage({ id: getTrad('table.headers.name'), defaultMessage: 'Name' })}
|
||||
</Typography>
|
||||
</th>
|
||||
<th colSpan="2">
|
||||
<Typography variant="sigma" textColor="neutral600">
|
||||
{formatMessage({ id: 'table.headers.type', defaultMessage: 'Type' })}
|
||||
{formatMessage({ id: getTrad('table.headers.type'), defaultMessage: 'Type' })}
|
||||
</Typography>
|
||||
</th>
|
||||
</tr>
|
||||
|
@ -142,7 +142,7 @@ function ListRow({
|
||||
onClick={handleClick}
|
||||
label={`${formatMessage({
|
||||
id: 'app.utils.edit',
|
||||
formatMessage: 'Edit',
|
||||
defaultMessage: 'Edit',
|
||||
})} ${name}`}
|
||||
noBorder
|
||||
icon={<Pencil />}
|
||||
|
@ -38,7 +38,10 @@ const SelectDateType = ({ intlLabel, error, modifiedData, name, onChange, option
|
||||
{options.map(({ metadatas: { intlLabel, disabled, hidden }, key, value }) => {
|
||||
return (
|
||||
<Option key={key} value={value} disabled={disabled} hidden={hidden}>
|
||||
{formatMessage(intlLabel)}
|
||||
{formatMessage(
|
||||
{ id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
|
||||
intlLabel.values
|
||||
)}
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
|
@ -148,7 +148,7 @@ const ListView = () => {
|
||||
!isCreatingFirstContentType && (
|
||||
<Button startIcon={<Pencil />} variant="tertiary" onClick={onEdit}>
|
||||
{formatMessage({
|
||||
id: getTrad('app.utils.edit'),
|
||||
id: 'app.utils.edit',
|
||||
defaultMessage: 'Edit',
|
||||
})}
|
||||
</Button>
|
||||
|
@ -55,9 +55,6 @@
|
||||
"form.attribute.component.option.single.description": "Vhodné pro seskupení políček, např. celá adresa",
|
||||
"form.attribute.item.customColumnName": "Vlastné názvy stĺpcov",
|
||||
"form.attribute.item.customColumnName.description": "Umožňuje přejmenovat databázový sloupec pro potřeby API",
|
||||
"form.attribute.item.date.type.date": "datum",
|
||||
"form.attribute.item.date.type.datetime": "datum a čas",
|
||||
"form.attribute.item.date.type.time": "čas",
|
||||
"form.attribute.item.defineRelation.fieldName": "Název pole",
|
||||
"form.attribute.item.enumeration.graphql": "Název pole pro GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Umožňuje přepsat přednastavené názvy názvy pro GraphQL",
|
||||
|
@ -65,9 +65,6 @@
|
||||
"form.attribute.component.option.single.description": "Nützlich um Felder wie volle Addresse, Hauptinformationen, etc. zu grupppieren",
|
||||
"form.attribute.item.customColumnName": "Eigener Spaltenname",
|
||||
"form.attribute.item.customColumnName.description": "Dies ist nützlich, um Spalten in der Datenbank für Antworten der API umzubenennen",
|
||||
"form.attribute.item.date.type.date": "Datum",
|
||||
"form.attribute.item.date.type.datetime": "Datum und Uhrzeit",
|
||||
"form.attribute.item.date.type.time": "Uhrzeit",
|
||||
"form.attribute.item.defineRelation.fieldName": "Feldname",
|
||||
"form.attribute.item.enumeration.graphql": "Namensüberschreibung für GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Ermöglicht, den standardmäßig generierten Namen für GraphQL zu überschreiben",
|
||||
|
@ -75,9 +75,6 @@
|
||||
"form.attribute.component.option.single.description": "Bedst til at gruppere felter som fulde adresse, primær information osv...",
|
||||
"form.attribute.item.customColumnName": "Specielle kolonne navne",
|
||||
"form.attribute.item.customColumnName.description": "Dette er brugbart til at omdøbe database kolonne navne i et mere omfattende format til API svar",
|
||||
"form.attribute.item.date.type.date": "dato",
|
||||
"form.attribute.item.date.type.datetime": "dato - tid",
|
||||
"form.attribute.item.date.type.time": "tid",
|
||||
"form.attribute.item.defineRelation.fieldName": "Felt navn",
|
||||
"form.attribute.item.enumeration.graphql": "Navn overskrivning til GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Tillader dig at overskrive standard genereret navn til GraphQL",
|
||||
|
@ -76,9 +76,9 @@
|
||||
"form.attribute.component.option.single.description": "Best for grouping fields like full address, main information, etc...",
|
||||
"form.attribute.item.customColumnName": "Custom column names",
|
||||
"form.attribute.item.customColumnName.description": "This is useful to rename database column names in a more comprehensive format for the API's responses",
|
||||
"form.attribute.item.date.type.date": "date",
|
||||
"form.attribute.item.date.type.datetime": "datetime",
|
||||
"form.attribute.item.date.type.time": "time",
|
||||
"form.attribute.item.date.type.date": "date (ex: 01/01/{currentYear})",
|
||||
"form.attribute.item.date.type.datetime": "datetime (ex: 01/01/{currentYear} 00:00 AM)",
|
||||
"form.attribute.item.date.type.time": "time (ex: 00:00 AM)",
|
||||
"form.attribute.item.defineRelation.fieldName": "Field name",
|
||||
"form.attribute.item.enumeration.graphql": "Name override for GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Allows you to override the default generated name for GraphQL",
|
||||
|
@ -75,9 +75,6 @@
|
||||
"form.attribute.component.option.single.description": "Lo mejor para agrupar campos como dirección completa, información principal...",
|
||||
"form.attribute.item.customColumnName": "Nombres de columna personalizados",
|
||||
"form.attribute.item.customColumnName.description": "Esto es útil para renombrar los nombres de las columnas de la base de datos en un formato más completo para las respuestas de la API.",
|
||||
"form.attribute.item.date.type.date": "fecha",
|
||||
"form.attribute.item.date.type.datetime": "fecha y hora",
|
||||
"form.attribute.item.date.type.time": "hora",
|
||||
"form.attribute.item.defineRelation.fieldName": "Nombre del campo",
|
||||
"form.attribute.item.enumeration.graphql": "Sobreescritura de nombre para GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Le permite redefinir el nombre generado por defecto para GraphQL",
|
||||
|
@ -65,9 +65,6 @@
|
||||
"form.attribute.component.option.single.description": "Paling baik untuk mengelompokkan bidang seperti alamat lengkap, informasi utama, dll ...",
|
||||
"form.attribute.item.customColumnName": "Nama kolom kustom",
|
||||
"form.attribute.item.customColumnName.description": "Ini berguna untuk mengganti nama kolom database dalam format yang lebih komprehensif untuk respons API",
|
||||
"form.attribute.item.date.type.date": "tanggal",
|
||||
"form.attribute.item.date.type.datetime": "tanggalwaktu",
|
||||
"form.attribute.item.date.type.time": "waktu",
|
||||
"form.attribute.item.defineRelation.fieldName": "Nama bidang",
|
||||
"form.attribute.item.enumeration.graphql": "Nama pengganti untuk GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Memungkinkan Anda untuk mengganti nama default yang dibuat untuk GraphQL ",
|
||||
|
@ -65,9 +65,6 @@
|
||||
"form.attribute.component.option.single.description": "Utile per raggruppare campi correlati come quelli di un indirizzo",
|
||||
"form.attribute.item.customColumnName": "Nome della colonna personalizzato",
|
||||
"form.attribute.item.customColumnName.description": "Utile per rinominare le colonne del database e mantenere consistente il formato delle risposte API",
|
||||
"form.attribute.item.date.type.date": "data",
|
||||
"form.attribute.item.date.type.datetime": "data e ora",
|
||||
"form.attribute.item.date.type.time": "orario",
|
||||
"form.attribute.item.defineRelation.fieldName": "Nome del campo",
|
||||
"form.attribute.item.enumeration.graphql": "Override del nome GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Consente di ignorare l'impostazione predefinita del nome generato per GraphQL",
|
||||
|
@ -75,9 +75,6 @@
|
||||
"form.attribute.component.option.single.description": "전체 주소지, 기본 정보 등과 같은 필드를 그룹화하는 데 적합합니다.",
|
||||
"form.attribute.item.customColumnName": "커스텀 컬럼 이름",
|
||||
"form.attribute.item.customColumnName.description": "API 응답을 위해 데이터베이스 컬럼 이름을 포괄적인 형식으로 변경하는데 유용합니다.",
|
||||
"form.attribute.item.date.type.date": "date",
|
||||
"form.attribute.item.date.type.datetime": "datetime",
|
||||
"form.attribute.item.date.type.time": "time",
|
||||
"form.attribute.item.defineRelation.fieldName": "필드 이름",
|
||||
"form.attribute.item.enumeration.graphql": "GraphQL에서 사용할 이름",
|
||||
"form.attribute.item.enumeration.graphql.description": "기본 생성된 이름을 GraphQL에서 사용합니다.",
|
||||
|
@ -62,9 +62,6 @@
|
||||
"form.attribute.component.option.single.description": "Sesuai untuk ruang kumpulan seperti alamat penuh, maklumat utama dan lain-lain ...",
|
||||
"form.attribute.item.customColumnName": "Gubah nama lajur",
|
||||
"form.attribute.item.customColumnName.description": "Ini berguna untuk menamakan semula nama lajur didalam pangkalan data dengan format yang lebih komprehensif untuk respons API",
|
||||
"form.attribute.item.date.type.date": "tarikh",
|
||||
"form.attribute.item.date.type.datetime": "masa dan tarikh",
|
||||
"form.attribute.item.date.type.time": "masa",
|
||||
"form.attribute.item.defineRelation.fieldName": "Nama ruang",
|
||||
"form.attribute.item.enumeration.graphql": "Ganti nama untuk GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Membolehkan anda menggantikan nama yang dihasilkan secara lalai untuk GraphQL",
|
||||
|
@ -61,9 +61,6 @@
|
||||
"form.attribute.component.option.single.description": "het beste voor het groeperen van velden zoals volledig adres, hoofdinformatie, enz",
|
||||
"form.attribute.item.customColumnName": "Aangepaste kolom namen",
|
||||
"form.attribute.item.customColumnName.description": "Dit is handig om database kolom namen te hernoemen in een meer uitgebreid formaat voor de API responses",
|
||||
"form.attribute.item.date.type.date": "datum",
|
||||
"form.attribute.item.date.type.datetime": "datum-tijd",
|
||||
"form.attribute.item.date.type.time": "tijd",
|
||||
"form.attribute.item.defineRelation.fieldName": "Veld naam",
|
||||
"form.attribute.item.enumeration.graphql": "Naam overschreven voor GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Zorgt ervoor dat je de standaard gegenereerde naam voor GraphQL kan overschrijven",
|
||||
|
@ -56,9 +56,6 @@
|
||||
"form.attribute.component.option.single.description": "Najlepsze do grupowania pól takich jak pełny adres, główne informacje itp.",
|
||||
"form.attribute.item.customColumnName": "Własne nazwy tabel",
|
||||
"form.attribute.item.customColumnName.description": "Jest to przydatne do zmiany nazwy tabel bazy danych w bardziej wszechstronnym formacie odpowiedzi API",
|
||||
"form.attribute.item.date.type.date": "data",
|
||||
"form.attribute.item.date.type.datetime": "data i czas",
|
||||
"form.attribute.item.date.type.time": "czas",
|
||||
"form.attribute.item.defineRelation.fieldName": "Atrybut",
|
||||
"form.attribute.item.enumeration.graphql": "Nadpisanie nazwy dla GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Pozwalaj na nadpisanie domyślnie wygenerowanej nazwy dla GraphQL.",
|
||||
|
@ -66,9 +66,6 @@
|
||||
"form.attribute.component.option.single.description": "Применимо для группировки полей, таких как полный адрес, основная информация и т.д.",
|
||||
"form.attribute.item.customColumnName": "Названия столбцов",
|
||||
"form.attribute.item.customColumnName.description": "Может быть полезно переименовать названия столбцов для более читаемых ответов API.",
|
||||
"form.attribute.item.date.type.date": "дата",
|
||||
"form.attribute.item.date.type.datetime": "дата/время",
|
||||
"form.attribute.item.date.type.time": "время",
|
||||
"form.attribute.item.defineRelation.fieldName": "Название поля",
|
||||
"form.attribute.item.enumeration.graphql": "Название поля в GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Позволяет переопределить название поля в GraphQL, сгенерированное по умолчанию",
|
||||
|
@ -65,9 +65,6 @@
|
||||
"form.attribute.component.option.single.description": "Vhodné pre zoskúpenie políčok, napr. celá adresa",
|
||||
"form.attribute.item.customColumnName": "Vlastné názvy stĺpcov",
|
||||
"form.attribute.item.customColumnName.description": "Umožňuje premenovať databázový stĺpček pre potreby API",
|
||||
"form.attribute.item.date.type.date": "dátum",
|
||||
"form.attribute.item.date.type.datetime": "dátum a čas",
|
||||
"form.attribute.item.date.type.time": "čas",
|
||||
"form.attribute.item.defineRelation.fieldName": "Názov políčka",
|
||||
"form.attribute.item.enumeration.graphql": "Názov políčka pre GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Umožňuje prepísať predvolené názvy pre GraphQL",
|
||||
|
@ -63,9 +63,6 @@
|
||||
"form.attribute.component.option.single.description": "ดีที่สุดสำหรับการจัดกลุ่มฟิลด์เช่นแอดเดรสแบบเต็มข้อมูลหลักและอื่นๆ",
|
||||
"form.attribute.item.customColumnName": "ชื่อคอลัมน์แบบกำหนดเอง",
|
||||
"form.attribute.item.customColumnName.description": "สิ่งนี้มีประโยชน์ในการเปลี่ยนชื่อคอลัมน์ฐานข้อมูลในรูปแบบที่ครอบคลุมมากขึ้นสำหรับการตอบกลับของ API",
|
||||
"form.attribute.item.date.type.date": "วันที่",
|
||||
"form.attribute.item.date.type.datetime": "วันที่เวลา",
|
||||
"form.attribute.item.date.type.time": "เวลา",
|
||||
"form.attribute.item.defineRelation.fieldName": "ชื่อฟิลด์",
|
||||
"form.attribute.item.enumeration.graphql": "การเขียนทับชื่อสำหรับ GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "อนุญาตให้คุณเขียนทับชื่อที่สร้างขึ้นพื้นฐานสำหรับ GraphQL",
|
||||
|
@ -63,9 +63,6 @@
|
||||
"form.attribute.component.option.single.description": "Підходить для групування полей, наприклад, повна адреса, основна інформація тощо...",
|
||||
"form.attribute.item.customColumnName": "Власні назви стовпців",
|
||||
"form.attribute.item.customColumnName.description": "Корисно для перейменування назв стовпців у базі даних для підтримки більш зрозумілого формату відповідей API",
|
||||
"form.attribute.item.date.type.date": "дата",
|
||||
"form.attribute.item.date.type.datetime": "дата та час",
|
||||
"form.attribute.item.date.type.time": "час",
|
||||
"form.attribute.item.defineRelation.fieldName": "Назва поля",
|
||||
"form.attribute.item.enumeration.graphql": "Назва поля для GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Дозволяє перейменувати згенеровану для GraphQL назву поля",
|
||||
|
@ -56,9 +56,6 @@
|
||||
"form.attribute.component.option.single.description": "最适合的对完整地址,主要信息等字段进行分组...",
|
||||
"form.attribute.item.customColumnName": "自定义列名称",
|
||||
"form.attribute.item.customColumnName.description": "修改数据库列名,使得API返回更容易理解。",
|
||||
"form.attribute.item.date.type.date": "日期",
|
||||
"form.attribute.item.date.type.datetime": "日期与时间",
|
||||
"form.attribute.item.date.type.time": "时间",
|
||||
"form.attribute.item.defineRelation.fieldName": "字段名称",
|
||||
"form.attribute.item.enumeration.graphql": "GraphQL 的名称重写",
|
||||
"form.attribute.item.enumeration.graphql.description": "允许您覆盖 GraphQL 的默认生成名称",
|
||||
|
@ -62,9 +62,6 @@
|
||||
"form.attribute.component.option.single.description": "適用於組合型欄位群,如:完整地址,基本完整資訊 ......等",
|
||||
"form.attribute.item.customColumnName": "自訂欄位名稱",
|
||||
"form.attribute.item.customColumnName.description": "將資料庫欄位名稱以更易懂的格式重新命名,對 API 回應很有用。",
|
||||
"form.attribute.item.date.type.date": "日期",
|
||||
"form.attribute.item.date.type.datetime": "日期及時間",
|
||||
"form.attribute.item.date.type.time": "時間",
|
||||
"form.attribute.item.defineRelation.fieldName": "欄位名稱",
|
||||
"form.attribute.item.enumeration.graphql": "GraphQL 名稱覆寫",
|
||||
"form.attribute.item.enumeration.graphql.description": "可以讓您覆寫 GraphQL 的預設名稱",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-content-type-builder",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Strapi plugin to create content type",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -28,9 +28,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sindresorhus/slugify": "1.1.0",
|
||||
"@strapi/generators": "4.1.3",
|
||||
"@strapi/helper-plugin": "4.1.3",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/generators": "4.1.5",
|
||||
"@strapi/helper-plugin": "4.1.5",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"fs-extra": "10.0.0",
|
||||
"lodash": "4.17.21",
|
||||
"pluralize": "^8.0.0",
|
||||
|
1
packages/core/database/examples/.gitignore
vendored
1
packages/core/database/examples/.gitignore
vendored
@ -1 +0,0 @@
|
||||
data
|
@ -1,36 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const postgres = {
|
||||
client: 'postgres',
|
||||
connection: {
|
||||
database: 'strapi',
|
||||
user: 'strapi',
|
||||
password: 'strapi',
|
||||
},
|
||||
// debug: true,
|
||||
};
|
||||
|
||||
const mysql = {
|
||||
client: 'mysql',
|
||||
connection: {
|
||||
database: 'strapi',
|
||||
user: 'strapi',
|
||||
password: 'strapi',
|
||||
},
|
||||
// debug: true,
|
||||
};
|
||||
|
||||
const sqlite = {
|
||||
client: 'sqlite',
|
||||
connection: {
|
||||
filename: 'data.sqlite',
|
||||
},
|
||||
useNullAsDefault: true,
|
||||
// debug: true,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
sqlite,
|
||||
postgres,
|
||||
mysql,
|
||||
};
|
@ -1,29 +0,0 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres
|
||||
restart: always
|
||||
volumes:
|
||||
- ./data/postgresql:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_USER: strapi
|
||||
POSTGRES_PASSWORD: strapi
|
||||
POSTGRES_DB: strapi
|
||||
ports:
|
||||
- '5432:5432'
|
||||
|
||||
mysql:
|
||||
image: mysql
|
||||
restart: always
|
||||
command: --default-authentication-plugin=mysql_native_password
|
||||
environment:
|
||||
MYSQL_DATABASE: strapi
|
||||
MYSQL_USER: strapi
|
||||
MYSQL_PASSWORD: strapi
|
||||
MYSQL_ROOT_HOST: '%'
|
||||
MYSQL_ROOT_PASSWORD: strapi
|
||||
volumes:
|
||||
- ./data/mysql:/var/lib/mysql
|
||||
ports:
|
||||
- '3306:3306'
|
@ -1,73 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const util = require('util');
|
||||
|
||||
const { Database } = require('../lib/index');
|
||||
const models = require('./models');
|
||||
const connections = require('./connections');
|
||||
|
||||
async function main(connection) {
|
||||
const orm = await Database.init({
|
||||
connection,
|
||||
models: Database.transformContentTypes(models),
|
||||
});
|
||||
|
||||
try {
|
||||
// await orm.schema.drop();
|
||||
// await orm.schema.create();
|
||||
|
||||
await orm.schema.reset();
|
||||
|
||||
let res;
|
||||
|
||||
const c1 = await orm.query('comment').create({
|
||||
data: {
|
||||
title: 'coucou',
|
||||
},
|
||||
});
|
||||
|
||||
const c2 = await orm.query('video-comment').create({
|
||||
data: {
|
||||
title: 'coucou',
|
||||
},
|
||||
});
|
||||
|
||||
res = await orm.query('article').create({
|
||||
data: {
|
||||
dz: [
|
||||
{
|
||||
__type: 'comment',
|
||||
id: c1.id,
|
||||
},
|
||||
{
|
||||
__type: 'video-comment',
|
||||
id: c2.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
populate: {
|
||||
dz: true,
|
||||
},
|
||||
});
|
||||
|
||||
log(res);
|
||||
|
||||
res = await orm.query('article').findMany({
|
||||
populate: {
|
||||
dz: true,
|
||||
},
|
||||
});
|
||||
|
||||
log(res);
|
||||
|
||||
// await tests(orm);
|
||||
} finally {
|
||||
orm.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
function log(res) {
|
||||
console.log(util.inspect(res, null, null, true));
|
||||
}
|
||||
|
||||
main(connections.sqlite);
|
@ -1,341 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const category = {
|
||||
modelName: 'category',
|
||||
uid: 'category',
|
||||
collectionName: 'categories',
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
price: {
|
||||
type: 'integer',
|
||||
required: true,
|
||||
default: 12,
|
||||
|
||||
column: {
|
||||
unique: true,
|
||||
nonNullable: true,
|
||||
unsigned: true,
|
||||
defaultTo: 12,
|
||||
},
|
||||
},
|
||||
articles: {
|
||||
type: 'relation',
|
||||
relation: 'oneToMany',
|
||||
target: 'article',
|
||||
mappedBy: 'category',
|
||||
},
|
||||
compo: {
|
||||
type: 'component',
|
||||
component: 'compo',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const article = {
|
||||
modelName: 'article',
|
||||
uid: 'article',
|
||||
collectionName: 'articles',
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
category: {
|
||||
type: 'relation',
|
||||
relation: 'manyToOne',
|
||||
target: 'category',
|
||||
inversedBy: 'articles',
|
||||
// useJoinTable: false,
|
||||
},
|
||||
// tags: {
|
||||
// type: 'relation',
|
||||
// relation: 'manyToMany',
|
||||
// target: 'tag',
|
||||
// inversedBy: 'articles',
|
||||
// },
|
||||
// compo: {
|
||||
// type: 'component',
|
||||
// component: 'compo',
|
||||
// // repeatable: true,
|
||||
// },
|
||||
// cover: {
|
||||
// type: 'media',
|
||||
// single: true,
|
||||
// },
|
||||
// gallery: {
|
||||
// type: 'media',
|
||||
// multiple: true,
|
||||
// },
|
||||
},
|
||||
};
|
||||
|
||||
const tags = {
|
||||
modelName: 'tag',
|
||||
uid: 'tag',
|
||||
collectionName: 'tags',
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
articles: {
|
||||
type: 'relation',
|
||||
relation: 'manyToMany',
|
||||
target: 'article',
|
||||
mappedBy: 'tag',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const compo = {
|
||||
modelName: 'compo',
|
||||
uid: 'compo',
|
||||
collectionName: 'compos',
|
||||
attributes: {
|
||||
key: {
|
||||
type: 'string',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const user = {
|
||||
modelName: 'user',
|
||||
uid: 'user',
|
||||
collectionName: 'users',
|
||||
attributes: {
|
||||
address: {
|
||||
type: 'relation',
|
||||
relation: 'oneToOne',
|
||||
target: 'address',
|
||||
inversedBy: 'user',
|
||||
// useJoinTable: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const address = {
|
||||
modelName: 'address',
|
||||
uid: 'address',
|
||||
collectionName: 'addresses',
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
user: {
|
||||
type: 'relation',
|
||||
relation: 'oneToOne',
|
||||
target: 'user',
|
||||
mappedBy: 'address',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const file = {
|
||||
modelName: 'file',
|
||||
uid: 'file',
|
||||
collectionName: 'files',
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
alternativeText: {
|
||||
type: 'string',
|
||||
},
|
||||
caption: {
|
||||
type: 'string',
|
||||
},
|
||||
width: {
|
||||
type: 'integer',
|
||||
},
|
||||
height: {
|
||||
type: 'integer',
|
||||
},
|
||||
formats: {
|
||||
type: 'json',
|
||||
},
|
||||
hash: {
|
||||
type: 'string',
|
||||
},
|
||||
ext: {
|
||||
type: 'string',
|
||||
},
|
||||
mime: {
|
||||
type: 'string',
|
||||
},
|
||||
size: {
|
||||
type: 'decimal',
|
||||
},
|
||||
url: {
|
||||
type: 'string',
|
||||
},
|
||||
previewUrl: {
|
||||
type: 'string',
|
||||
},
|
||||
provider: {
|
||||
type: 'string',
|
||||
},
|
||||
provider_metadata: {
|
||||
type: 'json',
|
||||
},
|
||||
// related: {
|
||||
// type: 'relation',
|
||||
// relation: 'oneToMany',
|
||||
// target: 'file_morph',
|
||||
// mappedBy: 'file',
|
||||
// },
|
||||
// related: {
|
||||
// type: 'relation',
|
||||
// realtion: 'morphTo',
|
||||
// },
|
||||
},
|
||||
};
|
||||
|
||||
const fileMorph = {
|
||||
modelName: 'file-morph',
|
||||
uid: 'file-morph',
|
||||
collectionName: 'file_morphs',
|
||||
attributes: {
|
||||
// file: {
|
||||
// type: 'relation',
|
||||
// relation: 'manyToOne',
|
||||
// target: 'file',
|
||||
// inversedBy: 'related',
|
||||
// useJoinTable: false,
|
||||
// },
|
||||
},
|
||||
};
|
||||
|
||||
const blogPost = {
|
||||
modelName: 'blogPost',
|
||||
uid: 'blogPost',
|
||||
collectionName: 'blog_posts',
|
||||
attributes: {
|
||||
passwordField: {
|
||||
type: 'password',
|
||||
},
|
||||
emailField: {
|
||||
type: 'email',
|
||||
},
|
||||
stringField: {
|
||||
type: 'string',
|
||||
},
|
||||
uidField: {
|
||||
type: 'uid',
|
||||
},
|
||||
richtextField: {
|
||||
type: 'richtext',
|
||||
},
|
||||
textField: {
|
||||
type: 'text',
|
||||
},
|
||||
enumerationField: {
|
||||
type: 'enumeration',
|
||||
enum: ['A', 'B'],
|
||||
},
|
||||
jsonField: {
|
||||
type: 'json',
|
||||
},
|
||||
bigintegerField: {
|
||||
type: 'biginteger',
|
||||
},
|
||||
integerField: {
|
||||
type: 'integer',
|
||||
},
|
||||
floatField: {
|
||||
type: 'float',
|
||||
},
|
||||
decimalField: {
|
||||
type: 'decimal',
|
||||
},
|
||||
dateField: {
|
||||
type: 'date',
|
||||
},
|
||||
timeField: {
|
||||
type: 'time',
|
||||
},
|
||||
datetimeField: {
|
||||
type: 'datetime',
|
||||
},
|
||||
timestampField: {
|
||||
type: 'timestamp',
|
||||
},
|
||||
booleanField: {
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = [category, article, tags, compo, user, address, file, fileMorph, blogPost];
|
||||
|
||||
// const article = {
|
||||
// modelName: 'article',
|
||||
// uid: 'article',
|
||||
// collectionName: 'articles',
|
||||
// attributes: {
|
||||
// commentable: {
|
||||
// type: 'relation',
|
||||
// relation: 'morphToOne',
|
||||
// },
|
||||
// reportables: {
|
||||
// type: 'relation',
|
||||
// relation: 'morphToMany',
|
||||
// },
|
||||
// dz: {
|
||||
// type: 'dynamiczone',
|
||||
// components: ['comment', 'video-comment'],
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// const comment = {
|
||||
// modelName: 'comment',
|
||||
// uid: 'comment',
|
||||
// collectionName: 'comments',
|
||||
// attributes: {
|
||||
// article: {
|
||||
// type: 'relation',
|
||||
// relation: 'morphOne',
|
||||
// target: 'article',
|
||||
// morphBy: 'commentable',
|
||||
// },
|
||||
// title: {
|
||||
// type: 'string',
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// const videoComment = {
|
||||
// modelName: 'video-comment',
|
||||
// uid: 'video-comment',
|
||||
// collectionName: 'video_comments',
|
||||
// attributes: {
|
||||
// articles: {
|
||||
// type: 'relation',
|
||||
// relation: 'morphMany',
|
||||
// target: 'article',
|
||||
// morphBy: 'commentable',
|
||||
// },
|
||||
// title: {
|
||||
// type: 'string',
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// const folder = {
|
||||
// modelName: 'folder',
|
||||
// uid: 'folder',
|
||||
// collectionName: 'folders',
|
||||
// attributes: {
|
||||
// articles: {
|
||||
// type: 'relation',
|
||||
// relation: 'morphMany',
|
||||
// target: 'article',
|
||||
// morphBy: 'reportables',
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// module.exports = [article, comment, videoComment, folder];
|
@ -1,17 +0,0 @@
|
||||
type ID = number | string;
|
||||
|
||||
interface Category {
|
||||
id: ID;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface Article {
|
||||
id: ID;
|
||||
title: string;
|
||||
category: Category | ID;
|
||||
}
|
||||
|
||||
interface AllTypes {
|
||||
article: Article;
|
||||
category: Category;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/database",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Strapi's database layer",
|
||||
"homepage": "https://strapi.io",
|
||||
"bugs": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-email",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Easily configure your Strapi application to send emails.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -26,12 +26,12 @@
|
||||
"test:front:watch:ce": "cross-env IS_EE=false jest --config ./jest.config.front.js --watchAll"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/provider-email-sendmail": "4.1.3",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/provider-email-sendmail": "4.1.5",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"lodash": "4.17.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@strapi/helper-plugin": "4.1.3"
|
||||
"@strapi/helper-plugin": "4.1.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0 <=16.x.x",
|
||||
|
@ -8,7 +8,7 @@ import { Box } from '@strapi/design-system/Box';
|
||||
import { Flex } from '@strapi/design-system/Flex';
|
||||
import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox';
|
||||
import { Dialog, DialogBody, DialogFooter } from '@strapi/design-system/Dialog';
|
||||
import { Tbody, Td, Tr } from '@strapi/design-system/Table';
|
||||
import { Tbody, Td, Tr, TFooter } from '@strapi/design-system/Table';
|
||||
import { Typography } from '@strapi/design-system/Typography';
|
||||
import { IconButton } from '@strapi/design-system/IconButton';
|
||||
import { Plus, Pencil, Trash } from '@strapi/icons';
|
||||
@ -93,6 +93,43 @@ import { DynamicTable } from '@strapi/helper-plugin';
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
||||
## Usage No content with footer
|
||||
|
||||
<Canvas>
|
||||
<Story name="no-content-with-footer">
|
||||
{() => {
|
||||
const headers = [
|
||||
{
|
||||
name: 'firstname',
|
||||
metadatas: { label: 'Firstname', sortable: false },
|
||||
key: '__firstname_key__',
|
||||
},
|
||||
{
|
||||
name: 'lastname',
|
||||
metadatas: { label: 'Email', sortable: false },
|
||||
key: '__lastname_key__',
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
metadatas: { label: 'Email', sortable: false },
|
||||
key: '__email_key__',
|
||||
},
|
||||
];
|
||||
const [{ query }, setQuery] = useQueryParams();
|
||||
useEffect(() => {
|
||||
setQuery({ filters: { $and: [{ firstname: { $eq: 'soupette' } }] } });
|
||||
}, []);
|
||||
return (
|
||||
<Main>
|
||||
<Box paddingTop={6}>
|
||||
<DynamicTable headers={headers} contentType="users" footer={<TFooter icon={<Plus />}>Add another user</TFooter>}/>
|
||||
</Box>
|
||||
</Main>
|
||||
);
|
||||
}}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
||||
## Usage No content with filters
|
||||
|
||||
<Canvas>
|
||||
|
@ -23,10 +23,11 @@ const BlockActions = styled(Flex)`
|
||||
`;
|
||||
|
||||
const Table = ({
|
||||
action,
|
||||
children,
|
||||
contentType,
|
||||
components,
|
||||
action,
|
||||
footer,
|
||||
headers,
|
||||
isLoading,
|
||||
onConfirmDeleteAll,
|
||||
@ -159,7 +160,7 @@ const Table = ({
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
<TableCompo colCount={COL_COUNT} rowCount={ROW_COUNT}>
|
||||
<TableCompo colCount={COL_COUNT} rowCount={ROW_COUNT} footer={footer}>
|
||||
<TableHead
|
||||
areAllEntriesSelected={areAllEntriesSelected}
|
||||
entriesToDelete={entriesToDelete}
|
||||
@ -207,12 +208,13 @@ const Table = ({
|
||||
};
|
||||
|
||||
Table.defaultProps = {
|
||||
action: undefined,
|
||||
children: undefined,
|
||||
components: {
|
||||
ConfirmDialogDeleteAll: undefined,
|
||||
ConfirmDialogDelete: undefined,
|
||||
},
|
||||
action: undefined,
|
||||
footer: undefined,
|
||||
headers: [],
|
||||
isLoading: false,
|
||||
onConfirmDeleteAll: () => {},
|
||||
@ -224,13 +226,14 @@ Table.defaultProps = {
|
||||
};
|
||||
|
||||
Table.propTypes = {
|
||||
action: PropTypes.node,
|
||||
children: PropTypes.node,
|
||||
contentType: PropTypes.string.isRequired,
|
||||
components: PropTypes.shape({
|
||||
ConfirmDialogDelete: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
ConfirmDialogDeleteAll: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
}),
|
||||
action: PropTypes.node,
|
||||
footer: PropTypes.node,
|
||||
headers: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
cellFormatter: PropTypes.func,
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/helper-plugin",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Helper for Strapi plugins development",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/strapi",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "An open source headless CMS solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier. Databases supported: MySQL, MariaDB, PostgreSQL, SQLite",
|
||||
"keywords": [
|
||||
"strapi",
|
||||
@ -80,16 +80,16 @@
|
||||
"dependencies": {
|
||||
"@koa/cors": "3.1.0",
|
||||
"@koa/router": "10.1.1",
|
||||
"@strapi/admin": "4.1.3",
|
||||
"@strapi/database": "4.1.3",
|
||||
"@strapi/generate-new": "4.1.3",
|
||||
"@strapi/generators": "4.1.3",
|
||||
"@strapi/logger": "4.1.3",
|
||||
"@strapi/plugin-content-manager": "4.1.3",
|
||||
"@strapi/plugin-content-type-builder": "4.1.3",
|
||||
"@strapi/plugin-email": "4.1.3",
|
||||
"@strapi/plugin-upload": "4.1.3",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/admin": "4.1.5",
|
||||
"@strapi/database": "4.1.5",
|
||||
"@strapi/generate-new": "4.1.5",
|
||||
"@strapi/generators": "4.1.5",
|
||||
"@strapi/logger": "4.1.5",
|
||||
"@strapi/plugin-content-manager": "4.1.5",
|
||||
"@strapi/plugin-content-type-builder": "4.1.5",
|
||||
"@strapi/plugin-email": "4.1.5",
|
||||
"@strapi/plugin-upload": "4.1.5",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"bcryptjs": "2.4.3",
|
||||
"boxen": "5.1.2",
|
||||
"chalk": "4.1.2",
|
||||
|
@ -48,7 +48,8 @@ export const VideoAssetCard = ({
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const [duration, setDuration] = useState();
|
||||
const formattedDuration = duration ? formatDuration(duration) : undefined;
|
||||
|
||||
const formattedDuration = duration && formatDuration(duration);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
|
@ -17,7 +17,7 @@ export const SelectedStep = ({ selectedAssets, onSelectAsset, onReorderAsset })
|
||||
{
|
||||
id: getTrad('list.assets.selected'),
|
||||
defaultMessage:
|
||||
'{number, plural, =0 {No asset} one {1 asset} other {# assets}} selected',
|
||||
'{number, plural, =0 {No asset} one {1 asset} other {# assets}} ready to upload',
|
||||
},
|
||||
{ number: selectedAssets.length }
|
||||
)}
|
||||
@ -25,7 +25,7 @@ export const SelectedStep = ({ selectedAssets, onSelectAsset, onReorderAsset })
|
||||
<Typography variant="pi" textColor="neutral600">
|
||||
{formatMessage({
|
||||
id: getTrad('modal.upload-list.sub-header-subtitle'),
|
||||
defaultMessage: 'Manage the assets before uploading them to the Media Library',
|
||||
defaultMessage: 'Manage the assets before adding them to the Media Library',
|
||||
})}
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
@ -78,7 +78,7 @@ export const PendingAssetStep = ({
|
||||
{
|
||||
id: getTrad('list.assets.selected'),
|
||||
defaultMessage:
|
||||
'{number, plural, =0 {No asset} one {1 asset} other {# assets}} selected',
|
||||
'{number, plural, =0 {No asset} one {1 asset} other {# assets}} ready to upload',
|
||||
},
|
||||
{ number: assets.length }
|
||||
)}
|
||||
@ -86,7 +86,7 @@ export const PendingAssetStep = ({
|
||||
<Typography variant="pi" textColor="neutral600">
|
||||
{formatMessage({
|
||||
id: getTrad('modal.upload-list.sub-header-subtitle'),
|
||||
defaultMessage: 'Manage the assets before uploading them to the Media Library',
|
||||
defaultMessage: 'Manage the assets before adding them to the Media Library',
|
||||
})}
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
@ -768,7 +768,7 @@ exports[`PendingAssetStep snapshots the component with valid cards 1`] = `
|
||||
<span
|
||||
class="c12"
|
||||
>
|
||||
Manage the assets before uploading them to the Media Library
|
||||
Manage the assets before adding them to the Media Library
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
|
@ -101,7 +101,7 @@ describe('UploadAssetDialog', () => {
|
||||
)
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Manage the assets before uploading them to the Media Library')
|
||||
screen.getByText('Manage the assets before adding them to the Media Library')
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getAllByText(`test.${ext}`).length).toBe(number);
|
||||
expect(screen.getByText(ext)).toBeInTheDocument();
|
||||
@ -199,7 +199,7 @@ describe('UploadAssetDialog', () => {
|
||||
);
|
||||
expect(screen.getAllByText(`Add new assets`).length).toBe(2);
|
||||
expect(
|
||||
screen.getByText('Manage the assets before uploading them to the Media Library')
|
||||
screen.getByText('Manage the assets before adding them to the Media Library')
|
||||
).toBeInTheDocument();
|
||||
|
||||
assets.forEach(asset => {
|
||||
|
@ -68,7 +68,7 @@
|
||||
"modal.remove.success-label": "The asset has been successfully removed.",
|
||||
"modal.selected-list.sub-header-subtitle": "Drag & drop to reorder the assets in the field",
|
||||
"modal.upload-list.footer.button": "Upload {number, plural, one {# asset} other {# assets}} to the library",
|
||||
"modal.upload-list.sub-header-subtitle": "Manage the assets before uploading them to the Media Library",
|
||||
"modal.upload-list.sub-header-subtitle": "Manage the assets before adding them to the Media Library",
|
||||
"modal.upload-list.sub-header.button": "Add more assets",
|
||||
"modal.upload.cancelled": "Upload manually aborted.",
|
||||
"page.title": "Settings - Media Library",
|
||||
|
@ -1,12 +1,9 @@
|
||||
import { intervalToDuration } from 'date-fns';
|
||||
|
||||
const zeroPad = num => String(num).padStart(2, '0');
|
||||
|
||||
export const formatDuration = durationInSecond => {
|
||||
const formatter = new Intl.DateTimeFormat('default', {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: 'numeric',
|
||||
});
|
||||
const duration = intervalToDuration({ start: 0, end: durationInSecond * 1000 });
|
||||
|
||||
const date = new Date(1970, 0, 1);
|
||||
date.setSeconds(durationInSecond);
|
||||
|
||||
return formatter.format(date);
|
||||
return `${zeroPad(duration.hours)}:${zeroPad(duration.minutes)}:${zeroPad(duration.seconds)}`;
|
||||
};
|
||||
|
@ -0,0 +1,9 @@
|
||||
import { formatDuration } from '../formatDuration';
|
||||
|
||||
describe('formatDuration', () => {
|
||||
test('properly format seconds', () => {
|
||||
expect(formatDuration(1)).toBe('00:00:01');
|
||||
expect(formatDuration(60)).toBe('00:01:00');
|
||||
expect(formatDuration(3600)).toBe('01:00:00');
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-upload",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Makes it easy to upload images and files to your Strapi Application.",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"author": {
|
||||
@ -23,9 +23,9 @@
|
||||
"test:front:watch:ce": "cross-env IS_EE=false jest --config ./jest.config.front.js --watchAll"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/helper-plugin": "4.1.3",
|
||||
"@strapi/provider-upload-local": "4.1.3",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/helper-plugin": "4.1.5",
|
||||
"@strapi/provider-upload-local": "4.1.5",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"byte-size": "7.0.1",
|
||||
"cropperjs": "1.5.11",
|
||||
"fs-extra": "10.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/utils",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Shared utilities for the Strapi packages",
|
||||
"keywords": [
|
||||
"strapi",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/generate-new",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Generate a new Strapi application.",
|
||||
"keywords": [
|
||||
"generate",
|
||||
|
@ -1,5 +1,5 @@
|
||||
const pluginPkg = require('../../package.json');
|
||||
|
||||
const pluginId = pluginPkg.name.replace(/^@strapi\/plugin-/i, '');
|
||||
const pluginId = pluginPkg.name.replace(/^(@[^-,.][\w,-]+\/|strapi-)plugin-/i, '');
|
||||
|
||||
module.exports = pluginId;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/generators",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Interactive API generator.",
|
||||
"keywords": [
|
||||
"strapi",
|
||||
@ -30,7 +30,7 @@
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"@sindresorhus/slugify": "1.1.0",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"chalk": "4.1.2",
|
||||
"fs-extra": "10.0.0",
|
||||
"node-plop": "0.26.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-documentation",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Create an OpenAPI Document and visualize your API with SWAGGER UI.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -24,8 +24,8 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/helper-plugin": "4.1.3",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/helper-plugin": "4.1.5",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"bcryptjs": "2.4.3",
|
||||
"cheerio": "^1.0.0-rc.5",
|
||||
"fs-extra": "10.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-graphql",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Adds GraphQL endpoint with default API methods.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -30,7 +30,7 @@
|
||||
"@apollo/federation": "^0.28.0",
|
||||
"@graphql-tools/schema": "8.1.2",
|
||||
"@graphql-tools/utils": "^8.0.2",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"apollo-server-core": "3.1.2",
|
||||
"apollo-server-koa": "3.1.2",
|
||||
"glob": "^7.1.7",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-i18n",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "This plugin enables to create, to read and to update content in different languages, both from the Admin Panel and from the API",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -24,7 +24,7 @@
|
||||
"test:unit": "jest --verbose"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"lodash": "4.17.21"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1 +1,4 @@
|
||||
{}
|
||||
{
|
||||
"plugin.description.long": "Gửi lỗi Strapi lên Sentry.",
|
||||
"plugin.description.short": "Gửi lỗi Strapi lên Sentry."
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-sentry",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Send Strapi error events to Sentry",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/plugin-users-permissions",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Protect your API with a full-authentication process based on JWT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -28,8 +28,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@purest/providers": "^1.0.2",
|
||||
"@strapi/helper-plugin": "4.1.3",
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/helper-plugin": "4.1.5",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"bcryptjs": "2.4.3",
|
||||
"grant-koa": "5.4.8",
|
||||
"jsonwebtoken": "^8.1.0",
|
||||
|
@ -17,7 +17,7 @@ const {
|
||||
validateSendEmailConfirmationBody,
|
||||
} = require('./validation/auth');
|
||||
|
||||
const { sanitize } = utils;
|
||||
const { getAbsoluteAdminUrl, getAbsoluteServerUrl, sanitize } = utils;
|
||||
const { ApplicationError, ValidationError } = utils.errors;
|
||||
|
||||
const emailRegExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
@ -243,6 +243,8 @@ module.exports = {
|
||||
|
||||
settings.message = await getService('users-permissions').template(settings.message, {
|
||||
URL: advanced.email_reset_password,
|
||||
SERVER_URL: getAbsoluteServerUrl(strapi.config),
|
||||
ADMIN_URL: getAbsoluteAdminUrl(strapi.config),
|
||||
USER: userInfo,
|
||||
TOKEN: resetPasswordToken,
|
||||
});
|
||||
|
@ -3,7 +3,16 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
const invalidPatternsRegexes = [/<%[^=]([^<>%]*)%>/m, /\${([^{}]*)}/m];
|
||||
const authorizedKeys = ['URL', 'CODE', 'USER', 'USER.email', 'USER.username', 'TOKEN'];
|
||||
const authorizedKeys = [
|
||||
'URL',
|
||||
'ADMIN_URL',
|
||||
'SERVER_URL',
|
||||
'CODE',
|
||||
'USER',
|
||||
'USER.email',
|
||||
'USER.username',
|
||||
'TOKEN',
|
||||
];
|
||||
|
||||
const matchAll = (pattern, src) => {
|
||||
const matches = [];
|
||||
|
@ -10,7 +10,7 @@ const crypto = require('crypto');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const urlJoin = require('url-join');
|
||||
|
||||
const { getAbsoluteServerUrl, sanitize } = require('@strapi/utils');
|
||||
const { getAbsoluteAdminUrl, getAbsoluteServerUrl, sanitize } = require('@strapi/utils');
|
||||
const { getService } = require('../utils');
|
||||
|
||||
module.exports = ({ strapi }) => ({
|
||||
@ -118,6 +118,8 @@ module.exports = ({ strapi }) => ({
|
||||
const apiPrefix = strapi.config.get('api.rest.prefix');
|
||||
settings.message = await userPermissionService.template(settings.message, {
|
||||
URL: urlJoin(getAbsoluteServerUrl(strapi.config), apiPrefix, '/auth/email-confirmation'),
|
||||
SERVER_URL: getAbsoluteServerUrl(strapi.config),
|
||||
ADMIN_URL: getAbsoluteAdminUrl(strapi.config),
|
||||
USER: sanitizedUserInfo,
|
||||
CODE: confirmationToken,
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-email-amazon-ses",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Amazon SES provider for strapi email",
|
||||
"keywords": [
|
||||
"email",
|
||||
@ -36,7 +36,7 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"node-ses": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-email-mailgun",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Mailgun provider for strapi email plugin",
|
||||
"keywords": [
|
||||
"email",
|
||||
@ -36,7 +36,7 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"mailgun-js": "0.22.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-email-nodemailer",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Nodemailer provider for Strapi 3",
|
||||
"keywords": [
|
||||
"strapi",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-email-sendgrid",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Sendgrid provider for strapi email",
|
||||
"keywords": [
|
||||
"email",
|
||||
@ -37,7 +37,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sendgrid/mail": "7.4.7",
|
||||
"@strapi/utils": "4.1.3"
|
||||
"@strapi/utils": "4.1.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0 <=16.x.x",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-email-sendmail",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Sendmail provider for strapi email",
|
||||
"keywords": [
|
||||
"email",
|
||||
@ -35,7 +35,7 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"sendmail": "^1.6.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-upload-aws-s3",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "AWS S3 provider for strapi upload",
|
||||
"keywords": [
|
||||
"upload",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-upload-cloudinary",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Cloudinary provider for strapi upload",
|
||||
"keywords": [
|
||||
"upload",
|
||||
@ -36,7 +36,7 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.1.3",
|
||||
"@strapi/utils": "4.1.5",
|
||||
"cloudinary": "^1.25.1",
|
||||
"into-stream": "^5.1.0"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-upload-local",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Local provider for strapi upload",
|
||||
"keywords": [
|
||||
"upload",
|
||||
@ -35,7 +35,7 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.1.3"
|
||||
"@strapi/utils": "4.1.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0 <=16.x.x",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/provider-upload-rackspace",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Rackspace provider for strapi upload",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/babel-plugin-switch-ee-ce",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"private": false,
|
||||
"description": "Babel plugin to switch from CE to EE at runtime",
|
||||
"repository": "git://github.com/strapi/strapi.git",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strapi/logger",
|
||||
"version": "4.1.3",
|
||||
"version": "4.1.5",
|
||||
"description": "Strapi's logger",
|
||||
"homepage": "https://strapi.io",
|
||||
"bugs": {
|
||||
|
@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const { updateMissingKeysToJSON } = require('../add-missing-keys-to-other-language');
|
||||
|
||||
describe('updateMissingKeysToJSON', () => {
|
||||
it('should add missing keys from en.json to translation file', async () => {
|
||||
const TARGET_TRANSLATION_FILE_PATH = 'scripts/front/__tests__/vi.json';
|
||||
const SOURCE_TRANSLATION_FILE_PATH = 'scripts/front/__tests__/en.json';
|
||||
// Save original `vi.json` file content
|
||||
const originalTargetTranslationFileContent = fs.readFileSync(
|
||||
TARGET_TRANSLATION_FILE_PATH,
|
||||
'utf8'
|
||||
);
|
||||
const originalTargetTranslationFileJSON = JSON.parse(originalTargetTranslationFileContent);
|
||||
const mainTranslationFileJSON = await fs.readJSON(SOURCE_TRANSLATION_FILE_PATH);
|
||||
|
||||
// Add missing keys for `vi.json`
|
||||
const updatedTargetTranslationFileJSON = await updateMissingKeysToJSON(
|
||||
TARGET_TRANSLATION_FILE_PATH
|
||||
);
|
||||
|
||||
// `vi.json` should have all keys from `en.json`
|
||||
Object.keys(mainTranslationFileJSON).forEach(key => {
|
||||
expect(key in updatedTargetTranslationFileJSON).toBe(true);
|
||||
});
|
||||
|
||||
// `vi.json` should keep the current translation
|
||||
Object.keys(originalTargetTranslationFileContent).forEach(key => {
|
||||
expect(updatedTargetTranslationFileJSON[key]).toEqual(originalTargetTranslationFileJSON[key]);
|
||||
});
|
||||
});
|
||||
});
|
8
scripts/front/__tests__/en.json
Normal file
8
scripts/front/__tests__/en.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Analytics": "Analytics",
|
||||
"Auth.components.Oops.text": "Your account has been suspended.",
|
||||
"Auth.components.Oops.text.admin": "If this is a mistake, please contact your administrator.",
|
||||
"Auth.components.Oops.title": "Oops...",
|
||||
"Auth.form.button.forgot-password": "Send Email",
|
||||
"Auth.form.button.go-home": "GO BACK HOME"
|
||||
}
|
6
scripts/front/__tests__/vi.json
Normal file
6
scripts/front/__tests__/vi.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Analytics": "Phân Tích",
|
||||
"Auth.components.Oops.text.admin": "Nếu có sự nhầm lẫn, hãy liên hệ người quản trị",
|
||||
"Auth.components.Oops.title": "Oops...",
|
||||
"Auth.form.button.go-home": "QUAY VỀ TRANG CHỦ"
|
||||
}
|
81
scripts/front/add-missing-keys-to-other-language.js
Normal file
81
scripts/front/add-missing-keys-to-other-language.js
Normal file
@ -0,0 +1,81 @@
|
||||
// Add missing keys to non-english languages from `en.json`.
|
||||
// This script eases the process of translating strapi to other languages.
|
||||
// Usage:
|
||||
// node scripts/front/add-missing-keys-to-other-language.js [language]
|
||||
// Example:
|
||||
// node scripts/front/add-missing-keys-to-other-language.js vi
|
||||
'use strict';
|
||||
|
||||
const { join, dirname } = require('path');
|
||||
const { promisify } = require('util');
|
||||
const fs = require('fs-extra');
|
||||
const glob = promisify(require('glob').glob);
|
||||
const chalk = require('chalk');
|
||||
|
||||
const updateMissingKeysToJSON = async filePath => {
|
||||
// Read translation file
|
||||
const currentTranslationFileJSON = await fs.readJSON(filePath);
|
||||
// Read en.json
|
||||
const mainTranslationFile = join(dirname(filePath), 'en.json');
|
||||
const mainTranslationFileJSON = await fs.readJSON(mainTranslationFile);
|
||||
// Add missing keys from en.json to translation file
|
||||
const updatedFileJSON = Object.keys(mainTranslationFileJSON).reduce((acc, current) => {
|
||||
if (currentTranslationFileJSON[current]) {
|
||||
acc[current] = currentTranslationFileJSON[current];
|
||||
} else {
|
||||
acc[current] = mainTranslationFileJSON[current];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
return updatedFileJSON;
|
||||
};
|
||||
|
||||
const addMissingKeyForSingleFile = async filePath => {
|
||||
console.log('Start adding missing keys to', filePath);
|
||||
try {
|
||||
const updatedFileJSON = await updateMissingKeysToJSON(filePath);
|
||||
await fs.writeJson(filePath, updatedFileJSON, { spaces: 2 });
|
||||
console.log('Added missing keys to', filePath);
|
||||
return Promise.resolve();
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
};
|
||||
|
||||
const addMissingKeys = async lang => {
|
||||
// Get translation files
|
||||
const corePackageDirs = await glob('packages/core/*');
|
||||
const pluginsPackageDirs = await glob('packages/plugins/*');
|
||||
const packageDirs = [...corePackageDirs, ...pluginsPackageDirs];
|
||||
const pathToTranslationsFolder = ['admin', 'src', 'translations'];
|
||||
|
||||
const translationFiles = packageDirs
|
||||
.filter(dir => {
|
||||
return fs.existsSync(join(dir, ...pathToTranslationsFolder, `${lang}.json`));
|
||||
})
|
||||
.map(dir => {
|
||||
return join(dir, ...pathToTranslationsFolder, `${lang}.json`);
|
||||
});
|
||||
console.log('List of files to add missing keys', translationFiles, '\n');
|
||||
|
||||
// For each file run addMissingKeyForSingleFile
|
||||
translationFiles.forEach(addMissingKeyForSingleFile);
|
||||
};
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
'Please provide a language. For example:\nnode scripts/front/add-missing-keys-to-other-language.js vi'
|
||||
)
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
addMissingKeys(process.argv[2]).catch(err => console.error(err));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
updateMissingKeysToJSON,
|
||||
};
|
@ -26,7 +26,7 @@ const cleanFile = async filePath => {
|
||||
|
||||
return Promise.resolve();
|
||||
} catch (err) {
|
||||
return Promise.reject();
|
||||
return Promise.reject(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user