Skip to content

Commit

Permalink
Merge pull request #3978 from epam/3914-add-support-for-opening-struc…
Browse files Browse the repository at this point in the history
…tures-in-cdx-format-embedded-into-ms-powerpoint

#3914 Add support for opening structures in CDX format embedded into …
  • Loading branch information
captain2b authored Jan 29, 2024
2 parents d2aae8a + d575504 commit b5ab5f2
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 55 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion packages/ketcher-react/src/components/StructRender/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
import { RenderOptions } from 'application/render/render.types';
import { Struct } from 'ketcher-core';

interface CasheOptions {
cachePrefix?: string;
needCache?: boolean;
}
export interface IStructRenderProps {
struct: Struct;
options?: RenderOptions & { cachePrefix?: string; needCache?: boolean };
options?: (RenderOptions & CasheOptions) | CasheOptions;
className?: string;
update?: boolean;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/****************************************************************************
* Copyright 2021 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/

export const editorOptionsSelector = (state) => state.editor?.render?.options;
2 changes: 1 addition & 1 deletion packages/ketcher-react/src/script/ui/state/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function loadStruct(struct) {
};
}

function parseStruct(
export function parseStruct(
struct: string | Struct,
server,
options?,
Expand Down
2 changes: 1 addition & 1 deletion packages/ketcher-react/src/script/ui/utils/fileOpener.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function throughFileReader(file) {
structures.push(base64String);
}
});
content = { structures: structures.reverse(), isPPTX: true };
content = { structures, isPPTX: true };
break;
default:
content = rd.result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,4 @@
width: 100%;
height: 100%;
box-sizing: border-box;

> img {
max-width: 100%;
max-height: 100%;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ import { useSelector } from 'react-redux';
import { MenuList } from '@mui/material';
import MenuItem from '@mui/material/MenuItem';
import { Icon } from 'components';
import { Struct } from 'ketcher-core';
import { LoadingCircles } from '../../../../../../components';
import styles from './CDXStructuresViewer.module.less';
import { serverSelector } from '../../../../../../../state/server/selectors';
import StructRender from '../../../../../../../../../components/StructRender/StructRender';
import { parseStruct } from '../../../../../../../state/shared';
import styles from './CDXStructuresViewer.module.less';
import { editorOptionsSelector } from '../../../../../../../state/editor/selectors';

export type CDXStructuresViewerProps = {
structList?: string[];
Expand All @@ -30,17 +34,10 @@ export type CDXStructuresViewerProps = {
fileName: string;
};

type itemsMapInterface = {
[x: number]: { struct: string; error?: string; imageUrl?: string };
};
type item = { base64struct: string; error?: string; struct?: Struct };

const isError = (string: string) => {
try {
JSON.parse(string);
} catch (e) {
return false;
}
return JSON.parse(string).error;
type itemsMapInterface = {
[x: number]: item;
};

export const CDXStructuresViewer = ({
Expand All @@ -49,6 +46,7 @@ export const CDXStructuresViewer = ({
fileName,
}: CDXStructuresViewerProps) => {
const server = useSelector(serverSelector);
const editorOptions = useSelector(editorOptionsSelector);
const [selectedIndex, setSelectedIndex] = useState(0);
const [itemsMap, setItemsMap] = useState<itemsMapInterface>({});
const [loading, setLoading] = useState(false);
Expand All @@ -57,33 +55,24 @@ export const CDXStructuresViewer = ({
if (!itemsMap[selectedIndex] || itemsMap[selectedIndex].error) {
inputHandler('');
} else {
inputHandler(itemsMap[selectedIndex].struct);
inputHandler(itemsMap[selectedIndex].base64struct);
}
}, [inputHandler, itemsMap, selectedIndex]);

const getImages = useCallback(() => {
const options = { outputFormat: 'png', bondThickness: 1 };
const itemsList = {};
setLoading(true);
const promises = structList.map((str) => {
return server
.generateImageAsBase64(str, options)
.then((base64) => {
const error = isError(base64);
if (error) {
return {
struct: str,
error,
};
}
return parseStruct(str, server)
.then((struct) => {
return {
struct: str,
imageUrl: base64,
base64struct: str,
struct,
};
})
.catch((error) => {
return {
struct: str,
base64struct: str,
error: error.message || error,
};
});
Expand All @@ -104,6 +93,21 @@ export const CDXStructuresViewer = ({
getImages();
}, [getImages]);

const renderStructure = (structure: item) => {
if (structure?.error) {
return <div>Error: {itemsMap[selectedIndex]?.error}</div>;
}
if (structure?.struct) {
return (
<StructRender
className={styles.image}
struct={structure.struct}
options={{ ...editorOptions, autoScale: true, needCache: false }}
/>
);
}
return null;
};
const renderStructures = () => {
if (!structList?.length) {
return (
Expand All @@ -120,7 +124,7 @@ export const CDXStructuresViewer = ({
<MenuList>
{menuList.map((value, index) => (
<MenuItem
key={value.struct + index}
key={value.base64struct + index}
selected={index === selectedIndex}
onClick={() => setSelectedIndex(index)}
>
Expand All @@ -131,16 +135,7 @@ export const CDXStructuresViewer = ({
</MenuList>
</div>
<div className={styles.imageWrapper}>
{itemsMap[selectedIndex]?.error ? (
<div>Error: {itemsMap[selectedIndex]?.error}</div>
) : (
<div className={styles.image}>
<img
src={`data:image/png+xml;base64,${itemsMap[selectedIndex]?.imageUrl}`}
alt={`preview of a structure #${selectedIndex + 1}`}
/>
</div>
)}
{renderStructure(itemsMap[selectedIndex])}
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ self.onmessage = (e: MessageEvent<InputMessage<CommandData>>) => {
indigo.convert(data.struct, data.format, indigoOptions),
data.options,
Command.Convert,
data.struct,
);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,16 @@ class IndigoService implements StructService {
const action = ({ data }: OutputMessageWrapper) => {
console.log('convert action', data);
const msg: OutputMessage<string> = data;
if (!msg.hasError) {
const result: ConvertResult = {
struct: msg.payload,
format: outputFormat,
};
resolve(result);
} else {
reject(msg.error);
if (msg.inputData === struct) {
if (!msg.hasError) {
const result: ConvertResult = {
struct: msg.payload,
format: outputFormat,
};
resolve(result);
} else {
reject(msg.error);
}
}
};
if (options?.['input-format']) {
Expand All @@ -292,7 +294,7 @@ class IndigoService implements StructService {
data: commandData,
};

this.EE.removeAllListeners(WorkerEvent.Convert);
this.EE.removeListener(WorkerEvent.Convert, action);
this.EE.addListener(WorkerEvent.Convert, action);

this.worker.postMessage(inputMessage);
Expand Down

0 comments on commit b5ab5f2

Please sign in to comment.