Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix disabling buttons
  • Loading branch information
presleyp committed Dec 16, 2022
commit 35a77fb122bb08cabb4b2e797cdb19def6b0146c
1 change: 0 additions & 1 deletion site/src/components/Workspace/Workspace.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ Running.args = {
return canExtendDeadline(
dayjs(Mocks.MockWorkspace.latest_build.deadline),
Mocks.MockWorkspace,
Mocks.MockTemplate,
)
},
maxDeadlineDecrease: 1000,
Expand Down
4 changes: 0 additions & 4 deletions site/src/components/Workspace/Workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ export interface WorkspaceProps {
scheduleProps: {
onDeadlinePlus: (hours: number) => void
onDeadlineMinus: (hours: number) => void
deadlinePlusEnabled: () => boolean
deadlineMinusEnabled: () => boolean
maxDeadlineIncrease: number
maxDeadlineDecrease: number
}
Expand Down Expand Up @@ -131,8 +129,6 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
workspace={workspace}
onDeadlineMinus={scheduleProps.onDeadlineMinus}
onDeadlinePlus={scheduleProps.onDeadlinePlus}
deadlineMinusEnabled={scheduleProps.deadlineMinusEnabled}
deadlinePlusEnabled={scheduleProps.deadlinePlusEnabled}
maxDeadlineDecrease={scheduleProps.maxDeadlineDecrease}
maxDeadlineIncrease={scheduleProps.maxDeadlineIncrease}
canUpdateWorkspace={canUpdateWorkspace}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ export interface WorkspaceScheduleButtonProps {
workspace: Workspace
onDeadlinePlus: (hours: number) => void
onDeadlineMinus: (hours: number) => void
deadlineMinusEnabled: () => boolean
deadlinePlusEnabled: () => boolean
maxDeadlineIncrease: number
maxDeadlineDecrease: number
canUpdateWorkspace: boolean
Expand All @@ -63,8 +61,6 @@ export const WorkspaceScheduleButton: React.FC<
workspace,
onDeadlinePlus,
onDeadlineMinus,
deadlinePlusEnabled,
deadlineMinusEnabled,
maxDeadlineDecrease,
maxDeadlineIncrease,
canUpdateWorkspace,
Expand All @@ -75,6 +71,8 @@ export const WorkspaceScheduleButton: React.FC<
const [editMode, setEditMode] = useState<EditMode>("off")
const id = isOpen ? "schedule-popover" : undefined
const styles = useStyles({ editMode })
const deadlinePlusEnabled = maxDeadlineIncrease >= 1
const deadlineMinusEnabled = maxDeadlineDecrease >= 1

const onClose = () => {
setIsOpen(false)
Expand Down Expand Up @@ -108,7 +106,7 @@ export const WorkspaceScheduleButton: React.FC<
<IconButton
className={styles.subtractButton}
size="small"
disabled={!deadlineMinusEnabled()}
disabled={!deadlineMinusEnabled}
onClick={() => {
setEditMode("subtract")
}}
Expand All @@ -122,7 +120,7 @@ export const WorkspaceScheduleButton: React.FC<
<IconButton
className={styles.addButton}
size="small"
disabled={!deadlinePlusEnabled()}
disabled={!deadlinePlusEnabled}
onClick={() => {
setEditMode("add")
}}
Expand Down
21 changes: 8 additions & 13 deletions site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Helmet } from "react-helmet-async"
import { useTranslation } from "react-i18next"
import { useNavigate } from "react-router-dom"
import {
getDeadline,
getMaxDeadline,
getMaxDeadlineChange,
getMinDeadline,
Expand Down Expand Up @@ -37,10 +38,9 @@ export const WorkspaceReadyPage = ({
quotaState,
workspaceSend,
}: WorkspaceReadyPageProps): JSX.Element => {
const [bannerState, bannerSend] = useActor(
const [_, bannerSend] = useActor(
workspaceState.children["scheduleBannerMachine"],
)
const deadline = bannerState.context.deadline
const xServices = useContext(XServiceContext)
const featureVisibility = useSelector(
xServices.entitlementsXService,
Expand All @@ -61,6 +61,7 @@ export const WorkspaceReadyPage = ({
if (workspace === undefined) {
throw Error("Workspace is undefined")
}
const deadline = getDeadline(workspace)
const canUpdateWorkspace = Boolean(permissions?.updateWorkspace)
const { t } = useTranslation("workspacePage")
const favicon = getFaviconByStatus(workspace.latest_build)
Expand Down Expand Up @@ -101,17 +102,11 @@ export const WorkspaceReadyPage = ({
hours,
})
},
deadlineMinusEnabled: () => !bannerState.matches("atMinDeadline"),
deadlinePlusEnabled: () => !bannerState.matches("atMaxDeadline"),
maxDeadlineDecrease: deadline
? getMaxDeadlineChange(deadline, getMinDeadline())
: 0,
maxDeadlineIncrease: deadline
? getMaxDeadlineChange(
getMaxDeadline(workspace),
deadline,
)
: 0,
maxDeadlineDecrease: getMaxDeadlineChange(deadline, getMinDeadline()),
maxDeadlineIncrease: getMaxDeadlineChange(
getMaxDeadline(workspace),
deadline,
)
}}
isUpdating={workspaceState.hasTag("updating")}
workspace={workspace}
Expand Down
31 changes: 25 additions & 6 deletions site/src/util/schedule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,26 +65,45 @@ describe("minDeadline", () => {
})

describe("canExtendDeadline", () => {
it("should be falsy if the deadline is more than 24 hours in the future", () => {
it("should be falsy if the deadline is more than 24 hours from the start time", () => {
expect(
canExtendDeadline(
startTime.add(25, "hours"),
Mocks.MockWorkspace,
),
).toBeFalsy()
})
it("should be falsy if the deadline is less than an hour below the max deadline", () => {
expect(
canExtendDeadline(
startTime.add(23.5, "hours"),
Mocks.MockWorkspace
)
).toBeFalsy()
})
it("should be true if the deadline is one hour below the max deadline", () => {
expect(
canExtendDeadline(
startTime.add(23, "hours"),
Mocks.MockWorkspace
)
).toBeTruthy()
})
})

describe("canReduceDeadline", () => {
it("should be falsy if the deadline is 30 minutes or less in the future", () => {
// the minimum ttl is 30 minutes from the current time
// ttl can be reduced by one hour at a time
// so current deadline must be >=90 minutes from current time to be reducible
it("should be falsy if the deadline is 90 minutes or less in the future", () => {
expect(canReduceDeadline(dayjs())).toBeFalsy()
expect(canReduceDeadline(dayjs().add(1, "minutes"))).toBeFalsy()
expect(canReduceDeadline(dayjs().add(29, "minutes"))).toBeFalsy()
expect(canReduceDeadline(dayjs().add(30, "minutes"))).toBeFalsy()
expect(canReduceDeadline(dayjs().add(89, "minutes"))).toBeFalsy()
expect(canReduceDeadline(dayjs().add(90, "minutes"))).toBeTruthy()
})

it("should be truthy if the deadline is 30 minutes or more in the future", () => {
expect(canReduceDeadline(dayjs().add(31, "minutes"))).toBeTruthy()
it("should be truthy if the deadline is 90 minutes or more in the future", () => {
expect(canReduceDeadline(dayjs().add(91, "minutes"))).toBeTruthy()
expect(canReduceDeadline(dayjs().add(100, "years"))).toBeTruthy()
})
})
Expand Down
18 changes: 16 additions & 2 deletions site/src/util/schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,29 @@ export function getMinDeadline(): dayjs.Dayjs {
return dayjs().add(deadlineExtensionMin)
}

/**
* Determines if ScheduleBanner can increase ttl by one or more hours
* without hitting the global max deadline.
* @param deadline
* @param workspace
*/
export function canExtendDeadline(
deadline: dayjs.Dayjs,
workspace: Workspace,
): boolean {
return deadline < getMaxDeadline(workspace)
const diff = (getMaxDeadline(workspace)).diff(deadline, 'hours')
return diff >= 1
}

/**
* Determines if ScheduleBanner can reduce ttl by one or more hours
* without hitting the global min remaining time to live.
* Depends on workspace deadline, current time, and a global constant.
* @param deadline current workspace deadline
*/
export function canReduceDeadline(deadline: dayjs.Dayjs): boolean {
return deadline > getMinDeadline()
const diff = deadline.diff(getMinDeadline(), 'hours')
return diff >= 1
}

export const getDeadline = (workspace: Workspace): dayjs.Dayjs =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const Language = {

export interface WorkspaceScheduleBannerContext {
workspace: Workspace
deadline?: dayjs.Dayjs
}

export type WorkspaceScheduleBannerEvent =
Expand Down Expand Up @@ -135,15 +134,17 @@ export const workspaceScheduleBannerMachine = createMachine(
},
{
guards: {
isAtMaxDeadline: (context) =>
context.deadline
isAtMaxDeadline: (context) => {
return context.workspace.latest_build.deadline
? !canExtendDeadline(
context.deadline,
getDeadline(context.workspace),
context.workspace,
)
: false,
isAtMinDeadline: (context) =>
context.deadline ? !canReduceDeadline(context.deadline) : false,
: false
},
isAtMinDeadline: (context) => {
return context.workspace.latest_build.deadline ? !canReduceDeadline(getDeadline(context.workspace)) : false
}
},
actions: {
// This error does not have a detail, so using the snackbar is okay
Expand All @@ -155,27 +156,26 @@ export const workspaceScheduleBannerMachine = createMachine(
},
assignWorkspace: assign((_, event) => ({
workspace: event.workspace,
deadline: getDeadline(event.workspace),
})),
},

services: {
increaseDeadline: async (context, event) => {
if (!context.deadline) {
if (!context.workspace.latest_build.deadline) {
throw Error("Deadline is undefined.")
}
const proposedDeadline = context.deadline.add(event.hours, "hours")
const proposedDeadline = getDeadline(context.workspace).add(event.hours, "hours")
const newDeadline = dayjs.min(
proposedDeadline,
getMaxDeadline(context.workspace),
)
await API.putWorkspaceExtension(context.workspace.id, newDeadline)
},
decreaseDeadline: async (context, event) => {
if (!context.deadline) {
if (!context.workspace.latest_build.deadline) {
throw Error("Deadline is undefined.")
}
const proposedDeadline = context.deadline.subtract(event.hours, "hours")
const proposedDeadline = getDeadline(context.workspace).subtract(event.hours, "hours")
const newDeadline = dayjs.max(proposedDeadline, getMinDeadline())
await API.putWorkspaceExtension(context.workspace.id, newDeadline)
},
Expand Down