diff --git a/docs/assets/title-and-description-markdown-cluster-workflow-template.png b/docs/assets/title-and-description-markdown-cluster-workflow-template.png new file mode 100644 index 000000000000..7f8b31aba6df Binary files /dev/null and b/docs/assets/title-and-description-markdown-cluster-workflow-template.png differ diff --git a/docs/assets/workflow-title-and-description-markdown-complex.png b/docs/assets/title-and-description-markdown-complex-workflow.png similarity index 100% rename from docs/assets/workflow-title-and-description-markdown-complex.png rename to docs/assets/title-and-description-markdown-complex-workflow.png diff --git a/docs/assets/title-and-description-markdown-cron-workflow.png b/docs/assets/title-and-description-markdown-cron-workflow.png new file mode 100644 index 000000000000..99ccd921fcb1 Binary files /dev/null and b/docs/assets/title-and-description-markdown-cron-workflow.png differ diff --git a/docs/assets/title-and-description-markdown-workflow-template.png b/docs/assets/title-and-description-markdown-workflow-template.png new file mode 100644 index 000000000000..f8564afaac5d Binary files /dev/null and b/docs/assets/title-and-description-markdown-workflow-template.png differ diff --git a/docs/assets/workflow-title-and-description-markdown.png b/docs/assets/title-and-description-markdown-workflow.png similarity index 100% rename from docs/assets/workflow-title-and-description-markdown.png rename to docs/assets/title-and-description-markdown-workflow.png diff --git a/docs/assets/workflow-title-and-description.png b/docs/assets/title-and-description-workflow.png similarity index 100% rename from docs/assets/workflow-title-and-description.png rename to docs/assets/title-and-description-workflow.png diff --git a/docs/title-and-description.md b/docs/title-and-description.md index 9d49082e6a0b..3e236be266af 100644 --- a/docs/title-and-description.md +++ b/docs/title-and-description.md @@ -15,7 +15,7 @@ metadata: ``` The above manifest will render as a row like the below image: -![Title and Description Example](assets/workflow-title-and-description.png) +![Title and Description Example](assets/title-and-description-workflow.png) ## Embedded Markdown @@ -34,7 +34,7 @@ metadata: ``` The above manifest will render as a row like the below image: -![Markdown Example](assets/workflow-title-and-description-markdown.png) +![Markdown Example](assets/title-and-description-markdown-workflow.png) Below are a few more examples: @@ -76,4 +76,67 @@ metadata: ``` The above examples will render as rows like the below image: -![More Markdown Examples](assets/workflow-title-and-description-markdown-complex.png) +![More Markdown Examples](assets/title-and-description-markdown-complex-workflow.png) + +### For `ClusterWorkflowTemplates` + +> v3.6 and after + +You can also add the `workflows.argoproj.io/title` and `workflows.argoproj.io/description` annotations with embedded markdown to a `ClusterWorkflowTemplate` to display in the list: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: ClusterWorkflowTemplate +metadata: + name: my-cluster-workflow-template + annotations: + workflows.argoproj.io/title: '**Test Title**' + workflows.argoproj.io/description: | + `This is a simple hello world example.` + You can also run it in Python: https://couler-proj.github.io/couler/examples/#hello-world +``` + +The above manifest will render as a row like the below image: +![ClusterWorkflowTemplate Example](assets/title-and-description-markdown-cluster-workflow-template.png) + +### For `CronWorkflows` + +> v3.6 and after + +You can also add the `workflows.argoproj.io/title` and `workflows.argoproj.io/description` annotations with embedded markdown to a `CronWorkflow` to display in the list: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: CronWorkflow +metadata: + name: my-cron-workflow + annotations: + workflows.argoproj.io/title: '**Test Title**' + workflows.argoproj.io/description: | + `This is a simple hello world example.` + You can also run it in Python: https://couler-proj.github.io/couler/examples/#hello-world +``` + +The above manifest will render as a row like the below image: +![CronWorkflow Example](assets/title-and-description-markdown-cron-workflow.png) + +### For `WorkflowTemplates` + +> v3.6 and after + +You can also add the `workflows.argoproj.io/title` and `workflows.argoproj.io/description` annotations with embedded markdown to a `WorkflowTemplate` to display in the list: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: WorkflowTemplate +metadata: + name: my-workflow-template + annotations: + workflows.argoproj.io/title: '**Test Title**' + workflows.argoproj.io/description: | + `This is a simple hello world example.` + You can also run it in Python: https://couler-proj.github.io/couler/examples/#hello-world +``` + +The above manifest will render as a row like the below image: +![WorkflowTemplate Example](assets/title-and-description-markdown-workflow-template.png) diff --git a/ui/src/cluster-workflow-templates/cluster-workflow-template-list.scss b/ui/src/cluster-workflow-templates/cluster-workflow-template-list.scss index 2293c1f83a06..72f21557118d 100644 --- a/ui/src/cluster-workflow-templates/cluster-workflow-template-list.scss +++ b/ui/src/cluster-workflow-templates/cluster-workflow-template-list.scss @@ -5,4 +5,22 @@ &__row:hover { box-shadow: 1px 2px 3px rgba($argo-color-gray-9, .1), 0 0 0 1px rgba($argo-color-teal-5, .5); } -} \ No newline at end of file +} + +.cluster-workflow-templates-list { + padding: 1em; + + &__row-container { + a { + color: $argo-color-gray-6; + } + + a:hover { + color: $argo-color-teal-5; + } + } +} + +.row.pt-60 { + padding-top: 60px; +} diff --git a/ui/src/cluster-workflow-templates/cluster-workflow-template-list.tsx b/ui/src/cluster-workflow-templates/cluster-workflow-template-list.tsx index 4b03930bad5a..c83f52a9c6e2 100644 --- a/ui/src/cluster-workflow-templates/cluster-workflow-template-list.tsx +++ b/ui/src/cluster-workflow-templates/cluster-workflow-template-list.tsx @@ -19,6 +19,7 @@ import {useCollectEvent} from '../shared/use-collect-event'; import {useQueryParams} from '../shared/use-query-params'; import useTimestamp, {TIMESTAMP_KEYS} from '../shared/use-timestamp'; import {ClusterWorkflowTemplateCreator} from './cluster-workflow-template-creator'; +import {ClusterWorkflowTemplateMarkdown} from './cluster-workflow-template-markdown'; import './cluster-workflow-template-list.scss'; @@ -83,15 +84,19 @@ export function ClusterWorkflowTemplateList({history, location}: RouteComponentP {templates.map(t => ( - -
- +
+
+
+ +
+ + + +
+ +
-
{t.metadata.name}
-
- -
- +
))}
diff --git a/ui/src/cluster-workflow-templates/cluster-workflow-template-markdown.scss b/ui/src/cluster-workflow-templates/cluster-workflow-template-markdown.scss new file mode 100644 index 000000000000..fca441264981 --- /dev/null +++ b/ui/src/cluster-workflow-templates/cluster-workflow-template-markdown.scss @@ -0,0 +1,8 @@ +@import 'node_modules/argo-ui/src/styles/config'; + +.wf-rows-name { + line-height: 1.5em; + display: inline-block; + vertical-align: middle; + white-space: pre-line; +} diff --git a/ui/src/cluster-workflow-templates/cluster-workflow-template-markdown.tsx b/ui/src/cluster-workflow-templates/cluster-workflow-template-markdown.tsx new file mode 100644 index 000000000000..59b0f7041b34 --- /dev/null +++ b/ui/src/cluster-workflow-templates/cluster-workflow-template-markdown.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; + +import {ANNOTATION_DESCRIPTION, ANNOTATION_TITLE} from '../shared/annotations'; +import {SuspenseReactMarkdownGfm} from '../shared/components/suspense-react-markdown-gfm'; +import {ClusterWorkflowTemplate} from '../shared/models'; + +require('./cluster-workflow-template-markdown.scss'); + +interface ClusterWorkflowTemplateMarkdownProps { + workflow: ClusterWorkflowTemplate; +} + +export function ClusterWorkflowTemplateMarkdown(props: ClusterWorkflowTemplateMarkdownProps) { + const wf = props.workflow; + // title + description vars + const title = wf.metadata.annotations?.[ANNOTATION_TITLE] ?? wf.metadata.name; + const description = (wf.metadata.annotations?.[ANNOTATION_DESCRIPTION] && `\n${wf.metadata.annotations[ANNOTATION_DESCRIPTION]}`) || ''; + const hasAnnotation = title !== wf.metadata.name || description !== ''; + const markdown = `${title}${description}`; + + return
{hasAnnotation ? : markdown}
; +} diff --git a/ui/src/cron-workflows/cron-workflow-list.scss b/ui/src/cron-workflows/cron-workflow-list.scss index e9dd2862a52b..3c8d9f7edd2c 100644 --- a/ui/src/cron-workflows/cron-workflow-list.scss +++ b/ui/src/cron-workflows/cron-workflow-list.scss @@ -4,4 +4,22 @@ &__row:hover { box-shadow: 1px 2px 3px rgba($argo-color-gray-9, .1), 0 0 0 1px rgba($argo-color-teal-5, .5); } -} \ No newline at end of file +} + +.cron-workflows-list { + padding: 1em; + + &__row-container { + a { + color: $argo-color-gray-6; + } + + a:hover { + color: $argo-color-teal-5; + } + } +} + +.row.pt-60 { + padding-top: 60px; +} diff --git a/ui/src/cron-workflows/cron-workflow-list.tsx b/ui/src/cron-workflows/cron-workflow-list.tsx index 4ff8ed3ff647..dbbd6ba27967 100644 --- a/ui/src/cron-workflows/cron-workflow-list.tsx +++ b/ui/src/cron-workflows/cron-workflow-list.tsx @@ -1,23 +1,20 @@ import {Page} from 'argo-ui/src/components/page/page'; import {SlidingPanel} from 'argo-ui/src/components/sliding-panel/sliding-panel'; -import {Ticker} from 'argo-ui/src/components/ticker'; import * as React from 'react'; import {useContext, useEffect, useState} from 'react'; -import {Link, RouteComponentProps} from 'react-router-dom'; +import {RouteComponentProps} from 'react-router-dom'; -import {ANNOTATION_DESCRIPTION, ANNOTATION_TITLE} from '../shared/annotations'; import {uiUrl} from '../shared/base'; import {ErrorNotice} from '../shared/components/error-notice'; import {ExampleManifests} from '../shared/components/example-manifests'; import {InfoIcon} from '../shared/components/fa-icons'; import {Loading} from '../shared/components/loading'; -import {Timestamp, TimestampSwitch} from '../shared/components/timestamp'; +import {TimestampSwitch} from '../shared/components/timestamp'; import {ZeroState} from '../shared/components/zero-state'; import {Context} from '../shared/context'; -import {getNextScheduledTime} from '../shared/cron'; import {Footnote} from '../shared/footnote'; import {historyUrl} from '../shared/history'; -import {CronWorkflow, CronWorkflowSpec} from '../shared/models'; +import {CronWorkflow} from '../shared/models'; import * as nsUtils from '../shared/namespaces'; import {services} from '../shared/services'; import {useCollectEvent} from '../shared/use-collect-event'; @@ -25,7 +22,7 @@ import {useQueryParams} from '../shared/use-query-params'; import useTimestamp, {TIMESTAMP_KEYS} from '../shared/use-timestamp'; import {CronWorkflowCreator} from './cron-workflow-creator'; import {CronWorkflowFilters} from './cron-workflow-filters'; -import {PrettySchedule} from './pretty-schedule'; +import {CronWorkflowRow} from './cron-workflow-row'; import './cron-workflow-list.scss'; @@ -156,56 +153,16 @@ export function CronWorkflowList({match, location, history}: RouteComponentProps /> - {cronWorkflows.map(w => ( - -
{w.spec.suspend ? : }
-
- {w.metadata.annotations?.[ANNOTATION_TITLE] ?? w.metadata.name} - {w.metadata.annotations?.[ANNOTATION_DESCRIPTION] ?

{w.metadata.annotations[ANNOTATION_DESCRIPTION]}

: null} -
-
{w.metadata.namespace}
-
{w.spec.timezone}
-
- {w.spec.schedule - ? w.spec.schedule - : w.spec.schedules.map(schedule => ( - <> - {schedule} -
- - ))} -
-
- {w.spec.schedule ? ( - - ) : ( - <> - {w.spec.schedules.map(schedule => ( - <> - -
- - ))} - - )} -
-
- -
-
- {w.spec.suspend ? ( - '' - ) : ( - - {() => } - - )} -
- - ))} + {cronWorkflows.map(w => { + return ( + + ); + })} Cron workflows are workflows that run on a preset schedule. Next scheduled run assumes workflow-controller is in UTC.{' '} @@ -221,18 +178,3 @@ export function CronWorkflowList({match, location, history}: RouteComponentProps ); } - -function getSpecNextScheduledTime(spec: CronWorkflowSpec): Date { - if (spec.schedule) { - return getNextScheduledTime(spec.schedule, spec.timezone); - } - - let out: Date; - spec.schedules.forEach(schedule => { - const next = getNextScheduledTime(schedule, spec.timezone); - if (!out || next.getTime() < out.getTime()) { - out = next; - } - }); - return out; -} diff --git a/ui/src/cron-workflows/cron-workflow-row.scss b/ui/src/cron-workflows/cron-workflow-row.scss new file mode 100644 index 000000000000..fca441264981 --- /dev/null +++ b/ui/src/cron-workflows/cron-workflow-row.scss @@ -0,0 +1,8 @@ +@import 'node_modules/argo-ui/src/styles/config'; + +.wf-rows-name { + line-height: 1.5em; + display: inline-block; + vertical-align: middle; + white-space: pre-line; +} diff --git a/ui/src/cron-workflows/cron-workflow-row.tsx b/ui/src/cron-workflows/cron-workflow-row.tsx new file mode 100644 index 000000000000..d1fb5080a5ad --- /dev/null +++ b/ui/src/cron-workflows/cron-workflow-row.tsx @@ -0,0 +1,90 @@ +import {Ticker} from 'argo-ui/src/index'; +import * as React from 'react'; +import {Link} from 'react-router-dom'; + +import {ANNOTATION_DESCRIPTION, ANNOTATION_TITLE} from '../shared/annotations'; +import {uiUrl} from '../shared/base'; +import {SuspenseReactMarkdownGfm} from '../shared/components/suspense-react-markdown-gfm'; +import {Timestamp} from '../shared/components/timestamp'; +import {getNextScheduledTime} from '../shared/cron'; +import {CronWorkflow, CronWorkflowSpec} from '../shared/models'; +import {PrettySchedule} from './pretty-schedule'; + +require('./cron-workflow-row.scss'); + +interface CronWorkflowRowProps { + workflow: CronWorkflow; + displayISOFormatCreation: boolean; + displayISOFormatNextScheduled: boolean; +} + +export function CronWorkflowRow(props: CronWorkflowRowProps) { + const wf = props.workflow; + // title + description vars + const title = wf.metadata.annotations?.[ANNOTATION_TITLE] ?? wf.metadata.name; + const description = (wf.metadata.annotations?.[ANNOTATION_DESCRIPTION] && `\n${wf.metadata.annotations[ANNOTATION_DESCRIPTION]}`) || ''; + const hasAnnotation = title !== wf.metadata.name || description !== ''; + const markdown = `${title}${description}`; + + return ( +
+
+
{wf.spec.suspend ? : }
+ +
{hasAnnotation ? : markdown}
+ +
{wf.metadata.namespace}
+
{wf.spec.timezone}
+
+ {wf.spec.schedule != '' + ? wf.spec.schedule + : wf.spec.schedules.map(schedule => ( + <> + {schedule} +
+ + ))} +
+
+ {wf.spec.schedule != '' ? ( + + ) : ( + <> + {wf.spec.schedules.map(schedule => ( + <> + +
+ + ))} + + )} +
+
+ +
+
+ {wf.spec.suspend ? ( + '' + ) : ( + {() => } + )} +
+
+
+ ); +} + +function getCronNextScheduledTime(spec: CronWorkflowSpec): Date { + if (spec.schedule != '') { + return getNextScheduledTime(spec.schedule, spec.timezone); + } + + let out: Date; + spec.schedules.forEach(schedule => { + const next = getNextScheduledTime(schedule, spec.timezone); + if (!out || next.getTime() < out.getTime()) { + out = next; + } + }); + return out; +} diff --git a/ui/src/shared/components/_react-markdown-gfm.tsx b/ui/src/shared/components/_react-markdown-gfm.tsx new file mode 100644 index 000000000000..f0d2c1e9eae1 --- /dev/null +++ b/ui/src/shared/components/_react-markdown-gfm.tsx @@ -0,0 +1,27 @@ +// Use the lazy loaded suspense variant instead +import React from 'react'; +import ReactMarkdown from 'react-markdown'; +import remarkGfm from 'remark-gfm'; + +import {openLinkWithKey} from './links'; + +export function ReactMarkdownGfm({markdown}: {markdown: string}) { + return ( + + {markdown} + + ); +} +export default ReactMarkdownGfm; // for lazy loading + +function NestedAnchor(props: React.ComponentProps<'a'>) { + return ( + { + ev.preventDefault(); // don't bubble up + openLinkWithKey(props.href); // eslint-disable-line react/prop-types -- it's not interpreting the prop types correctly + }} + /> + ); +} diff --git a/ui/src/shared/components/suspense-react-markdown-gfm.tsx b/ui/src/shared/components/suspense-react-markdown-gfm.tsx new file mode 100644 index 000000000000..6de943c8ebbb --- /dev/null +++ b/ui/src/shared/components/suspense-react-markdown-gfm.tsx @@ -0,0 +1,16 @@ +import React from 'react'; + +import {Loading} from './loading'; + +// lazy load ReactMarkdown (and remark-gfm) as it is a large optional component (which can be split into a separate bundle) +const LazyReactMarkdownGfm = React.lazy(() => { + return import(/* webpackChunkName: "react-markdown-plus-gfm" */ './_react-markdown-gfm'); +}); + +export function SuspenseReactMarkdownGfm(props: {markdown: string}) { + return ( + }> + + + ); +} diff --git a/ui/src/workflow-templates/workflow-template-list.scss b/ui/src/workflow-templates/workflow-template-list.scss index 2293c1f83a06..29bc980980ce 100644 --- a/ui/src/workflow-templates/workflow-template-list.scss +++ b/ui/src/workflow-templates/workflow-template-list.scss @@ -5,4 +5,22 @@ &__row:hover { box-shadow: 1px 2px 3px rgba($argo-color-gray-9, .1), 0 0 0 1px rgba($argo-color-teal-5, .5); } -} \ No newline at end of file +} + +.workflow-templates-list { + padding: 1em; + + &__row-container { + a { + color: $argo-color-gray-6; + } + + a:hover { + color: $argo-color-teal-5; + } + } +} + +.row.pt-60 { + padding-top: 60px; +} diff --git a/ui/src/workflow-templates/workflow-template-list.tsx b/ui/src/workflow-templates/workflow-template-list.tsx index 6a9820b3572d..b7d4c1e23b98 100644 --- a/ui/src/workflow-templates/workflow-template-list.tsx +++ b/ui/src/workflow-templates/workflow-template-list.tsx @@ -2,16 +2,15 @@ import {Page} from 'argo-ui/src/components/page/page'; import {SlidingPanel} from 'argo-ui/src/components/sliding-panel/sliding-panel'; import * as React from 'react'; import {useContext, useEffect, useState} from 'react'; -import {Link, RouteComponentProps} from 'react-router-dom'; +import {RouteComponentProps} from 'react-router-dom'; -import {ANNOTATION_DESCRIPTION, ANNOTATION_TITLE} from '../shared/annotations'; import {uiUrl} from '../shared/base'; import {ErrorNotice} from '../shared/components/error-notice'; import {ExampleManifests} from '../shared/components/example-manifests'; import {InfoIcon} from '../shared/components/fa-icons'; import {Loading} from '../shared/components/loading'; import {PaginationPanel} from '../shared/components/pagination-panel'; -import {Timestamp, TimestampSwitch} from '../shared/components/timestamp'; +import {TimestampSwitch} from '../shared/components/timestamp'; import {ZeroState} from '../shared/components/zero-state'; import {Context} from '../shared/context'; import {Footnote} from '../shared/footnote'; @@ -26,6 +25,7 @@ import {useQueryParams} from '../shared/use-query-params'; import useTimestamp, {TIMESTAMP_KEYS} from '../shared/use-timestamp'; import {WorkflowTemplateCreator} from './workflow-template-creator'; import {WorkflowTemplateFilters} from './workflow-template-filters'; +import {WorkflowTemplateRow} from './workflow-template-row'; import './workflow-template-list.scss'; @@ -145,24 +145,9 @@ export function WorkflowTemplateList({match, location, history}: RouteComponentP CREATED - {templates.map(t => ( - -
- -
-
- {t.metadata.annotations?.[ANNOTATION_TITLE] ?? t.metadata.name} - {t.metadata.annotations?.[ANNOTATION_DESCRIPTION] ?

{t.metadata.annotations[ANNOTATION_DESCRIPTION]}

: null} -
-
{t.metadata.namespace}
-
- -
- - ))} + {templates.map(t => { + return ; + })} Workflow templates are reusable templates you can create new workflows from. . {learnMore}. diff --git a/ui/src/workflow-templates/workflow-template-row.scss b/ui/src/workflow-templates/workflow-template-row.scss new file mode 100644 index 000000000000..fca441264981 --- /dev/null +++ b/ui/src/workflow-templates/workflow-template-row.scss @@ -0,0 +1,8 @@ +@import 'node_modules/argo-ui/src/styles/config'; + +.wf-rows-name { + line-height: 1.5em; + display: inline-block; + vertical-align: middle; + white-space: pre-line; +} diff --git a/ui/src/workflow-templates/workflow-template-row.tsx b/ui/src/workflow-templates/workflow-template-row.tsx new file mode 100644 index 000000000000..1c3cab34dc4a --- /dev/null +++ b/ui/src/workflow-templates/workflow-template-row.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import {Link} from 'react-router-dom'; + +import {ANNOTATION_DESCRIPTION, ANNOTATION_TITLE} from '../shared/annotations'; +import {uiUrl} from '../shared/base'; +import {SuspenseReactMarkdownGfm} from '../shared/components/suspense-react-markdown-gfm'; +import {Timestamp} from '../shared/components/timestamp'; +import {WorkflowTemplate} from '../shared/models'; + +require('./workflow-template-row.scss'); + +interface WorkflowTemplateRowProps { + workflow: WorkflowTemplate; + displayISOFormat: boolean; +} + +export function WorkflowTemplateRow(props: WorkflowTemplateRowProps) { + const wf = props.workflow; + // title + description vars + const title = wf.metadata.annotations?.[ANNOTATION_TITLE] ?? wf.metadata.name; + const description = (wf.metadata.annotations?.[ANNOTATION_DESCRIPTION] && `\n${wf.metadata.annotations[ANNOTATION_DESCRIPTION]}`) || ''; + const hasAnnotation = title !== wf.metadata.name || description !== ''; + const markdown = `${title}${description}`; + + return ( +
+
+
+ +
+ +
{hasAnnotation ? : markdown}
+ +
{wf.metadata.namespace}
+
+ +
+
+
+ ); +} diff --git a/ui/src/workflows/components/workflows-row/react-markdown-gfm.tsx b/ui/src/workflows/components/workflows-row/react-markdown-gfm.tsx index 119f60b6e9f5..c1f73a49adb5 100644 --- a/ui/src/workflows/components/workflows-row/react-markdown-gfm.tsx +++ b/ui/src/workflows/components/workflows-row/react-markdown-gfm.tsx @@ -1,3 +1,4 @@ +// Use the lazy loaded suspense variant instead import React from 'react'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; diff --git a/ui/src/workflows/components/workflows-row/workflows-row.tsx b/ui/src/workflows/components/workflows-row/workflows-row.tsx index b22f412848ce..6a770674d5ea 100644 --- a/ui/src/workflows/components/workflows-row/workflows-row.tsx +++ b/ui/src/workflows/components/workflows-row/workflows-row.tsx @@ -6,8 +6,8 @@ import {Link} from 'react-router-dom'; import {ANNOTATION_DESCRIPTION, ANNOTATION_TITLE} from '../../../shared/annotations'; import {uiUrl} from '../../../shared/base'; import {DurationPanel} from '../../../shared/components/duration-panel'; -import {Loading} from '../../../shared/components/loading'; import {PhaseIcon} from '../../../shared/components/phase-icon'; +import {SuspenseReactMarkdownGfm} from '../../../shared/components/suspense-react-markdown-gfm'; import {Timestamp} from '../../../shared/components/timestamp'; import {wfDuration} from '../../../shared/duration'; import * as models from '../../../shared/models'; @@ -32,7 +32,7 @@ export function WorkflowsRow(props: WorkflowsRowProps) { // title + description vars const title = wf.metadata.annotations?.[ANNOTATION_TITLE] ?? wf.metadata.name; const description = (wf.metadata.annotations?.[ANNOTATION_DESCRIPTION] && `\n${wf.metadata.annotations[ANNOTATION_DESCRIPTION]}`) || ''; - const hasAnnotation = title !== wf.metadata.name && description !== ''; + const hasAnnotation = title !== wf.metadata.name || description !== ''; const markdown = `${title}${description}`; return ( @@ -110,16 +110,3 @@ export function WorkflowsRow(props: WorkflowsRowProps) { ); } - -// lazy load ReactMarkdown (and remark-gfm) as it is a large optional component (which can be split into a separate bundle) -const LazyReactMarkdownGfm = React.lazy(() => { - return import(/* webpackChunkName: "react-markdown-plus-gfm" */ './react-markdown-gfm'); -}); - -function SuspenseReactMarkdownGfm(props: {markdown: string}) { - return ( - }> - - - ); -}