From 7bdaf15242d1cdbb2a7b4bd45d519cf0b306943f Mon Sep 17 00:00:00 2001 From: Taras Hlukhovetskyi Date: Fri, 24 Apr 2026 19:04:24 +0300 Subject: [PATCH 1/2] [FEAT] Code Artifacts UI screen --- src/common/Editor/Editor.jsx | 92 +++++++++++ src/common/Editor/editor.util.js | 63 ++++++++ .../ArtifactsPreview/ArtifactsPreview.jsx | 6 +- .../ArtifactsPreview/ArtifactsPreviewView.jsx | 34 +++- .../CodePreview/CodePreview.jsx | 112 +++++++++++++ .../CodePreview/codePreview.scss | 135 ++++++++++++++++ .../ArtifactsPreview/artifactsPreview.scss | 53 +++++- .../Details/DetailsHeader/DetailsHeader.jsx | 16 +- .../Details/DetailsHeader/DetailsHeader.scss | 15 ++ src/components/Details/details.util.js | 17 ++ .../DetailsAnalysis/DetailsAnalysis.jsx | 2 +- .../DetailsInfo/DetailsInfoView.jsx | 31 ++-- .../DetailsPreview/DetailsPreview.jsx | 32 ++-- src/components/Files/Files.jsx | 18 ++- src/components/Files/files.util.jsx | 15 +- src/constants.js | 9 ++ src/utils/createArtifactPreviewContent.js | 54 ++++--- src/utils/getArtifactPreview.jsx | 39 ++++- tests/mockServer/data/artifacts.json | 122 ++++++++++++++ .../mockServer/data/artifacts/archive_js.zip | 1 + .../data/artifacts/archive_python.zip | 1 + .../data/artifacts/javascript_script.js | 153 ++++++++++++++++++ .../data/artifacts/python_script.py | 135 ++++++++++++++++ .../mockServer/data/artifacts/shell_script.sh | 144 +++++++++++++++++ tests/mockServer/data/featureSets.json | 5 +- tests/mockServer/mock.js | 2 +- 26 files changed, 1228 insertions(+), 78 deletions(-) create mode 100644 src/common/Editor/Editor.jsx create mode 100644 src/common/Editor/editor.util.js create mode 100644 src/components/ArtifactsPreview/CodePreview/CodePreview.jsx create mode 100644 src/components/ArtifactsPreview/CodePreview/codePreview.scss create mode 100644 src/components/Details/DetailsHeader/DetailsHeader.scss create mode 100644 tests/mockServer/data/artifacts/archive_js.zip create mode 100644 tests/mockServer/data/artifacts/archive_python.zip create mode 100644 tests/mockServer/data/artifacts/javascript_script.js create mode 100644 tests/mockServer/data/artifacts/python_script.py create mode 100644 tests/mockServer/data/artifacts/shell_script.sh diff --git a/src/common/Editor/Editor.jsx b/src/common/Editor/Editor.jsx new file mode 100644 index 0000000000..8228ad5a3c --- /dev/null +++ b/src/common/Editor/Editor.jsx @@ -0,0 +1,92 @@ +/* +Copyright 2019 Iguazio Systems Ltd. + +Licensed under the Apache License, Version 2.0 (the "License") with +an addition restriction as set forth herein. 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. + +In addition, you may not use the software for any purposes that are +illegal under applicable law, and the grant of the foregoing license +under the Apache 2.0 license is conditioned upon your compliance with +such restriction. +*/ +import React from 'react' +import PropTypes from 'prop-types' +import MonacoEditor from '@monaco-editor/react' +import { Loader } from 'igz-controls/components' +import { loader } from '@monaco-editor/react' + +import { getScssVariableValue } from 'igz-controls/utils/common.util' + +loader.init().then(monaco => { + const alabasterColor = getScssVariableValue('--alabasterColor') + const mischkaColor = getScssVariableValue('--mischkaColor') + const spunPearlColor = getScssVariableValue('--spunPearlColor') + const whiteSolidColor = getScssVariableValue('--whiteSolidColor') + + monaco.editor.defineTheme('custom-theme', { + base: 'vs', + inherit: true, + rules: [], + colors: { + 'editor.background': alabasterColor, + 'editorGutter.background': alabasterColor, + 'editor.lineHighlightBackground': whiteSolidColor, + 'editorLineNumber.foreground': spunPearlColor, + 'editor.selectionBackground': mischkaColor + } + }) +}) + +const Editor = ({ value, language, readOnly = true, contextmenu = false }) => { + return ( + } + /> + ) +} + +Editor.propTypes = { + contextmenu: PropTypes.bool, + value: PropTypes.string.isRequired, + language: PropTypes.string, + readOnly: PropTypes.bool +} + +export default Editor diff --git a/src/common/Editor/editor.util.js b/src/common/Editor/editor.util.js new file mode 100644 index 0000000000..864f469cc7 --- /dev/null +++ b/src/common/Editor/editor.util.js @@ -0,0 +1,63 @@ +/* +Copyright 2019 Iguazio Systems Ltd. + +Licensed under the Apache License, Version 2.0 (the "License") with +an addition restriction as set forth herein. 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. + +In addition, you may not use the software for any purposes that are +illegal under applicable law, and the grant of the foregoing license +under the Apache 2.0 license is conditioned upon your compliance with +such restriction. +*/ +export const commonLanguages = { + cpp: 'cpp', + c: 'cpp', + h: 'cpp', + cc: 'cpp', + cxx: 'cpp', + hpp: 'cpp', + hh: 'cpp', + hxx: 'cpp', + csharp: 'csharp', + cs: 'csharp', + go: 'go', + java: 'java', + javascript: 'javascript', + js: 'javascript', + jsx: 'javascript', + python: 'python', + py: 'python', + r: 'r', + ruby: 'ruby', + rb: 'ruby', + scala: 'scala', + shell: 'shell', + sh: 'shell', + bash: 'shell', + sql: 'sql', + mysql: 'sql', + pgsql: 'sql', + typescript: 'typescript', + ts: 'typescript', + tsx: 'typescript' +} + +export const getEditorLanguage = (fileFormat, descriptiveLanguage) => { + if (commonLanguages[fileFormat]) { + return commonLanguages[fileFormat] + } + + if (descriptiveLanguage) { + return descriptiveLanguage.split(':')[0] + } + + return 'plaintext' +} diff --git a/src/components/ArtifactsPreview/ArtifactsPreview.jsx b/src/components/ArtifactsPreview/ArtifactsPreview.jsx index 28c9f1bf9a..619df17cf7 100644 --- a/src/components/ArtifactsPreview/ArtifactsPreview.jsx +++ b/src/components/ArtifactsPreview/ArtifactsPreview.jsx @@ -25,7 +25,7 @@ import ArtifactsPreviewView from './ArtifactsPreviewView' import NoData from '../../common/NoData/NoData' import { Loader } from 'igz-controls/components' -const ArtifactsPreview = ({ className = '', noData, preview }) => { +const ArtifactsPreview = ({ className = '', noData, preview, popupButton }) => { const [showErrorBody, setShowErrorBody] = useState(false) const artifactsPreviewClasses = classnames('artifact-preview', className) @@ -44,6 +44,7 @@ const ArtifactsPreview = ({ className = '', noData, preview }) => { preview={previewItem} setShowErrorBody={setShowErrorBody} showErrorBody={showErrorBody} + popupButton={popupButton} /> ))} @@ -66,7 +67,8 @@ ArtifactsPreview.propTypes = { content: PropTypes.any.isRequired }) }) - ).isRequired + ).isRequired, + popupButton: PropTypes.element } export default ArtifactsPreview diff --git a/src/components/ArtifactsPreview/ArtifactsPreviewView.jsx b/src/components/ArtifactsPreview/ArtifactsPreviewView.jsx index 85a61ba9ec..a03521ca61 100644 --- a/src/components/ArtifactsPreview/ArtifactsPreviewView.jsx +++ b/src/components/ArtifactsPreview/ArtifactsPreviewView.jsx @@ -23,6 +23,8 @@ import Prism from 'prismjs' import DetailsResults from '../DetailsResults/DetailsResults' import PreviewError from './PreviewError/PreviewError' +import CodePreview from './CodePreview/CodePreview' +import Download from '../../common/Download/Download' import { Tooltip, TextTooltipTemplate } from 'igz-controls/components' import WarningMessage from '../../common/WarningMessage/WarningMessage' @@ -30,7 +32,13 @@ import { ARTIFACT_PREVIEW_TABLE_ROW_LIMIT, ERROR_STATE, UNKNOWN_STATE } from '.. import './artifactsPreview.scss' -const ArtifactsPreviewView = ({ className, preview, setShowErrorBody, showErrorBody }) => { +const ArtifactsPreviewView = ({ + className, + preview, + setShowErrorBody, + showErrorBody, + popupButton +}) => { const [showWarningMsg, setShowWarningMsg] = useState(true) const content = useMemo( () => @@ -47,7 +55,7 @@ const ArtifactsPreviewView = ({ className, preview, setShowErrorBody, showErrorB {showWarningMsg && preview.warningMsg && ( setShowWarningMsg(false)} /> )} -
+
{preview.header && (
{preview.header}
@@ -113,6 +121,9 @@ const ArtifactsPreviewView = ({ className, preview, setShowErrorBody, showErrorB {preview?.type === 'text' && (
{preview?.data.content}
)} + {preview?.type === 'code' && ( + + )} {preview?.type === 'html' && (