From c747c4be563f01548bacd32aeb9088b3f02cbcf2 Mon Sep 17 00:00:00 2001 From: jasquat <2487833+jasquat@users.noreply.github.com> Date: Thu, 7 Sep 2023 10:12:13 -0400 Subject: [PATCH] Feature/UI tweaks (#419) * some initial ui tweaks w/ burnettk * left align more items as per the figma page w/ burnettk * pyl w/ burnettk * left align additional pages w/ burnettk * use carbon components for the rjsf forms as well w/ burnettk * do not raise if the app cannot load an env specific config file w/ burnettk * attempting to center all the main elements except the diagram page WIP w/ burnettk * fix build issue * document media query * fixed centering of elements in webui w/ burnettk * some tweaks to taskshow markdown w/ burnettk * make filter button smaller as a medium size * medium styles for these buttons to the top right of tables * inscreased cap for metadata key when displayed and allow word-wrapping w/ burnettk --------- Co-authored-by: jasquat Co-authored-by: burnettk --- .../docker_image_for_main_builds.yml | 4 - spiffworkflow-frontend/src/App.tsx | 9 +- .../src/components/Filters.tsx | 2 +- .../src/components/InstructionsForEndUser.tsx | 2 +- .../components/ProcessInstanceListTable.tsx | 15 +- .../src/components/ProcessInstanceRun.tsx | 29 ++-- .../src/components/ProcessInterstitial.tsx | 7 +- .../src/components/TaskListTable.tsx | 1 + spiffworkflow-frontend/src/index.css | 136 +++++++++++++++++- spiffworkflow-frontend/src/index.scss | 74 ---------- .../rjsf/carbon_theme/AddButton/AddButton.tsx | 32 ++--- .../carbon_theme/IconButton/IconButton.tsx | 28 ++-- spiffworkflow-frontend/src/routes/About.tsx | 2 + .../src/routes/AdminRoutes.tsx | 2 + .../src/routes/EditorRoutes.tsx | 2 +- .../src/routes/Extension.tsx | 8 +- .../src/routes/HomePageRoutes.tsx | 2 + .../src/routes/ProcessInstanceShow.tsx | 56 ++++---- .../src/routes/ProcessModelEditDiagram.tsx | 14 +- .../src/routes/ProcessModelShow.tsx | 24 ++-- .../src/routes/TaskShow.tsx | 6 +- 21 files changed, 265 insertions(+), 190 deletions(-) diff --git a/.github/workflows/docker_image_for_main_builds.yml b/.github/workflows/docker_image_for_main_builds.yml index 8bfeb235..5054a003 100644 --- a/.github/workflows/docker_image_for_main_builds.yml +++ b/.github/workflows/docker_image_for_main_builds.yml @@ -31,11 +31,7 @@ on: push: branches: - main - - feature/event-payloads-part-2 - - feature/event-payload-migration-fix - spiffdemo - - feature/business_end_states - - feature/allow-markdown-in-extension-results jobs: create_frontend_docker_image: diff --git a/spiffworkflow-frontend/src/App.tsx b/spiffworkflow-frontend/src/App.tsx index 95a40933..4fee5ec5 100644 --- a/spiffworkflow-frontend/src/App.tsx +++ b/spiffworkflow-frontend/src/App.tsx @@ -13,7 +13,6 @@ import AdminRoutes from './routes/AdminRoutes'; import { AbilityContext } from './contexts/Can'; import UserService from './services/UserService'; -import ErrorDisplay from './components/ErrorDisplay'; import APIErrorProvider from './contexts/APIErrorContext'; import ScrollToTop from './components/ScrollToTop'; import EditorRoutes from './routes/EditorRoutes'; @@ -27,6 +26,11 @@ export default function App() { const ability = defineAbility(() => {}); + let contentClassName = 'main-site-body-centered'; + if (window.location.pathname.startsWith('/editor/')) { + contentClassName = 'no-center-stuff'; + } + return (
{/* @ts-ignore */} @@ -34,9 +38,8 @@ export default function App() { - + - } /> diff --git a/spiffworkflow-frontend/src/components/Filters.tsx b/spiffworkflow-frontend/src/components/Filters.tsx index abb45be1..6173ae4f 100644 --- a/spiffworkflow-frontend/src/components/Filters.tsx +++ b/spiffworkflow-frontend/src/components/Filters.tsx @@ -50,7 +50,7 @@ export default function Filters({ renderIcon={Filter} iconDescription="Filter Options" hasIconOnly - size="lg" + size="md" onClick={toggleShowFilterOptions} /> diff --git a/spiffworkflow-frontend/src/components/InstructionsForEndUser.tsx b/spiffworkflow-frontend/src/components/InstructionsForEndUser.tsx index 52a7102d..be21807d 100644 --- a/spiffworkflow-frontend/src/components/InstructionsForEndUser.tsx +++ b/spiffworkflow-frontend/src/components/InstructionsForEndUser.tsx @@ -79,7 +79,7 @@ export default function InstructionsForEndUser({ } return ( -
+
{/* https://www.npmjs.com/package/@uiw/react-md-editor switches to dark mode by default by respecting @media (prefers-color-scheme: dark) diff --git a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx index 6475bfb5..bb135797 100644 --- a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx +++ b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx @@ -49,6 +49,7 @@ import { REFRESH_INTERVAL_SECONDS, REFRESH_TIMEOUT_SECONDS, titleizeString, + truncateString, } from '../helpers'; import { useUriListForPermissions } from '../hooks/UriListForPermissions'; @@ -1268,7 +1269,7 @@ export default function ProcessInstanceListTable({ setReportColumnFormMode('edit'); }} > - {reportColumnLabel} + {truncateString(reportColumnLabel, 10)} @@ -1830,7 +1832,7 @@ export default function ProcessInstanceListTable({ renderIcon={ArrowRight} iconDescription="View Filterable List" hasIconOnly - size="lg" + size="md" onClick={() => navigate(`/admin/process-instances?report_hash=${reportHash}`) } @@ -1840,7 +1842,12 @@ export default function ProcessInstanceListTable({ } return ( <> - + {headerElement} {filterButtonLink} @@ -1897,7 +1904,7 @@ export default function ProcessInstanceListTable({ {reportColumnForm()} {advancedOptionsModal()} {processInstanceReportSaveTag()} - + {tableTitleLine()} - - - ); - } - return ( + const startButton = ( ); + + // if checkPermissions is false then assume the page using this component has already checked the permissions + if (checkPermissions) { + return ( + + {startButton} + + ); + } + return startButton; } diff --git a/spiffworkflow-frontend/src/components/ProcessInterstitial.tsx b/spiffworkflow-frontend/src/components/ProcessInterstitial.tsx index c72a6313..f3efa39b 100644 --- a/spiffworkflow-frontend/src/components/ProcessInterstitial.tsx +++ b/spiffworkflow-frontend/src/components/ProcessInterstitial.tsx @@ -135,7 +135,12 @@ export default function ProcessInterstitial({ ) => { return (
- +
); }; diff --git a/spiffworkflow-frontend/src/components/TaskListTable.tsx b/spiffworkflow-frontend/src/components/TaskListTable.tsx index ab1cdaf4..8365ee8a 100644 --- a/spiffworkflow-frontend/src/components/TaskListTable.tsx +++ b/spiffworkflow-frontend/src/components/TaskListTable.tsx @@ -208,6 +208,7 @@ export default function TaskListTable({ variant="primary" href={taskUrl} disabled={!hasAccessToCompleteTask} + size="sm" > Go diff --git a/spiffworkflow-frontend/src/index.css b/spiffworkflow-frontend/src/index.css index b2052c9e..99fbee3b 100644 --- a/spiffworkflow-frontend/src/index.css +++ b/spiffworkflow-frontend/src/index.css @@ -7,6 +7,7 @@ .megacondensed { padding-left: 0px; + margin-left: 0px; } /* defaults to 3rem, which isn't long sufficient for "elizabeth" */ @@ -61,8 +62,9 @@ h3 { color: #161616; } -.span-tag { +.tag-within-dl { color: black; + margin-left: -3px; } .cds--btn.button-white-background { @@ -121,6 +123,34 @@ h3 { padding-left: 0; } +/* make the colors black to make it easier to read */ +.cds--btn--tertiary { + color: black; + border-color: black; +} +.cds--btn--tertiary:visited { + color: black; + border-color: black; +} +/* make the colors a little lighter black on hover + * so they match our normal scheme better + */ +.cds--btn--tertiary:focus { + color: white; + border-color: #393939; + background-color: #393939; +} +.cds--btn--tertiary:hover { + color: white; + border-color: #474747; + background-color: #474747; +} +.cds--btn--tertiary:visited:hover { + color: white; + border-color: #474747; + background-color: #474747; +} + .cds--header__global .cds--btn--primary.button-link { color: #f4f4f4; background-color: #393939; @@ -189,8 +219,9 @@ h1.with-icons { dl { display: block; grid-template-columns: 35% 65%; - font-size: .8rem; + font-size: 14px; line-height: 1.2rem; + padding-top: 9px; } dl dt { @@ -200,6 +231,11 @@ dl dt { color: #161616; } +dl.metadata-display dt { + width: 7rem; + word-wrap: break-word; +} + dl dd { display: inline-block; padding-left: 1rem; @@ -347,7 +383,7 @@ in on this with the react-jsonschema-form repo. This is just a patch fix to allo .cds--tile.tile-process-group { padding: 0px; - margin: 12px; + margin: 12px 24px 12px 0px; width: 320px; height: 264px; background: #F4F4F4; @@ -404,6 +440,12 @@ in on this with the react-jsonschema-form repo. This is just a patch fix to allo max-width: 20rem; } +/* carbon wants padding on all sides. our UI person wanted everything leaning against the left wall. */ +.cds--tab-content { + padding-left: 0; + padding-right: 0; +} + .clear-left { clear: left; } @@ -427,10 +469,13 @@ td.actions-cell { .no-results-message { font-style: italic; - margin-left: 2rem; font-size: 14px; } +th.table-header-right-align .cds--data-table, th.table-header-right-align .cds--table-header-label{ + text-align: right; +} + .data-table-description { font-size: 14px; line-height: 18px; @@ -447,6 +492,7 @@ td.actions-cell { .filter-icon { text-align: right; padding-bottom: 10px; + margin-right: 0px; } .cds--btn--ghost:not([disabled]).red-icon svg { @@ -683,3 +729,85 @@ hr { #hidden-form-for-autosave { display: none; } + +fieldset legend.header { + margin-bottom: 32px; +} +fieldset fieldset fieldset legend.header { + margin-bottom: 16px; +} + +.fixed-width-container { + margin: auto; + justify-content: center; + overflow: visible; + /* border: 1px solid black; */ +} + +/* media min-width 75 means: do the stuff in the block if the browser width is greater than 75 */ +@media (min-width: 75rem) { + .fixed-width-container { + max-width: 75rem; + } +} + +p, li, h1, h2, h3, h4, h5, h6, blockquote, hr { + max-width: 640px; +} +li.cds--accordion__item { + max-width: 100%; +} + +div.markdown { + padding: 15px 0 15px 0; + overflow: visible; +} + +div.markdown-collapsed { + max-height: 200px; + overflow: hidden; + + --mask: linear-gradient(to bottom, + rgba(0,0,0, 1) 0, rgba(0,0,0, 1) 40%, + rgba(0,0,0, 0) 95%, rgba(0,0,0, 0) 0 + ) 100% 50% / 100% 100% repeat-x; + + font: 2em/1.6em Arial; + -webkit-mask: var(--mask); + mask: var(--mask); +} + + +.cds--data-table-content { + overflow-x: scroll; +} + +.wmde-markdown table { + width: fit-content; + overflow: scroll; +} + +/* override carbon variable so we can left align accordions*/ +.cds--accordion { + --cds-layout-density-padding-inline-local: 0px; +} +.megacondensed-button .cds--btn { + --cds-layout-density-padding-inline-local: 0px; +} + +.wmde-markdown ol { + list-style: decimal; +} + +.wmde-markdown ul { + list-style: disc; +} + +div.cds--tag svg { + vertical-align: middle; + display: inline-block; +} + +div.onboarding { + margin-bottom: 2rem; +} diff --git a/spiffworkflow-frontend/src/index.scss b/spiffworkflow-frontend/src/index.scss index 0497d5e1..08d50bc0 100644 --- a/spiffworkflow-frontend/src/index.scss +++ b/spiffworkflow-frontend/src/index.scss @@ -21,77 +21,3 @@ main { } - -.fixed-width-container { - padding-left: 0; - overflow: visible; -} - -@media (min-width: 99rem) { - .fixed-width-container { - max-width: 99rem; - padding-right: 0; - } -} - -@media (min-width: 80rem) { - .fixed-width-container { - padding-left: 10rem; - padding-right: 2rem; - } -} - -p, li, h1, h2, h3, h4, h5, h6, blockquote { - max-width: 640px; -} -li.cds--accordion__item { - max-width: 100%; -} - -div.markdown { - max-width: 1000px; - padding: 15px 0 15px 0; - overflow: visible; -} - -div.markdown-collapsed { - max-height: 200px; - overflow: hidden; - - --mask: linear-gradient(to bottom, - rgba(0,0,0, 1) 0, rgba(0,0,0, 1) 40%, - rgba(0,0,0, 0) 95%, rgba(0,0,0, 0) 0 - ) 100% 50% / 100% 100% repeat-x; - - font: 2em/1.6em Arial; - -webkit-mask: var(--mask); - mask: var(--mask); -} - - -.cds--data-table-content { - width: fit-content; - min-width: 100%; - overflow-x: visible; -} - -.wmde-markdown table { - width: fit-content; -} - -.wmde-markdown ol { - list-style: decimal; -} - -.wmde-markdown ul { - list-style: disc; -} - -div.cds--tag svg { - vertical-align: middle; - display: inline-block; -} - -div.onboarding { - margin-bottom: 2rem; -} \ No newline at end of file diff --git a/spiffworkflow-frontend/src/rjsf/carbon_theme/AddButton/AddButton.tsx b/spiffworkflow-frontend/src/rjsf/carbon_theme/AddButton/AddButton.tsx index f01d08fa..4bb2ad95 100644 --- a/spiffworkflow-frontend/src/rjsf/carbon_theme/AddButton/AddButton.tsx +++ b/spiffworkflow-frontend/src/rjsf/carbon_theme/AddButton/AddButton.tsx @@ -5,11 +5,8 @@ import { RJSFSchema, StrictRJSFSchema, } from '@rjsf/utils'; - -// @ts-ignore -import { AddAlt } from '@carbon/icons-react'; - -import IconButton from '../IconButton/IconButton'; +import { Button } from '@carbon/react'; +import { Add } from '@carbon/icons-react'; /** The `AddButton` renders a button that represent the `Add` action on a form */ @@ -19,18 +16,17 @@ export default function AddButton< F extends FormContextType = any >({ className, onClick, disabled, registry }: IconButtonProps) { return ( -
-

- -

-
+ ); } diff --git a/spiffworkflow-frontend/src/rjsf/carbon_theme/IconButton/IconButton.tsx b/spiffworkflow-frontend/src/rjsf/carbon_theme/IconButton/IconButton.tsx index 64eb883d..93680967 100644 --- a/spiffworkflow-frontend/src/rjsf/carbon_theme/IconButton/IconButton.tsx +++ b/spiffworkflow-frontend/src/rjsf/carbon_theme/IconButton/IconButton.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { Button } from '@carbon/react'; import { FormContextType, IconButtonProps, @@ -6,7 +7,6 @@ import { StrictRJSFSchema, } from '@rjsf/utils'; -// @ts-ignore import { Add, TrashCan, ArrowUp, ArrowDown } from '@carbon/icons-react'; export default function IconButton< @@ -20,32 +20,32 @@ export default function IconButton< className, uiSchema, registry, + title, ...otherProps } = props; // icon string optios: plus, remove, arrow-up, arrow-down - let carbonIcon = ( -

- Add new -

- ); + let carbonIcon = Add; if (icon === 'remove') { - carbonIcon = ; + carbonIcon = TrashCan; } if (icon === 'arrow-up') { - carbonIcon = ; + carbonIcon = ArrowUp; } if (icon === 'arrow-down') { - carbonIcon = ; + carbonIcon = ArrowDown; } return ( - + /> ); } diff --git a/spiffworkflow-frontend/src/routes/About.tsx b/spiffworkflow-frontend/src/routes/About.tsx index 786521d8..6cc8303b 100644 --- a/spiffworkflow-frontend/src/routes/About.tsx +++ b/spiffworkflow-frontend/src/routes/About.tsx @@ -1,6 +1,7 @@ // @ts-ignore import { Table } from '@carbon/react'; import { useEffect, useState } from 'react'; +import ErrorDisplay from '../components/ErrorDisplay'; import appVersionInfo from '../helpers/appVersionInfo'; import { ObjectWithStringKeysAndValues } from '../interfaces'; import HttpService from '../services/HttpService'; @@ -57,6 +58,7 @@ export default function About() { return (
+

About

{versionInfoFromDict('Frontend version information', frontendVersionInfo)} {versionInfoFromDict('Backend version information', backendVersionInfo)} diff --git a/spiffworkflow-frontend/src/routes/AdminRoutes.tsx b/spiffworkflow-frontend/src/routes/AdminRoutes.tsx index b60eb717..e3915a11 100644 --- a/spiffworkflow-frontend/src/routes/AdminRoutes.tsx +++ b/spiffworkflow-frontend/src/routes/AdminRoutes.tsx @@ -22,6 +22,7 @@ import ProcessInstanceFindById from './ProcessInstanceFindById'; import ProcessInterstitialPage from './ProcessInterstitialPage'; import MessageListPage from './MessageListPage'; import DataStorePage from './DataStorePage'; +import ErrorDisplay from '../components/ErrorDisplay'; export default function AdminRoutes() { const location = useLocation(); @@ -31,6 +32,7 @@ export default function AdminRoutes() { if (UserService.hasRole(['admin'])) { return (
+ } /> } /> diff --git a/spiffworkflow-frontend/src/routes/EditorRoutes.tsx b/spiffworkflow-frontend/src/routes/EditorRoutes.tsx index 8fc2cac6..c3090f61 100644 --- a/spiffworkflow-frontend/src/routes/EditorRoutes.tsx +++ b/spiffworkflow-frontend/src/routes/EditorRoutes.tsx @@ -11,7 +11,7 @@ export default function EditorRoutes() { if (UserService.hasRole(['admin'])) { return ( -
+
{componentsToDisplay}
; + return ( +
+ + {componentsToDisplay} +
+ ); } return null; } diff --git a/spiffworkflow-frontend/src/routes/HomePageRoutes.tsx b/spiffworkflow-frontend/src/routes/HomePageRoutes.tsx index d618ba21..f40b8514 100644 --- a/spiffworkflow-frontend/src/routes/HomePageRoutes.tsx +++ b/spiffworkflow-frontend/src/routes/HomePageRoutes.tsx @@ -7,6 +7,7 @@ import CompletedInstances from './CompletedInstances'; import CreateNewInstance from './CreateNewInstance'; import InProgressInstances from './InProgressInstances'; import OnboardingView from './OnboardingView'; +import ErrorDisplay from '../components/ErrorDisplay'; export default function HomePageRoutes() { const location = useLocation(); @@ -49,6 +50,7 @@ export default function HomePageRoutes() { return (
+ {renderTabs()} diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx index b96b6483..f2414df2 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx @@ -45,6 +45,7 @@ import { getLastMilestoneFromProcessInstance, HUMAN_TASK_TYPES, modifyProcessIdentifierForPathParam, + truncateString, unModifyProcessIdentifierForPathParam, } from '../helpers'; import ButtonWithConfirmation from '../components/ButtonWithConfirmation'; @@ -359,7 +360,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { ); return ( - +
Status:
@@ -367,7 +368,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { {processInstance.status} {statusIcon} @@ -418,8 +419,10 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { {(processInstance.process_metadata || []).map( (processInstanceMetadata) => ( -
-
{processInstanceMetadata.key}:
+
+
+ {truncateString(processInstanceMetadata.key, 50)}: +
{processInstanceMetadata.value}
) @@ -1287,6 +1290,9 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { [`Process Instance Id: ${processInstance.id}`], ]} /> + {taskUpdateDisplayArea()} + {processDataDisplayArea()} + {viewMostRecentStateComponent()}

Process Instance Id: {processInstance.id} @@ -1294,6 +1300,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { {buttonIcons()} {getInfoTag()} +
- - - - - - {taskUpdateDisplayArea()} - {processDataDisplayArea()}
- {viewMostRecentStateComponent()} + {getTabs()} ); diff --git a/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx b/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx index 51e33f73..6af11cb7 100644 --- a/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx @@ -834,12 +834,14 @@ export default function ProcessModelEditDiagram() { onRequestClose={handleMarkdownEditorClose} size="lg" > - +
+ +
); }; diff --git a/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx b/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx index 44fcc5d7..b5afb231 100644 --- a/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx @@ -7,7 +7,6 @@ import { TrashCan, Upload, View, - // @ts-ignore } from '@carbon/icons-react'; import { Accordion, @@ -25,7 +24,6 @@ import { TableHead, TableHeader, TableRow, - // @ts-ignore } from '@carbon/react'; import { Can } from '@casl/react'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; @@ -346,7 +344,7 @@ export default function ProcessModelShow() { let actionsTableCell = null; if (processModelFile.name.match(/\.(dmn|bpmn|json|md)$/)) { actionsTableCell = ( - + {renderButtonElements(processModelFile, isPrimaryBpmnFile)} ); @@ -378,16 +376,20 @@ export default function ProcessModelShow() { return constructedTag; }); - const headers = ['Name', 'Actions']; return ( - {headers.map((header) => ( - - {header} - - ))} + + Name + + + Actions + {tags} @@ -525,7 +527,7 @@ export default function ProcessModelShow() { titleText="" size="lg" label="Add File" - type="inline" + type="default" data-qa="process-model-add-file" onChange={(a: any) => { if (a.selectedItem.text === 'New BPMN File') { @@ -564,7 +566,7 @@ export default function ProcessModelShow() { className="megacondensed process-model-files-section" > - + + ); pageElements.push( -

+

Task: {basicTask.name_for_display} ( {basicTask.process_model_display_name}){statusString} -

+ ); } if (basicTask && taskData) {