Skip to content

Commit ef14197

Browse files
refactor: remove fields from deleted sandboxes query and fix type errors (#8829)
* refactor: remove irrelevant fields from query and fix type errors * fix: recover Stats component * fix: runtime and typechecks for potentially undefined properties * chore: rename fragment to not include fragment twice * fix(dashboard): use type guard instead of type assertion in search items filter * fix(dashboard): support filtering deleted sandboxes with reduced field set * fix: handle null/undefined fields for deleted sandboxes
1 parent 6ad6c5a commit ef14197

File tree

16 files changed

+248
-157
lines changed

16 files changed

+248
-157
lines changed

packages/app/src/app/graphql/types.ts

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4636,6 +4636,20 @@ export type JoinEligibleWorkspaceMutation = {
46364636
joinEligibleWorkspace: { __typename?: 'Team'; id: any };
46374637
};
46384638

4639+
export type RecentlyDeletedTeamSandboxesFragment = {
4640+
__typename?: 'Sandbox';
4641+
id: string;
4642+
alias: string | null;
4643+
isV2: boolean;
4644+
removedAt: string | null;
4645+
title: string | null;
4646+
collection: {
4647+
__typename?: 'Collection';
4648+
id: any | null;
4649+
path: string;
4650+
} | null;
4651+
};
4652+
46394653
export type RecentlyDeletedTeamSandboxesQueryVariables = Exact<{
46404654
teamId: Scalars['UUID4'];
46414655
}>;
@@ -4651,44 +4665,13 @@ export type RecentlyDeletedTeamSandboxesQuery = {
46514665
__typename?: 'Sandbox';
46524666
id: string;
46534667
alias: string | null;
4654-
title: string | null;
4655-
description: string | null;
4656-
lastAccessedAt: any;
4657-
insertedAt: string;
4658-
updatedAt: string;
4659-
removedAt: string | null;
4660-
privacy: number;
4661-
isFrozen: boolean;
4662-
screenshotUrl: string | null;
4663-
viewCount: number;
4664-
likeCount: number;
46654668
isV2: boolean;
4666-
draft: boolean;
4667-
restricted: boolean;
4668-
authorId: any | null;
4669-
teamId: any | null;
4670-
source: { __typename?: 'Source'; template: string | null };
4671-
customTemplate: {
4672-
__typename?: 'Template';
4673-
id: any | null;
4674-
iconUrl: string | null;
4675-
} | null;
4676-
forkedTemplate: {
4677-
__typename?: 'Template';
4678-
id: any | null;
4679-
color: string | null;
4680-
iconUrl: string | null;
4681-
} | null;
4669+
removedAt: string | null;
4670+
title: string | null;
46824671
collection: {
46834672
__typename?: 'Collection';
4684-
path: string;
46854673
id: any | null;
4686-
} | null;
4687-
author: { __typename?: 'User'; username: string } | null;
4688-
permissions: {
4689-
__typename?: 'SandboxProtectionSettings';
4690-
preventSandboxLeaving: boolean;
4691-
preventSandboxExport: boolean;
4674+
path: string;
46924675
} | null;
46934676
}>;
46944677
} | null;

packages/app/src/app/overmind/effects/gql/dashboard/queries.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,23 @@ import {
6060
githubRepoFragment,
6161
} from './fragments';
6262

