diff --git a/js_modules/dagster-ui/packages/ui-components/src/components/Icon.tsx b/js_modules/dagster-ui/packages/ui-components/src/components/Icon.tsx index 9bce5a4c8547f..b9a529ef29031 100644 --- a/js_modules/dagster-ui/packages/ui-components/src/components/Icon.tsx +++ b/js_modules/dagster-ui/packages/ui-components/src/components/Icon.tsx @@ -40,10 +40,12 @@ import checklist from '../icon-svgs/checklist.svg'; import chevron_left from '../icon-svgs/chevron_left.svg'; import chevron_right from '../icon-svgs/chevron_right.svg'; import close from '../icon-svgs/close.svg'; +import code_location from '../icon-svgs/code_location.svg'; import collapse_arrows from '../icon-svgs/collapse_arrows.svg'; import concept_book from '../icon-svgs/concept-book.svg'; import console_icon from '../icon-svgs/console.svg'; import content_copy from '../icon-svgs/content_copy.svg'; +import corporate_fare from '../icon-svgs/corporate_fare.svg'; import datatype_array from '../icon-svgs/datatype_array.svg'; import datatype_bool from '../icon-svgs/datatype_bool.svg'; import datatype_number from '../icon-svgs/datatype_number.svg'; @@ -109,6 +111,7 @@ import multi_asset from '../icon-svgs/multi_asset.svg'; import new_in_branch from '../icon-svgs/new_in_branch.svg'; import nightlight from '../icon-svgs/nightlight.svg'; import no_access from '../icon-svgs/no_access.svg'; +import notifications from '../icon-svgs/notifications.svg'; import observation from '../icon-svgs/observation.svg'; import open_in_new from '../icon-svgs/open_in_new.svg'; import panel_hide_right from '../icon-svgs/panel_hide_right.svg'; @@ -122,6 +125,7 @@ import partition_failure from '../icon-svgs/partition_failure.svg'; import partition_missing from '../icon-svgs/partition_missing.svg'; import partition_stale from '../icon-svgs/partition_stale.svg'; import partition_success from '../icon-svgs/partition_success.svg'; +import password from '../icon-svgs/password.svg'; import people from '../icon-svgs/people.svg'; import refresh from '../icon-svgs/refresh.svg'; import replay from '../icon-svgs/replay.svg'; @@ -138,11 +142,13 @@ import source from '../icon-svgs/source.svg'; import source_asset from '../icon-svgs/source_asset.svg'; import speed from '../icon-svgs/speed.svg'; import splitscreen from '../icon-svgs/splitscreen.svg'; +import stacks from '../icon-svgs/stacks.svg'; import star from '../icon-svgs/star.svg'; import star_outline from '../icon-svgs/star_outline.svg'; import status from '../icon-svgs/status.svg'; import sticky_note from '../icon-svgs/sticky_note.svg'; import subtract from '../icon-svgs/subtract.svg'; +import sync_alt from '../icon-svgs/sync_alt.svg'; import sync_problem from '../icon-svgs/sync_problem.svg'; import table_view from '../icon-svgs/table_view.svg'; import tag from '../icon-svgs/tag.svg'; @@ -273,9 +279,11 @@ export const Icons = { chevron_right, chevron_left, close, + code_location, console: console_icon, content_copy, collapse_arrows, + corporate_fare, delete: deleteSVG, done, dot, @@ -314,6 +322,8 @@ export const Icons = { new_in_branch, nightlight, no_access, + notifications, + password, people, refresh, replay, @@ -327,10 +337,12 @@ export const Icons = { subtract, speed, splitscreen, + stacks, star, star_outline, status, sticky_note, + sync_alt, sync_problem, table_view, timer, diff --git a/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/code_location.svg b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/code_location.svg new file mode 100644 index 0000000000000..893b2f5ff4c2b --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/code_location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/corporate_fare.svg b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/corporate_fare.svg new file mode 100644 index 0000000000000..f4d5085256004 --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/corporate_fare.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/notifications.svg b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/notifications.svg new file mode 100644 index 0000000000000..dbfe0e0409161 --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/notifications.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/password.svg b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/password.svg new file mode 100644 index 0000000000000..ad674c8bf23fa --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/password.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/stacks.svg b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/stacks.svg new file mode 100644 index 0000000000000..33c5c2490e3ec --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/stacks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/sync_alt.svg b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/sync_alt.svg new file mode 100644 index 0000000000000..f65d5b39d630c --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-components/src/icon-svgs/sync_alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js_modules/dagster-ui/packages/ui-core/src/app/AppTopNav.tsx b/js_modules/dagster-ui/packages/ui-core/src/app/AppTopNav.tsx index 61b8896319000..84265df6a20a7 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/app/AppTopNav.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/app/AppTopNav.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import {Link, NavLink, useHistory} from 'react-router-dom'; import styled from 'styled-components'; +import {useFeatureFlags} from './Flags'; import {LayoutContext} from './LayoutProvider'; import {ShortcutHandler} from './ShortcutHandler'; import {WebSocketStatus} from './WebSocketProvider'; @@ -35,6 +36,7 @@ export const AppTopNav = ({ allowGlobalReload = false, }: Props) => { const history = useHistory(); + const {flagSettingsPage} = useFeatureFlags(); const navLinks = () => { return [ @@ -91,35 +93,61 @@ export const AppTopNav = ({ ), }, - { - title: 'deployment', - element: ( - history.push('/locations')} - shortcutLabel="⌥4" - shortcutFilter={(e) => e.altKey && e.code === 'Digit4'} - > - { - const {pathname} = location; - return ( - pathname.startsWith('/locations') || - pathname.startsWith('/health') || - pathname.startsWith('/config') - ); - }} - > - - Deployment - - - - - ), - }, + flagSettingsPage + ? { + title: 'settings', + element: ( + history.push('/settings')} + shortcutLabel="⌥4" + shortcutFilter={(e) => e.altKey && e.code === 'Digit4'} + > + { + const {pathname} = location; + return pathname.startsWith('/settings') || pathname.startsWith('/locations'); + }} + > + + Settings + + + + + ), + } + : { + title: 'deployment', + element: ( + history.push('/locations')} + shortcutLabel="⌥4" + shortcutFilter={(e) => e.altKey && e.code === 'Digit4'} + > + { + const {pathname} = location; + return ( + pathname.startsWith('/locations') || + pathname.startsWith('/health') || + pathname.startsWith('/config') + ); + }} + > + + Deployment + + + + + ), + }, ]; }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/app/ContentRoot.tsx b/js_modules/dagster-ui/packages/ui-core/src/app/ContentRoot.tsx index 9bb7929e2263d..5ca95c42b81f1 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/app/ContentRoot.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/app/ContentRoot.tsx @@ -18,6 +18,7 @@ const RunsRoot = lazy(() => import('../runs/RunsRoot')); const ScheduledRunListRoot = lazy(() => import('../runs/ScheduledRunListRoot')); const SnapshotRoot = lazy(() => import('../snapshots/SnapshotRoot')); const GuessJobLocationRoot = lazy(() => import('../workspace/GuessJobLocationRoot')); +const SettingsRoot = lazy(() => import('../settings/SettingsRoot')); export const ContentRoot = memo(() => { const {pathname} = useLocation(); @@ -98,6 +99,11 @@ export const ContentRoot = memo(() => { + + }> + + + }> diff --git a/js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx b/js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx index 2fc2910941675..c018f6c835d60 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx @@ -14,6 +14,7 @@ export const FeatureFlag = { flagUseNewAutomationPage: 'flagUseNewAutomationPage' as const, flagUseNewOverviewPage: 'flagUseNewOverviewPage' as const, flagExperimentalBranchDiff: 'flagExperimentalBranchDiff' as const, + flagSettingsPage: 'flagSettingsPage' as const, }; export type FeatureFlagType = keyof typeof FeatureFlag; diff --git a/js_modules/dagster-ui/packages/ui-core/src/instance/CodeLocationsPage.tsx b/js_modules/dagster-ui/packages/ui-core/src/instance/CodeLocationsPage.tsx index 4b6da8fb240bf..6a0e3ef7adb5f 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/instance/CodeLocationsPage.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/instance/CodeLocationsPage.tsx @@ -12,11 +12,10 @@ import {WorkspaceContext} from '../workspace/WorkspaceContext'; const SEARCH_THRESHOLD = 10; -export const CodeLocationsPage = () => { +export const CodeLocationsPageContent = () => { useTrackPageView(); useDocumentTitle('Code locations'); - const {pageTitle} = React.useContext(InstancePageContext); const {locationEntries, loading} = React.useContext(WorkspaceContext); const [searchValue, setSearchValue] = React.useState(''); @@ -42,8 +41,7 @@ export const CodeLocationsPage = () => { }; return ( - - {pageTitle}} tabs={} /> + <> { codeLocations={filtered} searchValue={searchValue} /> + + ); +}; + +export const CodeLocationsPage = () => { + const {pageTitle} = React.useContext(InstancePageContext); + return ( + + {pageTitle}} tabs={} /> + ); }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/instance/DaemonList.tsx b/js_modules/dagster-ui/packages/ui-core/src/instance/DaemonList.tsx index 4b7f62d6e863b..9a3cb22521ad9 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/instance/DaemonList.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/instance/DaemonList.tsx @@ -55,8 +55,8 @@ export const DaemonList = ({daemonStatuses, showTimestampColumn = true}: Props) - - + + {showTimestampColumn && } diff --git a/js_modules/dagster-ui/packages/ui-core/src/instance/InstanceConcurrency.tsx b/js_modules/dagster-ui/packages/ui-core/src/instance/InstanceConcurrency.tsx index efa2a1c7f2a50..c2b48997d24c6 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/instance/InstanceConcurrency.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/instance/InstanceConcurrency.tsx @@ -48,7 +48,12 @@ import { SetConcurrencyLimitMutationVariables, } from './types/InstanceConcurrency.types'; import {showSharedToaster} from '../app/DomUtils'; -import {FIFTEEN_SECONDS, useQueryRefreshAtInterval} from '../app/QueryRefresh'; +import { + FIFTEEN_SECONDS, + QueryRefreshCountdown, + QueryRefreshState, + useQueryRefreshAtInterval, +} from '../app/QueryRefresh'; import {COMMON_COLLATOR} from '../app/Util'; import {useTrackPageView} from '../app/analytics'; import {RunStatus} from '../graphql/types'; @@ -61,10 +66,10 @@ import {TimeElapsed} from '../runs/TimeElapsed'; const DEFAULT_MIN_VALUE = 1; const DEFAULT_MAX_VALUE = 1000; -const InstanceConcurrencyPage = React.memo(() => { +export const InstanceConcurrencyPageContent = React.memo(() => { useTrackPageView(); useDocumentTitle('Concurrency'); - const {pageTitle} = React.useContext(InstancePageContext); + const queryResult = useQuery< InstanceConcurrencyLimitsQuery, InstanceConcurrencyLimitsQueryVariables @@ -76,15 +81,12 @@ const InstanceConcurrencyPage = React.memo(() => { const {data} = queryResult; return ( - - {pageTitle}} - tabs={} - /> + <> {data ? ( <> @@ -103,10 +105,23 @@ const InstanceConcurrencyPage = React.memo(() => { )} - + ); }); +export const InstanceConcurrencyPage = () => { + const {pageTitle} = React.useContext(InstancePageContext); + return ( + + {pageTitle}} + tabs={} + /> + + + ); +}; + // Imported via React.lazy, which requires a default export. // eslint-disable-next-line import/no-default-export export default InstanceConcurrencyPage; @@ -130,16 +145,23 @@ export const RunConcurrencyContent = ({ hasRunQueue, runQueueConfig, onEdit, + refreshState, }: { hasRunQueue: boolean; runQueueConfig: RunQueueConfigFragment | null | undefined; + refreshState?: QueryRefreshState; onEdit?: () => void; }) => { if (!hasRunQueue) { return ( <> - + Run concurrency + {refreshState ? : null}
Run concurrency is not supported with this run coordinator. To enable run concurrency @@ -158,7 +180,7 @@ export const RunConcurrencyContent = ({ ); } - const info_content = ( + const infoContent = ( Run concurrency can be set in your run queue settings. See the{' '}
- + @@ -200,27 +220,34 @@ export const RunConcurrencyContent = ({ return ( <> - - {info_content} + + {infoContent} {settings_content} ); }; -const RunConcurrencyLimitHeader = ({onEdit}: {onEdit?: () => void}) => ( +const RunConcurrencyLimitHeader = ({ + onEdit, + refreshState, +}: { + onEdit?: () => void; + refreshState?: QueryRefreshState; +}) => ( Run concurrency - {onEdit ? ( - - ) : ( - - )} + + {refreshState ? : null} + {onEdit ? ( + + ) : null} + ); @@ -399,12 +426,10 @@ const ConcurrencyLimitHeader = ({onAdd}: {onAdd?: () => void}) => ( padding={{vertical: 16, horizontal: 24}} border="top-and-bottom" > - - - Global op/asset concurrency - Experimental - - + + Global op/asset concurrency + Experimental + {onAdd ? ( @@ -34,7 +40,7 @@ export const ReloadAllButton = ({label = 'Reload all'}: {label?: string}) => { return ( <> - {errorLocationId ? (
DaemonStatusDaemonStatusLast heartbeat
Max concurrent runs: - {runQueueConfig.maxConcurrentRuns} - {runQueueConfig.maxConcurrentRuns}
Tag concurrency limits: