Skip to content

Commit

Permalink
Merge pull request #1489 from argos-ci/improve-overall-ux
Browse files Browse the repository at this point in the history
feat: improve overall ux
  • Loading branch information
gregberge authored Dec 29, 2024
2 parents b620d98 + e7ec9fe commit e0423f0
Show file tree
Hide file tree
Showing 33 changed files with 694 additions and 534 deletions.
36 changes: 4 additions & 32 deletions apps/frontend/src/containers/Apollo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
QueryHookOptions,
QueryResult,
TypedDocumentNode,
useQuery as useApolloQuery,
useQuery,
} from "@apollo/client";
import { onError } from "@apollo/client/link/error";
import { RetryLink } from "@apollo/client/link/retry";
Expand Down Expand Up @@ -78,44 +78,16 @@ export const ApolloInitializer = (props: { children: React.ReactNode }) => {
);
};

export function useQuery<
export function useSafeQuery<
TData = any,
TVariables extends OperationVariables = OperationVariables,
>(
query: DocumentNode | TypedDocumentNode<TData, TVariables>,
options?: QueryHookOptions<TData, TVariables>,
): QueryResult<TData, TVariables> {
const { loading, error, data, ...others } = useApolloQuery(query, options);
): Omit<QueryResult<TData, TVariables>, "error"> {
const { loading, error, data, ...others } = useQuery(query, options);
if (error) {
throw error;
}
return { loading, data, ...others };
}

export function Query<
TData = any,
TVariables extends OperationVariables = OperationVariables,
>({
fallback = null,
children,
query,
...options
}: {
children: (
data: NonNullable<QueryResult<TData, TVariables>["data"]>,
) => React.ReactElement | null;
fallback?: React.ReactElement | null;
query: DocumentNode | TypedDocumentNode<TData, TVariables>;
variables?: TVariables;
skip?: boolean;
}): React.ReactElement | null {
const { data, previousData } = useQuery(query, options);

const dataOrPreviousData = data || previousData;

if (!dataOrPreviousData) {
return fallback;
}

return children(dataOrPreviousData);
}
130 changes: 64 additions & 66 deletions apps/frontend/src/containers/GithubRepositoryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from "@/ui/Pagination";
import { Time } from "@/ui/Time";

import { Query } from "./Apollo";
import { useSafeQuery } from "./Apollo";
import { getGitHubAppInstallURL } from "./GitHub";

