@strapi/admin 4.5.0-beta.0 → 4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/src/StrapiApp.js +17 -6
- package/admin/src/assets/images/hot-air-balloon.png +0 -0
- package/admin/src/assets/images/icon_offline-cloud.svg +3 -3
- package/admin/src/assets/images/logo-strapi-2022.svg +7 -0
- package/admin/src/assets/images/upgrade-details.png +0 -0
- package/admin/src/content-manager/components/DynamicTable/CellContent/CellValue.js +1 -1
- package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +5 -4
- package/admin/src/content-manager/components/DynamicTable/CellContent/index.js +10 -0
- package/admin/src/content-manager/components/DynamicTable/index.js +21 -4
- package/admin/src/content-manager/components/DynamicZone/components/{AddComponentButton/index.js → AddComponentButton.js} +12 -6
- package/admin/src/content-manager/components/DynamicZone/components/{ComponentPicker/Category/ComponentCard/index.js → ComponentCard.js} +8 -19
- package/admin/src/content-manager/components/DynamicZone/components/{ComponentPicker/Category/index.js → ComponentCategory.js} +19 -18
- package/admin/src/content-manager/components/DynamicZone/components/{ComponentPicker/index.js → ComponentPicker.js} +36 -38
- package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +195 -0
- package/admin/src/content-manager/components/DynamicZone/components/{DzLabel/index.js → DynamicZoneLabel.js} +13 -5
- package/admin/src/content-manager/components/DynamicZone/index.js +35 -116
- package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +103 -60
- package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +169 -162
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +70 -16
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findLeafByPathAndReplace.js +52 -0
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js +2 -0
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/recursivelyFindPathsBasedOnCondition.js +72 -0
- package/admin/src/content-manager/components/FieldComponent/index.js +9 -2
- package/admin/src/content-manager/components/PreviewWysiwyg/index.js +1 -1
- package/admin/src/content-manager/components/RelationInput/RelationInput.js +80 -76
- package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +95 -63
- package/admin/src/content-manager/components/RelationInputDataManager/utils/diffRelations.js +24 -0
- package/admin/src/content-manager/components/RelationInputDataManager/utils/index.js +2 -1
- package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js +8 -29
- package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeSearchResults.js +8 -4
- package/admin/src/content-manager/components/RelationInputDataManager/utils/select.js +1 -0
- package/admin/src/content-manager/components/RepeatableComponent/index.js +4 -3
- package/admin/src/content-manager/hooks/__test__/usePrev.test.js +26 -0
- package/admin/src/content-manager/hooks/index.js +1 -0
- package/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js +19 -48
- package/admin/src/content-manager/hooks/usePrev.js +14 -0
- package/admin/src/content-manager/hooks/useRelation/useRelation.js +100 -7
- package/admin/src/content-manager/pages/App/reducer.js +3 -0
- package/admin/src/content-manager/pages/ListSettingsView/components/DraggableCard.js +3 -3
- package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +2 -2
- package/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.js +1 -1
- package/admin/src/core/apis/CustomFields.js +0 -1
- package/admin/src/core/store/configureStore.js +17 -2
- package/admin/src/favicon.png +0 -0
- package/admin/src/hooks/useFetchMarketplacePlugins/index.js +2 -2
- package/admin/src/hooks/useFetchMarketplacePlugins/utils/api.js +4 -2
- package/admin/src/hooks/useFetchMarketplaceProviders/index.js +3 -3
- package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +5 -3
- package/admin/src/index.js +1 -0
- package/admin/src/pages/App/index.js +1 -1
- package/admin/src/pages/HomePage/assets/corner-ornament.svg +48 -0
- package/admin/src/pages/HomePage/index.js +4 -3
- package/admin/src/pages/MarketplacePage/components/NpmPackageCard/CardButton.js +110 -0
- package/admin/src/pages/MarketplacePage/components/NpmPackageCard/InstallPluginButton.js +32 -21
- package/admin/src/pages/MarketplacePage/components/NpmPackageCard/PackageStats.js +79 -0
- package/admin/src/pages/MarketplacePage/components/NpmPackageCard/index.js +28 -11
- package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/FilterSelect.js +42 -0
- package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/FiltersPopover.js +96 -0
- package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/index.js +107 -0
- package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +4 -0
- package/admin/src/pages/MarketplacePage/components/SortSelect/index.js +70 -0
- package/admin/src/pages/MarketplacePage/index.js +68 -8
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +5 -4
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +4 -3
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormHead/index.js +6 -2
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +5 -4
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/schema.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/index.js +7 -38
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/utils/options.js +31 -0
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/index.js +32 -43
- package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Roles/ListPage/components/RoleRow/index.js +3 -1
- package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +2 -1
- package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/index.js +2 -2
- package/admin/src/translations/ca.json +1 -1
- package/admin/src/translations/de.json +1 -1
- package/admin/src/translations/dk.json +1 -1
- package/admin/src/translations/en.json +21 -7
- package/admin/src/translations/es.json +1 -1
- package/admin/src/translations/fr.json +1 -1
- package/admin/src/translations/gu.json +1 -1
- package/admin/src/translations/he.json +1 -1
- package/admin/src/translations/hi.json +1 -1
- package/admin/src/translations/hu.json +1 -1
- package/admin/src/translations/id.json +1 -1
- package/admin/src/translations/it.json +1 -1
- package/admin/src/translations/ja.json +1 -1
- package/admin/src/translations/ko.json +1 -1
- package/admin/src/translations/ml.json +1 -1
- package/admin/src/translations/nl.json +1 -1
- package/admin/src/translations/no.json +1 -1
- package/admin/src/translations/pl.json +1 -1
- package/admin/src/translations/pt-BR.json +15 -15
- package/admin/src/translations/ru.json +1 -1
- package/admin/src/translations/sa.json +1 -1
- package/admin/src/translations/sk.json +1 -1
- package/admin/src/translations/sv.json +118 -86
- package/admin/src/translations/th.json +1 -1
- package/admin/src/translations/zh-Hans.json +1 -1
- package/admin/src/translations/zh.json +1 -1
- package/build/1856.db9f5782.chunk.js +174 -0
- package/build/2077.fed8c9c3.chunk.js +206 -0
- package/build/2912.fccb2c43.chunk.js +259 -0
- package/build/4318.5e670740.chunk.js +30 -0
- package/build/{9166.8fcb3019.chunk.js → 4610.7614b003.chunk.js} +22 -21
- package/build/4715.8e33d630.chunk.js +387 -0
- package/build/{4800.d09f1225.chunk.js → 4800.a6935af6.chunk.js} +1 -1
- package/build/4982.9e58ea3f.chunk.js +325 -0
- package/build/617f9c948fa79e6d73bd.png +0 -0
- package/build/6925.bb6dd64d.chunk.js +762 -0
- package/build/6d21938306785f176538.png +0 -0
- package/build/70674f63fc3904c20de0.svg +7 -0
- package/build/{7379.d246dd38.chunk.js → 7379.e972985f.chunk.js} +1 -1
- package/build/7692.31e83caa.chunk.js +470 -0
- package/build/7841.4804bd98.chunk.js +259 -0
- package/build/7866.6db2248d.chunk.js +505 -0
- package/build/7e9af4fb7e723fcebf1f.svg +48 -0
- package/build/8380.37126e0d.chunk.js +299 -0
- package/build/8549.5e5fb6b6.chunk.js +159 -0
- package/build/8738.5a02bffb.chunk.js +463 -0
- package/build/{9066.26faf397.chunk.js → 9066.5d980488.chunk.js} +5 -5
- package/build/9420.7addc099.chunk.js +505 -0
- package/build/9649.b6afc945.chunk.js +199 -0
- package/build/9d5d788027e86620c234.svg +5 -0
- package/build/Admin-authenticatedApp.c07d2a86.chunk.js +80 -0
- package/build/{Admin_homePage.4b2be829.chunk.js → Admin_homePage.26d32e30.chunk.js} +5 -4
- package/build/Admin_marketplace.444ff7b8.chunk.js +22 -0
- package/build/Admin_settingsPage.bf2234e1.chunk.js +178 -0
- package/build/admin-app.b157c10a.chunk.js +112 -0
- package/build/{admin-edit-roles-page.4dd6bcb9.chunk.js → admin-edit-roles-page.69d9fcb2.chunk.js} +1 -1
- package/build/ca-json.07ae0f2c.chunk.js +1 -0
- package/build/content-manager.f38edbb6.chunk.js +1202 -0
- package/build/content-type-builder-translation-pt-BR-json.6fe3b8d1.chunk.js +1 -0
- package/build/content-type-builder-translation-sv-json.6deff030.chunk.js +1 -0
- package/build/{content-type-builder.a6e29716.chunk.js → content-type-builder.16af63a6.chunk.js} +13 -13
- package/build/de-json.6b3e1894.chunk.js +1 -0
- package/build/dk-json.144c6a8e.chunk.js +1 -0
- package/build/{email-settings-page.bfe6227f.chunk.js → email-settings-page.91c925a5.chunk.js} +6 -6
- package/build/email-translation-en-json.ebad8943.chunk.js +1 -0
- package/build/en-json.4a269f6b.chunk.js +1 -0
- package/build/es-json.6d123a82.chunk.js +1 -0
- package/build/fr-json.28ab54cb.chunk.js +1 -0
- package/build/gu-json.9a50ea64.chunk.js +1 -0
- package/build/he-json.72f18790.chunk.js +1 -0
- package/build/hi-json.0301b7ba.chunk.js +1 -0
- package/build/hu-json.c4b641bb.chunk.js +1 -0
- package/build/{i18n-settings-page.18166125.chunk.js → i18n-settings-page.4ef64441.chunk.js} +5 -5
- package/build/id-json.86035797.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/it-json.bbdc8993.chunk.js +1 -0
- package/build/ja-json.1c9eeeec.chunk.js +1 -0
- package/build/ko-json.e1f66398.chunk.js +1 -0
- package/build/main.ca8b0ee3.js +9465 -0
- package/build/ml-json.963c889f.chunk.js +1 -0
- package/build/nl-json.2b8cc3a0.chunk.js +1 -0
- package/build/no-json.a58c28bd.chunk.js +1 -0
- package/build/pl-json.249626b3.chunk.js +1 -0
- package/build/pt-BR-json.2b72b1d6.chunk.js +1 -0
- package/build/ru-json.d7cfc2ff.chunk.js +1 -0
- package/build/runtime~main.ede9da1e.js +2 -0
- package/build/sa-json.44e95991.chunk.js +1 -0
- package/build/sk-json.7ba4b330.chunk.js +1 -0
- package/build/sv-json.fb1081ff.chunk.js +1 -0
- package/build/th-json.a67309b1.chunk.js +1 -0
- package/build/{upload-settings.3d613216.chunk.js → upload-settings.3f7ad973.chunk.js} +5 -5
- package/build/{users-advanced-settings-page.f4051d92.chunk.js → users-advanced-settings-page.6a838320.chunk.js} +5 -5
- package/build/users-permissions-translation-sv-json.d5d11648.chunk.js +1 -0
- package/build/{webhook-edit-page.9e46fc3f.chunk.js → webhook-edit-page.dc9442ce.chunk.js} +1 -1
- package/build/webhook-list-page.a110c462.chunk.js +134 -0
- package/build/zh-Hans-json.21617c24.chunk.js +1 -0
- package/build/zh-json.608aaf24.chunk.js +1 -0
- package/ee/admin/pages/SettingsPage/pages/Roles/ListPage/index.js +3 -2
- package/env.js +1 -0
- package/package.json +18 -17
- package/scripts/build.js +11 -0
- package/server/content-types/api-token.js +1 -1
- package/utils/create-plugins-exclude-path.js +40 -0
- package/webpack.alias.js +0 -13
- package/webpack.config.js +4 -1
- package/admin/src/assets/images/banner_strapi-rocket.png +0 -0
- package/admin/src/assets/images/big-logo-home.png +0 -0
- package/admin/src/assets/images/homepage-logo.png +0 -0
- package/admin/src/assets/images/icon_made-by-strapi.svg +0 -5
- package/admin/src/assets/images/logo_strapi_auth.png +0 -0
- package/admin/src/assets/images/logo_strapi_auth_v4.png +0 -0
- package/admin/src/assets/images/logo_strapi_menu.png +0 -0
- package/admin/src/assets/images/oops.png +0 -0
- package/admin/src/content-manager/components/DynamicZone/components/Component/Rectangle.js +0 -19
- package/admin/src/content-manager/components/DynamicZone/components/Component/index.js +0 -191
- package/admin/src/content-manager/components/State/index.js +0 -37
- package/admin/src/content-manager/icons/Bold/index.js +0 -22
- package/admin/src/content-manager/icons/Code/index.js +0 -13
- package/admin/src/content-manager/icons/Cross/index.js +0 -28
- package/admin/src/content-manager/icons/Italic/index.js +0 -23
- package/admin/src/content-manager/icons/Link/index.js +0 -21
- package/admin/src/content-manager/icons/Media/index.js +0 -14
- package/admin/src/content-manager/icons/Na/index.js +0 -39
- package/admin/src/content-manager/icons/Ol/index.js +0 -13
- package/admin/src/content-manager/icons/Quote/index.js +0 -13
- package/admin/src/content-manager/icons/Striked/index.js +0 -24
- package/admin/src/content-manager/icons/Ul/index.js +0 -15
- package/admin/src/content-manager/icons/Underline/index.js +0 -22
- package/admin/src/favicon.ico +0 -0
- package/build/15026a3d58aeb2828134.png +0 -0
- package/build/1856.d8f13391.chunk.js +0 -173
- package/build/1939.e3c87653.chunk.js +0 -325
- package/build/2077.31a2d91e.chunk.js +0 -205
- package/build/2912.ab68a736.chunk.js +0 -258
- package/build/4318.7d167b58.chunk.js +0 -30
- package/build/4715.44b1ef9b.chunk.js +0 -386
- package/build/4982.c2a311b7.chunk.js +0 -324
- package/build/6925.f5c8b6fc.chunk.js +0 -761
- package/build/7841.4b67af3f.chunk.js +0 -258
- package/build/7866.5fbeb7e5.chunk.js +0 -504
- package/build/8380.9b53a31d.chunk.js +0 -284
- package/build/8549.cf10b5d1.chunk.js +0 -158
- package/build/8738.a30a2160.chunk.js +0 -461
- package/build/90f49a385afb000fb1d4.svg +0 -5
- package/build/9420.0fe11290.chunk.js +0 -504
- package/build/962.8651ba3f.chunk.js +0 -184
- package/build/Admin-authenticatedApp.883449a5.chunk.js +0 -80
- package/build/Admin_marketplace.82c0570b.chunk.js +0 -11
- package/build/Admin_settingsPage.98e2a62b.chunk.js +0 -178
- package/build/a6b842e0b6d2b61135d1.svg +0 -5
- package/build/admin-app.a61d5c2e.chunk.js +0 -112
- package/build/b997a22a2e0b87ef1fa2.ico +0 -0
- package/build/bd81ba6c07827282255d.png +0 -0
- package/build/c3de6118ef47086ad05c.png +0 -0
- package/build/ca-json.82df6eab.chunk.js +0 -1
- package/build/content-manager.933dc286.chunk.js +0 -1201
- package/build/content-type-builder-translation-pt-BR-json.d6c7fcc1.chunk.js +0 -1
- package/build/de-json.0ad554eb.chunk.js +0 -1
- package/build/dk-json.e195ea1a.chunk.js +0 -1
- package/build/email-translation-en-json.3d74ff95.chunk.js +0 -1
- package/build/en-json.1889403c.chunk.js +0 -1
- package/build/es-json.09f80f6e.chunk.js +0 -1
- package/build/fb376b132d18bf4522ca.png +0 -0
- package/build/fde9b1ad0670d29a2516.png +0 -0
- package/build/fr-json.606d056b.chunk.js +0 -1
- package/build/gu-json.9881264f.chunk.js +0 -1
- package/build/he-json.3b825d80.chunk.js +0 -1
- package/build/hi-json.83dcf48f.chunk.js +0 -1
- package/build/hu-json.6f328bce.chunk.js +0 -1
- package/build/id-json.1f3c4303.chunk.js +0 -1
- package/build/it-json.494ac432.chunk.js +0 -1
- package/build/ja-json.6f262117.chunk.js +0 -1
- package/build/ko-json.36dc3b9a.chunk.js +0 -1
- package/build/main.63e7ea0a.js +0 -9338
- package/build/ml-json.9566bf9a.chunk.js +0 -1
- package/build/nl-json.94c3a289.chunk.js +0 -1
- package/build/no-json.40386397.chunk.js +0 -1
- package/build/pl-json.ccc6ef23.chunk.js +0 -1
- package/build/pt-BR-json.744f024d.chunk.js +0 -1
- package/build/ru-json.d22ea13c.chunk.js +0 -1
- package/build/runtime~main.3a5e1b07.js +0 -2
- package/build/sa-json.8fb1c04d.chunk.js +0 -1
- package/build/sk-json.6c7335d4.chunk.js +0 -1
- package/build/sv-json.2e589a7d.chunk.js +0 -1
- package/build/th-json.72e8de3d.chunk.js +0 -1
- package/build/users-permissions-translation-sv-json.83c60841.chunk.js +0 -1
- package/build/webhook-list-page.a712ae40.chunk.js +0 -134
- package/build/zh-Hans-json.a4d7dc69.chunk.js +0 -1
- package/build/zh-json.66aa2ae1.chunk.js +0 -1
package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js
CHANGED
|
@@ -32,34 +32,13 @@ export const normalizeRelation = (relation, { shouldAddLink, mainFieldName, targ
|
|
|
32
32
|
|
|
33
33
|
export const normalizeRelations = (
|
|
34
34
|
relations,
|
|
35
|
-
{
|
|
35
|
+
{ shouldAddLink = false, mainFieldName, targetModel } = {}
|
|
36
36
|
) => {
|
|
37
|
-
return
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
]
|
|
45
|
-
?.map((page) =>
|
|
46
|
-
page?.results
|
|
47
|
-
.filter(
|
|
48
|
-
(relation) =>
|
|
49
|
-
!modifiedData?.disconnect?.find(
|
|
50
|
-
(disconnectRelation) => disconnectRelation.id === relation.id
|
|
51
|
-
)
|
|
52
|
-
)
|
|
53
|
-
.map((relation) =>
|
|
54
|
-
normalizeRelation(relation, {
|
|
55
|
-
shouldAddLink,
|
|
56
|
-
mainFieldName,
|
|
57
|
-
targetModel,
|
|
58
|
-
})
|
|
59
|
-
)
|
|
60
|
-
.filter(Boolean)
|
|
61
|
-
)
|
|
62
|
-
?.filter((page) => page.length > 0) ?? [],
|
|
63
|
-
},
|
|
64
|
-
};
|
|
37
|
+
return [...relations].map((relation) =>
|
|
38
|
+
normalizeRelation(relation, {
|
|
39
|
+
shouldAddLink,
|
|
40
|
+
mainFieldName,
|
|
41
|
+
targetModel,
|
|
42
|
+
})
|
|
43
|
+
);
|
|
65
44
|
};
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { normalizeRelation } from './normalizeRelations';
|
|
2
2
|
|
|
3
3
|
export const normalizeSearchResults = (relations, { mainFieldName }) => {
|
|
4
|
+
const { data } = relations;
|
|
5
|
+
const { pages = [] } = data ?? {};
|
|
6
|
+
|
|
4
7
|
return {
|
|
5
8
|
...relations,
|
|
6
|
-
data:
|
|
7
|
-
|
|
9
|
+
data: pages
|
|
10
|
+
.map((page) =>
|
|
8
11
|
page?.results.map((relation) => normalizeRelation(relation, { mainFieldName }))
|
|
9
|
-
)
|
|
10
|
-
|
|
12
|
+
)
|
|
13
|
+
.filter(Boolean)
|
|
14
|
+
.flat(),
|
|
11
15
|
};
|
|
12
16
|
};
|
|
@@ -48,7 +48,7 @@ const RepeatableComponent = ({
|
|
|
48
48
|
const [collapseToOpen, setCollapseToOpen] = useState('');
|
|
49
49
|
const [isDraggingSibling, setIsDraggingSibling] = useState(false);
|
|
50
50
|
const [, drop] = useDrop({ accept: ItemTypes.COMPONENT });
|
|
51
|
-
const { getComponentLayout } = useContentTypeLayout();
|
|
51
|
+
const { getComponentLayout, components } = useContentTypeLayout();
|
|
52
52
|
const componentLayoutData = useMemo(
|
|
53
53
|
() => getComponentLayout(componentUid),
|
|
54
54
|
[componentUid, getComponentLayout]
|
|
@@ -73,7 +73,7 @@ const RepeatableComponent = ({
|
|
|
73
73
|
if (componentValueLength < max) {
|
|
74
74
|
const shouldCheckErrors = hasMinError;
|
|
75
75
|
|
|
76
|
-
addRepeatableComponentToField(name,
|
|
76
|
+
addRepeatableComponentToField(name, componentLayoutData, components, shouldCheckErrors);
|
|
77
77
|
|
|
78
78
|
setCollapseToOpen(nextTempKey);
|
|
79
79
|
} else if (componentValueLength >= max) {
|
|
@@ -84,8 +84,9 @@ const RepeatableComponent = ({
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
}, [
|
|
87
|
+
components,
|
|
87
88
|
addRepeatableComponentToField,
|
|
88
|
-
|
|
89
|
+
componentLayoutData,
|
|
89
90
|
componentValueLength,
|
|
90
91
|
hasMinError,
|
|
91
92
|
isReadOnly,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
2
|
+
|
|
3
|
+
import { usePrev } from '../usePrev';
|
|
4
|
+
|
|
5
|
+
describe('usePrev', () => {
|
|
6
|
+
const setup = () => renderHook(({ state }) => usePrev(state), { initialProps: { state: 0 } });
|
|
7
|
+
|
|
8
|
+
it('should return undefined on initial render', () => {
|
|
9
|
+
const { result } = setup();
|
|
10
|
+
|
|
11
|
+
expect(result.current).toBeUndefined();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should always return previous state after each update', () => {
|
|
15
|
+
const { result, rerender } = setup();
|
|
16
|
+
|
|
17
|
+
rerender({ state: 2 });
|
|
18
|
+
expect(result.current).toBe(0);
|
|
19
|
+
|
|
20
|
+
rerender({ state: 4 });
|
|
21
|
+
expect(result.current).toBe(2);
|
|
22
|
+
|
|
23
|
+
rerender({ state: 6 });
|
|
24
|
+
expect(result.current).toBe(4);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -5,3 +5,4 @@ export { default as useLayoutDnd } from './useLayoutDnd';
|
|
|
5
5
|
export { default as usePluginsQueryParams } from './usePluginsQueryParams';
|
|
6
6
|
export { default as useSyncRbac } from './useSyncRbac';
|
|
7
7
|
export { default as useWysiwyg } from './useWysiwyg';
|
|
8
|
+
export { usePrev } from './usePrev';
|
|
@@ -6,21 +6,19 @@ const getRelationModel = (targetModel, models) => models.find((model) => model.u
|
|
|
6
6
|
const formatLayouts = (initialData, models) => {
|
|
7
7
|
const data = createMetasSchema(initialData, models);
|
|
8
8
|
|
|
9
|
-
const formattedCTEditLayout = formatLayoutWithMetas(data.contentType,
|
|
10
|
-
const ctUid = data.contentType.uid;
|
|
9
|
+
const formattedCTEditLayout = formatLayoutWithMetas(data.contentType, models);
|
|
11
10
|
const formattedListLayout = formatListLayoutWithMetas(data.contentType, data.components);
|
|
12
11
|
|
|
13
12
|
set(data, ['contentType', 'layouts', 'edit'], formattedCTEditLayout);
|
|
14
13
|
set(data, ['contentType', 'layouts', 'list'], formattedListLayout);
|
|
15
14
|
|
|
16
|
-
Object.keys(data.components).forEach((
|
|
17
|
-
const
|
|
18
|
-
data.components[
|
|
19
|
-
ctUid,
|
|
15
|
+
Object.keys(data.components).forEach((componentUid) => {
|
|
16
|
+
const formattedComponentEditLayout = formatLayoutWithMetas(
|
|
17
|
+
data.components[componentUid],
|
|
20
18
|
models
|
|
21
19
|
);
|
|
22
20
|
|
|
23
|
-
set(data, ['components',
|
|
21
|
+
set(data, ['components', componentUid, 'layouts', 'edit'], formattedComponentEditLayout);
|
|
24
22
|
});
|
|
25
23
|
|
|
26
24
|
return data;
|
|
@@ -73,8 +71,8 @@ const createMetasSchema = (initialData, models) => {
|
|
|
73
71
|
return data;
|
|
74
72
|
};
|
|
75
73
|
|
|
76
|
-
const formatLayoutWithMetas = (contentTypeConfiguration,
|
|
77
|
-
|
|
74
|
+
const formatLayoutWithMetas = (contentTypeConfiguration, models) =>
|
|
75
|
+
contentTypeConfiguration.layouts.edit.reduce((acc, current) => {
|
|
78
76
|
const row = current.map((attribute) => {
|
|
79
77
|
const fieldSchema = get(contentTypeConfiguration, ['attributes', attribute.name], {});
|
|
80
78
|
|
|
@@ -85,20 +83,17 @@ const formatLayoutWithMetas = (contentTypeConfiguration, ctUid, models) => {
|
|
|
85
83
|
};
|
|
86
84
|
|
|
87
85
|
if (fieldSchema.type === 'relation') {
|
|
88
|
-
const
|
|
89
|
-
const targetModelSchema = getRelationModel(targetModelUID, models);
|
|
86
|
+
const targetModelSchema = getRelationModel(fieldSchema.targetModel, models);
|
|
90
87
|
const targetModelPluginOptions = targetModelSchema.pluginOptions || {};
|
|
91
88
|
|
|
92
|
-
const queryInfos = ctUid
|
|
93
|
-
? generateRelationQueryInfosForComponents(
|
|
94
|
-
contentTypeConfiguration,
|
|
95
|
-
attribute.name,
|
|
96
|
-
models
|
|
97
|
-
)
|
|
98
|
-
: generateRelationQueryInfos(contentTypeConfiguration, attribute.name, models);
|
|
99
|
-
|
|
100
89
|
set(data, 'targetModelPluginOptions', targetModelPluginOptions);
|
|
101
|
-
set(data, 'queryInfos',
|
|
90
|
+
set(data, 'queryInfos', {
|
|
91
|
+
shouldDisplayRelationLink: shouldDisplayRelationLink(
|
|
92
|
+
contentTypeConfiguration,
|
|
93
|
+
attribute.name,
|
|
94
|
+
models
|
|
95
|
+
),
|
|
96
|
+
});
|
|
102
97
|
}
|
|
103
98
|
|
|
104
99
|
return data;
|
|
@@ -109,9 +104,6 @@ const formatLayoutWithMetas = (contentTypeConfiguration, ctUid, models) => {
|
|
|
109
104
|
return acc;
|
|
110
105
|
}, []);
|
|
111
106
|
|
|
112
|
-
return formatted;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
107
|
const formatListLayoutWithMetas = (contentTypeConfiguration, components) => {
|
|
116
108
|
const formatted = contentTypeConfiguration.layouts.list.reduce((acc, current) => {
|
|
117
109
|
const fieldSchema = get(contentTypeConfiguration, ['attributes', current], {});
|
|
@@ -120,11 +112,7 @@ const formatListLayoutWithMetas = (contentTypeConfiguration, components) => {
|
|
|
120
112
|
const type = fieldSchema.type;
|
|
121
113
|
|
|
122
114
|
if (type === 'relation') {
|
|
123
|
-
|
|
124
|
-
defaultParams: {},
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
acc.push({ key: `__${current}_key__`, name: current, fieldSchema, metadatas, queryInfos });
|
|
115
|
+
acc.push({ key: `__${current}_key__`, name: current, fieldSchema, metadatas });
|
|
128
116
|
|
|
129
117
|
return acc;
|
|
130
118
|
}
|
|
@@ -158,26 +146,10 @@ const formatListLayoutWithMetas = (contentTypeConfiguration, components) => {
|
|
|
158
146
|
return formatted;
|
|
159
147
|
};
|
|
160
148
|
|
|
161
|
-
const
|
|
149
|
+
const shouldDisplayRelationLink = (contentTypeConfiguration, fieldName, models) => {
|
|
162
150
|
const targetModel = get(contentTypeConfiguration, ['attributes', fieldName, 'targetModel'], '');
|
|
163
|
-
const shouldDisplayRelationLink = getDisplayedModels(models).includes(targetModel);
|
|
164
151
|
|
|
165
|
-
return
|
|
166
|
-
defaultParams: {},
|
|
167
|
-
shouldDisplayRelationLink,
|
|
168
|
-
};
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const generateRelationQueryInfosForComponents = (contentTypeConfiguration, fieldName, models) => {
|
|
172
|
-
const targetModel = get(contentTypeConfiguration, ['attributes', fieldName, 'targetModel'], '');
|
|
173
|
-
const shouldDisplayRelationLink = getDisplayedModels(models).includes(targetModel);
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
defaultParams: {
|
|
177
|
-
component: contentTypeConfiguration.uid,
|
|
178
|
-
},
|
|
179
|
-
shouldDisplayRelationLink,
|
|
180
|
-
};
|
|
152
|
+
return getDisplayedModels(models).includes(targetModel);
|
|
181
153
|
};
|
|
182
154
|
|
|
183
155
|
const getDisplayedModels = (models) =>
|
|
@@ -187,7 +159,6 @@ export default formatLayouts;
|
|
|
187
159
|
export {
|
|
188
160
|
formatLayoutWithMetas,
|
|
189
161
|
formatListLayoutWithMetas,
|
|
190
|
-
|
|
191
|
-
generateRelationQueryInfosForComponents,
|
|
162
|
+
shouldDisplayRelationLink,
|
|
192
163
|
getDisplayedModels,
|
|
193
164
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {<T>(value: T) => T | undefined}
|
|
5
|
+
*/
|
|
6
|
+
export const usePrev = (value) => {
|
|
7
|
+
const ref = useRef();
|
|
8
|
+
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
ref.current = value;
|
|
11
|
+
}, [value]);
|
|
12
|
+
|
|
13
|
+
return ref.current;
|
|
14
|
+
};
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
2
|
import { useInfiniteQuery } from 'react-query';
|
|
3
3
|
|
|
4
4
|
import { axiosInstance } from '../../../core/utils';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const [searchParams, setSearchParams] = useState({});
|
|
6
|
+
import { normalizeRelations } from '../../components/RelationInputDataManager/utils';
|
|
8
7
|
|
|
8
|
+
export const useRelation = (cacheKey, { name, relation, search }) => {
|
|
9
|
+
const [searchParams, setSearchParams] = useState({});
|
|
10
|
+
const [currentPage, setCurrentPage] = useState(0);
|
|
11
|
+
/**
|
|
12
|
+
* This runs in `useInfiniteQuery` to actually fetch the data
|
|
13
|
+
*/
|
|
9
14
|
const fetchRelations = async ({ pageParam = 1 }) => {
|
|
10
15
|
try {
|
|
11
16
|
const { data } = await axiosInstance.get(relation?.endpoint, {
|
|
@@ -15,6 +20,8 @@ export const useRelation = (cacheKey, { relation, search }) => {
|
|
|
15
20
|
},
|
|
16
21
|
});
|
|
17
22
|
|
|
23
|
+
setCurrentPage(pageParam);
|
|
24
|
+
|
|
18
25
|
return data;
|
|
19
26
|
} catch (err) {
|
|
20
27
|
return null;
|
|
@@ -37,12 +44,32 @@ export const useRelation = (cacheKey, { relation, search }) => {
|
|
|
37
44
|
}
|
|
38
45
|
};
|
|
39
46
|
|
|
47
|
+
const { onLoad: onLoadRelationsCallback, normalizeArguments = {} } = relation;
|
|
48
|
+
|
|
40
49
|
const relationsRes = useInfiniteQuery(['relation', cacheKey], fetchRelations, {
|
|
41
50
|
cacheTime: 0,
|
|
42
51
|
enabled: relation.enabled,
|
|
52
|
+
/**
|
|
53
|
+
* @type {(lastPage:
|
|
54
|
+
* | { data: null }
|
|
55
|
+
* | { results: any[],
|
|
56
|
+
* pagination: {
|
|
57
|
+
* page: number,
|
|
58
|
+
* pageCount: number,
|
|
59
|
+
* pageSize: number,
|
|
60
|
+
* total: number
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
* ) => number}
|
|
64
|
+
*/
|
|
43
65
|
getNextPageParam(lastPage) {
|
|
44
|
-
|
|
45
|
-
|
|
66
|
+
const isXToOneRelation = !lastPage?.pagination;
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
!lastPage || // the API may send an empty 204 response
|
|
70
|
+
isXToOneRelation || // xToOne relations do not have a pagination
|
|
71
|
+
lastPage?.pagination.page >= lastPage?.pagination.pageCount
|
|
72
|
+
) {
|
|
46
73
|
return undefined;
|
|
47
74
|
}
|
|
48
75
|
|
|
@@ -50,17 +77,83 @@ export const useRelation = (cacheKey, { relation, search }) => {
|
|
|
50
77
|
return lastPage.pagination.page + 1;
|
|
51
78
|
},
|
|
52
79
|
select: (data) => ({
|
|
53
|
-
|
|
80
|
+
...data,
|
|
81
|
+
pages: data.pages.map((page) => {
|
|
82
|
+
if (!page) {
|
|
83
|
+
return page;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const { data, results, pagination } = page;
|
|
87
|
+
const isXToOneRelation = !!data;
|
|
88
|
+
let normalizedResults = [];
|
|
89
|
+
|
|
90
|
+
// xToOne relations return an object, which we normalize so that relations
|
|
91
|
+
// always have the same shape
|
|
92
|
+
if (isXToOneRelation) {
|
|
93
|
+
normalizedResults = [data];
|
|
94
|
+
} else if (results) {
|
|
95
|
+
normalizedResults = [...results].reverse();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
pagination,
|
|
100
|
+
results: normalizedResults,
|
|
101
|
+
};
|
|
102
|
+
}),
|
|
54
103
|
}),
|
|
55
104
|
});
|
|
56
105
|
|
|
106
|
+
const { pageGoal } = relation;
|
|
107
|
+
|
|
108
|
+
const { status, data, fetchNextPage, hasNextPage } = relationsRes;
|
|
109
|
+
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
/**
|
|
112
|
+
* This ensures the infiniteQuery hook fetching has caught-up with the modifiedData
|
|
113
|
+
* state i.e. in circumstances where you add 10 relations, the browserState knows this,
|
|
114
|
+
* but the hook would think it could fetch more, when in reality, it can't.
|
|
115
|
+
*/
|
|
116
|
+
if (pageGoal > currentPage && hasNextPage && status === 'success') {
|
|
117
|
+
fetchNextPage({
|
|
118
|
+
pageParam: currentPage + 1,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}, [pageGoal, currentPage, fetchNextPage, hasNextPage, status]);
|
|
122
|
+
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
if (status === 'success' && data && data.pages?.at(-1)?.results && onLoadRelationsCallback) {
|
|
125
|
+
// everytime we fetch, we normalize prior to adding to redux
|
|
126
|
+
const normalizedResults = normalizeRelations(data.pages.at(-1).results, normalizeArguments);
|
|
127
|
+
|
|
128
|
+
// this is loadRelation from EditViewDataManagerProvider
|
|
129
|
+
onLoadRelationsCallback({
|
|
130
|
+
target: { name, value: normalizedResults },
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
135
|
+
}, [status, onLoadRelationsCallback, name, data]);
|
|
136
|
+
|
|
57
137
|
const searchRes = useInfiniteQuery(
|
|
58
138
|
['relation', cacheKey, 'search', JSON.stringify(searchParams)],
|
|
59
139
|
fetchSearch,
|
|
60
140
|
{
|
|
61
141
|
enabled: Object.keys(searchParams).length > 0,
|
|
142
|
+
/**
|
|
143
|
+
* @type {(lastPage:
|
|
144
|
+
* | { data: null }
|
|
145
|
+
* | { results: any[],
|
|
146
|
+
* pagination: {
|
|
147
|
+
* page: number,
|
|
148
|
+
* pageCount: number,
|
|
149
|
+
* pageSize: number,
|
|
150
|
+
* total: number
|
|
151
|
+
* }
|
|
152
|
+
* }
|
|
153
|
+
* ) => number}
|
|
154
|
+
*/
|
|
62
155
|
getNextPageParam(lastPage) {
|
|
63
|
-
if (lastPage.pagination.page >= lastPage.pagination.pageCount) {
|
|
156
|
+
if (!lastPage?.pagination || lastPage.pagination.page >= lastPage.pagination.pageCount) {
|
|
64
157
|
return undefined;
|
|
65
158
|
}
|
|
66
159
|
|
|
@@ -201,7 +201,7 @@ const DraggableCard = ({
|
|
|
201
201
|
id: getTrad('components.DraggableCard.move.field'),
|
|
202
202
|
defaultMessage: 'Move {item}',
|
|
203
203
|
},
|
|
204
|
-
{ item:
|
|
204
|
+
{ item: labelField }
|
|
205
205
|
)}
|
|
206
206
|
onClick={(e) => e.stopPropagation()}
|
|
207
207
|
ref={refs.dragRef}
|
|
@@ -223,7 +223,7 @@ const DraggableCard = ({
|
|
|
223
223
|
id: getTrad('components.DraggableCard.edit.field'),
|
|
224
224
|
defaultMessage: 'Edit {item}',
|
|
225
225
|
},
|
|
226
|
-
{ item:
|
|
226
|
+
{ item: labelField }
|
|
227
227
|
)}
|
|
228
228
|
type="button"
|
|
229
229
|
>
|
|
@@ -237,7 +237,7 @@ const DraggableCard = ({
|
|
|
237
237
|
id: getTrad('components.DraggableCard.delete.field'),
|
|
238
238
|
defaultMessage: 'Delete {item}',
|
|
239
239
|
},
|
|
240
|
-
{ item:
|
|
240
|
+
{ item: labelField }
|
|
241
241
|
)}
|
|
242
242
|
type="button"
|
|
243
243
|
>
|
|
@@ -16,7 +16,7 @@ const FlexGap = styled(Flex)`
|
|
|
16
16
|
|
|
17
17
|
const Settings = ({ modifiedData, onChange, sortOptions }) => {
|
|
18
18
|
const { formatMessage } = useIntl();
|
|
19
|
-
const { settings } = modifiedData;
|
|
19
|
+
const { settings, metadatas } = modifiedData;
|
|
20
20
|
|
|
21
21
|
return (
|
|
22
22
|
<>
|
|
@@ -122,7 +122,7 @@ const Settings = ({ modifiedData, onChange, sortOptions }) => {
|
|
|
122
122
|
>
|
|
123
123
|
{sortOptions.map((sortBy) => (
|
|
124
124
|
<Option key={sortBy} value={sortBy}>
|
|
125
|
-
{sortBy}
|
|
125
|
+
{metadatas[sortBy].list.label || sortBy}
|
|
126
126
|
</Option>
|
|
127
127
|
))}
|
|
128
128
|
</Select>
|
|
@@ -1,14 +1,29 @@
|
|
|
1
|
-
import { createStore, applyMiddleware } from 'redux';
|
|
1
|
+
import { createStore, applyMiddleware, compose } from 'redux';
|
|
2
2
|
import createReducer from './createReducer';
|
|
3
3
|
|
|
4
4
|
const configureStore = (appMiddlewares, appReducers) => {
|
|
5
|
+
let composeEnhancers = compose;
|
|
6
|
+
|
|
5
7
|
const middlewares = [];
|
|
6
8
|
|
|
7
9
|
appMiddlewares.forEach((middleware) => {
|
|
8
10
|
middlewares.push(middleware());
|
|
9
11
|
});
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
// If Redux Dev Tools are installed, enable them
|
|
14
|
+
if (
|
|
15
|
+
process.env.NODE_ENV !== 'production' &&
|
|
16
|
+
typeof window === 'object' &&
|
|
17
|
+
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
|
18
|
+
) {
|
|
19
|
+
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return createStore(
|
|
23
|
+
createReducer(appReducers),
|
|
24
|
+
{},
|
|
25
|
+
composeEnhancers(applyMiddleware(...middlewares))
|
|
26
|
+
);
|
|
12
27
|
};
|
|
13
28
|
|
|
14
29
|
export default configureStore;
|
|
Binary file
|
|
@@ -2,10 +2,10 @@ import { useQuery } from 'react-query';
|
|
|
2
2
|
import { useNotification } from '@strapi/helper-plugin';
|
|
3
3
|
import { fetchMarketplacePlugins } from './utils/api';
|
|
4
4
|
|
|
5
|
-
const useFetchMarketplacePlugins = (notifyLoad) => {
|
|
5
|
+
const useFetchMarketplacePlugins = (notifyLoad, params) => {
|
|
6
6
|
const toggleNotification = useNotification();
|
|
7
7
|
|
|
8
|
-
return useQuery('list-marketplace-plugins', () => fetchMarketplacePlugins(), {
|
|
8
|
+
return useQuery(['list-marketplace-plugins', params], () => fetchMarketplacePlugins(params), {
|
|
9
9
|
onSuccess() {
|
|
10
10
|
if (notifyLoad) {
|
|
11
11
|
notifyLoad();
|
|
@@ -2,8 +2,10 @@ import axios from 'axios';
|
|
|
2
2
|
|
|
3
3
|
const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
|
|
4
4
|
|
|
5
|
-
const fetchMarketplacePlugins = async () => {
|
|
6
|
-
const { data: response } = await axios.get(`${MARKETPLACE_API_URL}/plugins
|
|
5
|
+
const fetchMarketplacePlugins = async (params = {}) => {
|
|
6
|
+
const { data: response } = await axios.get(`${MARKETPLACE_API_URL}/plugins`, {
|
|
7
|
+
params,
|
|
8
|
+
});
|
|
7
9
|
|
|
8
10
|
// Only keep v4 plugins
|
|
9
11
|
const filteredResponse = {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { useQuery } from 'react-query';
|
|
2
2
|
import { useNotification } from '@strapi/helper-plugin';
|
|
3
|
-
import {
|
|
3
|
+
import { fetchMarketplaceProviders } from './utils/api';
|
|
4
4
|
|
|
5
|
-
const useFetchMarketplaceProviders = (notifyLoad) => {
|
|
5
|
+
const useFetchMarketplaceProviders = (notifyLoad, params) => {
|
|
6
6
|
const toggleNotification = useNotification();
|
|
7
7
|
|
|
8
|
-
return useQuery('list-marketplace-providers', () =>
|
|
8
|
+
return useQuery(['list-marketplace-providers', params], () => fetchMarketplaceProviders(params), {
|
|
9
9
|
onSuccess() {
|
|
10
10
|
if (notifyLoad) {
|
|
11
11
|
notifyLoad();
|
|
@@ -2,10 +2,12 @@ import axios from 'axios';
|
|
|
2
2
|
|
|
3
3
|
const MARKETPLACE_API_URL = 'https://market-api.strapi.io';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const { data } = await axios.get(`${MARKETPLACE_API_URL}/providers
|
|
5
|
+
const fetchMarketplaceProviders = async (params = {}) => {
|
|
6
|
+
const { data } = await axios.get(`${MARKETPLACE_API_URL}/providers`, {
|
|
7
|
+
params,
|
|
8
|
+
});
|
|
7
9
|
|
|
8
10
|
return data;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
|
-
export {
|
|
13
|
+
export { fetchMarketplaceProviders };
|
package/admin/src/index.js
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<svg width="148" height="148" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g opacity=".8" fill-rule="evenodd" clip-rule="evenodd">
|
|
3
|
+
<path opacity=".15" d="M110.81 37H73.97V74.1h36.84V37Z" fill="url(#a)"/>
|
|
4
|
+
<path opacity=".07" d="M36.84 0H0v37.08h36.84V0Z" fill="url(#b)"/>
|
|
5
|
+
<path opacity=".07" d="M73.92 73.95H37.08v37.08h36.84V73.95Z" fill="url(#c)"/>
|
|
6
|
+
<path opacity=".07" d="M147.99 110.92h-37.3V148H148v-37.08Z" fill="url(#d)"/>
|
|
7
|
+
<path opacity=".15" d="M73.83 37H36.84L73.83 0v37Z" fill="url(#e)"/>
|
|
8
|
+
<path opacity=".15" d="M110.6 111.02v-37h36.98l-36.99 37Z" fill="url(#f)"/>
|
|
9
|
+
<path opacity=".4" d="M73.83 0v37h36.98v37.01h37V3a3 3 0 0 0-3-3H73.82Z" fill="url(#g)"/>
|
|
10
|
+
</g>
|
|
11
|
+
|
|
12
|
+
<defs>
|
|
13
|
+
<linearGradient id="a" x1="91.31" y1="83.31" x2="118.24" y2="56.59" gradientUnits="userSpaceOnUse">
|
|
14
|
+
<stop stop-color="#7A92FF"/>
|
|
15
|
+
<stop offset="1" stop-color="#3253EA"/>
|
|
16
|
+
</linearGradient>
|
|
17
|
+
|
|
18
|
+
<linearGradient id="b" x1="40.99" y1="13.88" x2=".01" y2="11.64" gradientUnits="userSpaceOnUse">
|
|
19
|
+
<stop stop-color="#A8B8FF"/>
|
|
20
|
+
<stop offset="1" stop-color="#3253EA"/>
|
|
21
|
+
</linearGradient>
|
|
22
|
+
|
|
23
|
+
<linearGradient id="c" x1="54.41" y1="120.25" x2="81.35" y2="93.52" gradientUnits="userSpaceOnUse">
|
|
24
|
+
<stop stop-color="#A8B8FF"/>
|
|
25
|
+
<stop offset="1" stop-color="#3253EA"/>
|
|
26
|
+
</linearGradient>
|
|
27
|
+
|
|
28
|
+
<linearGradient id="d" x1="128.24" y1="157.22" x2="155.17" y2="130.17" gradientUnits="userSpaceOnUse">
|
|
29
|
+
<stop stop-color="#A8B8FF"/>
|
|
30
|
+
<stop offset="1" stop-color="#3253EA"/>
|
|
31
|
+
</linearGradient>
|
|
32
|
+
|
|
33
|
+
<linearGradient id="e" x1="54.24" y1="46.21" x2="81.12" y2="19.38" gradientUnits="userSpaceOnUse">
|
|
34
|
+
<stop stop-color="#7A92FF"/>
|
|
35
|
+
<stop offset="1" stop-color="#3253EA"/>
|
|
36
|
+
</linearGradient>
|
|
37
|
+
|
|
38
|
+
<linearGradient id="f" x1="126.28" y1="74.05" x2="124.94" y2="111.07" gradientUnits="userSpaceOnUse">
|
|
39
|
+
<stop stop-color="#7A92FF"/>
|
|
40
|
+
<stop offset="1" stop-color="#3253EA"/>
|
|
41
|
+
</linearGradient>
|
|
42
|
+
|
|
43
|
+
<linearGradient id="g" x1="73.37" y1="36.87" x2="132.87" y2="66.74" gradientUnits="userSpaceOnUse">
|
|
44
|
+
<stop stop-color="#7A92FF"/>
|
|
45
|
+
<stop offset="1" stop-color="#3858EA"/>
|
|
46
|
+
</linearGradient>
|
|
47
|
+
</defs>
|
|
48
|
+
</svg>
|