Skip to content

Commit

Permalink
Make handleLaunchResult agnostic to the query that returned the data (#…
Browse files Browse the repository at this point in the history
…10179)

* make handleLaunchResult agnostic to the query that returned the data

* rm unused import

* also add hook for feature gate UI

* allow passing label element

* rm toString

* rm feature gate context

* export rows
  • Loading branch information
salazarm committed Oct 26, 2022
1 parent bad2e44 commit bd6e269
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 100 deletions.
28 changes: 15 additions & 13 deletions js_modules/dagit/packages/core/src/app/Flags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,38 @@ import {getJSONForKey} from '../hooks/useStateWithStorage';

export const DAGIT_FLAGS_KEY = 'DAGIT_FLAGS';

export enum FeatureFlag {
flagDebugConsoleLogging = 'flagDebugConsoleLogging',
flagDisableWebsockets = 'flagDisableWebsockets',
flagNewWorkspace = 'flagNewWorkspace',
flagNewAssetDetails = 'flagNewAssetDetails',
flagAssetGraphExperimentalZoom = 'flagAssetGraphExperimentalZoom',
}

export const getFeatureFlags: () => FeatureFlag[] = memoize(
// Use const because we need to extend this in cloud. https://blog.logrocket.com/extend-enums-typescript/
export const FeatureFlag = {
flagDebugConsoleLogging: 'flagDebugConsoleLogging' as const,
flagDisableWebsockets: 'flagDisableWebsockets' as const,
flagNewWorkspace: 'flagNewWorkspace' as const,
flagNewAssetDetails: 'flagNewAssetDetails' as const,
flagAssetGraphExperimentalZoom: 'flagAssetGraphExperimentalZoom' as const,
};
export type FeatureFlagType = keyof typeof FeatureFlag;

export const getFeatureFlags: () => FeatureFlagType[] = memoize(
() => getJSONForKey(DAGIT_FLAGS_KEY) || [],
);

export const featureEnabled = memoize((flag: FeatureFlag) => getFeatureFlags().includes(flag));
export const featureEnabled = memoize((flag: FeatureFlagType) => getFeatureFlags().includes(flag));

type FlagMap = {
readonly [F in FeatureFlag]: boolean;
readonly [F in FeatureFlagType]: boolean;
};

export const useFeatureFlags = () => {
return React.useMemo(() => {
const flagSet = new Set(getFeatureFlags());
const all = {};
for (const flag in FeatureFlag) {
all[flag] = flagSet.has(flag as FeatureFlag);
all[flag] = flagSet.has(flag as FeatureFlagType);
}
return all as FlagMap;
}, []);
};

export const setFeatureFlags = (flags: FeatureFlag[]) => {
export const setFeatureFlags = (flags: FeatureFlagType[]) => {
if (!(flags instanceof Array)) {
throw new Error('flags must be an array');
}
Expand Down
119 changes: 62 additions & 57 deletions js_modules/dagit/packages/core/src/app/UserSettingsRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import * as React from 'react';
import {useDocumentTitle} from '../hooks/useDocumentTitle';
import {useStateWithStorage} from '../hooks/useStateWithStorage';

import {FeatureFlag, getFeatureFlags, setFeatureFlags} from './Flags';
import {FeatureFlag, FeatureFlagType, getFeatureFlags, setFeatureFlags} from './Flags';
import {SHORTCUTS_STORAGE_KEY} from './ShortcutHandler';
import {useTrackPageView} from './analytics';
import {TimezoneSelect} from './time/TimezoneSelect';
Expand All @@ -26,7 +26,7 @@ const UserSettingsRoot: React.FC<SettingsRootProps> = ({tabs}) => {
useTrackPageView();
useDocumentTitle('User settings');

const [flags, setFlags] = React.useState<FeatureFlag[]>(() => getFeatureFlags());
const [flags, setFlags] = React.useState<FeatureFlagType[]>(() => getFeatureFlags());
const [shortcutsEnabled, setShortcutsEnabled] = useStateWithStorage(
SHORTCUTS_STORAGE_KEY,
(value: any) => (typeof value === 'boolean' ? value : true),
Expand All @@ -36,7 +36,7 @@ const UserSettingsRoot: React.FC<SettingsRootProps> = ({tabs}) => {
setFeatureFlags(flags);
});

const toggleFlag = (flag: FeatureFlag) => {
const toggleFlag = (flag: FeatureFlagType) => {
setFlags(flags.includes(flag) ? flags.filter((f) => f !== flag) : [...flags, flag]);
window.location.reload();
};
Expand Down Expand Up @@ -94,65 +94,70 @@ const UserSettingsRoot: React.FC<SettingsRootProps> = ({tabs}) => {
<Box padding={{bottom: 8}}>
<Subheading>Experimental features</Subheading>
</Box>
<MetadataTable
rows={[
{
key: 'Debug console logging',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagDebugConsoleLogging)}
onChange={() => toggleFlag(FeatureFlag.flagDebugConsoleLogging)}
/>
),
},
{
key: 'Disable WebSockets',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagDisableWebsockets)}
onChange={() => toggleFlag(FeatureFlag.flagDisableWebsockets)}
/>
),
},
{
key: 'New workspace pages, overview pages, and top navigation',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagNewWorkspace)}
onChange={() => toggleFlag(FeatureFlag.flagNewWorkspace)}
/>
),
},
{
key: 'New asset detail pages',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagNewAssetDetails)}
onChange={() => toggleFlag(FeatureFlag.flagNewAssetDetails)}
/>
),
},
{
key: 'Experimental "groups-only" asset graph zoom level',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagAssetGraphExperimentalZoom)}
onChange={() => toggleFlag(FeatureFlag.flagAssetGraphExperimentalZoom)}
/>
),
},
]}
/>
<MetadataTable rows={getFeatureFlagRows(flags, toggleFlag)} />
</Box>
</div>
);
};