const InstallationQuery = graphql(`
Expand Down Expand Up @@ -145,72 +145,70 @@ export function GithubRepositoryList(props: {
const reposPerPage = 100;
const [page, setPage] = useState(1);

return (
<Query
fallback={<Loader />}
query={InstallationQuery}
variables={{
installationId: props.installationId,
page,
reposPerPage,
fromAuthUser: props.app === "main",
}}
>
{({ ghApiInstallationRepositories }) => {
const pageCount = Math.ceil(
ghApiInstallationRepositories.pageInfo.totalCount / reposPerPage,
);
const result = useSafeQuery(InstallationQuery, {
variables: {
installationId: props.installationId,
page,
reposPerPage,
fromAuthUser: props.app === "main",
},
});

const data = result.data || result.previousData;

return (
<>
<List>
{ghApiInstallationRepositories.edges.map((repo) => (
<ListRow
key={repo.id}
className="items-center justify-between p-4"
>
<div>
{repo.name}{" "}
<Time date={repo.updated_at} className="text-low" />
</div>
<Button
onPress={() => {
props.onSelectRepository(repo);
}}
isDisabled={props.disabled}
>
{props.connectButtonLabel}
</Button>
</ListRow>
))}
{page === pageCount && (
<ListRow className="p-4 text-sm">
<div>
Repository not in the list?{" "}
<Link
href={getGitHubAppInstallURL(props.app, {
accountId: props.accountId,
})}
target="_blank"
>
Manage repositories
</Link>
</div>
</ListRow>
)}
</List>
if (!data) {
return <Loader />;
}

const { ghApiInstallationRepositories } = data;

{pageCount > 1 && (
<ReposPagination
page={page}
pageCount={pageCount}
setPage={setPage}
paginationItemCount={5}
/>
)}
</>
);
}}
</Query>
const pageCount = Math.ceil(
ghApiInstallationRepositories.pageInfo.totalCount / reposPerPage,
);

return (
<>
<List>
{ghApiInstallationRepositories.edges.map((repo) => (
<ListRow key={repo.id} className="items-center justify-between p-4">
<div>
{repo.name}<Time date={repo.updated_at} className="text-low" />
</div>
<Button
onPress={() => {
props.onSelectRepository(repo);
}}
isDisabled={props.disabled}
>
{props.connectButtonLabel}
</Button>
</ListRow>
))}
{page === pageCount && (
<ListRow className="p-4 text-sm">
<div>
Repository not in the list?{" "}
<Link
href={getGitHubAppInstallURL(props.app, {
accountId: props.accountId,
})}
target="_blank"
>
Manage repositories
</Link>
</div>
</ListRow>
)}
</List>

{pageCount > 1 && (
<ReposPagination
page={page}
pageCount={pageCount}
setPage={setPage}
paginationItemCount={5}
/>
)}
</>
);
}
85 changes: 41 additions & 44 deletions apps/frontend/src/containers/GitlabProjectList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { List, ListRow } from "@/ui/List";
import { Loader } from "@/ui/Loader";
import { Time } from "@/ui/Time";

import { Query } from "./Apollo";
import { useSafeQuery } from "./Apollo";

const ProjectsQuery = graphql(`
query GitlabProjectList_glApiProjects(
Expand Down Expand Up @@ -49,49 +49,46 @@ export type GitlabProjectListProps = {
);

export function GitlabProjectList(props: GitlabProjectListProps) {
const result = useSafeQuery(ProjectsQuery, {
variables: {
accountId: props.accountId,
userId: props.userId,
groupId: props.groupId,
allProjects: props.allProjects,
search: props.search,
page: 1,
},
});

const data = result.data || result.previousData;

if (!data) {
return <Loader />;
}

const { glApiProjects } = data;

if (glApiProjects.edges.length === 0) {
return <div className="text-center">No projects in this namespace</div>;
}
return (
<Query
fallback={<Loader />}
query={ProjectsQuery}
variables={{
accountId: props.accountId,
userId: props.userId,
groupId: props.groupId,
allProjects: props.allProjects,
search: props.search,
page: 1,
}}
>
{({ glApiProjects }) => {
if (glApiProjects.edges.length === 0) {
return (
<div className="text-center">No projects in this namespace</div>
);
}
return (
<List>
{glApiProjects.edges.map((project) => (
<ListRow
key={project.id}
className="items-center justify-between p-4"
>
<div>
{project.name}{" "}
<Time date={project.last_activity_at} className="text-low" />
</div>
<Button
onPress={() => {
props.onSelectProject(project);
}}
isDisabled={props.disabled}
>
{props.connectButtonLabel}
</Button>
</ListRow>
))}
</List>
);
}}
</Query>
<List>
{glApiProjects.edges.map((project) => (
<ListRow key={project.id} className="items-center justify-between p-4">
<div>
{project.name}{" "}
<Time date={project.last_activity_at} className="text-low" />
</div>
<Button
onPress={() => {
props.onSelectProject(project);
}}
isDisabled={props.disabled}
>
{props.connectButtonLabel}
</Button>
</ListRow>
))}
</List>
);
}
6 changes: 3 additions & 3 deletions apps/frontend/src/containers/PaymentBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { memo } from "react";
import { useSuspenseQuery } from "@apollo/client";
import { invariant } from "@argos/util/invariant";

import { useQuery } from "@/containers/Apollo";
import { TeamSubscribeDialog } from "@/containers/Team/SubscribeDialog";
import { FragmentType, graphql, useFragment } from "@/gql";
import { AccountPermission, AccountSubscriptionStatus } from "@/gql/graphql";
Expand Down Expand Up @@ -88,12 +88,12 @@ function BannerTemplate(props: {
export const PaymentBanner = memo(
(props: { account: FragmentType<typeof PaymentBannerFragment> }) => {
const account = useFragment(PaymentBannerFragment, props.account);
const { data: { me } = {} } = useQuery(PaymentBannerQuery);
const { data } = useSuspenseQuery(PaymentBannerQuery);

const { subscription, subscriptionStatus, permissions, stripeCustomerId } =
account;

if (!me) {
if (!data.me) {
return null;
}

Expand Down
8 changes: 2 additions & 6 deletions apps/frontend/src/containers/Project/ConnectRepository.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useCallback, useState } from "react";
import { useQuery } from "@apollo/client";
import { invariant } from "@apollo/client/utilities/globals";
import { assertNever } from "@argos/util/assertNever";
import { MarkGithubIcon } from "@primer/octicons-react";
Expand All @@ -23,6 +22,7 @@ import { Link } from "@/ui/Link";
import { PageLoader } from "@/ui/PageLoader";
import { TextInput } from "@/ui/TextInput";

import { useSafeQuery } from "../Apollo";
import { getMainGitHubAppInstallURL, GitHubLoginButton } from "../GitHub";
import { GitLabLogo } from "../GitLab";
import {
Expand Down Expand Up @@ -287,16 +287,12 @@ export function ConnectRepository(props: ConnectRepositoryProps) {
}
}, []);

const result = useQuery(ConnectRepositoryQuery, {
const result = useSafeQuery(ConnectRepositoryQuery, {
variables: {
accountSlug: props.accountSlug,
},
});

if (result.error) {
throw result.error;
}

if (!result.data) {
return (
<Card className="h-full">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react";
import { invariant } from "@argos/util/invariant";
import { useDebounce } from "use-debounce";

import { useQuery } from "@/containers/Apollo";
import { useSafeQuery } from "@/containers/Apollo";
import { UserListRow } from "@/containers/UserList";
import { FragmentType, graphql, useFragment } from "@/gql";
import { Button } from "@/ui/Button";
Expand Down Expand Up @@ -94,7 +94,7 @@ function TeamContributorsList(props: {
const [search, setSearch] = useState("");
const [debouncedSearch] = useDebounce(search, 300);
const searchInputRef = useRef<HTMLInputElement>(null);
const result = useQuery(TeamContributorsQuery, {
const result = useSafeQuery(TeamContributorsQuery, {
variables: {
projectId: props.projectId,
teamAccountId: props.teamAccountId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from "react";
import { invariant } from "@argos/util/invariant";

import { useQuery } from "@/containers/Apollo";
import { useSafeQuery } from "@/containers/Apollo";
import { useAssertAuthTokenPayload } from "@/containers/Auth";
import { ProjectContributorLevelLabel } from "@/containers/ProjectContributor";
import { RemoveMenu, UserListRow } from "@/containers/UserList";
Expand Down Expand Up @@ -60,7 +60,7 @@ export function ProjectContributorsList(props: {
}
},
};
const result = useQuery(ProjectContributorsQuery, {
const result = useSafeQuery(ProjectContributorsQuery, {
variables: {
projectId: props.projectId,
after: 0,
Expand Down
Loading

0 comments on commit e0423f0

Please sign in to comment.