From be746cc71252ebfb6376974d547d33718e8d63f9 Mon Sep 17 00:00:00 2001 From: Marvin Bertram Date: Wed, 20 Nov 2024 09:23:42 +0100 Subject: [PATCH] Localized fields language switch (#708) * Integrate language switch * Display language switch based on active tab * Remove editor settings * Ignore vs code settings * Reduce language selection to single selection * Automatic frontend build --------- Co-authored-by: vin0401 --- .gitignore | 2 + .vscode/settings.json | 3 - .../icons/split-cells-outlined.inline.svg | 3 + .../core/modules/asset/asset-draft-slice.tsx | 12 +- .../modules/asset/hooks/use-asset-draft.ts | 15 +- .../data-object/data-object-draft-slice.tsx | 16 +- .../data-object/editor/editor-container.tsx | 23 +- .../language-selection/language-selection.tsx | 30 + .../provider/language-selection-provider.tsx | 39 + .../provider/use-language-selection.tsx | 25 + .../data-object/editor/toolbar/toolbar.tsx | 13 +- .../tabs/edit/components/data-component.tsx | 23 +- .../tabs/edit/components/root-component.tsx | 4 + .../hooks/use-data-object-draft.ts | 15 +- .../modules/element/draft/hooks/use-tabs.ts | 77 + .../draft/hooks/use-trackable-changes.ts | 4 +- .../localized-fields/localized-fields.tsx | 9 +- .../dynamic-type-object-data-abstract.ts | 4 +- .../element/editor/tabs/editor-tabs.tsx | 10 +- .../element/hooks/use-element-draft.ts | 2 + assets/tsconfig.json | 2 +- .../entrypoints.json | 9 + .../main.js | 2 + .../main.js.LICENSE.txt | 16 + .../manifest.json | 3 + .../entrypoints.json | 9 + .../manifest.json | 3 + .../vendor.js | 2 + .../vendor.js.LICENSE.txt | 190 ++ .../105.js | 2 + .../105.js.LICENSE.txt | 16 + .../core-dll.css | 16 + .../core-dll.js | 2 + .../core-dll.js.LICENSE.txt | 133 ++ .../entrypoints.json | 12 + .../fonts/Lato-Bold.636be8de.ttf | Bin 0 -> 73332 bytes .../fonts/Lato-Light.c7400fca.ttf | Bin 0 -> 77208 bytes .../fonts/Lato-Regular.9d883d54.ttf | Bin 0 -> 75152 bytes .../manifest.json | 1736 +++++++++++++++++ 39 files changed, 2435 insertions(+), 47 deletions(-) delete mode 100644 .vscode/settings.json create mode 100644 assets/js/src/core/assets/icons/split-cells-outlined.inline.svg create mode 100644 assets/js/src/core/modules/data-object/editor/toolbar/language-selection/language-selection.tsx create mode 100644 assets/js/src/core/modules/data-object/editor/toolbar/language-selection/provider/language-selection-provider.tsx create mode 100644 assets/js/src/core/modules/data-object/editor/toolbar/language-selection/provider/use-language-selection.tsx create mode 100644 assets/js/src/core/modules/element/draft/hooks/use-tabs.ts create mode 100644 public/build/d3baa7e3-cc0e-4b58-81d9-ef71abfe940b/entrypoints.json create mode 100644 public/build/d3baa7e3-cc0e-4b58-81d9-ef71abfe940b/main.js create mode 100644 public/build/d3baa7e3-cc0e-4b58-81d9-ef71abfe940b/main.js.LICENSE.txt create mode 100644 public/build/d3baa7e3-cc0e-4b58-81d9-ef71abfe940b/manifest.json create mode 100644 public/build/e2d04c82-bcf9-4767-af1e-4a877b8e5787/entrypoints.json create mode 100644 public/build/e2d04c82-bcf9-4767-af1e-4a877b8e5787/manifest.json create mode 100644 public/build/e2d04c82-bcf9-4767-af1e-4a877b8e5787/vendor.js create mode 100644 public/build/e2d04c82-bcf9-4767-af1e-4a877b8e5787/vendor.js.LICENSE.txt create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/105.js create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/105.js.LICENSE.txt create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/core-dll.css create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/core-dll.js create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/core-dll.js.LICENSE.txt create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/entrypoints.json create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/fonts/Lato-Bold.636be8de.ttf create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/fonts/Lato-Light.c7400fca.ttf create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/fonts/Lato-Regular.9d883d54.ttf create mode 100644 public/build/e5a0936a-52b7-4ac8-84bc-ed36f096d969/manifest.json diff --git a/.gitignore b/.gitignore index d9cf4277d..a97c4f006 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ Thumbs.db # PhpStorm / IDEA .idea +# VS Code +.vscode # Test env /bin diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index b27c665e5..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "livePreview.defaultPreviewPath": "/assets/storybook-static/index.html" -} diff --git a/assets/js/src/core/assets/icons/split-cells-outlined.inline.svg b/assets/js/src/core/assets/icons/split-cells-outlined.inline.svg new file mode 100644 index 000000000..d79e5771a --- /dev/null +++ b/assets/js/src/core/assets/icons/split-cells-outlined.inline.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/js/src/core/modules/asset/asset-draft-slice.tsx b/assets/js/src/core/modules/asset/asset-draft-slice.tsx index d3c345fda..d031b384e 100644 --- a/assets/js/src/core/modules/asset/asset-draft-slice.tsx +++ b/assets/js/src/core/modules/asset/asset-draft-slice.tsx @@ -23,8 +23,9 @@ import { } from '@Pimcore/modules/element/draft/hooks/use-trackable-changes' import { useImageSettingsReducers } from '@Pimcore/modules/asset/draft/hooks/use-image-settings' import { type SchedulesDraft, useSchedulesReducers } from '@Pimcore/modules/element/draft/hooks/use-schedules' +import { initialTabsStateValue, type TabsDraft, useTabsReducers } from '../element/draft/hooks/use-tabs' -export interface AssetDraft extends Asset, PropertiesDraft, SchedulesDraft, CustomMetadataDraft, TrackableChangesDraft { +export interface AssetDraft extends Asset, PropertiesDraft, SchedulesDraft, CustomMetadataDraft, TrackableChangesDraft, TabsDraft { imageSettings: ImageData } @@ -39,7 +40,8 @@ export const slice = createSlice({ imageSettings: [], schedule: [], changes: {}, - modifiedCells: {} + modifiedCells: {}, + ...initialTabsStateValue }), reducers: { assetReceived: assetsAdapter.upsertOne, @@ -57,7 +59,8 @@ export const slice = createSlice({ ...usePropertiesReducers(assetsAdapter), ...useSchedulesReducers(assetsAdapter), ...useCustomMetadataReducers(assetsAdapter), - ...useImageSettingsReducers(assetsAdapter) + ...useImageSettingsReducers(assetsAdapter), + ...useTabsReducers(assetsAdapter) } }) @@ -90,6 +93,7 @@ export const { addCustomMetadata: addCustomMetadataToAsset, removeCustomMetadata: removeCustomMetadataFromAsset, updateCustomMetadata: updateCustomMetadataForAsset, - setCustomMetadata: setCustomMetadataForAsset + setCustomMetadata: setCustomMetadataForAsset, + setActiveTab: setActiveTabForAsset } = slice.actions export const { selectById: selectAssetById } = assetsAdapter.getSelectors((state: RootState) => state['asset-draft']) diff --git a/assets/js/src/core/modules/asset/hooks/use-asset-draft.ts b/assets/js/src/core/modules/asset/hooks/use-asset-draft.ts index 7d326128a..3b88de548 100644 --- a/assets/js/src/core/modules/asset/hooks/use-asset-draft.ts +++ b/assets/js/src/core/modules/asset/hooks/use-asset-draft.ts @@ -27,6 +27,7 @@ import { resetChanges, resetSchedulesChangesForAsset, selectAssetById, + setActiveTabForAsset, setCustomMetadataForAsset, setModifiedCells, setPropertiesForAsset, @@ -56,12 +57,14 @@ import { useSchedulesDraft, type UseSchedulesDraftReturn } from '@Pimcore/module import { type ElementEditorType, type TypeRegistryInterface } from '@Pimcore/modules/element/editor/services/type-registry' import { useInjection } from '@Pimcore/app/depency-injection' import { serviceIds } from '@Pimcore/app/config/services/service-ids' +import { initialTabsStateValue, useTabsDraft, type UseTabsDraftReturn } from '@Pimcore/modules/element/draft/hooks/use-tabs' interface UseAssetDraftReturn extends UseCustomMetadataDraftReturn, UsePropertiesDraftReturn, UseSchedulesDraftReturn, UseTrackableChangesDraftReturn, + UseTabsDraftReturn, UseImageSettingsDraftReturn { isLoading: boolean isError: boolean @@ -148,7 +151,8 @@ export const useAssetDraft = (id: number): UseAssetDraftReturn => { schedules: [], imageSettings: customSettingsResponse, changes: {}, - modifiedCells: {} + modifiedCells: {}, + ...initialTabsStateValue } if (assetData !== undefined) { @@ -213,6 +217,12 @@ export const useAssetDraft = (id: number): UseAssetDraftReturn => { updateImageSettingForAsset ) + const tabsActions = useTabsDraft( + id, + asset, + setActiveTabForAsset + ) + const editorType = asset?.type === undefined ? undefined : (typeRegistry.get(asset.type) ?? typeRegistry.get('unknown')) @@ -228,6 +238,7 @@ export const useAssetDraft = (id: number): UseAssetDraftReturn => { ...propertyActions, ...schedulesActions, ...customMetadataActions, - ...imageSettingsActions + ...imageSettingsActions, + ...tabsActions } } diff --git a/assets/js/src/core/modules/data-object/data-object-draft-slice.tsx b/assets/js/src/core/modules/data-object/data-object-draft-slice.tsx index b5e64c16f..fe8e7f14e 100644 --- a/assets/js/src/core/modules/data-object/data-object-draft-slice.tsx +++ b/assets/js/src/core/modules/data-object/data-object-draft-slice.tsx @@ -19,10 +19,15 @@ import { type TrackableChangesDraft, useTrackableChangesReducers } from '@Pimcore/modules/element/draft/hooks/use-trackable-changes' +import { + initialTabsStateValue, + type TabsDraft, + useTabsReducers +} from '@Pimcore/modules/element/draft/hooks/use-tabs' import { type SchedulesDraft, useSchedulesReducers } from '@Pimcore/modules/element/draft/hooks/use-schedules' import { type DataObject } from '@Pimcore/modules/data-object/data-object-api-slice-enhanced' -export interface DataObjectDraft extends DataObject, PropertiesDraft, SchedulesDraft, TrackableChangesDraft { +export interface DataObjectDraft extends DataObject, PropertiesDraft, SchedulesDraft, TrackableChangesDraft, TabsDraft { } export const dataObjectsAdapter: EntityAdapter = createEntityAdapter({}) @@ -34,7 +39,8 @@ export const slice = createSlice({ properties: [], schedule: [], changes: {}, - modifiedCells: {} + modifiedCells: {}, + ...initialTabsStateValue }), reducers: { dataObjectReceived: dataObjectsAdapter.upsertOne, @@ -50,7 +56,8 @@ export const slice = createSlice({ }, ...useTrackableChangesReducers(dataObjectsAdapter), ...usePropertiesReducers(dataObjectsAdapter), - ...useSchedulesReducers(dataObjectsAdapter) + ...useSchedulesReducers(dataObjectsAdapter), + ...useTabsReducers(dataObjectsAdapter) } }) @@ -73,7 +80,8 @@ export const { removeSchedule: removeScheduleFromDataObject, setSchedules: setSchedulesForDataObject, updateSchedule: updateScheduleForDataObject, - resetSchedulesChanges: resetSchedulesChangesForDataObject + resetSchedulesChanges: resetSchedulesChangesForDataObject, + setActiveTab: setActiveTabForDataObject } = slice.actions export const { selectById: selectDataObjectById } = dataObjectsAdapter.getSelectors((state: RootState) => state['data-object-draft']) diff --git a/assets/js/src/core/modules/data-object/editor/editor-container.tsx b/assets/js/src/core/modules/data-object/editor/editor-container.tsx index 68128818c..8167f3068 100644 --- a/assets/js/src/core/modules/data-object/editor/editor-container.tsx +++ b/assets/js/src/core/modules/data-object/editor/editor-container.tsx @@ -20,6 +20,7 @@ import { useGlobalDataObjectContext } from '@Pimcore/modules/data-object/hooks/u import { TabsContainer } from '@Pimcore/modules/element/editor/shared-tab-manager/tabs-container' import { Toolbar } from '@Pimcore/modules/data-object/editor/toolbar/toolbar' import { TabsToolbarView } from '@Pimcore/modules/element/editor/layouts/tabs-toolbar-view' +import { LanguageSelectionProvider } from './toolbar/language-selection/provider/language-selection-provider' export interface EditorContainerProps { id: number @@ -64,17 +65,19 @@ const EditorContainer = (props: EditorContainerProps): React.JSX.Element => { return ( - - } + + + } - renderToolbar={ - - } - /> + renderToolbar={ + + } + /> + ) } diff --git a/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/language-selection.tsx b/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/language-selection.tsx new file mode 100644 index 000000000..199f07b1b --- /dev/null +++ b/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/language-selection.tsx @@ -0,0 +1,30 @@ +/** +* Pimcore +* +* This source file is available under two different licenses: +* - Pimcore Open Core License (POCL) +* - Pimcore Commercial License (PCL) +* Full copyright and license information is available in +* LICENSE.md which is distributed with this source code. +* +* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) +* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL +*/ + +import { LanguageSelection as BaseLanguageSelection } from '@Pimcore/components/language-selection/language-selection' +import { useSettings } from '@Pimcore/modules/app/settings/hooks/use-settings' +import React from 'react' +import { useLanguageSelection } from './provider/use-language-selection' + +export const LanguageSelection = (): React.JSX.Element => { + const settings = useSettings() + const { currentLanguage, setCurrentLanguage } = useLanguageSelection() + + return ( + + ) +} diff --git a/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/provider/language-selection-provider.tsx b/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/provider/language-selection-provider.tsx new file mode 100644 index 000000000..7af2925f3 --- /dev/null +++ b/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/provider/language-selection-provider.tsx @@ -0,0 +1,39 @@ +/** +* Pimcore +* +* This source file is available under two different licenses: +* - Pimcore Open Core License (POCL) +* - Pimcore Commercial License (PCL) +* Full copyright and license information is available in +* LICENSE.md which is distributed with this source code. +* +* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) +* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL +*/ + +import React, { createContext, useMemo, useState } from 'react' + +export interface ILanguageSelectionContext { + currentLanguage: string + setCurrentLanguage: (language: string) => void +} + +export const LanguageSelectionContext = createContext({ + currentLanguage: 'en', + setCurrentLanguage: () => {} +}) + +export interface LanguageSelectionProviderProps { + children: React.ReactNode +} + +export const LanguageSelectionProvider = ({ children }: LanguageSelectionProviderProps): React.JSX.Element => { + // @todo check for default language + const [currentLanguage, setCurrentLanguage] = useState('en') + + return useMemo(() => ( + + {children} + + ), [currentLanguage, children]) +} diff --git a/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/provider/use-language-selection.tsx b/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/provider/use-language-selection.tsx new file mode 100644 index 000000000..be709b5d8 --- /dev/null +++ b/assets/js/src/core/modules/data-object/editor/toolbar/language-selection/provider/use-language-selection.tsx @@ -0,0 +1,25 @@ +/** +* Pimcore +* +* This source file is available under two different licenses: +* - Pimcore Open Core License (POCL) +* - Pimcore Commercial License (PCL) +* Full copyright and license information is available in +* LICENSE.md which is distributed with this source code. +* +* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) +* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL +*/ + +import { useContext } from 'react' +import { type ILanguageSelectionContext, LanguageSelectionContext } from './language-selection-provider' + +export interface UseLanguageSelectionReturn extends ILanguageSelectionContext {} + +export const useLanguageSelection = (): UseLanguageSelectionReturn => { + const context = useContext(LanguageSelectionContext) + + return { + ...context + } +} diff --git a/assets/js/src/core/modules/data-object/editor/toolbar/toolbar.tsx b/assets/js/src/core/modules/data-object/editor/toolbar/toolbar.tsx index d489fb98f..6b30d3162 100644 --- a/assets/js/src/core/modules/data-object/editor/toolbar/toolbar.tsx +++ b/assets/js/src/core/modules/data-object/editor/toolbar/toolbar.tsx @@ -29,11 +29,14 @@ import { type DataObjectUpdateByIdApiArg, useDataObjectUpdateByIdMutation } from '@Pimcore/modules/data-object/data-object-api-slice-enhanced' +import { Flex } from '@Pimcore/components/flex/flex' +import { TAB_EDIT } from '../types/object/tab-manager/tabs/edit/edit-container' +import { LanguageSelection } from './language-selection/language-selection' export const Toolbar = (): React.JSX.Element => { const { t } = useTranslation() const { id } = useContext(DataObjectContext) - const { dataObject, properties, removeTrackedChanges } = useDataObjectDraft(id) + const { dataObject, properties, activeTab, removeTrackedChanges } = useDataObjectDraft(id) const hasChanges = dataObject?.modified === true const [saveDataObject, { isLoading, isSuccess, isError }] = useDataObjectUpdateByIdMutation() const { saveSchedules, isLoading: isSchedulesLoading, isSuccess: isSchedulesSuccess, isError: isSchedulesError } = useSaveSchedules('data-object', id, false) @@ -58,7 +61,13 @@ export const Toolbar = (): React.JSX.Element => { return ( - + + + + {activeTab === TAB_EDIT.key && ( + + )} +