Skip to content

Commit adaa585

Browse files
committed
wip: commit more progress
1 parent bd75671 commit adaa585

File tree

1 file changed

+59
-14
lines changed

1 file changed

+59
-14
lines changed

site/src/pages/WorkspacesPage/BatchUpdateModalForm.tsx

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Loader } from "components/Loader/Loader";
88
import { ErrorAlert } from "components/Alert/ErrorAlert";
99
import { Avatar } from "components/Avatar/Avatar";
1010
import { cn } from "utils/cn";
11+
import _ from "lodash";
1112

1213
/**
1314
* @todo Need to decide if we should include the template display name here, or
@@ -45,13 +46,15 @@ function groupWorkspacesByTemplateVersionId(
4546
return [...grouped.values()];
4647
}
4748

48-
type Separation = Readonly<{
49+
type UpdateTypePartition = Readonly<{
4950
dormant: readonly Workspace[];
5051
noUpdateNeeded: readonly Workspace[];
5152
readyToUpdate: readonly Workspace[];
5253
}>;
5354

54-
function separateWorkspaces(workspaces: readonly Workspace[]): Separation {
55+
function separateWorkspacesByUpdateType(
56+
workspaces: readonly Workspace[],
57+
): UpdateTypePartition {
5558
const noUpdateNeeded: Workspace[] = [];
5659
const dormant: Workspace[] = [];
5760
const readyToUpdate: Workspace[] = [];
@@ -74,6 +77,7 @@ function separateWorkspaces(workspaces: readonly Workspace[]): Separation {
7477
type WorkspacePanelProps = Readonly<{
7578
workspaceName: string;
7679
workspaceIconUrl: string;
80+
running?: boolean;
7781
label?: ReactNode;
7882
adornment?: ReactNode;
7983
className?: string;
@@ -144,12 +148,17 @@ const ReviewForm: FC<ReviewFormProps> = ({
144148
// they can be changed by another user + be subject to a query invalidation
145149
// while the form is open
146150
const [cachedWorkspaces, setCachedWorkspaces] = useState(workspacesToUpdate);
151+
// Used to force the user to acknowledge that batch updating has risks in
152+
// certain situations and could destroy their data. Initial value
153+
// deliberately *not* based on any derived values to avoid state sync issues
154+
// as cachedWorkspaces gets refreshed
155+
const [acceptedConsequences, setAcceptedConsequences] = useState(false);
147156

148157
// Dormant workspaces can't be activated without activating them first. For
149158
// now, we'll only show the user that some workspaces can't be updated, and
150159
// then skip over them for all other update logic
151160
const { dormant, noUpdateNeeded, readyToUpdate } =
152-
separateWorkspaces(cachedWorkspaces);
161+
separateWorkspacesByUpdateType(cachedWorkspaces);
153162

154163
// The workspaces don't have all necessary data by themselves, so we need to
155164
// fetch the unique template versions, and massage the results
@@ -167,18 +176,21 @@ const ReviewForm: FC<ReviewFormProps> = ({
167176
? templateVersionQueries.map((q) => q.data)
168177
: undefined;
169178

170-
// Also need to tease apart workspaces that are actively running, because
171-
// there's a whole set of warnings we need to issue about them
172-
const running = readyToUpdate.filter(
179+
const [running, notRunning] = _.partition(
180+
readyToUpdate,
173181
(ws) => ws.latest_build.status === "running",
174182
);
175183

176184
const workspacesChangedWhileOpen = workspacesToUpdate !== cachedWorkspaces;
177-
const updateIsReady = error === undefined && readyToUpdate.length > 0;
185+
const consequencesResolved = running.length === 0 || acceptedConsequences;
186+
const canSubmit =
187+
consequencesResolved &&
188+
error === undefined &&
189+
(running.length > 0 || notRunning.length > 0);
178190

179191
return (
180192
<form
181-
className="max-h-[90vh]"
193+
className="max-h-[80vh]"
182194
onSubmit={(e) => {
183195
e.preventDefault();
184196
onSubmit();
@@ -200,7 +212,10 @@ const ReviewForm: FC<ReviewFormProps> = ({
200212
variant="outline"
201213
size="sm"
202214
disabled={!workspacesChangedWhileOpen}
203-
onClick={() => setCachedWorkspaces(workspacesToUpdate)}
215+
onClick={() => {
216+
setCachedWorkspaces(workspacesToUpdate);
217+
setAcceptedConsequences(false);
218+
}}
204219
>
205220
Refresh list
206221
</Button>
@@ -211,13 +226,43 @@ const ReviewForm: FC<ReviewFormProps> = ({
211226
<div className="max-w-prose">
212227
<h4 className="m-0">Ready to update</h4>
213228
<p className="m-0 text-sm leading-snug text-content-secondary">
214-
These workspaces have available updates and require no
215-
additional action before updating.
229+
These workspaces require no additional action before
230+
updating.
216231
</p>
217232
</div>
218233

219234
<ul className="list-none p-0 flex flex-col rounded-md border border-solid border-border">
220-
{readyToUpdate.map((ws) => {
235+
{running.map((ws) => {
236+
const matchedQuery = templateVersionQueries.find(
237+
(q) => q.data?.id === ws.template_active_version_id,
238+
);
239+
const newTemplateName = matchedQuery?.data?.name;
240+
241+
return (
242+
<li
243+
key={ws.id}
244+
className="[&:not(:last-child)]:border-b-border [&:not(:last-child)]:border-b [&:not(:last-child)]:border-solid border-0"
245+
>
246+
<ReviewPanel
247+
running
248+
className="border-none"
249+
workspaceName={ws.name}
250+
workspaceIconUrl={ws.template_icon}
251+
label={
252+
newTemplateName !== undefined && (
253+
<TemplateNameChange
254+
newTemplateName={newTemplateName}
255+
oldTemplateName={
256+
ws.latest_build.template_version_name
257+
}
258+
/>
259+
)
260+
}
261+
/>
262+
</li>
263+
);
264+
})}
265+
{notRunning.map((ws) => {
221266
const matchedQuery = templateVersionQueries.find(
222267
(q) => q.data?.id === ws.template_active_version_id,
223268
);
@@ -305,11 +350,11 @@ const ReviewForm: FC<ReviewFormProps> = ({
305350
)}
306351
</div>
307352

308-
<div className="flex flex-row flex-wrap justify-end gap-4 border-0 border-t border-solid border-t-border pt-4">
353+
<div className="flex flex-row flex-wrap justify-end gap-4 border-0 border-t border-solid border-t-border pt-8">
309354
<Button variant="outline" onClick={onCancel}>
310355
Cancel
311356
</Button>
312-
<Button variant="default" type="submit" disabled={!updateIsReady}>
357+
<Button variant="default" type="submit" disabled={!canSubmit}>
313358
Update
314359
</Button>
315360
</div>

0 commit comments

Comments
 (0)