Skip to content

Commit 4672849

Browse files
authored
chore: clean up usage of Object.keys (#14484)
1 parent d2a22c5 commit 4672849

File tree

10 files changed

+83
-111
lines changed

10 files changed

+83
-111
lines changed

site/src/components/Timeline/Timeline.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,12 @@ export const Timeline = <TData,>({
3737

3838
return (
3939
<>
40-
{Object.keys(itemsByDate).map((dateStr) => {
41-
const items = itemsByDate[dateStr];
42-
43-
return (
44-
<Fragment key={dateStr}>
45-
<TimelineDateRow date={new Date(dateStr)} />
46-
{items.map(row)}
47-
</Fragment>
48-
);
49-
})}
40+
{Object.entries(itemsByDate).map(([dateStr, items]) => (
41+
<Fragment key={dateStr}>
42+
<TimelineDateRow date={new Date(dateStr)} />
43+
{items.map(row)}
44+
</Fragment>
45+
))}
5046
</>
5147
);
5248
};

site/src/contexts/ProxyContext.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -233,21 +233,9 @@ const selectByLatency = (
233233
return undefined;
234234
}
235235

236-
const proxyMap = proxies.reduce(
237-
(acc, proxy) => {
238-
acc[proxy.id] = proxy;
239-
return acc;
240-
},
241-
{} as Record<string, Region>,
242-
);
243-
244-
const best = Object.keys(latencies)
245-
.map((proxyId) => {
246-
return {
247-
id: proxyId,
248-
...latencies[proxyId],
249-
};
250-
})
236+
const proxyMap = Object.fromEntries(proxies.map((it) => [it.id, it]));
237+
const best = Object.entries(latencies)
238+
.map(([proxyId, latency]) => ({ id: proxyId, ...latency }))
251239
// If the proxy is not in our list, or it is unhealthy, ignore it.
252240
.filter((latency) => proxyMap[latency.id]?.healthy)
253241
.sort((a, b) => a.latencyMS - b.latencyMS)

site/src/modules/dashboard/entitlements.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ export const getFeatureVisibility = (
1313
return {};
1414
}
1515

16-
const permissionPairs = Object.keys(features).map((feature) => {
17-
const { entitlement, limit, actual, enabled } = features[feature];
18-
const entitled = ["entitled", "grace_period"].includes(entitlement);
19-
const limitCompliant = limit && actual ? limit >= actual : true;
20-
return [feature, entitled && limitCompliant && enabled];
21-
});
16+
const permissionPairs = Object.entries(features).map(
17+
([feature, { entitlement, limit, actual, enabled }]) => {
18+
const entitled = ["entitled", "grace_period"].includes(entitlement);
19+
const limitCompliant = limit && actual ? limit >= actual : true;
20+
return [feature, entitled && limitCompliant && enabled];
21+
},
22+
);
2223
return Object.fromEntries(permissionPairs);
2324
};
2425

site/src/modules/templates/TemplateFiles/TemplateFileTree.tsx

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,23 @@ import { DockerIcon } from "components/Icons/DockerIcon";
99
import { type CSSProperties, type ElementType, type FC, useState } from "react";
1010
import type { FileTree } from "utils/filetree";
1111

12-
const sortFileTree = (fileTree: FileTree) => (a: string, b: string) => {
13-
const contentA = fileTree[a];
14-
const contentB = fileTree[b];
15-
if (typeof contentA === "object") {
16-
return -1;
17-
}
18-
if (typeof contentB === "object") {
19-
return 1;
12+
const isFolder = (content?: FileTree | string): content is FileTree =>
13+
typeof content === "object";
14+
15+
type FileTreeEntry = [key: string, content: FileTree | string];
16+
function compareFileTreeEntries(
17+
[keyA, contentA]: FileTreeEntry,
18+
[keyB, contentB]: FileTreeEntry,
19+
) {
20+
// A and B are either both files or both folders, so they should be sorted
21+
// lexically.
22+
if (isFolder(contentA) === isFolder(contentB)) {
23+
return keyA.localeCompare(keyB);
2024
}
21-
return a.localeCompare(b);
22-
};
25+
// Either A or B is a folder, and the other is a file. Put whichever one is a
26+
// folder first.
27+
return isFolder(contentA) ? -1 : 1;
28+
}
2329

2430
type ContextMenu = {
2531
path: string;
@@ -51,9 +57,6 @@ export const TemplateFileTree: FC<TemplateFilesTreeProps> = ({
5157
}) => {
5258
const [contextMenu, setContextMenu] = useState<ContextMenu | undefined>();
5359

54-
const isFolder = (content?: FileTree | string): content is FileTree =>
55-
typeof content === "object";
56-
5760
const buildTreeItems = (
5861
label: string,
5962
filename: string,
@@ -181,12 +184,11 @@ export const TemplateFileTree: FC<TemplateFilesTreeProps> = ({
181184
}
182185
>
183186
{isFolder(content) &&
184-
Object.keys(content)
185-
.sort(sortFileTree(content))
186-
.map((filename) => {
187-
const child = content[filename];
188-
return buildTreeItems(filename, filename, child, currentPath);
189-
})}
187+
Object.entries(content)
188+
.sort(compareFileTreeEntries)
189+
.map(([filename, child]) =>
190+
buildTreeItems(filename, filename, child, currentPath),
191+
)}
190192
</TreeItem>
191193
);
192194
};
@@ -198,12 +200,9 @@ export const TemplateFileTree: FC<TemplateFilesTreeProps> = ({
198200
defaultExpandedItems={activePath ? expandablePaths(activePath) : []}
199201
defaultSelectedItems={activePath}
200202
>
201-
{Object.keys(fileTree)
202-
.sort(sortFileTree(fileTree))
203-
.map((filename) => {
204-
const child = fileTree[filename];
205-
return buildTreeItems(filename, filename, child);
206-
})}
203+
{Object.entries(fileTree)
204+
.sort(compareFileTreeEntries)
205+
.map(([filename, child]) => buildTreeItems(filename, filename, child))}
207206

208207
<Menu
209208
onClose={() => setContextMenu(undefined)}

site/src/modules/templates/TemplateFiles/TemplateFiles.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { type Interpolation, type Theme, useTheme } from "@emotion/react";
22
import EditOutlined from "@mui/icons-material/EditOutlined";
33
import RadioButtonCheckedOutlined from "@mui/icons-material/RadioButtonCheckedOutlined";
44
import { SyntaxHighlighter } from "components/SyntaxHighlighter/SyntaxHighlighter";
5-
import set from "lodash/fp/set";
5+
import set from "lodash/set";
66
import { linkToTemplate, useLinks } from "modules/navigation";
77
import { type FC, useCallback, useMemo } from "react";
88
import { Link } from "react-router-dom";
@@ -31,8 +31,6 @@ export const TemplateFiles: FC<TemplateFilesProps> = ({
3131
const getLink = useLinks();
3232
const theme = useTheme();
3333

34-
const filenames = Object.keys(currentFiles);
35-
3634
const fileInfo = useCallback(
3735
(filename: string) => {
3836
const value = currentFiles[filename].trim();
@@ -49,13 +47,13 @@ export const TemplateFiles: FC<TemplateFilesProps> = ({
4947
);
5048

5149
const fileTree: FileTree = useMemo(() => {
52-
let tree: FileTree = {};
53-
for (const filename of filenames) {
50+
const tree: FileTree = {};
51+
for (const filename of Object.keys(currentFiles)) {
5452
const info = fileInfo(filename);
55-
tree = set(filename.split("/"), info.value, tree);
53+
set(tree, filename.split("/"), info.value);
5654
}
5755
return tree;
58-
}, [fileInfo, filenames]);
56+
}, [fileInfo, currentFiles]);
5957

6058
const versionLink = `${getLink(
6159
linkToTemplate(organizationName, templateName),
@@ -88,7 +86,7 @@ export const TemplateFiles: FC<TemplateFilesProps> = ({
8886
</div>
8987

9088
<div css={styles.files} data-testid="template-files-content">
91-
{[...filenames]
89+
{Object.keys(currentFiles)
9290
.sort((a, b) => a.localeCompare(b))
9391
.map((filename) => {
9492
const info = fileInfo(filename);

site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ export const WorkspaceBuildLogs: FC<WorkspaceBuildLogsProps> = ({
5151
}) => {
5252
const theme = useTheme();
5353
const groupedLogsByStage = groupLogsByStage(logs);
54-
const stages = Object.keys(groupedLogsByStage);
5554

5655
return (
5756
<div
@@ -62,8 +61,7 @@ export const WorkspaceBuildLogs: FC<WorkspaceBuildLogsProps> = ({
6261
}}
6362
{...attrs}
6463
>
65-
{stages.map((stage) => {
66-
const logs = groupedLogsByStage[stage];
64+
{Object.entries(groupedLogsByStage).map(([stage, logs]) => {
6765
const isEmpty = logs.every((log) => log.output === "");
6866
const lines = logs.map((log) => ({
6967
time: log.created_at,

site/src/pages/HealthPage/HealthLayout.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,9 @@ export const HealthLayout: FC = () => {
152152
</div>
153153

154154
<nav css={{ display: "flex", flexDirection: "column", gap: 1 }}>
155-
{Object.keys(visibleSections)
155+
{Object.entries(visibleSections)
156156
.sort()
157-
.map((key) => {
158-
const label =
159-
visibleSections[key as keyof typeof visibleSections];
157+
.map(([key, label]) => {
160158
const healthSection =
161159
healthStatus[key as keyof typeof visibleSections];
162160

site/src/pages/HealthPage/ProvisionerDaemonsPage.tsx

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,10 @@ export const ProvisionerDaemonsPage: FC = () => {
6060
const daemonScope = daemon.tags.scope || "organization";
6161
const iconScope =
6262
daemonScope === "organization" ? <Business /> : <Person />;
63-
const extraTags = Object.keys(daemon.tags)
64-
.filter((key) => key !== "scope" && key !== "owner")
65-
.reduce(
66-
(acc, key) => {
67-
acc[key] = daemon.tags[key];
68-
return acc;
69-
},
70-
{} as Record<string, string>,
71-
);
63+
64+
const extraTags = Object.entries(daemon.tags).filter(
65+
([key]) => key !== "scope" && key !== "owner",
66+
);
7267
const isWarning = warnings.length > 0;
7368
return (
7469
<div
@@ -131,8 +126,8 @@ export const ProvisionerDaemonsPage: FC = () => {
131126
</span>
132127
</Pill>
133128
</Tooltip>
134-
{Object.keys(extraTags).map((k) => (
135-
<ProvisionerTag key={k} k={k} v={extraTags[k]} />
129+
{extraTags.map(([key, value]) => (
130+
<ProvisionerTag key={key} tagName={key} tagValue={value} />
136131
))}
137132
</div>
138133
</header>
@@ -150,8 +145,8 @@ export const ProvisionerDaemonsPage: FC = () => {
150145
>
151146
{warnings.length > 0 ? (
152147
<div css={{ display: "flex", flexDirection: "column" }}>
153-
{warnings.map((warning, i) => (
154-
<span key={i}>{warning.message}</span>
148+
{warnings.map((warning) => (
149+
<span key={warning.code}>{warning.message}</span>
155150
))}
156151
</div>
157152
) : (
@@ -191,32 +186,30 @@ const parseBool = (s: string): { valid: boolean; value: boolean } => {
191186
};
192187

193188
interface ProvisionerTagProps {
194-
k: string;
195-
v: string;
196-
onDelete?: (key: string) => void;
189+
tagName: string;
190+
tagValue: string;
191+
onDelete?: (tagName: string) => void;
197192
}
198193

199-
export const ProvisionerTag: FC<ProvisionerTagProps> = ({ k, v, onDelete }) => {
200-
const { valid, value: boolValue } = parseBool(v);
201-
const kv = `${k}: ${v}`;
194+
export const ProvisionerTag: FC<ProvisionerTagProps> = ({
195+
tagName,
196+
tagValue,
197+
onDelete,
198+
}) => {
199+
const { valid, value: boolValue } = parseBool(tagValue);
200+
const kv = `${tagName}: ${tagValue}`;
202201
const content = onDelete ? (
203202
<>
204203
{kv}
205204
<IconButton
206-
aria-label={`delete-${k}`}
205+
aria-label={`delete-${tagName}`}
207206
size="small"
208207
color="secondary"
209208
onClick={() => {
210-
onDelete(k);
209+
onDelete(tagName);
211210
}}
212211
>
213-
<CloseIcon
214-
fontSize="inherit"
215-
css={{
216-
width: 14,
217-
height: 14,
218-
}}
219-
/>
212+
<CloseIcon fontSize="inherit" css={{ width: 14, height: 14 }} />
220213
</IconButton>
221214
</>
222215
) : (

site/src/pages/TemplateVersionEditorPage/ProvisionerTagsPopover.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,19 @@ export const ProvisionerTagsPopover: FC<ProvisionerTagsPopoverProps> = ({
104104
}
105105
/>
106106
<Stack direction="row" spacing={1} wrap="wrap">
107-
{Object.keys(tags)
108-
.filter((key) => {
109-
// filter out owner since you cannot override it
110-
return key !== "owner";
111-
})
112-
.map((k) => (
113-
<Fragment key={k}>
114-
{k === "scope" ? (
115-
<ProvisionerTag k={k} v={tags[k]} />
107+
{Object.entries(tags)
108+
// filter out owner since you cannot override it
109+
.filter(([key]) => key !== "owner")
110+
.map(([key, value]) => (
111+
<Fragment key={key}>
112+
{key === "scope" ? (
113+
<ProvisionerTag tagName={key} tagValue={value} />
116114
) : (
117-
<ProvisionerTag k={k} v={tags[k]} onDelete={onDelete} />
115+
<ProvisionerTag
116+
tagName={key}
117+
tagValue={value}
118+
onDelete={onDelete}
119+
/>
118120
)}
119121
</Fragment>
120122
))}

site/src/utils/filetree.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,8 @@ export const traverse = (
9696
) => void,
9797
parent?: string,
9898
) => {
99-
for (const filename of Object.keys(fileTree)) {
99+
for (const [filename, content] of Object.entries(fileTree)) {
100100
const fullPath = parent ? `${parent}/${filename}` : filename;
101-
const content = fileTree[filename];
102101
callback(content, filename, fullPath);
103102
if (typeof content === "object") {
104103
traverse(content, callback, fullPath);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy