diff --git a/site/website/diff/index.xml b/site/website/diff/index.xml deleted file mode 100644 index 630b26843b..0000000000 --- a/site/website/diff/index.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - /page/diff /templates/web/diff.ftl - inherit-levels - 2074 - 20747fa3-693d-ebd8-0aa8-5109a588fced - index.xml - diff - Diff - 2014-3-20T21:21:4.000Z - 2014-3-20T21:21:4.000Z - \ No newline at end of file diff --git a/templates/web/diff.ftl b/templates/web/diff.ftl deleted file mode 100644 index 7978a53a09..0000000000 --- a/templates/web/diff.ftl +++ /dev/null @@ -1,142 +0,0 @@ -<#assign mode = RequestParameters["mode"]!"" /> -<#assign ui = RequestParameters["ui"]!"" /> - - - - - - - <#include "/templates/web/common/page-fragments/head.ftl" /> - - Crafter Studio - - - - - - - - <#assign path="/studio/static-assets/components/cstudio-common/resources/" /> - - - - - - <#include "/templates/web/common/page-fragments/studio-context.ftl" /> - - - - - - - - - -<#if mode != "iframe"> -
- -
- - -
- -
- - - -
as-dialog"> -
${diff}
-
- -<#if mode == "iframe" && ui != "next"> -
-
- -
-
- - -<#include "/static-assets/app/pages/legacy.html"> - - - - diff --git a/ui/app/package.json b/ui/app/package.json index be8fe61e4c..6ce26b2de3 100644 --- a/ui/app/package.json +++ b/ui/app/package.json @@ -59,6 +59,7 @@ "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "@graphiql/plugin-explorer": "^3.0.1", + "@monaco-editor/react": "^4.6.0", "@mui/icons-material": "^6.1.7", "@mui/lab": "6.0.0-beta.15", "@mui/material": "^6.1.7", @@ -75,6 +76,7 @@ "@types/video.js": "^7.3.58", "autosuggest-highlight": "^3.3.4", "clsx": "^2.1.1", + "diff": "^7.0.0", "fast-xml-parser": "^4.3.6", "graphiql": "^3.2.2", "graphql": "^16.8.1", @@ -113,6 +115,7 @@ "devDependencies": { "@formatjs/cli": "^6.2.12", "@rollup/plugin-swc": "^0.3.0", + "@types/diff": "^6.0.0", "@types/js-cookie": "^3.0.6", "@types/react-infinite-scroller": "^1.2.5", "@types/uuid": "^10", diff --git a/ui/app/src/CHANGELOG.md b/ui/app/src/CHANGELOG.md index 49a3b46a53..90bf879aea 100644 --- a/ui/app/src/CHANGELOG.md +++ b/ui/app/src/CHANGELOG.md @@ -19,6 +19,7 @@ * @mui/x-data-grid * @mui/x-date-pickers * @mui/x-tree-view +* Removed LegacyVersionDialog and the entire associated `/studio/diff` route ## 4.2.0 diff --git a/ui/app/src/components/AccountManagement/utils.tsx b/ui/app/src/components/AccountManagement/utils.tsx index a8d0ae5bca..13ed7c1fa1 100644 --- a/ui/app/src/components/AccountManagement/utils.tsx +++ b/ui/app/src/components/AccountManagement/utils.tsx @@ -35,7 +35,9 @@ import { removeStoredPullBranch, removeStoredPullMergeStrategy, removeStoredPushBranch, - removeStoredShowToolsPanel + removeStoredShowToolsPanel, + removeCompareVersionDialogViewModes, + removeViewVersionDialogViewModes } from '../../utils/state'; export const preferencesGroups: Array<{ @@ -132,6 +134,8 @@ export const preferencesGroups: Array<{ removeStoredPreviewBackgroundMode(props.username); removeStoredBrowseDialogViewMode(props.username); removeStoredItems((key) => widgetsAccordionsKeyRegex.test(key)); + removeCompareVersionDialogViewModes(props.username); + removeViewVersionDialogViewModes(props.username); } } ]; diff --git a/ui/app/src/components/CompareVersionsDialog/CompareAssetPanel.tsx b/ui/app/src/components/CompareVersionsDialog/CompareAssetPanel.tsx new file mode 100644 index 0000000000..33ab4f2425 --- /dev/null +++ b/ui/app/src/components/CompareVersionsDialog/CompareAssetPanel.tsx @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007-2024 Crafter Software Corporation. All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import React, { ReactNode, useMemo } from 'react'; +import { isImage, isPdfDocument, isVideo } from '../PathNavigator/utils'; +import TextDiffView from './FieldsTypesDiffViews/TextDiffView'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import Divider from '@mui/material/Divider'; +import ImageView from '../ViewVersionDialog/FieldTypesViews/ImageView'; +import VideoView from '../ViewVersionDialog/FieldTypesViews/VideoView'; +import { PDFView } from '../ViewVersionDialog/AssetTypesViews/PDFView'; + +const typesDiffMap = { + image: ImageView, + video: VideoView, + text: TextDiffView, + pdf: PDFView +}; + +export interface AssetDiffViewProps { + aContent?: string; + bContent?: string; + type: 'image' | 'video' | 'pdf' | 'text'; + renderContent: (xml: string) => ReactNode; + noContent?: ReactNode; +} + +function AssetDiffView(props: AssetDiffViewProps) { + const { + aContent, + bContent, + type, + renderContent, + noContent = ( + + no content set + + ) + } = props; + const verticalLayout = type === 'image' || type === 'video'; + return ( + div': { + flexGrow: verticalLayout && 1 + } + }} + > + {aContent ? renderContent(aContent) : noContent} + {verticalLayout && } + {bContent ? renderContent(bContent) : noContent} + + ); +} + +export function CompareAssetPanel(props) { + const { a, b, item } = props; + const assetType = useMemo(() => { + if (isImage(item)) { + return 'image'; + } else if (isVideo(item)) { + return 'video'; + } else if (isPdfDocument(item.mimeType)) { + return 'pdf'; + } else { + return 'text'; + } + }, [item]); + const ViewComponent = typesDiffMap[assetType]; + const isVerticalLayout = assetType === 'image' || assetType === 'video'; + const viewComponentProps = { + ...(isVerticalLayout ? { sxs: { image: { maxHeight: '100%' } } } : {}) + }; + + if (assetType === 'text') { + return ; + } else { + return ( + ( + + + + )} + /> + ); + } +} + +export default CompareAssetPanel; diff --git a/ui/app/src/components/CompareVersionsDialog/CompareFieldPanel.tsx b/ui/app/src/components/CompareVersionsDialog/CompareFieldPanel.tsx new file mode 100644 index 0000000000..ea0b53dd58 --- /dev/null +++ b/ui/app/src/components/CompareVersionsDialog/CompareFieldPanel.tsx @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import { ContentTypeField } from '../../models/ContentType'; +import React from 'react'; +import Box from '@mui/material/Box'; +import { getContentInstanceValueFromProp } from '../../utils/content'; +import { fromString, serialize } from '../../utils/xml'; +import { DiffViewComponentBaseProps, SelectionContentVersion, typesDiffMap } from './utils'; +import ContentFieldView from '../ViewVersionDialog/ContentFieldView'; +import { countLines } from '../../utils/string'; +import { ErrorBoundary } from '../ErrorBoundary'; +import { initialFieldViewState, useVersionsDialogContext } from './VersionsDialogContext'; +import DefaultDiffView from './FieldsTypesDiffViews/DefaultDiffView'; +import TextDiffView from './FieldsTypesDiffViews/TextDiffView'; +import { DiffEditorProps } from '@monaco-editor/react'; +import ContentInstance from '../../models/ContentInstance'; + +export interface CompareFieldPanelProps { + a: SelectionContentVersion; + b: SelectionContentVersion; + field: ContentTypeField; + dynamicHeight?: boolean; + onSelectField?(field: ContentTypeField): void; +} + +export interface DiffComponentProps extends Pick { + editorProps?: DiffEditorProps; +} + +export function CompareFieldPanel(props: CompareFieldPanelProps) { + const { a, b, field, onSelectField, dynamicHeight } = props; + const [{ fieldsViewState }] = useVersionsDialogContext(); + const fieldType = field.type; + const versionAXmlDoc = fromString(a.xml); + const versionBXmlDoc = fromString(b.xml); + const versionAFieldDoc = + versionAXmlDoc.querySelector(`page > ${field.id}`) ?? + versionAXmlDoc.querySelector(`component > ${field.id}`) ?? + versionAXmlDoc.querySelector(`item > ${field.id}`); + const versionBFieldDoc = + versionBXmlDoc.querySelector(`page > ${field.id}`) ?? + versionBXmlDoc.querySelector(`component > ${field.id}`) ?? + versionBXmlDoc.querySelector(`item > ${field.id}`); + const versionAFieldXml = versionAFieldDoc ? serialize(versionAFieldDoc) : ''; + const versionBFieldXml = versionBFieldDoc ? serialize(versionBFieldDoc) : ''; + const unchanged = versionAFieldXml === versionBFieldXml; + const contentA = getContentInstanceValueFromProp(a.content as ContentInstance, field.id); + const longerXmlContent = versionAFieldXml.length > versionBFieldXml.length ? versionAFieldXml : versionBFieldXml; + const monacoEditorHeight = dynamicHeight ? (countLines(longerXmlContent) < 15 ? '200px' : '600px') : '100%'; + const DiffComponent = typesDiffMap[fieldType] ?? DefaultDiffView; + const viewState = fieldsViewState[field.id] ?? initialFieldViewState; + const { compareXml, monacoOptions } = viewState; + const diffComponentProps: DiffComponentProps = { + aXml: versionAFieldXml, + bXml: versionBFieldXml, + field, + editorProps: { options: monacoOptions, height: monacoEditorHeight } + }; + + return ( + + {unchanged ? ( + + ) : ( + <> + {compareXml ? ( + + ) : ( + + + + )} + + )} + + ); +} + +export default CompareFieldPanel; diff --git a/ui/app/src/components/CompareVersionsDialog/CompareVersions.tsx b/ui/app/src/components/CompareVersionsDialog/CompareVersions.tsx index 48c078d155..e69de29bb2 100644 --- a/ui/app/src/components/CompareVersionsDialog/CompareVersions.tsx +++ b/ui/app/src/components/CompareVersionsDialog/CompareVersions.tsx @@ -1,408 +0,0 @@ -/* - * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// Next UI code disabled temporarily - -import { makeStyles } from 'tss-react/mui'; -import ContentInstance from '../../models/ContentInstance'; -import React from 'react'; -import { useSelection } from '../../hooks/useSelection'; - -// declare const monaco: any; - -/*const CompareVersionsStyles = makeStyles(() => - createStyles({ - monacoWrapper: { - width: '100%', - height: '150px', - '&.unChanged': { - height: 'auto' - } - }, - singleImage: { - display: 'flex', - width: '100%', - justifyContent: 'center' - }, - imagesCompare: { - display: 'flex', - alignItems: 'center', - '& img': { - width: '50%', - padding: '20px' - } - }, - compareBoxHeader: { - display: 'flex', - justifyContent: 'space-around' - }, - compareBoxHeaderItem: { - flexBasis: '50%', - margin: '0 10px 10px 10px', - '& .blackText': { - color: palette.black - } - }, - compareVersionsContent: { - background: palette.white - }, - root: { - margin: 0, - border: 0, - boxShadow: 'none', - '&.Mui-expanded': { - margin: 0, - borderBottom: '1px solid rgba(0,0,0,0.12)' - } - }, - bold: { - fontWeight: 600 - }, - unchangedChip: { - marginLeft: 'auto', - height: '26px', - color: palette.gray.medium4, - backgroundColor: palette.gray.light1 - } - }) -); */ - -/*const ContentInstanceComponentsStyles = makeStyles(() => - createStyles({ - componentsWrapper: { - display: 'flex', - flexDirection: 'column', - width: '100%' - }, - component: { - padding: '10px', - marginBottom: '12px', - display: 'flex', - justifyContent: 'space-between', - borderRadius: '5px', - alignItems: 'center', - '&.unchanged': { - color: palette.gray.medium4, - backgroundColor: palette.gray.light1 - }, - '&.new': { - color: palette.green.shade, - backgroundColor: palette.green.highlight, - width: '50%', - marginLeft: 'auto' - }, - '&.changed': { - color: palette.yellow.shade, - backgroundColor: palette.yellow.highlight - }, - '&.deleted': { - color: palette.red.shade, - backgroundColor: palette.red.highlight, - width: '50%', - marginRight: 'auto' - }, - '&:last-child': { - marginBottom: 0 - } - }, - status: { - fontSize: '0.8125rem', - color: palette.gray.medium4 - } - }) -); */ - -/*const translations = defineMessages({ - changed: { - id: 'words.changed', - defaultMessage: 'Changed' - }, - unchanged: { - id: 'words.unchanged', - defaultMessage: 'Unchanged' - }, - deleted: { - id: 'words.deleted', - defaultMessage: 'Deleted' - }, - empty: { - id: 'words.empty', - defaultMessage: 'Empty' - }, - noItemsStatus: { - id: 'compareVersionsDialog.noItemsStatus', - defaultMessage: 'No items' - } -}); */ - -interface CompareVersionsProps { - versions: ContentInstance[]; -} - -const getLegacyDialogStyles = makeStyles()(() => ({ - iframe: { - border: 'none', - height: '80vh' - } -})); - -export function CompareVersions(props: CompareVersionsProps) { - const [a, b] = props.versions; - const { classes } = getLegacyDialogStyles(); - const authoringUrl = useSelection((state) => state.env.authoringBase); - return ( -