export function getFeatureFlagRows(
flags: FeatureFlagType[],
toggleFlag: (flag: FeatureFlagType) => void,
) {
return [
{
key: 'Debug console logging',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagDebugConsoleLogging)}
onChange={() => toggleFlag(FeatureFlag.flagDebugConsoleLogging)}
/>
),
},
{
key: 'Disable WebSockets',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagDisableWebsockets)}
onChange={() => toggleFlag(FeatureFlag.flagDisableWebsockets)}
/>
),
},
{
key: 'New workspace pages, overview pages, and top navigation',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagNewWorkspace)}
onChange={() => toggleFlag(FeatureFlag.flagNewWorkspace)}
/>
),
},
{
key: 'New asset detail pages',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagNewAssetDetails)}
onChange={() => toggleFlag(FeatureFlag.flagNewAssetDetails)}
/>
),
},
{
key: 'Experimental "groups-only" asset graph zoom level',
value: (
<Checkbox
format="switch"
checked={flags.includes(FeatureFlag.flagAssetGraphExperimentalZoom)}
onChange={() => toggleFlag(FeatureFlag.flagAssetGraphExperimentalZoom)}
/>
),
},
];
}

// Imported via React.lazy, which requires a default export.
// eslint-disable-next-line import/no-default-export
export default UserSettingsRoot;
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export function useLaunchWithTelemetry() {
const result = await launchPipelineExecution({variables});
logTelemetry(TelemetryAction.LAUNCH_RUN, metadata);
try {
handleLaunchResult(jobName, result, history, {behavior});
handleLaunchResult(jobName, result.data?.launchPipelineExecution, history, {behavior});
} catch (error) {
showLaunchError(error as Error);
}
Expand Down
11 changes: 8 additions & 3 deletions js_modules/dagit/packages/core/src/runs/RunActionsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,14 @@ export const RunActionsMenu: React.FC<{
repositoryName: repoMatch.match.repository.name,
}),
});
handleLaunchResult(run.pipelineName, result, history, {
behavior: 'open',
});
handleLaunchResult(
run.pipelineName,
result.data?.launchPipelineReexecution,
history,
{
behavior: 'open',
},
);
}
}}
/>
Expand Down
32 changes: 12 additions & 20 deletions js_modules/dagit/packages/core/src/runs/RunUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import {ExecutionParams, RunStatus} from '../types/globalTypes';
import {DagsterTag} from './RunTag';
import {StepSelection} from './StepSelection';
import {TimeElapsed} from './TimeElapsed';
import {LaunchPipelineExecution} from './types/LaunchPipelineExecution';
import {LaunchPipelineReexecution} from './types/LaunchPipelineReexecution';
import {LaunchPipelineExecution_launchPipelineExecution} from './types/LaunchPipelineExecution';
import {RunFragment} from './types/RunFragment';
import {RunTableRunFragment} from './types/RunTableRunFragment';
import {RunTimeFragment} from './types/RunTimeFragment';
Expand Down Expand Up @@ -65,24 +64,17 @@ export type LaunchBehavior = 'open' | 'open-in-new-tab' | 'toast';

