Skip to content

Commit

Permalink
feat: improve recent page (#8426)
Browse files Browse the repository at this point in the history
* intial commit

* align components

* remove older components in favor of a single reusable recent page

* final cleanup for recent content

* Add get started page

* feat: add workspace sandboxes

* fix condition

* fix typecheck

* update wording
  • Loading branch information
alexnm committed Apr 16, 2024
1 parent 6cdcab8 commit 6680b46
Show file tree
Hide file tree
Showing 24 changed files with 540 additions and 478 deletions.
77 changes: 75 additions & 2 deletions packages/app/src/app/graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1422,6 +1422,15 @@ export type CurrentUser = {
* Returns false if they have created any teams that have used a trial in the last 6 months.
*/
eligibleForTrial: Scalars['Boolean'];
/**
* List workspaces a user is eligible to join
*
* This endpoint looks at the user's verified email address domains to find workspaces that allow
* automatically joining.
*
* Note that this endpoint is _expensive_ to calculate, and should only be called when necessary.
*/
eligibleWorkspaces: Array<TeamPreview>;
email: Scalars['String'];
/** User-based feature flags and whether or not they are active for the current user */
featureFlags: UserFeatureFlags;
Expand Down Expand Up @@ -1913,6 +1922,19 @@ export type RootMutationType = {
inviteToTeam: Team;
/** Invite someone to a team via email */
inviteToTeamViaEmail: Scalars['String'];
/**
* Join a workspace the user is eligible to join based on email domain
*
* A list of eligible workspaces (and their IDs) is available from the `me > eligibleWorkspaces`
* query. This endpoint requires an authenticated user and an eligible workspace ID. Otherwise,
* one of the following errors will be returned:
*
* * `Please log in`
* * `Workspace not found`
*
* The latter error represents both invalid IDs and ineligible workspaces.
*/
joinEligibleWorkspace: Team;
/**
* Join an existing live session
*
Expand Down Expand Up @@ -2376,6 +2398,10 @@ export type RootMutationTypeInviteToTeamViaEmailArgs = {
teamId: Scalars['UUID4'];
};

export type RootMutationTypeJoinEligibleWorkspaceArgs = {
workspaceId: Scalars['ID'];
};

export type RootMutationTypeJoinLiveSessionArgs = {
id: Scalars['ID'];
};
Expand Down Expand Up @@ -6654,7 +6680,12 @@ export type SidebarTemplateFragmentFragment = {

export type SidebarProjectFragmentFragment = {
__typename?: 'Project';
repository: { __typename?: 'GitHubRepository'; name: string; owner: string };
repository: {
__typename?: 'GitHubRepository';
name: string;
owner: string;
defaultBranch: string;
};
};

export type TeamSidebarDataQueryVariables = Exact<{
Expand All @@ -6667,16 +6698,58 @@ export type TeamSidebarDataQuery = {
__typename?: 'CurrentUser';
team: {
__typename?: 'Team';
sandboxes: Array<{ __typename?: 'Sandbox'; id: string }>;
syncedSandboxes: Array<{ __typename?: 'Sandbox'; id: string }>;
templates: Array<{ __typename?: 'Template'; id: any | null }>;
projects: Array<{
__typename?: 'Project';
repository: {
__typename?: 'GitHubRepository';
name: string;
owner: string;
defaultBranch: string;
};
}>;
sandboxes: Array<{
__typename?: 'Sandbox';
id: string;
alias: string | null;
title: string | null;
description: string | null;
lastAccessedAt: any;
insertedAt: string;
updatedAt: string;
removedAt: string | null;
privacy: number;
isFrozen: boolean;
isSse: boolean | null;
screenshotUrl: string | null;
screenshotOutdated: boolean;
viewCount: number;
likeCount: number;
isV2: boolean;
draft: boolean;
restricted: boolean;
authorId: any | null;
teamId: any | null;
source: { __typename?: 'Source'; template: string | null };
customTemplate: {
__typename?: 'Template';
id: any | null;
iconUrl: string | null;
} | null;
forkedTemplate: {
__typename?: 'Template';
id: any | null;
color: string | null;
iconUrl: string | null;
} | null;
collection: { __typename?: 'Collection'; path: string } | null;
permissions: {
__typename?: 'SandboxProtectionSettings';
preventSandboxLeaving: boolean;
preventSandboxExport: boolean;
} | null;
}>;
} | null;
} | null;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const sidebarProjectFragment = gql`
... on GitHubRepository {
name
owner
defaultBranch
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion packages/app/src/app/overmind/effects/gql/sidebar/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
sidebarSyncedSandboxFragment,
sidebarTemplateFragment,
} from './fragments';
import { sandboxFragmentDashboard } from '../dashboard/fragments';

export const getTeamSidebarData: Query<
TeamSidebarDataQuery,
Expand All @@ -18,7 +19,7 @@ export const getTeamSidebarData: Query<
query TeamSidebarData($id: UUID4!) {
me {
team(id: $id) {
sandboxes(hasOriginalGit: true) {
syncedSandboxes: sandboxes(hasOriginalGit: true) {
...sidebarSyncedSandboxFragment
}
templates {
Expand All @@ -27,10 +28,14 @@ export const getTeamSidebarData: Query<
projects(syncData: false) {
...sidebarProjectFragment
}
sandboxes(limit: 10, orderBy: { field: "updatedAt", direction: DESC }) {
...sandboxFragmentDashboard
}
}
}
}
${sidebarSyncedSandboxFragment}
${sidebarTemplateFragment}
${sidebarProjectFragment}
${sandboxFragmentDashboard}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SidebarCollectionDashboardFragment as Collection } from 'app/graphql/ty
export type PageTypes =
| 'search'
| 'recent'
| 'get-started'
| 'deleted'
| 'templates'
| 'drafts'
Expand Down
7 changes: 5 additions & 2 deletions packages/app/src/app/overmind/namespaces/sidebar/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,23 @@ export const getSidebarData = async (
*/
const result = await queries.getTeamSidebarData({ id: teamId });

const sandboxes = result.me?.team?.sandboxes || null;
const syncedSandboxes = result.me?.team?.syncedSandboxes || null;
const sandboxes = result.me?.team?.sandboxes || [];
const templates = result.me?.team?.templates || null;
const repositories =
result.me?.team?.projects?.map(p => ({
owner: p.repository.owner,
name: p.repository.name,
defaultBranch: p.repository.defaultBranch,
})) || [];

const hasSyncedSandboxes = sandboxes && sandboxes.length > 0;
const hasSyncedSandboxes = syncedSandboxes && syncedSandboxes.length > 0;
const hasTemplates = templates && templates.length > 0;

state.sidebar[teamId] = {
hasSyncedSandboxes,
hasTemplates,
sandboxes,
repositories,
};
} catch {
Expand Down
6 changes: 5 additions & 1 deletion packages/app/src/app/overmind/namespaces/sidebar/state.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { SandboxFragmentDashboardFragment as Sandbox } from 'app/graphql/types';
import { RepoInfo } from './types';

type SidebarState = {
hasSyncedSandboxes: boolean | null;
hasTemplates: boolean | null;
repositories: Array<{ name: string; owner: string }>;
repositories: Array<RepoInfo>;
sandboxes: Array<Sandbox>;
};

export type State = Record<string, SidebarState>;
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/app/overmind/namespaces/sidebar/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type RepoInfo = { owner: string; name: string; defaultBranch: string };
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ import { EmptyPage } from '../EmptyPage';
export const StyledWrapper = styled(Element)`
position: relative;
overflow: hidden;
margin-right: calc(-2 * ${GUTTER}px);
`;

export const StyledInvisibleGrid = styled(EmptyPage.StyledGrid)`
position: absolute;
width: calc(100% - 2 * ${GUTTER}px);
width: 100%;
height: 0;
visibility: hidden;
`;
Expand All @@ -25,7 +24,6 @@ export const StyledCarousel = styled(Stack)`
position: relative;
width: 100%;
padding: 0;
padding-right: calc(2 * ${GUTTER}px);
margin: 0;
overflow-x: scroll;
white-space: nowrap;
Expand All @@ -46,7 +44,7 @@ export const StyledCarousel = styled(Stack)`
}
`;

type CarouselItem = {
export type CarouselItem = {
id: string;
Component: React.FunctionComponent;
props: Record<string, unknown>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { Text, Stack } from '@codesandbox/components';

export const ContentSection: React.FC<{ title: string }> = ({
title,
children,
}) => (
<Stack direction="vertical" gap={6}>
<Text
as="h2"
css={{
fontWeight: 400,
fontSize: '24px',
letterSpacing: '-0.019em',
color: '#FFFFFF',
margin: 0,
}}
>
{title}
</Text>
{children}
</Stack>
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Button, Element, Text } from '@codesandbox/components';
import { Button, Element, Text, Stack } from '@codesandbox/components';
import styled from 'styled-components';
import {
GRID_MAX_WIDTH,
GUTTER,
ITEM_HEIGHT_GRID,
ITEM_MIN_WIDTH,
} from '../VariableGrid/constants';

export const StyledDisclaimerWrapper = styled(Element)<{
insideGrid?: boolean;
Expand Down Expand Up @@ -40,3 +46,87 @@ export const StyledDisclaimerButton = styled(Button)<{ insideGrid?: boolean }>`
outline-offset: -2px;
}
`;

export const StyledContentWrapper = styled(Stack)`
width: 100%;
max-width: ${GRID_MAX_WIDTH}px;
padding: 0 ${GUTTER}px 64px;
overflow: auto;
scrollbar-gutter: stable;
margin: 12px auto 0;
flex-direction: column;
gap: 48px;
&::-webkit-scrollbar {
width: 0;
height: 0;
}
`;

export const StyledGrid = styled(Element)`
display: grid;
list-style-type: none;
margin: 0;
padding: 0;
gap: 16px;
grid-template-columns: repeat(auto-fill, minmax(${ITEM_MIN_WIDTH}px, 1fr));
grid-auto-rows: minmax(${ITEM_HEIGHT_GRID}px, 1fr);
@media (width <= 1149px) {
& li.create-branch:not(:nth-child(-n + 4)) {
display: none;
}
}
@media (width <= 1425px) {
& li.create-branch:not(:nth-child(-n + 3)) {
display: none;
}
}
@media (width <= 1702px) {
& li.recent-item:not(:nth-child(-n + 12)) {
display: none;
}
& li.create-branch:not(:nth-child(-n + 4)) {
display: none;
}
}
@media (1702px < width <= 1978px) {
& li.recent-item:not(:nth-child(-n + 15)) {
display: none;
}
& li.create-branch:not(:nth-child(-n + 5)) {
display: none;
}
}
@media (1978px < width <= 2254px) {
& li.recent-item:not(:nth-child(-n + 18)) {
display: none;
}
& li.create-branch:not(:nth-child(-n + 6)) {
display: none;
}
}
@media (2254px < width <= 2530px) {
& li.recent-item:not(:nth-child(-n + 14)) {
display: none;
}
& li.create-branch:not(:nth-child(-n + 7)) {
display: none;
}
}
@media (2530px < width <= 2806px) {
& li.recent-item:not(:nth-child(-n + 16)) {
display: none;
}
& li.create-branch:not(:nth-child(-n + 8)) {
display: none;
}
}
`;
2 changes: 2 additions & 0 deletions packages/app/src/app/pages/Dashboard/Content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useAppState, useActions } from 'app/overmind';
import { Templates } from './routes/Templates';
import { Deleted } from './routes/Deleted';
import { Drafts } from './routes/Drafts';
import { GetStarted } from './routes/GetStarted';
import { Recent } from './routes/Recent';
import { Shared } from './routes/Shared';
import { Sandboxes } from './routes/Sandboxes';
Expand Down Expand Up @@ -59,6 +60,7 @@ export const Content = withRouter(({ history }) => {
>
<Switch>
<Route path="/dashboard/recent" component={Recent} />
<Route path="/dashboard/get-started" component={GetStarted} />
<Route path="/dashboard/drafts" component={Drafts} />
<Route path="/dashboard/sandboxes/:path*" component={Sandboxes} />
<Route path="/dashboard/templates" component={Templates} />
Expand Down
Loading

0 comments on commit 6680b46

Please sign in to comment.