63+
const RECENTLY_DELETED_TEAM_SANDBOXES_FRAGMENT = gql`
64+
fragment recentlyDeletedTeamSandboxes on Sandbox {
65+
id
66+
67+
alias
68+
69+
collection {
70+
id
71+
path
72+
}
73+
74+
isV2
75+
removedAt
76+
title
77+
}
78+
`;
79+
6380
export const deletedTeamSandboxes: Query<
6481
RecentlyDeletedTeamSandboxesQuery,
6582
RecentlyDeletedTeamSandboxesQueryVariables
@@ -73,12 +90,12 @@ export const deletedTeamSandboxes: Query<
7390
showDeleted: true
7491
orderBy: { field: "updated_at", direction: DESC }
7592
) {
76-
...sandboxFragmentDashboard
93+
...recentlyDeletedTeamSandboxes
7794
}
7895
}
7996
}
8097
}
81-
${sandboxFragmentDashboard}
98+
${RECENTLY_DELETED_TEAM_SANDBOXES_FRAGMENT}
8299
`;
83100

84101
export const sandboxesByPath: Query<

packages/app/src/app/overmind/namespaces/dashboard/internalActions.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ export const deleteSandboxesFromState = (
151151
repoSandbox.sandboxes = newSandboxes;
152152
}
153153
});
154+
} else if (type === 'DELETED') {
155+
const newSandboxes = sandboxStructure[type].filter(
156+
sandbox => !ids.includes(sandbox.id)
157+
);
158+
if (newSandboxes.length !== sandboxStructure[type].length) {
159+
dashboard.sandboxes[type] = newSandboxes;
160+
}
154161
} else if (type !== 'RECENT_BRANCHES') {
155162
const newSandboxes = sandboxStructure[type].filter(sandboxFilter);
156163
if (newSandboxes.length !== sandboxStructure[type].length) {

packages/app/src/app/overmind/namespaces/dashboard/state.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
BranchFragment as Branch,
77
ProjectFragment as Repository,
88
ProjectWithBranchesFragment as RepositoryWithBranches,
9+
RecentlyDeletedTeamSandboxesFragment,
910
} from 'app/graphql/types';
1011
import isSameWeek from 'date-fns/isSameWeek';
1112
import { sortBy } from 'lodash-es';
@@ -17,7 +18,7 @@ import { DELETE_ME_COLLECTION, OrderBy } from './types';
1718
export type DashboardSandboxStructure = {
1819
DRAFTS: Sandbox[] | null;
1920
TEMPLATES: Template[] | null;
20-
DELETED: Sandbox[] | null;
21+
DELETED: RecentlyDeletedTeamSandboxesFragment[] | null;
2122
RECENT_SANDBOXES: Sandbox[] | null;
2223
RECENT_BRANCHES: Branch[] | null;
2324
SEARCH: Sandbox[] | null;
@@ -47,11 +48,11 @@ export type State = {
4748
viewMode: 'grid' | 'list';
4849
orderBy: OrderBy;
4950
getFilteredSandboxes: (
50-
sandboxes: Array<Sandbox | Repo | Template['sandbox']>
51+
sandboxes: Array<Sandbox | RecentlyDeletedTeamSandboxesFragment | Repo | Template['sandbox']>
5152
) => Sandbox[];
5253
deletedSandboxesByTime: {
53-
week: Sandbox[];
54-
older: Sandbox[];
54+
week: RecentlyDeletedTeamSandboxesFragment[];
55+
older: RecentlyDeletedTeamSandboxesFragment[];
5556
};
5657
contributions: Branch[] | null;
5758
/**
@@ -104,8 +105,7 @@ export const state: State = {
104105
week: [],
105106
older: [],
106107
};
107-
const noTemplateSandboxes = deletedSandboxes.filter(s => !s.customTemplate);
108-
const timeSandboxes = noTemplateSandboxes.reduce(
108+
const timeSandboxes = deletedSandboxes.reduce(
109109
(accumulator, currentValue) => {
110110
if (!currentValue.removedAt) return accumulator;
111111
if (isSameWeek(new Date(currentValue.removedAt), new Date())) {
@@ -137,7 +137,7 @@ export const state: State = {
137137
},
138138
getFilteredSandboxes: derived(
139139
({ orderBy }: State) => (
140-
sandboxes: Array<Sandbox | Template['sandbox']>
140+
sandboxes: Array<Sandbox | RecentlyDeletedTeamSandboxesFragment | Template['sandbox']>
141141
) => {
142142
const orderField = orderBy.field;
143143
const orderOrder = orderBy.order;
@@ -156,7 +156,7 @@ export const state: State = {
156156
return field.toLowerCase();
157157
}
158158

159-
if (orderField === 'views') {
159+
if ('viewCount' in sandbox && orderField === 'views') {
160160
return sandbox.viewCount;
161161
}
162162

packages/app/src/app/pages/Dashboard/Components/Sandbox/SandboxBadge.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import { Icon, Stack, Text } from '@codesandbox/components';
2-
import { SandboxFragmentDashboardFragment as Sandbox } from 'app/graphql/types';
32
import React from 'react';
43

54
export interface SandboxBadgeProps {
6-
sandbox: Sandbox;
7-
restricted: boolean;
5+
isSandboxV2: boolean;
6+
isSandboxTemplate: boolean;
7+
isSandboxRestricted: boolean;
88
}
99

1010
export const SandboxBadge: React.FC<SandboxBadgeProps> = ({
11-
sandbox,
12-
restricted,
11+
isSandboxV2,
12+
isSandboxTemplate,
13+
isSandboxRestricted,
1314
}) => {
14-
const isDevbox = sandbox.isV2;
15-
const isRestricted = restricted;
16-
const isTemplate = !!sandbox.customTemplate;
15+
const isDevbox = isSandboxV2;
16+
const isRestricted = isSandboxRestricted;
17+
const isTemplate = isSandboxTemplate;
1718

1819
const boxIcon = isDevbox ? 'server' : 'boxDevbox';
1920
let boxTypeLabel = isDevbox ? 'Devbox' : 'Sandbox';

packages/app/src/app/pages/Dashboard/Components/Sandbox/SandboxCard.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,11 @@ const SandboxTitle: React.FC<SandboxTitleProps> = React.memo(
7373
</form>
7474
) : (
7575
<Stack gap={3} align="flex-start" css={{ overflow: 'hidden' }}>
76-
<Element css={{ flexShrink: 0 }}>
77-
<TemplateIcon width="16" height="16" />
78-
</Element>
76+
{TemplateIcon && (
77+
<Element css={{ flexShrink: 0 }}>
78+
<TemplateIcon width="16" height="16" />
79+
</Element>
80+
)}
7981

8082
{interaction === 'button' ? (
8183
<InteractiveOverlay.Button
@@ -160,13 +162,17 @@ const SandboxStats: React.FC<SandboxStatsProps> = React.memo(
160162
className="sandbox-stats"
161163
>
162164
<Stack gap={2} align="center">
163-
<PrivacyIcon />
165+
{PrivacyIcon && <PrivacyIcon />}
164166
{isFrozen && (
165167
<Icon size={16} title={`Protected ${boxType}`} name="frozen" />
166168
)}
167169
{noDrag ? null : timeAgoText}
168170
</Stack>
169-
<SandboxBadge sandbox={sandbox} restricted={restricted} />
171+
<SandboxBadge
172+
isSandboxV2={sandbox.isV2}
173+
isSandboxTemplate={('customTemplate' in sandbox && !!sandbox.customTemplate)}
174+
isSandboxRestricted={restricted}
175+
/>
170176
</Stack>
171177
);
172178
}
@@ -297,7 +303,7 @@ export const SandboxCard = ({
297303
<SandboxStats
298304
noDrag={noDrag}
299305
timeAgo={timeAgo}
300-
isFrozen={sandbox.isFrozen && !sandbox.customTemplate}
306+
isFrozen={('isFrozen' in sandbox && sandbox.isFrozen) && !('customTemplate' in sandbox && !!sandbox.customTemplate)}
301307
PrivacyIcon={PrivacyIcon}
302308
restricted={restricted}
303309
sandbox={sandbox}

packages/app/src/app/pages/Dashboard/Components/Sandbox/SandboxListItem.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export const SandboxListItem = ({
2121
sandboxLocation,
2222
username,
2323
timeAgo,
24-
viewCount,
2524
TemplateIcon,
2625
PrivacyIcon,
2726
screenshotUrl,
@@ -115,7 +114,9 @@ export const SandboxListItem = ({
115114
: null]: `url(${screenshotUrl})`,
116115
}}
117116
>
118-
{screenshotUrl ? null : <TemplateIcon width="16" height="16" />}
117+
{!screenshotUrl && TemplateIcon && (
118+
<TemplateIcon width="16" height="16" />
119+
)}
119120
</Stack>
120121
<Element css={{ overflow: 'hidden' }}>
121122
{editing ? (
@@ -131,7 +132,7 @@ export const SandboxListItem = ({
131132
) : (
132133
<Tooltip label={sandboxTitle}>
133134
<Stack gap={1} align="center">
134-
<PrivacyIcon />
135+
{PrivacyIcon ? <PrivacyIcon /> : null}
135136
<Text
136137
size={3}
137138
weight="medium"
@@ -151,7 +152,13 @@ export const SandboxListItem = ({
151152
{/* Column span 0 on mobile because the Grid is bugged */}
152153
<Column span={[0, 2, 2]}>
153154
<Stack align="center">
154-
<SandboxBadge sandbox={sandbox} restricted={restricted} />
155+
<SandboxBadge
156+
isSandboxV2={sandbox.isV2}
157+
isSandboxTemplate={
158+
'customTemplate' in sandbox && !!sandbox.customTemplate
159+
}
160+
isSandboxRestricted={restricted}
161+
/>
155162
</Stack>
156163
</Column>
157164
<Column span={[0, 3, 3]} as={Stack} align="center">

0 commit comments

Comments
 (0)