export function handleLaunchResult(
pipelineName: string,
result: void | {data?: LaunchPipelineExecution | LaunchPipelineReexecution | null},
result: void | null | LaunchPipelineExecution_launchPipelineExecution,
history: History<unknown>,
options: {behavior: LaunchBehavior; preserveQuerystring?: boolean},
) {
const obj =
result && result.data && 'launchPipelineExecution' in result.data
? result.data.launchPipelineExecution
: result && result.data && 'launchPipelineReexecution' in result.data
? result.data.launchPipelineReexecution
: null;

if (!obj) {
if (!result) {
showCustomAlert({body: `No data was returned. Did Dagit crash?`});
return;
}

if (obj.__typename === 'LaunchRunSuccess') {
const pathname = `/instance/runs/${obj.run.runId}`;
if (result.__typename === 'LaunchRunSuccess') {
const pathname = `/instance/runs/${result.run.runId}`;
const search = options.preserveQuerystring ? history.location.search : '';
const openInNewTab = () => window.open(history.createHref({pathname, search}), '_blank');
const openInSameTab = () => history.push({pathname, search});
Expand All @@ -96,7 +88,7 @@ export function handleLaunchResult(
intent: 'success',
message: (
<div>
Launched run <Mono>{obj.run.runId.slice(0, 8)}</Mono>
Launched run <Mono>{result.run.runId.slice(0, 8)}</Mono>
</div>
),
action: {
Expand All @@ -106,18 +98,18 @@ export function handleLaunchResult(
});
}
document.dispatchEvent(new CustomEvent('run-launched'));
} else if (obj.__typename === 'InvalidSubsetError') {
showCustomAlert({body: obj.message});
} else if (obj.__typename === 'PythonError') {
} else if (result.__typename === 'InvalidSubsetError') {
showCustomAlert({body: result.message});
} else if (result.__typename === 'PythonError') {
showCustomAlert({
title: 'Error',
body: <PythonErrorInfo error={obj} />,
body: <PythonErrorInfo error={result} />,
});
} else {
let message = `${pipelineName} cannot be executed with the provided config.`;

if ('errors' in obj) {
message += ` Please fix the following errors:\n\n${obj.errors
if ('errors' in result) {
message += ` Please fix the following errors:\n\n${result.errors
.map((error) => error.message)
.join('\n\n')}`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const useJobReExecution = (run: RunFragment | undefined | null) => {

try {
const result = await launchPipelineReexecution({variables});
handleLaunchResult(run.pipelineName, result, history, {
handleLaunchResult(run.pipelineName, result.data?.launchPipelineReexecution, history, {
preserveQuerystring: true,
behavior: 'open',
});
Expand Down
10 changes: 5 additions & 5 deletions js_modules/dagit/packages/ui/src/components/MetadataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {Box} from './Box';
import {Colors} from './Colors';
import {Table, TableProps} from './Table';

type Row = {key: string; value: React.ReactNode};
export type MetadataTableRow = {key: string; label?: React.ReactNode; value: React.ReactNode};

interface Props {
dark?: boolean;
rows: (Row | null | undefined)[];
rows: (MetadataTableRow | null | undefined)[];
spacing: 0 | 2 | 4;
}

Expand All @@ -19,16 +19,16 @@ export const MetadataTable = (props: Props) => {
return (
<StyledTable>
<tbody>
{rows.map((pair: Row | null | undefined) => {
{rows.map((pair: MetadataTableRow | null | undefined) => {
if (!pair) {
return null;
}
const {key, value} = pair;
const {key, label, value} = pair;
return (
<tr key={key}>
<td>
<Box padding={{vertical: spacing, right: 32}}>
<MetadataKey $dark={dark}>{key}</MetadataKey>
<MetadataKey $dark={dark}>{label ?? key}</MetadataKey>
</Box>
</td>
<td>
Expand Down

1 comment on commit bd6e269

@vercel
Copy link

@vercel vercel bot commented on bd6e269 Oct 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

dagit-storybook – ./js_modules/dagit/packages/ui

dagit-storybook.vercel.app
dagit-storybook-git-master-elementl.vercel.app
dagit-storybook-elementl.vercel.app

Please sign in to comment.