diff --git a/.bitmap b/.bitmap index ac032b39115a..054650e6a7d6 100644 --- a/.bitmap +++ b/.bitmap @@ -195,12 +195,6 @@ "mainFile": "index.ts", "rootDir": "scopes/pipelines/modules/builder-data" }, - "builder-ui": { - "scope": "teambit.pipelines", - "version": "0.0.64", - "mainFile": "index.ts", - "rootDir": "scopes/pipelines/builder-ui" - }, "bundler": { "scope": "teambit.compilation", "version": "0.0.879", @@ -1098,6 +1092,24 @@ "mainFile": "index.ts", "rootDir": "scopes/design/ui/alert-card" }, + "ui/artifacts/artifacts-tree": { + "scope": "", + "version": "", + "mainFile": "index.ts", + "rootDir": "scopes/component/ui/component-artifacts/artifacts-tree" + }, + "ui/artifacts/models/component-artifacts-model": { + "scope": "", + "version": "", + "mainFile": "index.ts", + "rootDir": "scopes/component/ui/component-artifacts/models/component-artifacts-model" + }, + "ui/artifacts/queries/use-component-artifacts": { + "scope": "", + "version": "", + "mainFile": "index.ts", + "rootDir": "scopes/component/ui/component-artifacts/queries/use-component-artifacts" + }, "ui/aspect-box": { "scope": "teambit.harmony", "version": "0.0.492", @@ -1662,42 +1674,6 @@ "mainFile": "index.ts", "rootDir": "scopes/design/ui/pill-label" }, - "ui/pipelines/artifacts-panel": { - "scope": "teambit.component", - "version": "0.0.19", - "mainFile": "index.ts", - "rootDir": "scopes/component/ui/pipelines/artifacts-panel" - }, - "ui/pipelines/component-pipeline": { - "scope": "teambit.component", - "version": "0.0.19", - "mainFile": "index.ts", - "rootDir": "scopes/component/ui/pipelines/component-pipeline" - }, - "ui/pipelines/component-pipeline-context": { - "scope": "teambit.component", - "version": "0.0.8", - "mainFile": "index.ts", - "rootDir": "scopes/component/ui/pipelines/component-pipeline-context" - }, - "ui/pipelines/component-pipeline-model": { - "scope": "teambit.component", - "version": "0.0.8", - "mainFile": "index.ts", - "rootDir": "scopes/component/ui/pipelines/component-pipeline-model" - }, - "ui/pipelines/component-pipeline-queries": { - "scope": "teambit.component", - "version": "0.0.10", - "mainFile": "index.ts", - "rootDir": "scopes/component/ui/pipelines/component-pipeline-queries" - }, - "ui/pipelines/component-pipeline-utils": { - "scope": "teambit.component", - "version": "0.0.7", - "mainFile": "index.ts", - "rootDir": "scopes/component/ui/pipelines/component-pipeline-utils" - }, "ui/preview-placeholder": { "scope": "teambit.preview", "version": "0.0.493", diff --git a/scopes/code/ui/code-tab-page/code-tab-page.tsx b/scopes/code/ui/code-tab-page/code-tab-page.tsx index d5f9f61efd95..1aac5421a3ee 100644 --- a/scopes/code/ui/code-tab-page/code-tab-page.tsx +++ b/scopes/code/ui/code-tab-page/code-tab-page.tsx @@ -21,9 +21,10 @@ import styles from './code-tab-page.module.scss'; type CodePageProps = { fileIconSlot?: FileIconSlot; + host: string; } & HTMLAttributes; -export function CodePage({ className, fileIconSlot }: CodePageProps) { +export function CodePage({ className, fileIconSlot, host }: CodePageProps) { const urlParams = useCodeParams(); const component = useContext(ComponentContext); const { mainFile, fileTree = [], dependencies, devFiles } = useCode(component.id); @@ -52,6 +53,8 @@ export function CodePage({ className, fileIconSlot }: CodePageProps) { >[]; @@ -26,6 +30,8 @@ export function CodeTabTree({ widgets, getHref, getIcon, + host, + componentId, }: CodeTabTreeProps) { const [openDrawerList, onToggleDrawer] = useState(['FILES']); @@ -45,7 +51,7 @@ export function CodeTabTree({ onToggle={() => handleDrawerToggle('FILES')} name="FILES" contentClass={styles.codeDrawerContent} - className={classNames(styles.codeTabDrawer)} + className={classNames(styles.codeTabDrawer, openDrawerList.includes('FILES') && styles.openDrawer)} > handleDrawerToggle('DEPENDENCIES')} - className={classNames(styles.codeTabDrawer)} + className={classNames(styles.codeTabDrawer, openDrawerList.includes('DEPENDENCIES') && styles.openDrawer)} contentClass={styles.codeDrawerContent} name="DEPENDENCIES" > + handleDrawerToggle('ARTIFACTS')} + /> ); } diff --git a/scopes/code/ui/dependency-tree/dependency-drawer/dependency-drawer.module.scss b/scopes/code/ui/dependency-tree/dependency-drawer/dependency-drawer.module.scss index 7b0d074253a9..0458ac270e84 100644 --- a/scopes/code/ui/dependency-tree/dependency-drawer/dependency-drawer.module.scss +++ b/scopes/code/ui/dependency-tree/dependency-drawer/dependency-drawer.module.scss @@ -5,7 +5,9 @@ padding-left: 16px; } } - +.dependencyDrawerContent { + overflow-y: auto; +} .dependencyLink { height: 32px; display: flex; diff --git a/scopes/code/ui/dependency-tree/dependency-drawer/dependency-drawer.tsx b/scopes/code/ui/dependency-tree/dependency-drawer/dependency-drawer.tsx index 444287b9df50..4912eed6496e 100644 --- a/scopes/code/ui/dependency-tree/dependency-drawer/dependency-drawer.tsx +++ b/scopes/code/ui/dependency-tree/dependency-drawer/dependency-drawer.tsx @@ -13,7 +13,13 @@ export type DependencyDrawerProps = { export function DependencyDrawer({ name, isOpen, onToggle, dependencies }: DependencyDrawerProps) { if (!dependencies || dependencies.length === 0) return null; return ( - + ); diff --git a/scopes/component/code/code.ui.runtime.tsx b/scopes/component/code/code.ui.runtime.tsx index f0f85d953044..70d501f7935f 100644 --- a/scopes/component/code/code.ui.runtime.tsx +++ b/scopes/component/code/code.ui.runtime.tsx @@ -1,7 +1,7 @@ import { ComponentAspect, ComponentUI } from '@teambit/component'; import { UIRuntime } from '@teambit/ui'; import React from 'react'; -import { SlotRegistry, Slot } from '@teambit/harmony'; +import { Harmony, SlotRegistry, Slot } from '@teambit/harmony'; import type { FileIconMatch } from '@teambit/code.ui.utils.get-file-icon'; import { staticStorageUrl } from '@teambit/base-ui.constants.storage'; import { CodePage } from '@teambit/code.ui.code-tab-page'; @@ -23,11 +23,12 @@ export class CodeUI { /** * register an icon for a specific file type. pass icon and a match method/regexp */ + private host: string, private fileIconSlot?: FileIconSlot ) {} getCodePage = () => { - return ; + return ; }; registerEnvFileIcon(icons: FileIconMatch[]) { @@ -42,10 +43,13 @@ export class CodeUI { static async provider( [component, componentCompare]: [ComponentUI, ComponentCompareUI], - config, - [fileIconSlot]: [FileIconSlot] + _, + [fileIconSlot]: [FileIconSlot], + harmony: Harmony ) { - const ui = new CodeUI(fileIconSlot); + const { config } = harmony; + const host = String(config.get('teambit.harmony/bit')); + const ui = new CodeUI(host, fileIconSlot); const section = new CodeSection(ui); // overrides the default tsx react icon with the typescript icon ui.registerEnvFileIcon([ diff --git a/scopes/component/ui/component-artifacts/artifacts-tree/artifact-file-node-clicked.ts b/scopes/component/ui/component-artifacts/artifacts-tree/artifact-file-node-clicked.ts new file mode 100644 index 000000000000..ee75f85e7752 --- /dev/null +++ b/scopes/component/ui/component-artifacts/artifacts-tree/artifact-file-node-clicked.ts @@ -0,0 +1,27 @@ +import { ArtifactFile } from '@teambit/component.ui.artifacts.models.component-artifacts-model'; + +export const fileNodeClicked = + (files: (ArtifactFile & { id: string })[], opts: 'download' | 'new tab') => (e, node) => { + const { id } = node; + const artifactFile = files.find((file) => file.id === id); + + if (artifactFile?.downloadUrl) { + fetch(artifactFile.downloadUrl, { method: 'GET' }) + .then((res) => res.blob()) + .then((blob) => { + // create blob link to download + const url = window.URL.createObjectURL(new Blob([blob])); + const link = document.createElement('a'); + link.href = url; + if (opts === 'download') link.setAttribute('download', artifactFile.path); + if (opts === 'new tab') link.setAttribute('target', '_blank'); + // append to html page + document.body.appendChild(link); + // force download + link.click(); + // clean up and remove the link + link.parentNode?.removeChild(link); + }) + .catch(() => {}); + } + }; diff --git a/scopes/component/ui/pipelines/artifacts-panel/artifacts-panel.module.scss b/scopes/component/ui/component-artifacts/artifacts-tree/artifacts-tree.module.scss similarity index 90% rename from scopes/component/ui/pipelines/artifacts-panel/artifacts-panel.module.scss rename to scopes/component/ui/component-artifacts/artifacts-tree/artifacts-tree.module.scss index 6ef3b803fc66..101e71802b64 100644 --- a/scopes/component/ui/pipelines/artifacts-panel/artifacts-panel.module.scss +++ b/scopes/component/ui/component-artifacts/artifacts-tree/artifacts-tree.module.scss @@ -14,9 +14,11 @@ border: none; border-bottom: 1px solid var(--bit-border-color-lightest, #ededed); } +} +.openDrawer { + flex: 1; height: 100%; } - .artifactsPanelCodeDrawerContent { overflow-y: auto; } @@ -39,10 +41,10 @@ pointer-events: auto; } -.artifactsPanelTree { - pointer-events: none; -} - .artifactIconLink { text-decoration: none; } + +.link { + color: var(--bit-accent-color, #6c5ce7); +} diff --git a/scopes/component/ui/component-artifacts/artifacts-tree/artifacts-tree.tsx b/scopes/component/ui/component-artifacts/artifacts-tree/artifacts-tree.tsx new file mode 100644 index 000000000000..a806853a88a6 --- /dev/null +++ b/scopes/component/ui/component-artifacts/artifacts-tree/artifacts-tree.tsx @@ -0,0 +1,140 @@ +import React, { HTMLAttributes, useMemo, useState, useContext } from 'react'; +import classNames from 'classnames'; +import { Icon } from '@teambit/evangelist.elements.icon'; +import { WidgetProps, TreeNode as Node } from '@teambit/ui-foundation.ui.tree.tree-node'; +import { DrawerUI } from '@teambit/ui-foundation.ui.tree.drawer'; +import { FileTree, useFileTreeContext } from '@teambit/ui-foundation.ui.tree.file-tree'; +import { useComponentArtifacts } from '@teambit/component.ui.artifacts.queries.use-component-artifacts'; +import { useLocation } from '@teambit/base-react.navigation.link'; +import { ArtifactFile } from '@teambit/component.ui.artifacts.models.component-artifacts-model'; +import { TreeNode, TreeNodeProps } from '@teambit/design.ui.tree'; +import { TreeContext } from '@teambit/base-ui.graph.tree.tree-context'; +import { ComponentTreeLoader } from '@teambit/design.ui.skeletons.sidebar-loader'; +import { ComponentID } from '@teambit/component-id'; +import { FolderTreeNode } from '@teambit/ui-foundation.ui.tree.folder-tree-node'; +import { fileNodeClicked } from './artifact-file-node-clicked'; + +import styles from './artifacts-tree.module.scss'; + +export type ArtifactsTreeProps = { + getIcon?: (node: TreeNode) => string | undefined; + drawerOpen: boolean; + onToggleDrawer: () => void; + host: string; + componentId: ComponentID; + drawerName: string; +} & HTMLAttributes; + +export function ArtifactsTree({ + getIcon, + host, + componentId, + drawerName, + drawerOpen, + onToggleDrawer, +}: ArtifactsTreeProps) { + const [selected, setSelected] = useState(); + const location = useLocation(); + const { data: artifacts = [], loading } = useComponentArtifacts(host, componentId.toString()); + const hasArtifacts = artifacts.length > 0; + + const [files, artifactFilesTree] = useMemo(() => { + const _files = + (hasArtifacts && + artifacts.flatMap((artifact) => + artifact.files.map((file) => ({ ...file, id: `${artifact.taskName}/${artifact.name}/${file.path}` })) + )) || + []; + + const _artifactFilesTree = _files.map((file) => file.id); + return [_files, _artifactFilesTree]; + }, [artifacts]); + + const payloadMap = + (hasArtifacts && + artifacts.reduce((accum, next) => { + if (!accum.has(next.taskName)) accum.set(`${next.taskName}/`, { open: false }); + return accum; + }, new Map())) || + new Map(); + + const currentHref = location?.pathname || ''; + const getHref = () => currentHref; + const widgets = useMemo(() => [generateWidget(files || [])], [files]); + + if (!hasArtifacts) return null; + + return ( + + {loading && } + {loading || ( + { + setSelected(id); + fileNodeClicked(files, 'new tab')(e, { id }); + }} + /> + )} + + ); +} + +function generateWidget(files: (ArtifactFile & { id: string })[]) { + return function Widget({ node }: WidgetProps) { + const id = node?.id; + const artifactFile = files.find((file) => file.id === id); + if (artifactFile) { + return ( +
+ {/* fileNodeClicked(files, 'new tab')(e, node)} /> */} + { + fileNodeClicked(files, 'download')(e, node); + }} + /> +
+ ); + } + return null; + }; +} + +function FileTreeNode(props: TreeNodeProps) { + const { node } = props; + const fileTreeContext = useFileTreeContext(); + const { selected, onSelect } = useContext(TreeContext); + + const href = fileTreeContext?.getHref?.(node); + const widgets = fileTreeContext?.widgets; + const icon = fileTreeContext?.getIcon?.(node); + + if (!node?.children) { + return ( + onSelect(node.id, e))} + href={href} + isActive={node?.id === selected} + icon={icon} + widgets={widgets} + /> + ); + } + return ; +} diff --git a/scopes/component/ui/component-artifacts/artifacts-tree/index.ts b/scopes/component/ui/component-artifacts/artifacts-tree/index.ts new file mode 100644 index 000000000000..b9460a0c26dd --- /dev/null +++ b/scopes/component/ui/component-artifacts/artifacts-tree/index.ts @@ -0,0 +1 @@ +export { ArtifactsTree, ArtifactsTreeProps } from './artifacts-tree'; diff --git a/scopes/component/ui/component-artifacts/models/component-artifacts-model/component-artifacts.model.ts b/scopes/component/ui/component-artifacts/models/component-artifacts-model/component-artifacts.model.ts new file mode 100644 index 000000000000..a54875ef7467 --- /dev/null +++ b/scopes/component/ui/component-artifacts/models/component-artifacts-model/component-artifacts.model.ts @@ -0,0 +1,30 @@ +export type ArtifactFile = { + name: string; + path: string; + content?: string; + downloadUrl?: string; +}; + +export type Artifact = { + name: string; + taskId: string; + taskName: string; + description?: string; + files: Array; +}; + +export type ComponentArtifactsGQLResponse = Array<{ + taskId: string; + taskName: string; + artifact: Artifact; +}>; + +export function mapToArtifacts(gqlResponse: ComponentArtifactsGQLResponse): Artifact[] { + return gqlResponse + .filter((task) => task.artifact) + .map((task) => ({ + ...task.artifact, + taskId: task.taskId, + taskName: task.taskName, + })); +} diff --git a/scopes/component/ui/component-artifacts/models/component-artifacts-model/index.ts b/scopes/component/ui/component-artifacts/models/component-artifacts-model/index.ts new file mode 100644 index 000000000000..b9daf298222a --- /dev/null +++ b/scopes/component/ui/component-artifacts/models/component-artifacts-model/index.ts @@ -0,0 +1 @@ +export { mapToArtifacts, ArtifactFile, Artifact, ComponentArtifactsGQLResponse } from './component-artifacts.model'; diff --git a/scopes/component/ui/component-artifacts/queries/use-component-artifacts/index.ts b/scopes/component/ui/component-artifacts/queries/use-component-artifacts/index.ts new file mode 100644 index 000000000000..ecbaf80cb532 --- /dev/null +++ b/scopes/component/ui/component-artifacts/queries/use-component-artifacts/index.ts @@ -0,0 +1 @@ +export { useComponentArtifacts } from './use-component-artifacts'; diff --git a/scopes/component/ui/pipelines/component-pipeline-queries/use-component-pipeline.ts b/scopes/component/ui/component-artifacts/queries/use-component-artifacts/use-component-artifacts.ts similarity index 50% rename from scopes/component/ui/pipelines/component-pipeline-queries/use-component-pipeline.ts rename to scopes/component/ui/component-artifacts/queries/use-component-artifacts/use-component-artifacts.ts index 3e3c7d6cecbb..37930499f836 100644 --- a/scopes/component/ui/pipelines/component-pipeline-queries/use-component-pipeline.ts +++ b/scopes/component/ui/component-artifacts/queries/use-component-artifacts/use-component-artifacts.ts @@ -1,9 +1,9 @@ import { gql } from '@apollo/client'; import { useDataQuery, DataQueryResult } from '@teambit/ui-foundation.ui.hooks.use-data-query'; -import { TaskReport } from '@teambit/component.ui.pipelines.component-pipeline-model'; +import { mapToArtifacts, Artifact } from '@teambit/component.ui.artifacts.models.component-artifacts-model'; -const PIPELINE_REPORT_QUERY = gql` - query ComponentPipeline($id: String!, $extensionId: String!, $taskId: String) { +const ARTIFACTS_QUERY = gql` + query ComponentArtifacts($id: String!, $extensionId: String!) { getHost(id: $extensionId) { id # used for GQL caching get(id: $id) { @@ -12,15 +12,10 @@ const PIPELINE_REPORT_QUERY = gql` version scope } - pipelineReport(taskId: $taskId) { + pipelineReport { id taskId taskName - description - startTime - endTime - errors - warnings artifact { id name @@ -33,22 +28,23 @@ const PIPELINE_REPORT_QUERY = gql` } } } - buildStatus } } } `; -export function useComponentPipelineQuery( +export function useComponentArtifacts( host: string, componentId: string -): DataQueryResult<{ tasks: TaskReport[]; buildStatus?: string }, { id: string; extensionId: string }> { - const { data, ...rest } = useDataQuery(PIPELINE_REPORT_QUERY, { +): DataQueryResult { + const { data, ...rest } = useDataQuery(ARTIFACTS_QUERY, { variables: { id: componentId, extensionId: host }, }); + const artifacts = mapToArtifacts(data?.getHost?.get?.pipelineReport || []); + return { ...rest, - data: { tasks: data?.getHost?.get?.pipelineReport || [], buildStatus: data?.getHost?.get?.buildStatus }, + data: artifacts, }; } diff --git a/scopes/component/ui/pipelines/artifacts-panel/artifacts-panel.tsx b/scopes/component/ui/pipelines/artifacts-panel/artifacts-panel.tsx deleted file mode 100644 index d1a1f41c495a..000000000000 --- a/scopes/component/ui/pipelines/artifacts-panel/artifacts-panel.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React, { HTMLAttributes, useState, useMemo } from 'react'; -import classNames from 'classnames'; -import { EmptyBox } from '@teambit/design.ui.empty-box'; -import { Icon } from '@teambit/evangelist.elements.icon'; -import { WidgetProps } from '@teambit/ui-foundation.ui.tree.tree-node'; -import { DrawerUI } from '@teambit/ui-foundation.ui.tree.drawer'; -import { FileTree } from '@teambit/ui-foundation.ui.tree.file-tree'; -import { useComponentPipelineContext } from '@teambit/component.ui.pipelines.component-pipeline-context'; -import { ArtifactFile } from '@teambit/component.ui.pipelines.component-pipeline-model'; -import { useLocation } from '@teambit/base-react.navigation.link'; -import { generateIcon } from '@teambit/code.ui.code-tab-page'; -import { FileIconMatch } from '@teambit/code.ui.utils.get-file-icon'; - -import styles from './artifacts-panel.module.scss'; - -export type ArtifactsPanelProps = { - fileIconMatchers: FileIconMatch[]; -} & HTMLAttributes; - -export function ArtifactPanel({ className, fileIconMatchers }: ArtifactsPanelProps) { - const [drawerOpen, onToggleDrawer] = useState(true); - const componentPipelineContext = useComponentPipelineContext(); - const location = useLocation(); - - if (!componentPipelineContext) return null; - - const { pipeline, selectedPipelineId } = componentPipelineContext; - const { artifact, taskName } = pipeline.find((task) => task.id === selectedPipelineId) || {}; - const { name, files } = artifact || {}; - const artifactFiles = files?.map((file) => file.path) || []; - const currentHref = location?.pathname || ''; - const drawerName = `${taskName} ${name ? '/ '.concat(name) : ''}`; - const onToggle = () => onToggleDrawer((open) => !open); - const getIcon = useMemo(() => generateIcon(fileIconMatchers), [fileIconMatchers]); - const getHref = () => currentHref; - const widgets = useMemo(() => [generateWidget(files || [])], [files]); - - return ( -
- - {artifactFiles.length > 0 && ( - - )} - {artifactFiles.length === 0 && ( - - )} - -
- ); -} - -const fileNodeClicked = (files: ArtifactFile[], opts: 'download' | 'new tab') => (_, node) => { - const { id } = node; - const artifactFile = files.find((file) => file.path === id); - - if (artifactFile?.downloadUrl) { - fetch(artifactFile.downloadUrl, { method: 'GET' }) - .then((res) => res.blob()) - .then((blob) => { - // create blob link to download - const url = window.URL.createObjectURL(new Blob([blob])); - const link = document.createElement('a'); - link.href = url; - if (opts === 'download') link.setAttribute('download', artifactFile.path); - if (opts === 'new tab') link.setAttribute('target', '_blank'); - // append to html page - document.body.appendChild(link); - // force download - link.click(); - // clean up and remove the link - link.parentNode?.removeChild(link); - }) - .catch(() => {}); - } -}; - -function generateWidget(files: ArtifactFile[]) { - return function Widget({ node }: WidgetProps) { - const filePath = node?.id; - const artifactFile = files.find((file) => file.path === filePath); - if (artifactFile) { - return ( -
- fileNodeClicked(files, 'new tab')(e, node)} /> - fileNodeClicked(files, 'download')(e, node)} /> -
- ); - } - return null; - }; -} diff --git a/scopes/component/ui/pipelines/artifacts-panel/index.ts b/scopes/component/ui/pipelines/artifacts-panel/index.ts deleted file mode 100644 index d37dd2f2ae34..000000000000 --- a/scopes/component/ui/pipelines/artifacts-panel/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ArtifactPanel, ArtifactsPanelProps } from './artifacts-panel'; diff --git a/scopes/component/ui/pipelines/component-pipeline-context/component-pipeline.context.tsx b/scopes/component/ui/pipelines/component-pipeline-context/component-pipeline.context.tsx deleted file mode 100644 index d917334e8065..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline-context/component-pipeline.context.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { createContext, useContext } from 'react'; -import { ComponentPipelineModel } from '@teambit/component.ui.pipelines.component-pipeline-model'; - -export type ComponentPipelineContextModel = ComponentPipelineModel & { - selectedPipelineId?: string; - setSelectedPipelineId: React.Dispatch>; -}; - -export const ComponentPipelineContext = createContext(undefined); - -export const useComponentPipelineContext: () => ComponentPipelineContextModel | undefined = () => { - const componentPipelineContext = useContext(ComponentPipelineContext); - return componentPipelineContext; -}; diff --git a/scopes/component/ui/pipelines/component-pipeline-context/index.ts b/scopes/component/ui/pipelines/component-pipeline-context/index.ts deleted file mode 100644 index 254ee47b2ed9..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline-context/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { - ComponentPipelineContextModel, - ComponentPipelineContext, - useComponentPipelineContext, -} from './component-pipeline.context'; diff --git a/scopes/component/ui/pipelines/component-pipeline-model/component-pipeline.model.ts b/scopes/component/ui/pipelines/component-pipeline-model/component-pipeline.model.ts deleted file mode 100644 index 6d455456a94e..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline-model/component-pipeline.model.ts +++ /dev/null @@ -1,28 +0,0 @@ -export type ArtifactFile = { - name: string; - path: string; - content?: string; - downloadUrl?: string; -}; - -export type Artifact = { - name: string; - description?: string; - files: Array; -}; - -export type TaskReport = { - id: string; - taskId: string; - taskName: string; - description?: string; - errors: Array; - warnings: Array; - startTime?: number; - endTime?: number; - artifact: Artifact; -}; - -export type ComponentPipelineModel = { - pipeline: TaskReport[]; -}; diff --git a/scopes/component/ui/pipelines/component-pipeline-model/index.ts b/scopes/component/ui/pipelines/component-pipeline-model/index.ts deleted file mode 100644 index fc3ecf5abc55..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline-model/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ComponentPipelineModel, ArtifactFile, TaskReport, Artifact } from './component-pipeline.model'; diff --git a/scopes/component/ui/pipelines/component-pipeline-queries/index.ts b/scopes/component/ui/pipelines/component-pipeline-queries/index.ts deleted file mode 100644 index 38c31f2e7867..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline-queries/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useComponentPipelineQuery } from './use-component-pipeline'; diff --git a/scopes/component/ui/pipelines/component-pipeline-utils/index.ts b/scopes/component/ui/pipelines/component-pipeline-utils/index.ts deleted file mode 100644 index ab241abf400a..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline-utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { calcSeconds, calcMilliseconds, calcDuration } from './utils'; diff --git a/scopes/component/ui/pipelines/component-pipeline-utils/utils.ts b/scopes/component/ui/pipelines/component-pipeline-utils/utils.ts deleted file mode 100644 index 2a9162103ad2..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline-utils/utils.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function calcDuration(startTime?: number, endTime?: number): number { - return (endTime || 0) - (startTime || 0); -} - -export function calcSeconds(duration: number): number { - return Math.floor(duration / 1000); -} - -export function calcMilliseconds(duration: number): number { - return duration % 1000; -} diff --git a/scopes/component/ui/pipelines/component-pipeline/blank-state/blank-state.tsx b/scopes/component/ui/pipelines/component-pipeline/blank-state/blank-state.tsx deleted file mode 100644 index f48cc3873901..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline/blank-state/blank-state.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { HTMLAttributes } from 'react'; -import { EmptyBox } from '@teambit/design.ui.empty-box'; - -export type ComponentPipelineBlankStateProps = {} & HTMLAttributes; - -export function ComponentPipelineBlankState({ className }: ComponentPipelineBlankStateProps) { - return ( - - ); -} diff --git a/scopes/component/ui/pipelines/component-pipeline/blank-state/index.ts b/scopes/component/ui/pipelines/component-pipeline/blank-state/index.ts deleted file mode 100644 index eb23ad047501..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline/blank-state/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ComponentPipelineBlankState, ComponentPipelineBlankStateProps } from './blank-state'; diff --git a/scopes/component/ui/pipelines/component-pipeline/component-pipeline-page.module.scss b/scopes/component/ui/pipelines/component-pipeline/component-pipeline-page.module.scss deleted file mode 100644 index 16bd923a6286..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline/component-pipeline-page.module.scss +++ /dev/null @@ -1,40 +0,0 @@ -.page { - display: flex; - flex-direction: column; - height: 100%; - padding: 24px; - - h2 { - margin-bottom: 24px; - } -} -.graphContainer { - display: flex; - flex-direction: column; - height: 100%; -} - -.graph { - flex-grow: 1; - height: 100%; - width: 100%; - - border-radius: 5px; - border: solid 1px var(--bit-border-color-lightest, #ededed); - background: var(--bit-bg-dent, #f6f6f6); -} - -.statContainer { - display: flex; - margin-bottom: 24px; -} - -.statItem { - padding-left: 8px; - padding-right: 8px; -} - -.statTitle { - font-size: var(--bit-p-xxs); - color: #6c707c; -} diff --git a/scopes/component/ui/pipelines/component-pipeline/component-pipeline-page.tsx b/scopes/component/ui/pipelines/component-pipeline/component-pipeline-page.tsx deleted file mode 100644 index 0d5727fce4fd..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline/component-pipeline-page.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { ComponentContext } from '@teambit/component'; -import { H2 } from '@teambit/documenter.ui.heading'; -import React, { useContext, useMemo, useState } from 'react'; -import { FileIconMatch } from '@teambit/code.ui.utils.get-file-icon'; -import { useComponentPipelineQuery } from '@teambit/component.ui.pipelines.component-pipeline-queries'; -import { ArtifactPanel } from '@teambit/component.ui.pipelines.artifacts-panel'; -import { ComponentPipelineContext } from '@teambit/component.ui.pipelines.component-pipeline-context'; -import { SplitPane, Pane, Layout } from '@teambit/base-ui.surfaces.split-pane.split-pane'; -import ReactFlow, { - ArrowHeadType, - Background, - Controls, - Edge, - Node, - ReactFlowProvider, - NodeTypesType, -} from 'react-flow-renderer'; -import { HoverSplitter } from '@teambit/base-ui.surfaces.split-pane.hover-splitter'; -import { calcDuration, calcMilliseconds, calcSeconds } from '@teambit/component.ui.pipelines.component-pipeline-utils'; -import { PipelineNode } from './pipeline-node'; -import { ComponentPipelineBlankState } from './blank-state'; - -import styles from './component-pipeline-page.module.scss'; - -export type ComponentPipelinePageProps = { - host: string; - fileIconMatchers: FileIconMatch[]; -}; - -export function ComponentPipelinePage({ host, fileIconMatchers }: ComponentPipelinePageProps) { - const component = useContext(ComponentContext); - const { data } = useComponentPipelineQuery(host, component.id.toString()); - - const nodes = useMemo(() => { - if (!data) return []; - - const { tasks = [] } = data; - return tasks.map((task, index) => { - const duration = calcDuration(task.startTime, task.endTime); - return { - id: task.id, - type: 'artifactNode', - data: { - ...task, - duration, - }, - position: { x: 50 + index * 300, y: 300 }, - } as Node; - }); - }, [data]); - - const edges = useMemo(() => { - if (!nodes || nodes.length < 2) { - return []; - } - - const _edges: Array = []; - - for (let i = 1; i < nodes.length; i += 1) { - const edge: Edge = { - id: `${nodes[i - 1].id}_${nodes[i].id}`, - source: nodes[i - 1].id, - target: nodes[i].id, - arrowHeadType: ArrowHeadType.Arrow, - }; - _edges.push(edge); - } - return _edges; - }, [nodes]); - - const elements = [...nodes, ...edges]; - - const totalDurationSecs = useMemo(() => { - if (!data) return 0; - - const { tasks } = data; - return tasks.reduce((agg, cur) => { - return agg + calcDuration(cur.startTime, cur.endTime); - }, 0); - }, [data]); - - const NodeTypes: NodeTypesType = { - artifactNode: PipelineNode, - }; - - const [selectedPipelineId, setSelectedPipelineId] = useState(undefined); - const sidebarOpenness = selectedPipelineId ? Layout.row : Layout.left; - const showBlankState = elements.length === 0; - const onPanelClicked = () => { - setSelectedPipelineId(undefined); - }; - - return ( - - -
-

Pipeline

- {!showBlankState && ( -
-
-

Duration

-

- {calcSeconds(totalDurationSecs)}s {calcMilliseconds(totalDurationSecs)}ms -

-
-
-

Status

-

{data?.buildStatus}

-
-
- )} - - - {!showBlankState && ( - - - - - )} - {showBlankState && } - - {(selectedPipelineId && ) || <>} - {(selectedPipelineId && ( - - - - )) || <>} - -
-
-
- ); -} diff --git a/scopes/component/ui/pipelines/component-pipeline/index.ts b/scopes/component/ui/pipelines/component-pipeline/index.ts deleted file mode 100644 index 68d293314792..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { ComponentPipelinePage, ComponentPipelinePageProps } from './component-pipeline-page'; -export { PipelineNode, PipelineNodeProps } from './pipeline-node'; -export { ComponentPipelineBlankState, ComponentPipelineBlankStateProps } from './blank-state'; diff --git a/scopes/component/ui/pipelines/component-pipeline/pipeline-node/index.ts b/scopes/component/ui/pipelines/component-pipeline/pipeline-node/index.ts deleted file mode 100644 index 9fcf2ca02ed0..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline/pipeline-node/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { PipelineNode, PipelineNodeProps } from './pipeline-node'; diff --git a/scopes/component/ui/pipelines/component-pipeline/pipeline-node/pipeline-node.module.scss b/scopes/component/ui/pipelines/component-pipeline/pipeline-node/pipeline-node.module.scss deleted file mode 100644 index 0b3385ae24dd..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline/pipeline-node/pipeline-node.module.scss +++ /dev/null @@ -1,87 +0,0 @@ -.pipelineNode { - max-width: 300px; - min-width: 200px; - border-width: 2px; - border-style: solid; - padding: 12px; - - text-align: left; - - &.selected { - background: var(--bit-accent-bg, #eceaff); - } - &.error { - background: var(--bit-error-bg, #fdedd2); - } -} -.taskId { - margin-left: 5px; -} - -// component icon -.componentDetails { - display: flex; - align-items: center; - justify-content: space-between; - - .status { - text-transform: capitalize; - font-size: 10px; - color: var(--bit-accent-color); - } -} - -// breakcrumbs -.breadcrumbs { - color: #6c707c; - font-size: 12px; -} - -// component name -.componentName { - display: flex; - align-items: center; - flex-wrap: wrap; - color: var(--bit-text-color-heavy, #2b2b2b); - justify-content: 'space-between'; - - > div { - display: flex; - align-items: center; - flex-wrap: nowrap; - min-width: 0; - - > span { - padding-top: 1px; - margin: 0 4px; - } - } -} - -.name { - color: inherit; - font-weight: bold; - margin-right: 8px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - pointer-events: none; - text-decoration: none; - - &.link { - pointer-events: auto; - - &:hover { - text-decoration: underline; - } - } -} - -.version { - min-width: 40px; - text-align: center; -} - -.componentDetailsContainer { - display: flex; -} diff --git a/scopes/component/ui/pipelines/component-pipeline/pipeline-node/pipeline-node.tsx b/scopes/component/ui/pipelines/component-pipeline/pipeline-node/pipeline-node.tsx deleted file mode 100644 index a711b86420ba..000000000000 --- a/scopes/component/ui/pipelines/component-pipeline/pipeline-node/pipeline-node.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; -import { Card } from '@teambit/base-ui.surfaces.card'; -import { ellipsis } from '@teambit/design.ui.styles.ellipsis'; -import classNames from 'classnames'; -import { useComponentPipelineContext } from '@teambit/component.ui.pipelines.component-pipeline-context'; -import { TaskReport } from '@teambit/component.ui.pipelines.component-pipeline-model'; -import { calcMilliseconds, calcSeconds } from '@teambit/component.ui.pipelines.component-pipeline-utils'; -import { Handle, NodeProps, Position } from 'react-flow-renderer'; -import styles from './pipeline-node.module.scss'; - -export type PipelineNodeProps = NodeProps; - -export function PipelineNode(props: PipelineNodeProps) { - const { - id, - isConnectable, - data: { taskId, taskName, duration, warnings, errors }, - } = props; - const icon = 'https://static.bit.dev/extensions-icons/react.svg'; - const componentPipelineContext = useComponentPipelineContext(); - const isSelected = componentPipelineContext?.selectedPipelineId === id; - const onPipelineNodeClicked = () => { - const updatedId = isSelected ? undefined : id; - componentPipelineContext?.setSelectedPipelineId(updatedId); - }; - const showErrorStatus = errors.length > 0; - const showWarningStaus = !showErrorStatus && warnings.length > 0; - const Pipeline = ( -
- - - -
-
{}
-
-
{taskId}
-
-
-
-
{taskName}
-
- {calcSeconds(duration)}s {calcMilliseconds(duration)}ms -
-
-
-
- ); - - return Pipeline; -} - -export default PipelineNode; diff --git a/scopes/harmony/bit/manifests.ts b/scopes/harmony/bit/manifests.ts index 615becf6c050..3b38007fa957 100644 --- a/scopes/harmony/bit/manifests.ts +++ b/scopes/harmony/bit/manifests.ts @@ -89,7 +89,6 @@ import { IssuesAspect } from '@teambit/issues'; import { RefactoringAspect } from '@teambit/refactoring'; import { ComponentCompareAspect } from '@teambit/component-compare'; import { ListerAspect } from '@teambit/lister'; -import { BuilderUIAspect } from '@teambit/builder-ui'; import { DependenciesAspect } from '@teambit/dependencies'; import { RemoveAspect } from '@teambit/remove'; import { MergeLanesAspect } from '@teambit/merge-lanes'; @@ -187,7 +186,6 @@ export const manifestsMap = { [RefactoringAspect.id]: RefactoringAspect, [ComponentCompareAspect.id]: ComponentCompareAspect, [ListerAspect.id]: ListerAspect, - [BuilderUIAspect.id]: BuilderUIAspect, [DependenciesAspect.id]: DependenciesAspect, [RemoveAspect.id]: RemoveAspect, [MergeLanesAspect.id]: MergeLanesAspect, diff --git a/scopes/pipelines/builder-ui/builder-ui.aspect.ts b/scopes/pipelines/builder-ui/builder-ui.aspect.ts deleted file mode 100644 index 428be07d481c..000000000000 --- a/scopes/pipelines/builder-ui/builder-ui.aspect.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Aspect } from '@teambit/harmony'; - -export const BuilderUIAspect = Aspect.create({ - id: 'teambit.pipelines/builder-ui', -}); diff --git a/scopes/pipelines/builder-ui/builder.section.tsx b/scopes/pipelines/builder-ui/builder.section.tsx deleted file mode 100644 index 1b160a85c510..000000000000 --- a/scopes/pipelines/builder-ui/builder.section.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Section } from '@teambit/component'; -import React from 'react'; -import { ComponentPipelinePage } from '@teambit/component.ui.pipelines.component-pipeline'; -import { ComponentPipelineWidget } from './component-pipeline-widget'; -import { BuilderUI } from './builder.ui.runtime'; - -export class BuilderSection implements Section { - constructor(private host: string, private builderUi: BuilderUI) {} - - route = { - path: '~component-pipeline', - element: , - }; - - navigationLink = { - href: '~component-pipeline', - children: , - }; - - order = 50; -} diff --git a/scopes/pipelines/builder-ui/builder.ui.runtime.tsx b/scopes/pipelines/builder-ui/builder.ui.runtime.tsx deleted file mode 100644 index 3fd20fcb2440..000000000000 --- a/scopes/pipelines/builder-ui/builder.ui.runtime.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { ComponentAspect, ComponentUI } from '@teambit/component'; -import { UIRuntime } from '@teambit/ui'; -import { staticStorageUrl } from '@teambit/base-ui.constants.storage'; -import { Harmony, Slot, SlotRegistry } from '@teambit/harmony'; -import flatten from 'lodash.flatten'; -import type { FileIconMatch } from '@teambit/code.ui.utils.get-file-icon'; -import { BuilderSection } from './builder.section'; -import { BuilderUIAspect } from './builder-ui.aspect'; - -const isTsx = /\.tsx$/; - -export type FileIconSlot = SlotRegistry; - -export class BuilderUI { - constructor( - /** - * register an icon for a specific file type. pass icon and a match method/regexp - */ - private fileIconSlot?: FileIconSlot - ) {} - - registerEnvFileIcon(icons: FileIconMatch[]) { - this.fileIconSlot?.register(icons); - return this; - } - - getFileIconMatchers(): FileIconMatch[] { - return flatten(this.fileIconSlot?.values()); - } - - static dependencies = [ComponentAspect]; - - static runtime = UIRuntime; - static slots = [Slot.withType()]; - - static async provider([component]: [ComponentUI], _, __, harmony: Harmony) { - const ui = new BuilderUI(); - // overrides the default tsx react icon with the typescript icon - ui.registerEnvFileIcon([ - (fileName) => (isTsx.test(fileName) ? `${staticStorageUrl}/file-icons/file_type_typescript.svg` : undefined), - ]); - - const { config } = harmony; - const host = String(config.get('teambit.harmony/bit')); - - const section = new BuilderSection(host, ui); - - component.registerRoute(section.route); - // component.registerWidget(section.navigationLink, section.order); - - return ui; - } -} - -BuilderUIAspect.addRuntime(BuilderUI); diff --git a/scopes/pipelines/builder-ui/component-pipeline-widget/component-pipeline-widget.module.scss b/scopes/pipelines/builder-ui/component-pipeline-widget/component-pipeline-widget.module.scss deleted file mode 100644 index 11d7a608062c..000000000000 --- a/scopes/pipelines/builder-ui/component-pipeline-widget/component-pipeline-widget.module.scss +++ /dev/null @@ -1,10 +0,0 @@ -.widgetMenuIcon { - display: flex; - justify-content: center; - align-items: center; - - img { - height: 16px; - width: 16px; - } -} diff --git a/scopes/pipelines/builder-ui/component-pipeline-widget/component-pipeline-widget.tsx b/scopes/pipelines/builder-ui/component-pipeline-widget/component-pipeline-widget.tsx deleted file mode 100644 index 55081a7e0eaf..000000000000 --- a/scopes/pipelines/builder-ui/component-pipeline-widget/component-pipeline-widget.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React, { HTMLAttributes } from 'react'; -import classNames from 'classnames'; -import { Tooltip } from '@teambit/design.ui.tooltip'; -import styles from './component-pipeline-widget.module.scss'; - -export type ComponentPipelineWidgetProps = {} & HTMLAttributes; - -export function ComponentPipelineWidget({ className, ...rest }: ComponentPipelineWidgetProps) { - return ( - -
- -
-
- ); -} diff --git a/scopes/pipelines/builder-ui/component-pipeline-widget/index.ts b/scopes/pipelines/builder-ui/component-pipeline-widget/index.ts deleted file mode 100644 index dd2dbcf0d76a..000000000000 --- a/scopes/pipelines/builder-ui/component-pipeline-widget/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { ComponentPipelineWidget } from './component-pipeline-widget'; -export type { ComponentPipelineWidgetProps } from './component-pipeline-widget'; diff --git a/scopes/pipelines/builder-ui/index.ts b/scopes/pipelines/builder-ui/index.ts deleted file mode 100644 index a4fb8f81889e..000000000000 --- a/scopes/pipelines/builder-ui/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { BuilderUIAspect } from './builder-ui.aspect'; - -export { BuilderUIAspect } from './builder-ui.aspect'; -export type { BuilderUI } from './builder.ui.runtime'; -export default BuilderUIAspect; diff --git a/scopes/ui-foundation/tree/drawer/drawer.module.scss b/scopes/ui-foundation/tree/drawer/drawer.module.scss index deff86d7ac94..811ca5c437df 100644 --- a/scopes/ui-foundation/tree/drawer/drawer.module.scss +++ b/scopes/ui-foundation/tree/drawer/drawer.module.scss @@ -18,8 +18,9 @@ user-select: none; font-weight: bold; padding: 0 8px; - + line-height: 1.2em; transition: background-color 300ms, border-color 300ms ease-in-out; + &:hover { border-color: var(--bit-bg-heavy, #f6f6f6); background: var(--bit-bg-heavy, #f6f6f6); @@ -72,6 +73,7 @@ flex: 1 1; transition: max-height 300ms ease-in-out; max-height: 0; + line-height: 1.2em; &.open { max-height: calc(100% - 32px); diff --git a/scopes/ui-foundation/tree/file-tree/file-tree.node.tsx b/scopes/ui-foundation/tree/file-tree/file-tree.node.tsx index d64e46130e05..3d74c23999e5 100644 --- a/scopes/ui-foundation/tree/file-tree/file-tree.node.tsx +++ b/scopes/ui-foundation/tree/file-tree/file-tree.node.tsx @@ -8,14 +8,23 @@ import { useFileTreeContext } from './file-tree.context'; export function FileTreeNode(props: TreeNodeProps) { const { node } = props; const fileTreeContext = useFileTreeContext(); - const { selected } = useContext(TreeContext); + const { selected, onSelect } = useContext(TreeContext); const href = fileTreeContext?.getHref?.(node); const widgets = fileTreeContext?.widgets; const icon = fileTreeContext?.getIcon?.(node); if (!node?.children) { - return ; + return ( + onSelect(node.id, e))} + href={href} + isActive={node?.id === selected} + icon={icon} + widgets={widgets} + /> + ); } return ; } diff --git a/scopes/ui-foundation/tree/file-tree/file-tree.tsx b/scopes/ui-foundation/tree/file-tree/file-tree.tsx index 1d13fe29caf0..87722676dcaf 100644 --- a/scopes/ui-foundation/tree/file-tree/file-tree.tsx +++ b/scopes/ui-foundation/tree/file-tree/file-tree.tsx @@ -1,5 +1,5 @@ import React, { useMemo, HTMLAttributes, ComponentType } from 'react'; -import { inflateToTree } from '@teambit/base-ui.graph.tree.inflate-paths'; +import { inflateToTree, attachPayload } from '@teambit/base-ui.graph.tree.inflate-paths'; import { TreeContextProvider } from '@teambit/base-ui.graph.tree.tree-context'; import { indentStyle } from '@teambit/base-ui.graph.tree.indent'; import { RootNode } from '@teambit/base-ui.graph.tree.root-node'; @@ -10,9 +10,10 @@ import { FileTreeNode } from './file-tree.node'; import { FileTreeContext } from './file-tree.context'; type FileTreeProps = { - onSelect?: (id: string, event?: React.MouseEvent) => void; + onTreeNodeSelected?: (id: string, event?: React.MouseEvent) => void; selected?: string; files: string[]; + payloadMap?: Map; widgets?: ComponentType>[]; getHref?: (node: TreeNode) => string; getIcon?: (node: TreeNode) => string | undefined; @@ -24,11 +25,12 @@ type FileTreeProps = { */ export function FileTree({ files, - onSelect, + onTreeNodeSelected, selected, getIcon, getHref, widgets, + payloadMap, TreeNode: CustomTreeNode = FileTreeNode, ...rest }: FileTreeProps) { @@ -36,6 +38,7 @@ export function FileTree({ // make sure that Windows paths are converted to posix const filePaths = files.map((f) => f.replace(/\\/g, '/')); const tree = inflateToTree(filePaths, (c) => c); + payloadMap && attachPayload(tree, payloadMap); return tree; }, [files]); @@ -43,7 +46,7 @@ export function FileTree({
- + diff --git a/scopes/ui-foundation/tree/file-tree/index.ts b/scopes/ui-foundation/tree/file-tree/index.ts index c2118f82436f..7a42ad6371ef 100644 --- a/scopes/ui-foundation/tree/file-tree/index.ts +++ b/scopes/ui-foundation/tree/file-tree/index.ts @@ -1 +1,2 @@ +export { useFileTreeContext } from './file-tree.context'; export { FileTree } from './file-tree'; diff --git a/scopes/ui-foundation/tree/folder-tree-node/folder-tree-node.module.scss b/scopes/ui-foundation/tree/folder-tree-node/folder-tree-node.module.scss index 70eb8580b176..9948fc680569 100644 --- a/scopes/ui-foundation/tree/folder-tree-node/folder-tree-node.module.scss +++ b/scopes/ui-foundation/tree/folder-tree-node/folder-tree-node.module.scss @@ -9,6 +9,7 @@ user-select: none; font-weight: bold; font-size: inherit; + line-height: 1.2em; padding-right: 8px; font-size: var(--bit-p-xs); user-select: none; diff --git a/scopes/ui-foundation/tree/tree-node/tree-node.module.scss b/scopes/ui-foundation/tree/tree-node/tree-node.module.scss index 0d1e4f6fe5a6..66484cf6bd01 100644 --- a/scopes/ui-foundation/tree/tree-node/tree-node.module.scss +++ b/scopes/ui-foundation/tree/tree-node/tree-node.module.scss @@ -8,7 +8,7 @@ padding-right: 8px; font-size: inherit; font-size: var(--bit-p-xs); - + line-height: 1.2em; //TODO - move to a link component text-decoration: none; color: inherit; diff --git a/scopes/ui-foundation/tree/tree-node/tree-node.tsx b/scopes/ui-foundation/tree/tree-node/tree-node.tsx index 1e98880c8ec1..8e90fb56d5ab 100644 --- a/scopes/ui-foundation/tree/tree-node/tree-node.tsx +++ b/scopes/ui-foundation/tree/tree-node/tree-node.tsx @@ -15,6 +15,7 @@ export type TreeNodeComponentProps = { icon?: string; onClick?: (e: React.MouseEvent) => void; href?: string; + className?: string; } & TreeNodeProps; /** @@ -22,7 +23,7 @@ export type TreeNodeComponentProps = { * Renders a file node in the file tree */ export function TreeNode(props: TreeNodeComponentProps) { - const { node, isActive, icon, onClick, widgets, href } = props; + const { node, isActive, icon, onClick, widgets, href, className } = props; return ( (props: TreeNodeComponentProps) { active={isActive} exact strict - className={classNames(indentClass, styles.fileNode)} + className={classNames(indentClass, styles.fileNode, className)} activeClassName={styles.active} - onClick={onClick} > -
+
{icon && } {node.id.split('/').pop()}