Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration owner settings #528

Merged
merged 11 commits into from
Mar 13, 2023
54 changes: 28 additions & 26 deletions src/components/chips/TaskDurationChip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import Avatar from '@mui/material/Avatar';
import Chip from '@mui/material/Chip';
import Icon from '@mui/material/Icon';
import { graphql } from 'babel-plugin-relay/macro';
import React, { useEffect } from 'react';
import { createFragmentContainer, requestSubscription } from 'react-relay';
import React, { useEffect, useMemo } from 'react';
import { useFragment, requestSubscription } from 'react-relay';
import environment from '../../createRelayEnvironment';
import { useTaskStatusColor } from '../../utils/colors';
import { isTaskFinalStatus, isTaskInProgressStatus, taskStatusIconName } from '../../utils/status';
import { formatDuration } from '../../utils/time';
import { TaskDurationChip_task } from './__generated__/TaskDurationChip_task.graphql';
import { TaskDurationChip_task$key } from './__generated__/TaskDurationChip_task.graphql';
import { useTheme } from '@mui/material';

const taskSubscription = graphql`
Expand All @@ -20,19 +20,34 @@ const taskSubscription = graphql`
`;

interface Props {
task: TaskDurationChip_task;
task: TaskDurationChip_task$key;
className?: string;
}

function TaskDurationChip(props: Props) {
export default function TaskDurationChip(props: Props) {
let task = useFragment(
graphql`
fragment TaskDurationChip_task on Task {
id
status
creationTimestamp
scheduledTimestamp
executingTimestamp
durationInSeconds
}
`,
props.task,
);

let theme = useTheme();

const isFinalStatus = useMemo(() => isTaskFinalStatus(task.status), [task.status]);
useEffect(() => {
if (isTaskFinalStatus(props.task.status)) {
if (isFinalStatus) {
return;
}

let variables = { taskID: props.task.id };
let variables = { taskID: task.id };

const subscription = requestSubscription(environment, {
subscription: taskSubscription,
Expand All @@ -41,26 +56,26 @@ function TaskDurationChip(props: Props) {
return () => {
subscription.dispose();
};
}, [props.task.id, props.task.status]);
}, [task.id, isFinalStatus]);

const [now, setNow] = React.useState(Date.now());

useEffect(() => {
if (isTaskFinalStatus(props.task.status)) {
if (isFinalStatus) {
return;
}
const timeoutId = setInterval(() => {
setNow(Date.now());
}, 1_000);
return () => clearInterval(timeoutId);
}, [now, props.task.status]);
}, [now, isFinalStatus]);

let { task, className } = props;
let { className } = props;

let durationInSeconds = task.durationInSeconds;
if (!isTaskInProgressStatus(task.status) && !isTaskFinalStatus(task.status)) {
if (!isTaskInProgressStatus(task.status) && !isFinalStatus) {
durationInSeconds = 0;
} else if (!isTaskFinalStatus(task.status)) {
} else if (!isFinalStatus) {
let timestamp = Math.max(task.creationTimestamp, task.scheduledTimestamp, task.executingTimestamp);
durationInSeconds = (Date.now() - timestamp) / 1000;
}
Expand All @@ -77,16 +92,3 @@ function TaskDurationChip(props: Props) {
/>
);
}

export default createFragmentContainer(TaskDurationChip, {
task: graphql`
fragment TaskDurationChip_task on Task {
id
status
creationTimestamp
scheduledTimestamp
executingTimestamp
durationInSeconds
}
`,
});
32 changes: 16 additions & 16 deletions src/components/compute-credits/BillingSettingsButton.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
import React, { useState } from 'react';
import { createFragmentContainer } from 'react-relay';
import { useFragment } from 'react-relay';
import { graphql } from 'babel-plugin-relay/macro';
import AlarmOffIcon from '@mui/icons-material/AlarmOff';
import AlarmOnIcon from '@mui/icons-material/AlarmOn';
import Button from '@mui/material/Button';
import BillingSettingsDialog from './BillingSettingsDialog';
import { BillingSettingsButton_info } from './__generated__/BillingSettingsButton_info.graphql';
import { BillingSettingsButton_info$key } from './__generated__/BillingSettingsButton_info.graphql';

interface Props {
info: BillingSettingsButton_info;
info: BillingSettingsButton_info$key;
className?: string;
}

function BillingSettingsButton(props: Props) {
export default function BillingSettingsButton(props: Props) {
let info = useFragment(
graphql`
fragment BillingSettingsButton_info on OwnerInfo {
billingSettings {
enabled
...BillingSettingsDialog_billingSettings
}
}
`,
props.info,
);
let [openDialog, setOpenDialog] = useState(false);
let { info, className } = props;
let { className } = props;
if (!info) return null;

let { billingSettings } = info;
Expand All @@ -37,14 +48,3 @@ function BillingSettingsButton(props: Props) {
</div>
);
}

export default createFragmentContainer(BillingSettingsButton, {
info: graphql`
fragment BillingSettingsButton_info on OwnerInfo {
billingSettings {
enabled
...BillingSettingsDialog_billingSettings
}
}
`,
});
71 changes: 34 additions & 37 deletions src/components/compute-credits/BillingSettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import Switch from '@mui/material/Switch';
import Typography from '@mui/material/Typography';
import { graphql } from 'babel-plugin-relay/macro';
import React, { useState } from 'react';
import { commitMutation, createFragmentContainer } from 'react-relay';
import environment from '../../createRelayEnvironment';
import { useMutation, useFragment } from 'react-relay';
import {
BillingSettingsDialogMutation,
BillingSettingsDialogMutationResponse,
BillingSettingsDialogMutationVariables,
} from './__generated__/BillingSettingsDialogMutation.graphql';
import { BillingSettingsDialog_billingSettings } from './__generated__/BillingSettingsDialog_billingSettings.graphql';
import { BillingSettingsDialog_billingSettings$key } from './__generated__/BillingSettingsDialog_billingSettings.graphql';
import { Link } from '@mui/material';

const useStyles = makeStyles(theme => {
Expand All @@ -33,31 +33,28 @@ const useStyles = makeStyles(theme => {
};
});

const saveBillingSettingsMutation = graphql`
mutation BillingSettingsDialogMutation($input: BillingSettingsInput!) {
saveBillingSettings(input: $input) {
settings {
ownerUid
enabled
billingCreditsLimit
billingEmailAddress
invoiceTemplate
}
}
}
`;

interface Props {
billingSettings: BillingSettingsDialog_billingSettings;
billingSettings: BillingSettingsDialog_billingSettings$key;

onClose(...args: any[]): void;

open: boolean;
}

function BillingSettingsDialog(props: Props) {
export default function BillingSettingsDialog(props: Props) {
let billingSettings = useFragment(
graphql`
fragment BillingSettingsDialog_billingSettings on BillingSettings {
ownerUid
enabled
billingCreditsLimit
billingEmailAddress
invoiceTemplate
}
`,
props.billingSettings,
);
let classes = useStyles();
const { billingSettings, ...other } = props;
let [enabled, setEnabled] = useState(billingSettings.enabled);
let [billingEmailAddress, setBillingEmailAddress] = useState(billingSettings.billingEmailAddress);
let [invoiceTemplate, setInvoiceTemplate] = useState(billingSettings.invoiceTemplate);
Expand All @@ -67,18 +64,30 @@ function BillingSettingsDialog(props: Props) {
billingSettings.billingEmailAddress === billingEmailAddress &&
billingSettings.invoiceTemplate === invoiceTemplate;

const [commitSaveBillingSettingsMutation] = useMutation<BillingSettingsDialogMutation>(graphql`
mutation BillingSettingsDialogMutation($input: BillingSettingsInput!) {
saveBillingSettings(input: $input) {
settings {
ownerUid
enabled
billingCreditsLimit
billingEmailAddress
invoiceTemplate
}
}
}
`);
function updateSettings() {
const variables: BillingSettingsDialogMutationVariables = {
input: {
clientMutationId: 'save-billing-settings-' + props.billingSettings.ownerUid,
ownerUid: props.billingSettings.ownerUid,
clientMutationId: 'save-billing-settings-' + billingSettings.ownerUid,
ownerUid: billingSettings.ownerUid,
enabled: enabled,
billingEmailAddress: billingEmailAddress,
invoiceTemplate: invoiceTemplate,
},
};
commitMutation(environment, {
mutation: saveBillingSettingsMutation,
commitSaveBillingSettingsMutation({
variables: variables,
onCompleted: (response: BillingSettingsDialogMutationResponse, errors) => {
if (errors) {
Expand All @@ -95,7 +104,7 @@ function BillingSettingsDialog(props: Props) {
}

return (
<Dialog {...other}>
<Dialog onClose={props.onClose} open={props.open}>
<DialogTitle>Compute Credits Auto Pay</DialogTitle>
<DialogContent>
<FormControl fullWidth>
Expand Down Expand Up @@ -147,15 +156,3 @@ function BillingSettingsDialog(props: Props) {
</Dialog>
);
}

export default createFragmentContainer(BillingSettingsDialog, {
billingSettings: graphql`
fragment BillingSettingsDialog_billingSettings on BillingSettings {
ownerUid
enabled
billingCreditsLimit
billingEmailAddress
invoiceTemplate
}
`,
});
27 changes: 14 additions & 13 deletions src/components/compute-credits/ComputeCreditsBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import { makeStyles } from '@mui/styles';
import classNames from 'classnames';
import React, { useState } from 'react';
import BillingSettingsButton from './BillingSettingsButton';
import { createFragmentContainer } from 'react-relay';
import { useFragment } from 'react-relay';
import { graphql } from 'babel-plugin-relay/macro';
import { ComputeCreditsBase_info } from './__generated__/ComputeCreditsBase_info.graphql';
import { ComputeCreditsBase_info$key } from './__generated__/ComputeCreditsBase_info.graphql';
import { Helmet as Head } from 'react-helmet';
import ComputeCreditsStripeDialog from './ComputeCreditsStripeDialog';
import { Link } from '@mui/material';
Expand Down Expand Up @@ -58,12 +58,21 @@ const useStyles = makeStyles(theme => {

interface Props {
transactionsComponent: JSX.Element;
info?: ComputeCreditsBase_info;
info?: ComputeCreditsBase_info$key;
balanceInCredits?: string;
ownerUid: string;
}

function ComputeCreditsBase(props: Props) {
export default function ComputeCreditsBase(props: Props) {
let info = useFragment(
graphql`
fragment ComputeCreditsBase_info on OwnerInfo {
...BillingSettingsButton_info
}
`,
props.info,
);

let [expanded, setExpanded] = useState(false);
let [openBuyCredits, setOpenBuyCredits] = useState(false);
let classes = useStyles();
Expand Down Expand Up @@ -102,7 +111,7 @@ function ComputeCreditsBase(props: Props) {
<AttachMoneyIcon />
Add More Credits
</Button>
<BillingSettingsButton info={props.info} />
<BillingSettingsButton info={info} />
<IconButton
className={classNames(classes.expand, {
[classes.expandOpen]: expanded,
Expand All @@ -126,11 +135,3 @@ function ComputeCreditsBase(props: Props) {
</Card>
);
}

export default createFragmentContainer(ComputeCreditsBase, {
info: graphql`
fragment ComputeCreditsBase_info on OwnerInfo {
...BillingSettingsButton_info
}
`,
});
Loading