From e8a4f1447e38e49cdc12732f8f31327d4bf067b8 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Mon, 2 Dec 2024 15:55:52 -0800 Subject: [PATCH 01/18] list remotes --- graphql-server/schema.gql | 13 +++ .../queryFactory/dolt/doltEntityManager.ts | 8 ++ graphql-server/src/queryFactory/dolt/index.ts | 7 ++ .../src/queryFactory/doltgres/index.ts | 7 ++ graphql-server/src/queryFactory/index.ts | 2 + .../src/queryFactory/mysql/index.ts | 4 + graphql-server/src/remotes/remote.model.ts | 33 ++++++++ graphql-server/src/remotes/remote.resolver.ts | 31 +++++++ graphql-server/src/resolvers.ts | 2 + web/renderer/components/DatabaseNav/tabs.ts | 1 + web/renderer/components/DatabaseNav/utils.ts | 3 + .../breadcrumbs/RemotesBreadcrumbs.tsx | 19 +++++ .../breadcrumbs/breadcrumbDetails.tsx | 12 +++ web/renderer/components/breadcrumbs/types.ts | 1 + .../DatabasePage/ForRemotes/RemotesPage.tsx | 35 ++++++++ .../DatabasePage/ForRemotes/index.tsx | 30 +++++++ .../DatabasePage/ForRemotes/queries.ts | 18 ++++ .../pageComponents/DatabasePage/index.tsx | 2 + web/renderer/gen/graphql-types.tsx | 83 +++++++++++++++++++ web/renderer/lib/urls.ts | 3 + .../database/[databaseName]/remotes/index.tsx | 37 +++++++++ 21 files changed, 351 insertions(+) create mode 100644 graphql-server/src/remotes/remote.model.ts create mode 100644 graphql-server/src/remotes/remote.resolver.ts create mode 100644 web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts create mode 100644 web/renderer/pages/database/[databaseName]/remotes/index.tsx diff --git a/graphql-server/schema.gql b/graphql-server/schema.gql index afe9458b..32da2e3a 100644 --- a/graphql-server/schema.gql +++ b/graphql-server/schema.gql @@ -279,6 +279,18 @@ type TagList { list: [Tag!]! } +type Remote { + _id: ID! + name: String! + url: String! + fetch_specs: [String!]! +} + +type RemoteList { + nextOffset: Int + list: [Remote!]! +} + type Query { branch(databaseName: String!, branchName: String!): Branch branchOrDefault(databaseName: String!, branchName: String): Branch @@ -298,6 +310,7 @@ type Query { docs(databaseName: String!, refName: String!): DocList! docOrDefaultDoc(refName: String!, databaseName: String!, docType: DocType): Doc pullWithDetails(databaseName: String!, fromBranchName: String!, toBranchName: String!): PullWithDetails! + remotes(databaseName: String!, offset: Int): RemoteList! rowDiffs(offset: Int, databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, filterByRowType: DiffRowType, type: CommitDiffType): RowDiffList! rows(schemaName: String, refName: String!, databaseName: String!, tableName: String!, offset: Int): RowList! schemaDiff(databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, type: CommitDiffType): SchemaDiff diff --git a/graphql-server/src/queryFactory/dolt/doltEntityManager.ts b/graphql-server/src/queryFactory/dolt/doltEntityManager.ts index a59acbb1..678036aa 100644 --- a/graphql-server/src/queryFactory/dolt/doltEntityManager.ts +++ b/graphql-server/src/queryFactory/dolt/doltEntityManager.ts @@ -138,3 +138,11 @@ export async function getDoltTags(em: EntityManager): t.PR { .orderBy("dolt_tags.date", "DESC") .getRawMany(); } + +export async function getDoltRemotes(em: EntityManager): t.PR { + return em + .createQueryBuilder() + .select("*") + .from("dolt_remotes", "") + .getRawMany(); +} diff --git a/graphql-server/src/queryFactory/dolt/index.ts b/graphql-server/src/queryFactory/dolt/index.ts index 97488ad1..7e0d8bb6 100644 --- a/graphql-server/src/queryFactory/dolt/index.ts +++ b/graphql-server/src/queryFactory/dolt/index.ts @@ -434,6 +434,13 @@ export class DoltQueryFactory args.refName, ); } + + async getRemotes(args: t.DBArgs): t.PR { + return this.queryForBuilder( + async em => dem.getDoltRemotes(em), + args.databaseName, + ); + } } async function getTableInfoWithQR( diff --git a/graphql-server/src/queryFactory/doltgres/index.ts b/graphql-server/src/queryFactory/doltgres/index.ts index 0ca7f043..6682e254 100644 --- a/graphql-server/src/queryFactory/doltgres/index.ts +++ b/graphql-server/src/queryFactory/doltgres/index.ts @@ -425,6 +425,13 @@ export class DoltgresQueryFactory args.refName, ); } + + async getRemotes(args: t.DBArgs): t.PR { + return this.queryForBuilder( + async em => dem.getDoltRemotes(em), + args.databaseName, + ); + } } async function getTableInfoWithQR( diff --git a/graphql-server/src/queryFactory/index.ts b/graphql-server/src/queryFactory/index.ts index 6879ebb5..e44fcc76 100644 --- a/graphql-server/src/queryFactory/index.ts +++ b/graphql-server/src/queryFactory/index.ts @@ -144,4 +144,6 @@ export declare class QueryFactory { getRowDiffs(args: t.RowDiffArgs): t.DiffRes; restoreAllTables(args: t.RefArgs): t.PR; + + getRemotes(args: t.DBArgs): t.PR; } diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index 6db114f8..8cee7dee 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -301,4 +301,8 @@ export class MySQLQueryFactory async restoreAllTables(_args: t.RefArgs): t.PR { throw notDoltError("restore all tables"); } + + async getRemotes(args: t.DBArgs): t.PR { + throw notDoltError("get one-sided diff"); + } } diff --git a/graphql-server/src/remotes/remote.model.ts b/graphql-server/src/remotes/remote.model.ts new file mode 100644 index 00000000..11a201ed --- /dev/null +++ b/graphql-server/src/remotes/remote.model.ts @@ -0,0 +1,33 @@ +import { Field, ID, ObjectType } from "@nestjs/graphql"; +import { RawRow } from "src/queryFactory/types"; +import { ListOffsetRes } from "src/utils/commonTypes"; + +@ObjectType() +export class Remote { + @Field(_type => ID) + _id: string; + + @Field() + name: string; + + @Field() + url: string; + + @Field(_type => [String]) + fetch_specs: string[]; +} + +@ObjectType() +export class RemoteList extends ListOffsetRes { + @Field(_type => [Remote]) + list: Remote[]; +} + +export function fromDoltRemotesRow(databaseName: string, r: RawRow): Remote { + return { + _id: `databases/${databaseName}/remotes/${r.name}`, + name: r.name, + url: r.url, + fetch_specs: r.fetch_specs, + }; +} diff --git a/graphql-server/src/remotes/remote.resolver.ts b/graphql-server/src/remotes/remote.resolver.ts new file mode 100644 index 00000000..68da63d4 --- /dev/null +++ b/graphql-server/src/remotes/remote.resolver.ts @@ -0,0 +1,31 @@ +import { Args, Query, Resolver } from "@nestjs/graphql"; +import { ConnectionProvider } from "src/connections/connection.provider"; +import { fromDoltRemotesRow, Remote, RemoteList } from "./remote.model"; +import { DBArgsWithOffset } from "src/utils/commonTypes"; +import { RawRow } from "src/queryFactory/types"; +import { getNextOffset, ROW_LIMIT } from "src/utils"; + +@Resolver(_of => Remote) +export class RemoteResolver { + constructor(private readonly conn: ConnectionProvider) {} + + @Query(_returns => RemoteList) + async remotes(@Args() args: DBArgsWithOffset): Promise { + const conn = this.conn.connection(); + + const res = await conn.getRemotes(args); + return getRemoteListRes(res, args); + } +} + +function getRemoteListRes( + remotes: RawRow[], + args: DBArgsWithOffset, +): RemoteList { + return { + list: remotes + .slice(0, ROW_LIMIT) + .map(l => fromDoltRemotesRow(args.databaseName, l)), + nextOffset: getNextOffset(remotes.length, args.offset ?? 0), + }; +} diff --git a/graphql-server/src/resolvers.ts b/graphql-server/src/resolvers.ts index f92ffd35..3c695d45 100644 --- a/graphql-server/src/resolvers.ts +++ b/graphql-server/src/resolvers.ts @@ -14,6 +14,7 @@ import { StatusResolver } from "./status/status.resolver"; import { TableResolver } from "./tables/table.resolver"; import { FileUploadResolver } from "./tables/upload.resolver"; import { TagResolver } from "./tags/tag.resolver"; +import { RemoteResolver } from "./remotes/remote.resolver"; const resolvers = [ BranchResolver, @@ -24,6 +25,7 @@ const resolvers = [ DocsResolver, FileUploadResolver, PullResolver, + RemoteResolver, RowDiffResolver, RowResolver, SchemaDiffResolver, diff --git a/web/renderer/components/DatabaseNav/tabs.ts b/web/renderer/components/DatabaseNav/tabs.ts index 004a634c..aeba46d9 100644 --- a/web/renderer/components/DatabaseNav/tabs.ts +++ b/web/renderer/components/DatabaseNav/tabs.ts @@ -4,4 +4,5 @@ export const tabs = [ "Commit Log", "Releases", "Pull Requests", + "Remotes", ]; diff --git a/web/renderer/components/DatabaseNav/utils.ts b/web/renderer/components/DatabaseNav/utils.ts index 5f6add81..4bd85986 100644 --- a/web/renderer/components/DatabaseNav/utils.ts +++ b/web/renderer/components/DatabaseNav/utils.ts @@ -9,6 +9,7 @@ import { ref, RefUrl, releases, + remotes, } from "@lib/urls"; function getUrlFromName(name: string): [DatabaseUrl, RefUrl?] { @@ -23,6 +24,8 @@ function getUrlFromName(name: string): [DatabaseUrl, RefUrl?] { return [releases]; case "Pull Requests": return [pulls]; + case "Remotes": + return [remotes]; default: return [database, ref]; } diff --git a/web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx b/web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx new file mode 100644 index 00000000..8ae955e3 --- /dev/null +++ b/web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx @@ -0,0 +1,19 @@ +import { DatabaseParams } from "@lib/params"; +import Breadcrumbs from "."; +import { remoteBreadcrumbDetails } from "./breadcrumbDetails"; + +type Props = { + params: DatabaseParams; + className?: string; +}; + +export default function RemotesBreadcrumbs(props: Props) { + return ( + + ); +} \ No newline at end of file diff --git a/web/renderer/components/breadcrumbs/breadcrumbDetails.tsx b/web/renderer/components/breadcrumbs/breadcrumbDetails.tsx index 19644116..8ff42355 100644 --- a/web/renderer/components/breadcrumbs/breadcrumbDetails.tsx +++ b/web/renderer/components/breadcrumbs/breadcrumbDetails.tsx @@ -113,6 +113,18 @@ export function commitLogBreadcrumbDetails( ]; } +export function remoteBreadcrumbDetails(params: DatabaseParams): BreadcrumbDetails[] { + return [ + ...databaseBreadcrumbs(params), + { + child: remotes, + name: BreadcrumbName.DBRemote, + type: BreadcrumbType.Text, + }, + ]; +} + + export function tableBreadcrumbsDetails( params: TableParams, ): BreadcrumbDetails[] { diff --git a/web/renderer/components/breadcrumbs/types.ts b/web/renderer/components/breadcrumbs/types.ts index badd8fd1..589ceca1 100644 --- a/web/renderer/components/breadcrumbs/types.ts +++ b/web/renderer/components/breadcrumbs/types.ts @@ -23,6 +23,7 @@ export enum BreadcrumbName { DBSchema = "db-schema", DBCommitGraph = "db-commit-graph", DBNew = "db-new", + DBRemote = "db-remote", } export enum BreadcrumbType { diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx new file mode 100644 index 00000000..e07109a2 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx @@ -0,0 +1,35 @@ +import { QueryHandler } from "@dolthub/react-components"; +import { RemoteFragment, useRemoteListQuery } from "@gen/graphql-types"; +import { DatabaseParams } from "@lib/params"; + +type Props = { + params: DatabaseParams; +}; + +type InnerProps = { + remotes : RemoteFragment[]; +}; + +function Inner({ remotes }: InnerProps) { + return ( +
    + {remotes.map(remote => ( +
  • + {remote.name} + {remote.url} + {remote.fetch_specs} +
  • + ))} +
+ ); +} + +export default function RemotesPage({ params }: Props) { + const res = useRemoteListQuery({ variables: params }); + return ( + } + /> + ); +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx new file mode 100644 index 00000000..285b8d20 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx @@ -0,0 +1,30 @@ +import RemotesBreadcrumbs from "@components/breadcrumbs/RemotesBreadcrumbs"; +import NotDoltWrapper from "@components/util/NotDoltWrapper"; +import { OptionalRefParams } from "@lib/params"; +import { branches } from "@lib/urls"; +import ForDefaultBranch from "../ForDefaultBranch"; +import RemotesPage from "./RemotesPage"; + +type Props = { + params: OptionalRefParams; + newBranch?: boolean; +}; + +export default function ForBranches({ params, newBranch }: Props): JSX.Element { + const feature = newBranch ? "Creating new branches" : "Viewing branches"; + return ( + + } + routeRefChangeTo={urlParams => branches(urlParams)} + > + + + + + ); +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts new file mode 100644 index 00000000..dde9702c --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts @@ -0,0 +1,18 @@ +import { gql } from "@apollo/client"; + +export const REMOTES_FOR_REMOTES_PAGE_QUERY = gql` + fragment Remote on Remote { + _id + name + url + fetch_specs + } + query RemoteList($databaseName: String!, $offset: Int) { + remotes(databaseName: $databaseName, offset: $offset) { + list { + ...Remote + } + nextOffset + } + } +`; diff --git a/web/renderer/components/pageComponents/DatabasePage/index.tsx b/web/renderer/components/pageComponents/DatabasePage/index.tsx index ed61fb11..dfc6ed79 100644 --- a/web/renderer/components/pageComponents/DatabasePage/index.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/index.tsx @@ -9,6 +9,7 @@ import ForPulls from "./ForPulls"; import ForQuery from "./ForQuery"; import ForRef from "./ForRef"; import ForReleases from "./ForReleases"; +import ForRemotes from "./ForRemotes"; import ForSchema from "./ForSchema"; import ForTable from "./ForTable"; import DatabasePage from "./component"; @@ -25,6 +26,7 @@ export default Object.assign(DatabasePage, { ForPullDiff, ForRef, ForReleases, + ForRemotes, ForSchema, ForTable, }); diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index 1df88039..8913b999 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -381,6 +381,7 @@ export type Query = { doltProcedures: Array; doltSchemas: Array; pullWithDetails: PullWithDetails; + remotes: RemoteList; rowDiffs: RowDiffList; rows: RowList; schemaDiff?: Maybe; @@ -501,6 +502,12 @@ export type QueryPullWithDetailsArgs = { }; +export type QueryRemotesArgs = { + databaseName: Scalars['String']['input']; + offset?: InputMaybe; +}; + + export type QueryRowDiffsArgs = { databaseName: Scalars['String']['input']; filterByRowType?: InputMaybe; @@ -607,6 +614,20 @@ export enum QueryExecutionStatus { Timeout = 'Timeout' } +export type Remote = { + __typename?: 'Remote'; + _id: Scalars['ID']['output']; + fetch_specs: Array; + name: Scalars['String']['output']; + url: Scalars['String']['output']; +}; + +export type RemoteList = { + __typename?: 'RemoteList'; + list: Array; + nextOffset?: Maybe; +}; + export type Row = { __typename?: 'Row'; columnValues: Array; @@ -1161,6 +1182,16 @@ export type DeleteTagMutationVariables = Exact<{ export type DeleteTagMutation = { __typename?: 'Mutation', deleteTag: boolean }; +export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetch_specs: Array }; + +export type RemoteListQueryVariables = Exact<{ + databaseName: Scalars['String']['input']; + offset?: InputMaybe; +}>; + + +export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetch_specs: Array }> } }; + export type LoadDataMutationVariables = Exact<{ databaseName: Scalars['String']['input']; refName: Scalars['String']['input']; @@ -1579,6 +1610,14 @@ export const PullDetailsFragmentDoc = gql` } } ${PullDetailsForPullDetailsFragmentDoc}`; +export const RemoteFragmentDoc = gql` + fragment Remote on Remote { + _id + name + url + fetch_specs +} + `; export const ColumnForDataTableFragmentDoc = gql` fragment ColumnForDataTable on Column { name @@ -3447,6 +3486,50 @@ export function useDeleteTagMutation(baseOptions?: Apollo.MutationHookOptions; export type DeleteTagMutationResult = Apollo.MutationResult; export type DeleteTagMutationOptions = Apollo.BaseMutationOptions; +export const RemoteListDocument = gql` + query RemoteList($databaseName: String!, $offset: Int) { + remotes(databaseName: $databaseName, offset: $offset) { + list { + ...Remote + } + nextOffset + } +} + ${RemoteFragmentDoc}`; + +/** + * __useRemoteListQuery__ + * + * To run a query within a React component, call `useRemoteListQuery` and pass it any options that fit your needs. + * When your component renders, `useRemoteListQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useRemoteListQuery({ + * variables: { + * databaseName: // value for 'databaseName' + * offset: // value for 'offset' + * }, + * }); + */ +export function useRemoteListQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: RemoteListQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(RemoteListDocument, options); + } +export function useRemoteListLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(RemoteListDocument, options); + } +export function useRemoteListSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(RemoteListDocument, options); + } +export type RemoteListQueryHookResult = ReturnType; +export type RemoteListLazyQueryHookResult = ReturnType; +export type RemoteListSuspenseQueryHookResult = ReturnType; +export type RemoteListQueryResult = Apollo.QueryResult; export const LoadDataDocument = gql` mutation LoadData($databaseName: String!, $refName: String!, $schemaName: String, $tableName: String!, $importOp: ImportOperation!, $fileType: FileType!, $file: Upload!, $modifier: LoadDataModifier) { loadDataFile( diff --git a/web/renderer/lib/urls.ts b/web/renderer/lib/urls.ts index a6aca2a3..02522cbc 100644 --- a/web/renderer/lib/urls.ts +++ b/web/renderer/lib/urls.ts @@ -96,6 +96,9 @@ function getDiffRange(p: ps.DiffParams): string { export const releases = (p: ps.OptionalRefParams): Route => database(p).addStatic("releases").withQuery({ refName: p.refName }); +export const remotes = (p: ps.DatabaseParams): Route => + database(p).addStatic("remotes"); + const staticPulls = (p: ps.DatabaseParams) => database(p).addStatic("pulls"); export const pulls = (p: ps.PullParams): Route => diff --git a/web/renderer/pages/database/[databaseName]/remotes/index.tsx b/web/renderer/pages/database/[databaseName]/remotes/index.tsx new file mode 100644 index 00000000..79704714 --- /dev/null +++ b/web/renderer/pages/database/[databaseName]/remotes/index.tsx @@ -0,0 +1,37 @@ +import Page from "@components/util/Page"; +import { DatabaseParams, MaybeRefParams } from "@lib/params"; +import DatabasePage from "@pageComponents/DatabasePage"; +import { GetServerSideProps, NextPage } from "next"; + +type Props = { + params: MaybeRefParams; +}; + +const DatabaseRemotesPage: NextPage = ({ params }) => ( + + + +); + +// #!if !isElectron +export const getServerSideProps: GetServerSideProps = async ({ + params, + query, +}) => { + return { + props: { + params: { + ...(params as DatabaseParams), + refName: query.refName ? String(query.refName) : null, + }, + }, + }; +}; +// #!endif + +export default DatabaseRemotesPage; From 5f6d76bc6cad49c237c3b3d2059283d75205b86d Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Mon, 2 Dec 2024 16:00:46 -0800 Subject: [PATCH 02/18] lint fix --- graphql-server/schema.gql | 2 +- graphql-server/src/queryFactory/mysql/index.ts | 2 +- graphql-server/src/remotes/remote.model.ts | 4 ++-- graphql-server/src/remotes/remote.resolver.ts | 2 +- .../DatabasePage/ForRemotes/RemotesPage.tsx | 2 +- .../pageComponents/DatabasePage/ForRemotes/queries.ts | 2 +- web/renderer/gen/graphql-types.tsx | 8 ++++---- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/graphql-server/schema.gql b/graphql-server/schema.gql index 32da2e3a..e2999448 100644 --- a/graphql-server/schema.gql +++ b/graphql-server/schema.gql @@ -283,7 +283,7 @@ type Remote { _id: ID! name: String! url: String! - fetch_specs: [String!]! + fetchSpecs: [String!]! } type RemoteList { diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index 8cee7dee..7116dda3 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -302,7 +302,7 @@ export class MySQLQueryFactory throw notDoltError("restore all tables"); } - async getRemotes(args: t.DBArgs): t.PR { + async getRemotes(_args: t.DBArgs): t.PR { throw notDoltError("get one-sided diff"); } } diff --git a/graphql-server/src/remotes/remote.model.ts b/graphql-server/src/remotes/remote.model.ts index 11a201ed..eb3ee6c1 100644 --- a/graphql-server/src/remotes/remote.model.ts +++ b/graphql-server/src/remotes/remote.model.ts @@ -14,7 +14,7 @@ export class Remote { url: string; @Field(_type => [String]) - fetch_specs: string[]; + fetchSpecs: string[]; } @ObjectType() @@ -28,6 +28,6 @@ export function fromDoltRemotesRow(databaseName: string, r: RawRow): Remote { _id: `databases/${databaseName}/remotes/${r.name}`, name: r.name, url: r.url, - fetch_specs: r.fetch_specs, + fetchSpecs: r.fetch_specs, }; } diff --git a/graphql-server/src/remotes/remote.resolver.ts b/graphql-server/src/remotes/remote.resolver.ts index 68da63d4..e07dea4c 100644 --- a/graphql-server/src/remotes/remote.resolver.ts +++ b/graphql-server/src/remotes/remote.resolver.ts @@ -1,9 +1,9 @@ import { Args, Query, Resolver } from "@nestjs/graphql"; import { ConnectionProvider } from "src/connections/connection.provider"; -import { fromDoltRemotesRow, Remote, RemoteList } from "./remote.model"; import { DBArgsWithOffset } from "src/utils/commonTypes"; import { RawRow } from "src/queryFactory/types"; import { getNextOffset, ROW_LIMIT } from "src/utils"; +import { fromDoltRemotesRow, Remote, RemoteList } from "./remote.model"; @Resolver(_of => Remote) export class RemoteResolver { diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx index e07109a2..02e892eb 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx @@ -17,7 +17,7 @@ function Inner({ remotes }: InnerProps) {
  • {remote.name} {remote.url} - {remote.fetch_specs} + {remote.fetchSpecs}
  • ))} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts index dde9702c..db1f0212 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts @@ -5,7 +5,7 @@ export const REMOTES_FOR_REMOTES_PAGE_QUERY = gql` _id name url - fetch_specs + fetchSpecs } query RemoteList($databaseName: String!, $offset: Int) { remotes(databaseName: $databaseName, offset: $offset) { diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index 8913b999..15242c68 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -617,7 +617,7 @@ export enum QueryExecutionStatus { export type Remote = { __typename?: 'Remote'; _id: Scalars['ID']['output']; - fetch_specs: Array; + fetchSpecs: Array; name: Scalars['String']['output']; url: Scalars['String']['output']; }; @@ -1182,7 +1182,7 @@ export type DeleteTagMutationVariables = Exact<{ export type DeleteTagMutation = { __typename?: 'Mutation', deleteTag: boolean }; -export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetch_specs: Array }; +export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs: Array }; export type RemoteListQueryVariables = Exact<{ databaseName: Scalars['String']['input']; @@ -1190,7 +1190,7 @@ export type RemoteListQueryVariables = Exact<{ }>; -export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetch_specs: Array }> } }; +export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs: Array }> } }; export type LoadDataMutationVariables = Exact<{ databaseName: Scalars['String']['input']; @@ -1615,7 +1615,7 @@ export const RemoteFragmentDoc = gql` _id name url - fetch_specs + fetchSpecs } `; export const ColumnForDataTableFragmentDoc = gql` From ce498beada856174e92a3c567a3beed9ce6e1338 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Mon, 2 Dec 2024 16:28:19 -0800 Subject: [PATCH 03/18] remotes list ui --- .../breadcrumbs/RemotesBreadcrumbs.tsx | 20 ++++---- .../breadcrumbs/breadcrumbDetails.tsx | 5 +- .../DatabasePage/ForRemotes/RemotesPage.tsx | 41 +++++++++++++---- .../DatabasePage/ForRemotes/Row.tsx | 22 +++++++++ .../DatabasePage/ForRemotes/index.module.css | 46 +++++++++++++++++++ .../DatabasePage/ForRemotes/index.tsx | 6 +-- 6 files changed, 114 insertions(+), 26 deletions(-) create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css diff --git a/web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx b/web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx index 8ae955e3..7d9b032b 100644 --- a/web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx +++ b/web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx @@ -1,4 +1,4 @@ -import { DatabaseParams } from "@lib/params"; +import { DatabaseParams } from "@lib/params"; import Breadcrumbs from "."; import { remoteBreadcrumbDetails } from "./breadcrumbDetails"; @@ -8,12 +8,12 @@ type Props = { }; export default function RemotesBreadcrumbs(props: Props) { - return ( - - ); -} \ No newline at end of file + return ( + + ); +} diff --git a/web/renderer/components/breadcrumbs/breadcrumbDetails.tsx b/web/renderer/components/breadcrumbs/breadcrumbDetails.tsx index 8ff42355..8f5260f3 100644 --- a/web/renderer/components/breadcrumbs/breadcrumbDetails.tsx +++ b/web/renderer/components/breadcrumbs/breadcrumbDetails.tsx @@ -113,7 +113,9 @@ export function commitLogBreadcrumbDetails( ]; } -export function remoteBreadcrumbDetails(params: DatabaseParams): BreadcrumbDetails[] { +export function remoteBreadcrumbDetails( + params: DatabaseParams, +): BreadcrumbDetails[] { return [ ...databaseBreadcrumbs(params), { @@ -124,7 +126,6 @@ export function remoteBreadcrumbDetails(params: DatabaseParams): BreadcrumbDetai ]; } - export function tableBreadcrumbsDetails( params: TableParams, ): BreadcrumbDetails[] { diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx index 02e892eb..37586c52 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx @@ -1,26 +1,47 @@ import { QueryHandler } from "@dolthub/react-components"; import { RemoteFragment, useRemoteListQuery } from "@gen/graphql-types"; import { DatabaseParams } from "@lib/params"; +import css from "./index.module.css"; +import Row from "./Row"; type Props = { params: DatabaseParams; }; type InnerProps = { - remotes : RemoteFragment[]; + remotes: RemoteFragment[]; }; function Inner({ remotes }: InnerProps) { return ( -
      - {remotes.map(remote => ( -
    • - {remote.name} - {remote.url} - {remote.fetchSpecs} -
    • - ))} -
    +
    +
    +

    Remotes

    +
    + + {remotes.length ? ( +
    + + + + + + + + + + {remotes.map(r => ( + + ))} + +
    NameUrlFetch Specs
    +
    + ) : ( +

    + No remotes found +

    + )} +
    ); } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx new file mode 100644 index 00000000..a399b3b9 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx @@ -0,0 +1,22 @@ +import { RemoteFragment } from "@gen/graphql-types"; + +type Props = { + remote: RemoteFragment; +}; + +export default function Row({ remote }: Props) { + return ( + + {remote.name} + {remote.url} + + {remote.fetchSpecs.map((fs, i) => ( + + {fs} + {i < remote.fetchSpecs.length - 1 ? ", " : ""} + + ))} + + + ); +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css new file mode 100644 index 00000000..fd188186 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css @@ -0,0 +1,46 @@ +.container { + @apply mx-6; +} + +.top { + @apply flex justify-between pt-6; +} + +.tableParent { + @apply overflow-x-auto; +} + +.table { + @apply my-8 min-w-[55rem] w-full; + + tr { + @apply border-b-[6px] border-stone-50 relative; + } + + th { + @apply font-semibold; + } + + th, + td { + @apply pl-2 pr-4 py-2.5 text-left lg:pr-10; + } + + td { + @apply bg-white text-stone-500; + } + + th:first-child, + td:first-child { + @apply xl:pl-20; + } + + th:last-child, + td:last-child { + @apply xl:pr-32; + } +} + +.noRemotes { + @apply text-center text-lg m-6; +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx index 285b8d20..16ba2bb4 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx @@ -17,13 +17,11 @@ export default function ForBranches({ params, newBranch }: Props): JSX.Element { initialTabIndex={5} params={params} hideDefaultTable - smallHeaderBreadcrumbs={ - - } + smallHeaderBreadcrumbs={} routeRefChangeTo={urlParams => branches(urlParams)} > - + ); From 1b908069f3e03180660e189b576f645fefeb0c55 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 10:30:31 -0800 Subject: [PATCH 04/18] params --- graphql-server/schema.gql | 1 + graphql-server/src/remotes/remote.model.ts | 5 +++++ .../pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx | 1 + .../pageComponents/DatabasePage/ForRemotes/Row.tsx | 1 + .../pageComponents/DatabasePage/ForRemotes/queries.ts | 1 + web/renderer/gen/graphql-types.tsx | 6 ++++-- 6 files changed, 13 insertions(+), 2 deletions(-) diff --git a/graphql-server/schema.gql b/graphql-server/schema.gql index e2999448..c426e0ca 100644 --- a/graphql-server/schema.gql +++ b/graphql-server/schema.gql @@ -284,6 +284,7 @@ type Remote { name: String! url: String! fetchSpecs: [String!]! + params: String } type RemoteList { diff --git a/graphql-server/src/remotes/remote.model.ts b/graphql-server/src/remotes/remote.model.ts index eb3ee6c1..dc159357 100644 --- a/graphql-server/src/remotes/remote.model.ts +++ b/graphql-server/src/remotes/remote.model.ts @@ -1,4 +1,5 @@ import { Field, ID, ObjectType } from "@nestjs/graphql"; +import { __Type } from "graphql"; import { RawRow } from "src/queryFactory/types"; import { ListOffsetRes } from "src/utils/commonTypes"; @@ -15,6 +16,9 @@ export class Remote { @Field(_type => [String]) fetchSpecs: string[]; + + @Field({ nullable: true }) + params?: string; } @ObjectType() @@ -29,5 +33,6 @@ export function fromDoltRemotesRow(databaseName: string, r: RawRow): Remote { name: r.name, url: r.url, fetchSpecs: r.fetch_specs, + params: r.params, }; } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx index 37586c52..44c390fd 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx @@ -27,6 +27,7 @@ function Inner({ remotes }: InnerProps) { Name Url Fetch Specs + Params diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx index a399b3b9..fbd828cc 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx @@ -17,6 +17,7 @@ export default function Row({ remote }: Props) { ))} + {remote.params} ); } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts index db1f0212..663ec458 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts @@ -6,6 +6,7 @@ export const REMOTES_FOR_REMOTES_PAGE_QUERY = gql` name url fetchSpecs + params } query RemoteList($databaseName: String!, $offset: Int) { remotes(databaseName: $databaseName, offset: $offset) { diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index 15242c68..fb184cf7 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -619,6 +619,7 @@ export type Remote = { _id: Scalars['ID']['output']; fetchSpecs: Array; name: Scalars['String']['output']; + params?: Maybe; url: Scalars['String']['output']; }; @@ -1182,7 +1183,7 @@ export type DeleteTagMutationVariables = Exact<{ export type DeleteTagMutation = { __typename?: 'Mutation', deleteTag: boolean }; -export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs: Array }; +export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs: Array, params?: string | null }; export type RemoteListQueryVariables = Exact<{ databaseName: Scalars['String']['input']; @@ -1190,7 +1191,7 @@ export type RemoteListQueryVariables = Exact<{ }>; -export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs: Array }> } }; +export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs: Array, params?: string | null }> } }; export type LoadDataMutationVariables = Exact<{ databaseName: Scalars['String']['input']; @@ -1616,6 +1617,7 @@ export const RemoteFragmentDoc = gql` name url fetchSpecs + params } `; export const ColumnForDataTableFragmentDoc = gql` From 0cd26e517f412454304b4be5c627cf3655a4ac06 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 11:00:45 -0800 Subject: [PATCH 05/18] infinite scroll, clean up --- graphql-server/schema.gql | 2 +- .../src/queryFactory/mysql/index.ts | 2 +- graphql-server/src/remotes/remote.model.ts | 4 +- .../ForRemotes/{Row.tsx => RemoteRow.tsx} | 2 +- .../DatabasePage/ForRemotes/RemotesPage.tsx | 68 +++++++++++------ .../DatabasePage/ForRemotes/index.module.css | 4 + .../DatabasePage/ForRemotes/index.tsx | 11 +-- .../DatabasePage/ForRemotes/useRemoteList.ts | 74 +++++++++++++++++++ .../database/[databaseName]/remotes/index.tsx | 17 +---- 9 files changed, 138 insertions(+), 46 deletions(-) rename web/renderer/components/pageComponents/DatabasePage/ForRemotes/{Row.tsx => RemoteRow.tsx} (88%) create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/useRemoteList.ts diff --git a/graphql-server/schema.gql b/graphql-server/schema.gql index c426e0ca..ace26946 100644 --- a/graphql-server/schema.gql +++ b/graphql-server/schema.gql @@ -283,7 +283,7 @@ type Remote { _id: ID! name: String! url: String! - fetchSpecs: [String!]! + fetchSpecs: [String!] params: String } diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index 7116dda3..1f1157ec 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -303,6 +303,6 @@ export class MySQLQueryFactory } async getRemotes(_args: t.DBArgs): t.PR { - throw notDoltError("get one-sided diff"); + throw notDoltError("get remotes"); } } diff --git a/graphql-server/src/remotes/remote.model.ts b/graphql-server/src/remotes/remote.model.ts index dc159357..72a77769 100644 --- a/graphql-server/src/remotes/remote.model.ts +++ b/graphql-server/src/remotes/remote.model.ts @@ -14,8 +14,8 @@ export class Remote { @Field() url: string; - @Field(_type => [String]) - fetchSpecs: string[]; + @Field(_type => [String], { nullable: true }) + fetchSpecs?: string[]; @Field({ nullable: true }) params?: string; diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx similarity index 88% rename from web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx rename to web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx index fbd828cc..7c8c284f 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/Row.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx @@ -4,7 +4,7 @@ type Props = { remote: RemoteFragment; }; -export default function Row({ remote }: Props) { +export default function RemoteRow({ remote }: Props) { return ( {remote.name} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx index 44c390fd..06bc22e1 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx @@ -1,8 +1,13 @@ -import { QueryHandler } from "@dolthub/react-components"; -import { RemoteFragment, useRemoteListQuery } from "@gen/graphql-types"; +import { Loader, QueryHandler } from "@dolthub/react-components"; +import { RemoteFragment } from "@gen/graphql-types"; import { DatabaseParams } from "@lib/params"; +import { gqlDepNotFound } from "@lib/errors/graphql"; +import { errorMatches } from "@lib/errors/helpers"; +import Database404 from "@components/Database404"; +import InfiniteScroll from "react-infinite-scroller"; +import { useRemoteList } from "./useRemoteList"; +import RemoteRow from "./RemoteRow"; import css from "./index.module.css"; -import Row from "./Row"; type Props = { params: DatabaseParams; @@ -10,32 +15,42 @@ type Props = { type InnerProps = { remotes: RemoteFragment[]; + loadMore: () => Promise; + hasMore: boolean; }; -function Inner({ remotes }: InnerProps) { +function Inner({ remotes, loadMore, hasMore }: InnerProps) { return (

    Remotes

    - {remotes.length ? (
    - - - - - - - - - - - {remotes.map(r => ( - - ))} - -
    NameUrlFetch SpecsParams
    + Loading remotes ...
    } + useWindow={false} + initialLoad={false} + getScrollParent={() => document.getElementById("main-content")} + > + + + + + + + + + + + {remotes.map(r => ( + + ))} + +
    NameUrlFetch SpecsParams
    +
    ) : (

    @@ -47,11 +62,18 @@ function Inner({ remotes }: InnerProps) { } export default function RemotesPage({ params }: Props) { - const res = useRemoteListQuery({ variables: params }); + const res = useRemoteList(params); + if (res.loading) return ; + if (errorMatches(gqlDepNotFound, res.error)) { + return ; + } + return ( } + result={{ ...res, data: res.remotes }} + render={data => ( + + )} /> ); } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css index fd188186..9b6d8b05 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css @@ -44,3 +44,7 @@ .noRemotes { @apply text-center text-lg m-6; } + +.loader { + @apply text-primary my-4 text-center; +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx index 16ba2bb4..cf8aa4f5 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx @@ -1,24 +1,25 @@ import RemotesBreadcrumbs from "@components/breadcrumbs/RemotesBreadcrumbs"; import NotDoltWrapper from "@components/util/NotDoltWrapper"; import { OptionalRefParams } from "@lib/params"; -import { branches } from "@lib/urls"; +import { remotes } from "@lib/urls"; import ForDefaultBranch from "../ForDefaultBranch"; import RemotesPage from "./RemotesPage"; type Props = { params: OptionalRefParams; - newBranch?: boolean; + newRemote?: boolean; }; -export default function ForBranches({ params, newBranch }: Props): JSX.Element { - const feature = newBranch ? "Creating new branches" : "Viewing branches"; +export default function ForRemotes({ params, newRemote }: Props): JSX.Element { + const feature = newRemote ? "Creating remotes" : "Viewing Remotes"; return ( } - routeRefChangeTo={urlParams => branches(urlParams)} + title="remotes" + routeRefChangeTo={remotes} > diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/useRemoteList.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/useRemoteList.ts new file mode 100644 index 00000000..61205078 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/useRemoteList.ts @@ -0,0 +1,74 @@ +import { Maybe } from "@dolthub/web-utils"; +import { + RemoteFragment, + RemoteListDocument, + RemoteListQuery, + RemoteListQueryVariables, + useRemoteListQuery, +} from "@gen/graphql-types"; +import useApolloError from "@hooks/useApolloError"; +import { handleCaughtApolloError } from "@lib/errors/helpers"; +import { ApolloErrorType } from "@lib/errors/types"; +import { DatabaseParams } from "@lib/params"; +import { useEffect, useState } from "react"; + +type ReturnType = { + remotes: RemoteFragment[] | undefined; + loadMore: () => Promise; + error?: ApolloErrorType; + loading: boolean; + hasMore: boolean; + refetch: () => Promise; +}; + +export function useRemoteList(params: DatabaseParams): ReturnType { + const { data, ...res } = useRemoteListQuery({ + variables: params, + fetchPolicy: "cache-and-network", + }); + const [err, setErr] = useApolloError(res.error); + const [remotes, setRemotes] = useState(data?.remotes.list); + const [offset, setOffset] = useState(data?.remotes.nextOffset); + const [lastOffset, setLastOffset] = useState>(undefined); + + const refetch = async () => { + try { + const newRes = await res.refetch(params); + setRemotes(newRes.data.remotes.list); + } catch (e) { + handleCaughtApolloError(e, setErr); + } + }; + + useEffect(() => { + setRemotes(data?.remotes.list); + setOffset(data?.remotes.nextOffset); + }, [data, setRemotes]); + + const loadMore = async () => { + if (!offset) { + return; + } + setLastOffset(offset); + try { + const result = await res.client.query< + RemoteListQuery, + RemoteListQueryVariables + >({ + query: RemoteListDocument, + variables: { ...params, offset }, + }); + const newRemotes = result.data.remotes.list; + const newOffset = result.data.remotes.nextOffset; + setRemotes((remotes ?? []).concat(newRemotes)); + setOffset(newOffset); + } catch (e) { + handleCaughtApolloError(e, setErr); + } + }; + + const hasMore = + offset !== undefined && offset !== null && offset !== lastOffset; + + return { ...res, error: err, remotes, loadMore, hasMore, refetch }; +} diff --git a/web/renderer/pages/database/[databaseName]/remotes/index.tsx b/web/renderer/pages/database/[databaseName]/remotes/index.tsx index 79704714..961d0270 100644 --- a/web/renderer/pages/database/[databaseName]/remotes/index.tsx +++ b/web/renderer/pages/database/[databaseName]/remotes/index.tsx @@ -1,34 +1,25 @@ import Page from "@components/util/Page"; -import { DatabaseParams, MaybeRefParams } from "@lib/params"; +import { DatabaseParams } from "@lib/params"; import DatabasePage from "@pageComponents/DatabasePage"; import { GetServerSideProps, NextPage } from "next"; type Props = { - params: MaybeRefParams; + params: DatabaseParams; }; const DatabaseRemotesPage: NextPage = ({ params }) => ( - + ); // #!if !isElectron export const getServerSideProps: GetServerSideProps = async ({ params, - query, }) => { return { props: { - params: { - ...(params as DatabaseParams), - refName: query.refName ? String(query.refName) : null, - }, + params: params as DatabaseParams, }, }; }; From 9013727609a9225976bbeb67c6f74af9423b9334 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 11:04:57 -0800 Subject: [PATCH 06/18] generate types --- web/renderer/gen/graphql-types.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index fb184cf7..0ad0328d 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -617,7 +617,7 @@ export enum QueryExecutionStatus { export type Remote = { __typename?: 'Remote'; _id: Scalars['ID']['output']; - fetchSpecs: Array; + fetchSpecs?: Maybe>; name: Scalars['String']['output']; params?: Maybe; url: Scalars['String']['output']; @@ -1183,7 +1183,7 @@ export type DeleteTagMutationVariables = Exact<{ export type DeleteTagMutation = { __typename?: 'Mutation', deleteTag: boolean }; -export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs: Array, params?: string | null }; +export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null, params?: string | null }; export type RemoteListQueryVariables = Exact<{ databaseName: Scalars['String']['input']; @@ -1191,7 +1191,7 @@ export type RemoteListQueryVariables = Exact<{ }>; -export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs: Array, params?: string | null }> } }; +export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null, params?: string | null }> } }; export type LoadDataMutationVariables = Exact<{ databaseName: Scalars['String']['input']; From 2e79a554a05fb94078c18d328f6c91c6dba5a6f2 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 11:17:23 -0800 Subject: [PATCH 07/18] null --- .../pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx index 7c8c284f..b9e3e205 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx @@ -10,10 +10,10 @@ export default function RemoteRow({ remote }: Props) { {remote.name} {remote.url} - {remote.fetchSpecs.map((fs, i) => ( + {remote.fetchSpecs?.map((fs, i) => ( {fs} - {i < remote.fetchSpecs.length - 1 ? ", " : ""} + {i < (remote.fetchSpecs?.length ?? 0) - 1 ? ", " : ""} ))} From 8c2a8a54deed165e48564783dbfe351e03ed9fbc Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 11:39:50 -0800 Subject: [PATCH 08/18] use branch list ui --- .../DatabasePage/ForRemotes/index.module.css | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css index 9b6d8b05..50d24647 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css @@ -11,33 +11,34 @@ } .table { - @apply my-8 min-w-[55rem] w-full; + @apply border border-stone-100 border-separate rounded-lg text-primary mx-auto my-10 overflow-x-auto block; + border-spacing: 0; - tr { - @apply border-b-[6px] border-stone-50 relative; + @screen lg { + @apply min-w-[40rem] overflow-x-visible; + display: table; } + td, th { - @apply font-semibold; + @apply px-6 text-left; } - th, - td { - @apply pl-2 pr-4 py-2.5 text-left lg:pr-10; + th { + @apply pt-6 pb-2 bg-stone-50; } td { - @apply bg-white text-stone-500; - } - - th:first-child, - td:first-child { - @apply xl:pl-20; + @apply border-t border-stone-100 py-3; } - th:last-child, - td:last-child { - @apply xl:pr-32; + tr:first-child { + th:first-child { + @apply rounded-tl-lg; + } + th:last-child { + @apply rounded-tr-lg; + } } } From 4c6fd12a187046ba84c1207cf77f44e769a75546 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 11:51:36 -0800 Subject: [PATCH 09/18] remove params column --- graphql-server/schema.gql | 1 - graphql-server/src/remotes/remote.model.ts | 4 ---- .../pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx | 1 - .../pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx | 1 - .../pageComponents/DatabasePage/ForRemotes/queries.ts | 1 - web/renderer/gen/graphql-types.tsx | 6 ++---- 6 files changed, 2 insertions(+), 12 deletions(-) diff --git a/graphql-server/schema.gql b/graphql-server/schema.gql index ace26946..a64fb17f 100644 --- a/graphql-server/schema.gql +++ b/graphql-server/schema.gql @@ -284,7 +284,6 @@ type Remote { name: String! url: String! fetchSpecs: [String!] - params: String } type RemoteList { diff --git a/graphql-server/src/remotes/remote.model.ts b/graphql-server/src/remotes/remote.model.ts index 72a77769..94b8915f 100644 --- a/graphql-server/src/remotes/remote.model.ts +++ b/graphql-server/src/remotes/remote.model.ts @@ -16,9 +16,6 @@ export class Remote { @Field(_type => [String], { nullable: true }) fetchSpecs?: string[]; - - @Field({ nullable: true }) - params?: string; } @ObjectType() @@ -33,6 +30,5 @@ export function fromDoltRemotesRow(databaseName: string, r: RawRow): Remote { name: r.name, url: r.url, fetchSpecs: r.fetch_specs, - params: r.params, }; } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx index b9e3e205..4a0041fd 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx @@ -17,7 +17,6 @@ export default function RemoteRow({ remote }: Props) { ))} - {remote.params} ); } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx index 06bc22e1..594efe8f 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx @@ -41,7 +41,6 @@ function Inner({ remotes, loadMore, hasMore }: InnerProps) { Name Url Fetch Specs - Params diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts index 663ec458..db1f0212 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts @@ -6,7 +6,6 @@ export const REMOTES_FOR_REMOTES_PAGE_QUERY = gql` name url fetchSpecs - params } query RemoteList($databaseName: String!, $offset: Int) { remotes(databaseName: $databaseName, offset: $offset) { diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index 0ad0328d..8160046e 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -619,7 +619,6 @@ export type Remote = { _id: Scalars['ID']['output']; fetchSpecs?: Maybe>; name: Scalars['String']['output']; - params?: Maybe; url: Scalars['String']['output']; }; @@ -1183,7 +1182,7 @@ export type DeleteTagMutationVariables = Exact<{ export type DeleteTagMutation = { __typename?: 'Mutation', deleteTag: boolean }; -export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null, params?: string | null }; +export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }; export type RemoteListQueryVariables = Exact<{ databaseName: Scalars['String']['input']; @@ -1191,7 +1190,7 @@ export type RemoteListQueryVariables = Exact<{ }>; -export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null, params?: string | null }> } }; +export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }> } }; export type LoadDataMutationVariables = Exact<{ databaseName: Scalars['String']['input']; @@ -1617,7 +1616,6 @@ export const RemoteFragmentDoc = gql` name url fetchSpecs - params } `; export const ColumnForDataTableFragmentDoc = gql` From d8fd1b30ce8cb29d6f176b00768d8287f3175527 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 13:37:39 -0800 Subject: [PATCH 10/18] add remote --- graphql-server/schema.gql | 1 + graphql-server/src/queryFactory/dolt/index.ts | 8 ++ .../src/queryFactory/dolt/queries.ts | 4 + .../src/queryFactory/doltgres/index.ts | 8 ++ .../src/queryFactory/doltgres/queries.ts | 4 + graphql-server/src/queryFactory/index.ts | 2 + .../src/queryFactory/mysql/index.ts | 4 + graphql-server/src/queryFactory/types.ts | 1 + graphql-server/src/remotes/remote.resolver.ts | 27 +++++- .../AddRemoteForm/index.module.css | 14 ++++ .../AddRemotePage/AddRemoteForm/index.tsx | 84 +++++++++++++++++++ .../AddRemotePage/AddRemoteForm/queries.ts | 15 ++++ .../ForRemotes/AddRemotePage/index.module.css | 3 + .../ForRemotes/AddRemotePage/index.tsx | 16 ++++ .../DatabasePage/ForRemotes/RemotesPage.tsx | 24 +++++- .../DatabasePage/ForRemotes/index.tsx | 12 ++- web/renderer/gen/graphql-types.tsx | 54 ++++++++++++ web/renderer/lib/urls.ts | 3 + .../database/[databaseName]/remotes/new.tsx | 28 +++++++ 19 files changed, 303 insertions(+), 9 deletions(-) create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.module.css create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.tsx create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.module.css create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.tsx create mode 100644 web/renderer/pages/database/[databaseName]/remotes/new.tsx diff --git a/graphql-server/schema.gql b/graphql-server/schema.gql index a64fb17f..41760f18 100644 --- a/graphql-server/schema.gql +++ b/graphql-server/schema.gql @@ -361,6 +361,7 @@ type Mutation { resetDatabase(newDatabase: String): Boolean! loadDataFile(schemaName: String, tableName: String!, refName: String!, databaseName: String!, importOp: ImportOperation!, fileType: FileType!, file: Upload!, modifier: LoadDataModifier): Boolean! mergePull(fromBranchName: String!, toBranchName: String!, databaseName: String!, author: AuthorInfo): Boolean! + addRemote(databaseName: String!, remoteName: String!, remoteUrl: String!): String! restoreAllTables(databaseName: String!, refName: String!): Boolean! createTag(tagName: String!, databaseName: String!, message: String, fromRefName: String!, author: AuthorInfo): String! deleteTag(databaseName: String!, tagName: String!): Boolean! diff --git a/graphql-server/src/queryFactory/dolt/index.ts b/graphql-server/src/queryFactory/dolt/index.ts index 7e0d8bb6..cc8d9600 100644 --- a/graphql-server/src/queryFactory/dolt/index.ts +++ b/graphql-server/src/queryFactory/dolt/index.ts @@ -441,6 +441,14 @@ export class DoltQueryFactory args.databaseName, ); } + + async addRemote(args: t.AddRemoteArgs): t.PR { + return this.query( + qh.callAddRemote, + [args.remoteName, args.remoteUrl], + args.databaseName, + ); + } } async function getTableInfoWithQR( diff --git a/graphql-server/src/queryFactory/dolt/queries.ts b/graphql-server/src/queryFactory/dolt/queries.ts index 3026a790..c4b53fba 100644 --- a/graphql-server/src/queryFactory/dolt/queries.ts +++ b/graphql-server/src/queryFactory/dolt/queries.ts @@ -74,6 +74,10 @@ export const threeDotSchemaDiffQuery = `SELECT * FROM DOLT_SCHEMA_DIFF(?, ?)`; export const getCallMerge = (hasAuthor = false) => `CALL DOLT_MERGE(?, "--no-ff", "-m", ?${getAuthorNameString(hasAuthor)})`; +// REMOTES + +export const callAddRemote = `CALL DOLT_REMOTE("add", ?, ?)`; + // TAGS export const callDeleteTag = `CALL DOLT_TAG("-d", ?)`; diff --git a/graphql-server/src/queryFactory/doltgres/index.ts b/graphql-server/src/queryFactory/doltgres/index.ts index 6682e254..102255e7 100644 --- a/graphql-server/src/queryFactory/doltgres/index.ts +++ b/graphql-server/src/queryFactory/doltgres/index.ts @@ -432,6 +432,14 @@ export class DoltgresQueryFactory args.databaseName, ); } + + async addRemote(args: t.AddRemoteArgs): t.PR { + return this.query( + qh.callAddRemote, + [args.remoteName, args.remoteUrl], + args.databaseName, + ); + } } async function getTableInfoWithQR( diff --git a/graphql-server/src/queryFactory/doltgres/queries.ts b/graphql-server/src/queryFactory/doltgres/queries.ts index 00773529..548d3599 100644 --- a/graphql-server/src/queryFactory/doltgres/queries.ts +++ b/graphql-server/src/queryFactory/doltgres/queries.ts @@ -160,3 +160,7 @@ export function getOrderByFromDiffCols(cols: t.RawRows): string { export const callResetHard = `SELECT DOLT_RESET('--hard')`; export const callCheckoutTable = `SELECT DOLT_CHECKOUT($1::text)`; + +// REMOTES + +export const callAddRemote = `SELECT DOLT_REMOTE($1::text, $2::text)`; diff --git a/graphql-server/src/queryFactory/index.ts b/graphql-server/src/queryFactory/index.ts index e44fcc76..64ec65c2 100644 --- a/graphql-server/src/queryFactory/index.ts +++ b/graphql-server/src/queryFactory/index.ts @@ -146,4 +146,6 @@ export declare class QueryFactory { restoreAllTables(args: t.RefArgs): t.PR; getRemotes(args: t.DBArgs): t.PR; + + addRemote(args: t.AddRemoteArgs): t.PR; } diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index 1f1157ec..c09e0262 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -305,4 +305,8 @@ export class MySQLQueryFactory async getRemotes(_args: t.DBArgs): t.PR { throw notDoltError("get remotes"); } + + async addRemote(_: t.AddRemoteArgs): t.PR { + throw notDoltError("add remote"); + } } diff --git a/graphql-server/src/queryFactory/types.ts b/graphql-server/src/queryFactory/types.ts index ad151b1c..09854d6b 100644 --- a/graphql-server/src/queryFactory/types.ts +++ b/graphql-server/src/queryFactory/types.ts @@ -7,6 +7,7 @@ export type RefArgs = DBArgs & { refName: string }; export type RefSchemaArgs = RefArgs & { schemaName: string }; export type RefMaybeSchemaArgs = RefArgs & { schemaName?: string }; export type BranchArgs = DBArgs & { branchName: string }; +export type AddRemoteArgs = DBArgs & { remoteName: string; remoteUrl: string }; export type TagArgs = DBArgs & { tagName: string }; export type TableArgs = RefArgs & { tableName: string }; export type TableMaybeSchemaArgs = TableArgs & { schemaName?: string }; diff --git a/graphql-server/src/remotes/remote.resolver.ts b/graphql-server/src/remotes/remote.resolver.ts index e07dea4c..bb3a6cc5 100644 --- a/graphql-server/src/remotes/remote.resolver.ts +++ b/graphql-server/src/remotes/remote.resolver.ts @@ -1,10 +1,26 @@ -import { Args, Query, Resolver } from "@nestjs/graphql"; +import { + Args, + ArgsType, + Field, + Mutation, + Query, + Resolver, +} from "@nestjs/graphql"; import { ConnectionProvider } from "src/connections/connection.provider"; -import { DBArgsWithOffset } from "src/utils/commonTypes"; +import { DBArgs, DBArgsWithOffset } from "src/utils/commonTypes"; import { RawRow } from "src/queryFactory/types"; import { getNextOffset, ROW_LIMIT } from "src/utils"; import { fromDoltRemotesRow, Remote, RemoteList } from "./remote.model"; +@ArgsType() +export class AddRemoteArgs extends DBArgs { + @Field() + remoteName: string; + + @Field() + remoteUrl: string; +} + @Resolver(_of => Remote) export class RemoteResolver { constructor(private readonly conn: ConnectionProvider) {} @@ -16,6 +32,13 @@ export class RemoteResolver { const res = await conn.getRemotes(args); return getRemoteListRes(res, args); } + + @Mutation(_returns => String) + async addRemote(@Args() args: AddRemoteArgs): Promise { + const conn = this.conn.connection(); + await conn.addRemote(args); + return args.remoteName; + } } function getRemoteListRes( diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.module.css b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.module.css new file mode 100644 index 00000000..5287a3c7 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.module.css @@ -0,0 +1,14 @@ +.container { + @apply max-w-2xl mx-auto; +} + +.input { + @apply mt-4 px-0; + input { + @apply text-sm rounded bg-stone-50 border border-stone-100; + + &:focus { + @apply bg-white; + } + } +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.tsx new file mode 100644 index 00000000..338e7f13 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.tsx @@ -0,0 +1,84 @@ +import { + Button, + ButtonsWithError, + FormInput, + Loader, +} from "@dolthub/react-components"; +import { useReactiveWidth } from "@dolthub/react-hooks"; +import { useAddRemoteMutation } from "@gen/graphql-types"; +import useMutation from "@hooks/useMutation"; +import { DatabaseParams } from "@lib/params"; +import { refetchBranchQueries } from "@lib/refetchQueries"; +import { remotes } from "@lib/urls"; +import { useRouter } from "next/router"; +import { SyntheticEvent, useState } from "react"; +import css from "./index.module.css"; + +type Props = { + params: DatabaseParams; +}; + +export default function AddRemoteForm(props: Props): JSX.Element { + const router = useRouter(); + const [remoteName, setRemoteName] = useState(""); + const [remoteUrl, setRemoteUrl] = useState(""); + const { + mutateFn: addRemote, + err, + loading, + } = useMutation({ + hook: useAddRemoteMutation, + refetchQueries: refetchBranchQueries(props.params), + }); + const { isMobile } = useReactiveWidth(); + + const goToRemotesPage = () => { + const { href, as } = remotes(props.params); + router.push(href, as).catch(() => {}); + }; + + const onSubmit = async (e: SyntheticEvent) => { + e.preventDefault(); + if (!remoteName || !remoteUrl) return; + + const { data } = await addRemote({ + variables: { ...props.params, remoteName, remoteUrl }, + }); + if (!data) return; + const { href, as } = remotes(props.params); + router.push(href, as).catch(console.error); + }; + + return ( +

    +
    +
    + + + + + +
    + + +
    + ); +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts new file mode 100644 index 00000000..c606ad59 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts @@ -0,0 +1,15 @@ +import { gql } from "@apollo/client"; + +export const CREATE_BRANCH = gql` + mutation AddRemote( + $databaseName: String! + $remoteName: String! + $remoteUrl: String! + ) { + addRemote( + databaseName: $databaseName + remoteName: $remoteName + remoteUrl: $remoteUrl + ) + } +`; diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.module.css b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.module.css new file mode 100644 index 00000000..c816b6c0 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.module.css @@ -0,0 +1,3 @@ +.container { + @apply m-6; +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.tsx new file mode 100644 index 00000000..6070c9c5 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.tsx @@ -0,0 +1,16 @@ +import { DatabaseParams } from "@lib/params"; +import AddRemoteForm from "./AddRemoteForm"; +import css from "./index.module.css"; + +type Props = { + params: DatabaseParams; +}; + +export default function AddRemotePage(props: Props): JSX.Element { + return ( +
    +

    Add Remote

    + +
    + ); +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx index 594efe8f..a9f3821b 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx @@ -1,10 +1,13 @@ -import { Loader, QueryHandler } from "@dolthub/react-components"; +import { Button, Loader, QueryHandler } from "@dolthub/react-components"; import { RemoteFragment } from "@gen/graphql-types"; import { DatabaseParams } from "@lib/params"; import { gqlDepNotFound } from "@lib/errors/graphql"; import { errorMatches } from "@lib/errors/helpers"; import Database404 from "@components/Database404"; import InfiniteScroll from "react-infinite-scroller"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; +import Link from "@components/links/Link"; +import { newRemote } from "@lib/urls"; import { useRemoteList } from "./useRemoteList"; import RemoteRow from "./RemoteRow"; import css from "./index.module.css"; @@ -17,13 +20,21 @@ type InnerProps = { remotes: RemoteFragment[]; loadMore: () => Promise; hasMore: boolean; -}; +} & Props; -function Inner({ remotes, loadMore, hasMore }: InnerProps) { +function Inner({ remotes, loadMore, hasMore, params }: InnerProps) { + const createUrl = newRemote(params); return (

    Remotes

    +
    + + + + + +
    {remotes.length ? (
    @@ -71,7 +82,12 @@ export default function RemotesPage({ params }: Props) { ( - + )} /> ); diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx index cf8aa4f5..72fac016 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx @@ -1,17 +1,19 @@ import RemotesBreadcrumbs from "@components/breadcrumbs/RemotesBreadcrumbs"; import NotDoltWrapper from "@components/util/NotDoltWrapper"; -import { OptionalRefParams } from "@lib/params"; +import { DatabaseParams } from "@lib/params"; import { remotes } from "@lib/urls"; import ForDefaultBranch from "../ForDefaultBranch"; import RemotesPage from "./RemotesPage"; +import AddRemotePage from "./AddRemotePage"; type Props = { - params: OptionalRefParams; + params: DatabaseParams; newRemote?: boolean; }; export default function ForRemotes({ params, newRemote }: Props): JSX.Element { const feature = newRemote ? "Creating remotes" : "Viewing Remotes"; + console.log("ForRemotes", params, newRemote); return ( - + {newRemote ? ( + + ) : ( + + )} ); diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index 8160046e..d64182a9 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -223,6 +223,7 @@ export enum LoadDataModifier { export type Mutation = { __typename?: 'Mutation'; addDatabaseConnection: CurrentDatabaseState; + addRemote: Scalars['String']['output']; createBranch: Scalars['String']['output']; createDatabase: Scalars['Boolean']['output']; createSchema: Scalars['Boolean']['output']; @@ -246,6 +247,13 @@ export type MutationAddDatabaseConnectionArgs = { }; +export type MutationAddRemoteArgs = { + databaseName: Scalars['String']['input']; + remoteName: Scalars['String']['input']; + remoteUrl: Scalars['String']['input']; +}; + + export type MutationCreateBranchArgs = { databaseName: Scalars['String']['input']; fromRefName: Scalars['String']['input']; @@ -1182,6 +1190,15 @@ export type DeleteTagMutationVariables = Exact<{ export type DeleteTagMutation = { __typename?: 'Mutation', deleteTag: boolean }; +export type AddRemoteMutationVariables = Exact<{ + databaseName: Scalars['String']['input']; + remoteName: Scalars['String']['input']; + remoteUrl: Scalars['String']['input']; +}>; + + +export type AddRemoteMutation = { __typename?: 'Mutation', addRemote: string }; + export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }; export type RemoteListQueryVariables = Exact<{ @@ -3486,6 +3503,43 @@ export function useDeleteTagMutation(baseOptions?: Apollo.MutationHookOptions; export type DeleteTagMutationResult = Apollo.MutationResult; export type DeleteTagMutationOptions = Apollo.BaseMutationOptions; +export const AddRemoteDocument = gql` + mutation AddRemote($databaseName: String!, $remoteName: String!, $remoteUrl: String!) { + addRemote( + databaseName: $databaseName + remoteName: $remoteName + remoteUrl: $remoteUrl + ) +} + `; +export type AddRemoteMutationFn = Apollo.MutationFunction; + +/** + * __useAddRemoteMutation__ + * + * To run a mutation, you first call `useAddRemoteMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useAddRemoteMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [addRemoteMutation, { data, loading, error }] = useAddRemoteMutation({ + * variables: { + * databaseName: // value for 'databaseName' + * remoteName: // value for 'remoteName' + * remoteUrl: // value for 'remoteUrl' + * }, + * }); + */ +export function useAddRemoteMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(AddRemoteDocument, options); + } +export type AddRemoteMutationHookResult = ReturnType; +export type AddRemoteMutationResult = Apollo.MutationResult; +export type AddRemoteMutationOptions = Apollo.BaseMutationOptions; export const RemoteListDocument = gql` query RemoteList($databaseName: String!, $offset: Int) { remotes(databaseName: $databaseName, offset: $offset) { diff --git a/web/renderer/lib/urls.ts b/web/renderer/lib/urls.ts index 02522cbc..12b422fa 100644 --- a/web/renderer/lib/urls.ts +++ b/web/renderer/lib/urls.ts @@ -99,6 +99,9 @@ export const releases = (p: ps.OptionalRefParams): Route => export const remotes = (p: ps.DatabaseParams): Route => database(p).addStatic("remotes"); +export const newRemote = (p: ps.DatabaseParams): Route => + remotes(p).addStatic("new"); + const staticPulls = (p: ps.DatabaseParams) => database(p).addStatic("pulls"); export const pulls = (p: ps.PullParams): Route => diff --git a/web/renderer/pages/database/[databaseName]/remotes/new.tsx b/web/renderer/pages/database/[databaseName]/remotes/new.tsx new file mode 100644 index 00000000..c8d555b4 --- /dev/null +++ b/web/renderer/pages/database/[databaseName]/remotes/new.tsx @@ -0,0 +1,28 @@ +import Page from "@components/util/Page"; +import { DatabaseParams } from "@lib/params"; +import DatabasePage from "@pageComponents/DatabasePage"; +import { GetServerSideProps, NextPage } from "next"; + +type Props = { + params: DatabaseParams; +}; + +const DatabaseRemotesPage: NextPage = ({ params }) => ( + + + +); + +// #!if !isElectron +export const getServerSideProps: GetServerSideProps = async ({ + params, +}) => { + return { + props: { + params: params as DatabaseParams, + }, + }; +}; +// #!endif + +export default DatabaseRemotesPage; From 67175deec51e4dc375bdff6a8e82dc47545bf09e Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 14:21:58 -0800 Subject: [PATCH 11/18] delete remote --- graphql-server/schema.gql | 1 + graphql-server/src/queryFactory/dolt/index.ts | 8 ++++ .../src/queryFactory/dolt/queries.ts | 2 + .../src/queryFactory/doltgres/index.ts | 8 ++++ .../src/queryFactory/doltgres/queries.ts | 4 +- graphql-server/src/queryFactory/index.ts | 2 + .../src/queryFactory/mysql/index.ts | 4 ++ graphql-server/src/queryFactory/types.ts | 1 + graphql-server/src/remotes/remote.model.ts | 4 +- graphql-server/src/remotes/remote.resolver.ts | 15 ++++-- graphql-server/src/utils/commonTypes.ts | 6 +++ .../AddRemotePage/AddRemoteForm/queries.ts | 6 +++ .../DatabasePage/ForRemotes/RemoteRow.tsx | 19 +++++++- .../DatabasePage/ForRemotes/RemotesPage.tsx | 30 +++++++++++- .../DatabasePage/ForRemotes/index.module.css | 8 ++++ web/renderer/gen/graphql-types.tsx | 47 +++++++++++++++++++ web/renderer/lib/refetchQueries.ts | 4 ++ 17 files changed, 159 insertions(+), 10 deletions(-) diff --git a/graphql-server/schema.gql b/graphql-server/schema.gql index 41760f18..3978bb7c 100644 --- a/graphql-server/schema.gql +++ b/graphql-server/schema.gql @@ -362,6 +362,7 @@ type Mutation { loadDataFile(schemaName: String, tableName: String!, refName: String!, databaseName: String!, importOp: ImportOperation!, fileType: FileType!, file: Upload!, modifier: LoadDataModifier): Boolean! mergePull(fromBranchName: String!, toBranchName: String!, databaseName: String!, author: AuthorInfo): Boolean! addRemote(databaseName: String!, remoteName: String!, remoteUrl: String!): String! + deleteRemote(databaseName: String!, remoteName: String!): Boolean! restoreAllTables(databaseName: String!, refName: String!): Boolean! createTag(tagName: String!, databaseName: String!, message: String, fromRefName: String!, author: AuthorInfo): String! deleteTag(databaseName: String!, tagName: String!): Boolean! diff --git a/graphql-server/src/queryFactory/dolt/index.ts b/graphql-server/src/queryFactory/dolt/index.ts index cc8d9600..9d61b3cd 100644 --- a/graphql-server/src/queryFactory/dolt/index.ts +++ b/graphql-server/src/queryFactory/dolt/index.ts @@ -449,6 +449,14 @@ export class DoltQueryFactory args.databaseName, ); } + + async callDeleteRemote(args: t.RemoteArgs): t.PR { + return this.query( + qh.callDeleteRemote, + [args.remoteName], + args.databaseName, + ); + } } async function getTableInfoWithQR( diff --git a/graphql-server/src/queryFactory/dolt/queries.ts b/graphql-server/src/queryFactory/dolt/queries.ts index c4b53fba..8eb926e2 100644 --- a/graphql-server/src/queryFactory/dolt/queries.ts +++ b/graphql-server/src/queryFactory/dolt/queries.ts @@ -78,6 +78,8 @@ export const getCallMerge = (hasAuthor = false) => export const callAddRemote = `CALL DOLT_REMOTE("add", ?, ?)`; +export const callDeleteRemote = `CALL DOLT_REMOTE("remove", ?)`; + // TAGS export const callDeleteTag = `CALL DOLT_TAG("-d", ?)`; diff --git a/graphql-server/src/queryFactory/doltgres/index.ts b/graphql-server/src/queryFactory/doltgres/index.ts index 102255e7..b5fa4485 100644 --- a/graphql-server/src/queryFactory/doltgres/index.ts +++ b/graphql-server/src/queryFactory/doltgres/index.ts @@ -440,6 +440,14 @@ export class DoltgresQueryFactory args.databaseName, ); } + + async callDeleteRemote(args: t.RemoteArgs): t.PR { + return this.query( + qh.callDeleteRemote, + [args.remoteName], + args.databaseName, + ); + } } async function getTableInfoWithQR( diff --git a/graphql-server/src/queryFactory/doltgres/queries.ts b/graphql-server/src/queryFactory/doltgres/queries.ts index 548d3599..85eefa7b 100644 --- a/graphql-server/src/queryFactory/doltgres/queries.ts +++ b/graphql-server/src/queryFactory/doltgres/queries.ts @@ -163,4 +163,6 @@ export const callCheckoutTable = `SELECT DOLT_CHECKOUT($1::text)`; // REMOTES -export const callAddRemote = `SELECT DOLT_REMOTE($1::text, $2::text)`; +export const callAddRemote = `SELECT DOLT_REMOTE('add', $1::text, $2::text)`; + +export const callDeleteRemote = `SELECT DOLT_REMOTE('remove', $1::text)`; diff --git a/graphql-server/src/queryFactory/index.ts b/graphql-server/src/queryFactory/index.ts index 64ec65c2..d1b7554b 100644 --- a/graphql-server/src/queryFactory/index.ts +++ b/graphql-server/src/queryFactory/index.ts @@ -148,4 +148,6 @@ export declare class QueryFactory { getRemotes(args: t.DBArgs): t.PR; addRemote(args: t.AddRemoteArgs): t.PR; + + callDeleteRemote(args: t.RemoteArgs): t.PR; } diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index c09e0262..01c635d2 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -309,4 +309,8 @@ export class MySQLQueryFactory async addRemote(_: t.AddRemoteArgs): t.PR { throw notDoltError("add remote"); } + + async callDeleteRemote(_: t.RemoteArgs): t.PR { + throw notDoltError("delete remote"); + } } diff --git a/graphql-server/src/queryFactory/types.ts b/graphql-server/src/queryFactory/types.ts index 09854d6b..46533448 100644 --- a/graphql-server/src/queryFactory/types.ts +++ b/graphql-server/src/queryFactory/types.ts @@ -8,6 +8,7 @@ export type RefSchemaArgs = RefArgs & { schemaName: string }; export type RefMaybeSchemaArgs = RefArgs & { schemaName?: string }; export type BranchArgs = DBArgs & { branchName: string }; export type AddRemoteArgs = DBArgs & { remoteName: string; remoteUrl: string }; +export type RemoteArgs = DBArgs & { remoteName: string }; export type TagArgs = DBArgs & { tagName: string }; export type TableArgs = RefArgs & { tableName: string }; export type TableMaybeSchemaArgs = TableArgs & { schemaName?: string }; diff --git a/graphql-server/src/remotes/remote.model.ts b/graphql-server/src/remotes/remote.model.ts index 94b8915f..1920a9ab 100644 --- a/graphql-server/src/remotes/remote.model.ts +++ b/graphql-server/src/remotes/remote.model.ts @@ -1,7 +1,7 @@ import { Field, ID, ObjectType } from "@nestjs/graphql"; import { __Type } from "graphql"; -import { RawRow } from "src/queryFactory/types"; -import { ListOffsetRes } from "src/utils/commonTypes"; +import { RawRow } from "../queryFactory/types"; +import { ListOffsetRes } from "../utils/commonTypes"; @ObjectType() export class Remote { diff --git a/graphql-server/src/remotes/remote.resolver.ts b/graphql-server/src/remotes/remote.resolver.ts index bb3a6cc5..bcaf9f57 100644 --- a/graphql-server/src/remotes/remote.resolver.ts +++ b/graphql-server/src/remotes/remote.resolver.ts @@ -6,10 +6,10 @@ import { Query, Resolver, } from "@nestjs/graphql"; -import { ConnectionProvider } from "src/connections/connection.provider"; -import { DBArgs, DBArgsWithOffset } from "src/utils/commonTypes"; -import { RawRow } from "src/queryFactory/types"; -import { getNextOffset, ROW_LIMIT } from "src/utils"; +import { ConnectionProvider } from "../connections/connection.provider"; +import { DBArgs, DBArgsWithOffset, RemoteArgs } from "../utils/commonTypes"; +import { RawRow } from "../queryFactory/types"; +import { getNextOffset, ROW_LIMIT } from "../utils"; import { fromDoltRemotesRow, Remote, RemoteList } from "./remote.model"; @ArgsType() @@ -39,6 +39,13 @@ export class RemoteResolver { await conn.addRemote(args); return args.remoteName; } + + @Mutation(_returns => Boolean) + async deleteRemote(@Args() args: RemoteArgs): Promise { + const conn = this.conn.connection(); + await conn.callDeleteRemote(args); + return true; + } } function getRemoteListRes( diff --git a/graphql-server/src/utils/commonTypes.ts b/graphql-server/src/utils/commonTypes.ts index 0294dc7a..4bb68373 100644 --- a/graphql-server/src/utils/commonTypes.ts +++ b/graphql-server/src/utils/commonTypes.ts @@ -66,6 +66,12 @@ export class TagArgs extends DBArgs { tagName: string; } +@ArgsType() +export class RemoteArgs extends DBArgs { + @Field() + remoteName: string; +} + @InputType() export class AuthorInfo { @Field() diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts index c606ad59..300b4200 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts @@ -13,3 +13,9 @@ export const CREATE_BRANCH = gql` ) } `; + +export const DELETE_REMOTE = gql` + mutation DeleteRemote($remoteName: String!, $databaseName: String!) { + deleteRemote(remoteName: $remoteName, databaseName: $databaseName) + } +`; diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx index 4a0041fd..11ee6531 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx @@ -1,10 +1,15 @@ import { RemoteFragment } from "@gen/graphql-types"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; +import { Button } from "@dolthub/react-components"; +import { FaRegTrashAlt } from "@react-icons/all-files/fa/FaRegTrashAlt"; +import css from "./index.module.css"; type Props = { remote: RemoteFragment; + onDeleteClicked: (r: RemoteFragment) => void; }; -export default function RemoteRow({ remote }: Props) { +export default function RemoteRow({ remote, onDeleteClicked }: Props) { return ( {remote.name} @@ -17,6 +22,18 @@ export default function RemoteRow({ remote }: Props) { ))} + + + + + + + ); } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx index a9f3821b..fb0bfa72 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage.tsx @@ -1,5 +1,5 @@ import { Button, Loader, QueryHandler } from "@dolthub/react-components"; -import { RemoteFragment } from "@gen/graphql-types"; +import { RemoteFragment, useDeleteRemoteMutation } from "@gen/graphql-types"; import { DatabaseParams } from "@lib/params"; import { gqlDepNotFound } from "@lib/errors/graphql"; import { errorMatches } from "@lib/errors/helpers"; @@ -8,6 +8,9 @@ import InfiniteScroll from "react-infinite-scroller"; import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import Link from "@components/links/Link"; import { newRemote } from "@lib/urls"; +import { useState } from "react"; +import DeleteModal from "@components/DeleteModal"; +import { refetchRemoteQueries } from "@lib/refetchQueries"; import { useRemoteList } from "./useRemoteList"; import RemoteRow from "./RemoteRow"; import css from "./index.module.css"; @@ -24,6 +27,12 @@ type InnerProps = { function Inner({ remotes, loadMore, hasMore, params }: InnerProps) { const createUrl = newRemote(params); + const [isDeleteModalOpen, setDeleteModalOpen] = useState(false); + const [remoteNameToDelete, setRemoteNameToDelete] = useState(""); + const onDeleteClicked = (r: RemoteFragment) => { + setRemoteNameToDelete(r.name); + setDeleteModalOpen(true); + }; return (
    @@ -52,11 +61,16 @@ function Inner({ remotes, loadMore, hasMore, params }: InnerProps) { Name Url Fetch Specs + {remotes.map(r => ( - + onDeleteClicked(r)} + /> ))} @@ -67,6 +81,18 @@ function Inner({ remotes, loadMore, hasMore, params }: InnerProps) { No remotes found

    )} +
    ); } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css index 50d24647..23d4612e 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.module.css @@ -49,3 +49,11 @@ .loader { @apply text-primary my-4 text-center; } + +.trashColumn { + @apply flex justify-end; +} + +.icon { + @apply text-lg m-4; +} diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index d64182a9..fb5964b3 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -229,6 +229,7 @@ export type Mutation = { createSchema: Scalars['Boolean']['output']; createTag: Scalars['String']['output']; deleteBranch: Scalars['Boolean']['output']; + deleteRemote: Scalars['Boolean']['output']; deleteTag: Scalars['Boolean']['output']; loadDataFile: Scalars['Boolean']['output']; mergePull: Scalars['Boolean']['output']; @@ -288,6 +289,12 @@ export type MutationDeleteBranchArgs = { }; +export type MutationDeleteRemoteArgs = { + databaseName: Scalars['String']['input']; + remoteName: Scalars['String']['input']; +}; + + export type MutationDeleteTagArgs = { databaseName: Scalars['String']['input']; tagName: Scalars['String']['input']; @@ -1199,6 +1206,14 @@ export type AddRemoteMutationVariables = Exact<{ export type AddRemoteMutation = { __typename?: 'Mutation', addRemote: string }; +export type DeleteRemoteMutationVariables = Exact<{ + remoteName: Scalars['String']['input']; + databaseName: Scalars['String']['input']; +}>; + + +export type DeleteRemoteMutation = { __typename?: 'Mutation', deleteRemote: boolean }; + export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }; export type RemoteListQueryVariables = Exact<{ @@ -3540,6 +3555,38 @@ export function useAddRemoteMutation(baseOptions?: Apollo.MutationHookOptions; export type AddRemoteMutationResult = Apollo.MutationResult; export type AddRemoteMutationOptions = Apollo.BaseMutationOptions; +export const DeleteRemoteDocument = gql` + mutation DeleteRemote($remoteName: String!, $databaseName: String!) { + deleteRemote(remoteName: $remoteName, databaseName: $databaseName) +} + `; +export type DeleteRemoteMutationFn = Apollo.MutationFunction; + +/** + * __useDeleteRemoteMutation__ + * + * To run a mutation, you first call `useDeleteRemoteMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteRemoteMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [deleteRemoteMutation, { data, loading, error }] = useDeleteRemoteMutation({ + * variables: { + * remoteName: // value for 'remoteName' + * databaseName: // value for 'databaseName' + * }, + * }); + */ +export function useDeleteRemoteMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(DeleteRemoteDocument, options); + } +export type DeleteRemoteMutationHookResult = ReturnType; +export type DeleteRemoteMutationResult = Apollo.MutationResult; +export type DeleteRemoteMutationOptions = Apollo.BaseMutationOptions; export const RemoteListDocument = gql` query RemoteList($databaseName: String!, $offset: Int) { remotes(databaseName: $databaseName, offset: $offset) { diff --git a/web/renderer/lib/refetchQueries.ts b/web/renderer/lib/refetchQueries.ts index 36789eed..3c1c8b68 100644 --- a/web/renderer/lib/refetchQueries.ts +++ b/web/renderer/lib/refetchQueries.ts @@ -109,6 +109,10 @@ export const refetchDeletedBranch = ( ...refetchBranchQueries(params), ]; +export const refetchRemoteQueries = ( + variables: DatabaseParams, +): RefetchQueries => [{ query: gen.RemoteListDocument, variables }]; + export const refetchSqlUpdateQueriesCacheEvict: RefetchOptions = { updateCache(cache: TCacheShape) { [ From 0ce40ff2e3e6c71abf703e0a439f3f86d216caba Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 14:43:34 -0800 Subject: [PATCH 12/18] reorganize --- .../index.tsx => AddRemoteForm.tsx} | 2 +- .../AddRemoteForm/index.module.css | 14 --- .../AddRemotePage/AddRemoteForm/queries.ts | 21 ---- .../ForRemotes/AddRemotePage/index.module.css | 15 +++ .../Inner.tsx} | 46 ++------ .../{ => RemotesPage}/RemoteRow.tsx | 8 +- .../{ => RemotesPage}/index.module.css | 4 - .../ForRemotes/RemotesPage/index.tsx | 35 ++++++ .../{ => RemotesPage}/useRemoteList.ts | 0 .../DatabasePage/ForRemotes/index.tsx | 2 +- .../DatabasePage/ForRemotes/queries.ts | 20 ++++ web/renderer/gen/graphql-types.tsx | 108 +++++++++--------- 12 files changed, 143 insertions(+), 132 deletions(-) rename web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/{AddRemoteForm/index.tsx => AddRemoteForm.tsx} (98%) delete mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.module.css delete mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/queries.ts rename web/renderer/components/pageComponents/DatabasePage/ForRemotes/{RemotesPage.tsx => RemotesPage/Inner.tsx} (76%) rename web/renderer/components/pageComponents/DatabasePage/ForRemotes/{ => RemotesPage}/RemoteRow.tsx (80%) rename web/renderer/components/pageComponents/DatabasePage/ForRemotes/{ => RemotesPage}/index.module.css (94%) create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/index.tsx rename web/renderer/components/pageComponents/DatabasePage/ForRemotes/{ => RemotesPage}/useRemoteList.ts (100%) diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx similarity index 98% rename from web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.tsx rename to web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx index 338e7f13..042242f2 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm/index.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx @@ -52,7 +52,7 @@ export default function AddRemoteForm(props: Props): JSX.Element { return (
    -
    +
    Promise; hasMore: boolean; -} & Props; +}; -function Inner({ remotes, loadMore, hasMore, params }: InnerProps) { +export default function Inner({ + remotes, + loadMore, + hasMore, + params, +}: InnerProps) { const createUrl = newRemote(params); const [isDeleteModalOpen, setDeleteModalOpen] = useState(false); const [remoteNameToDelete, setRemoteNameToDelete] = useState(""); @@ -70,6 +69,7 @@ function Inner({ remotes, loadMore, hasMore, params }: InnerProps) { key={r._id} remote={r} onDeleteClicked={() => onDeleteClicked(r)} + params={params} /> ))} @@ -96,25 +96,3 @@ function Inner({ remotes, loadMore, hasMore, params }: InnerProps) {
    ); } - -export default function RemotesPage({ params }: Props) { - const res = useRemoteList(params); - if (res.loading) return ; - if (errorMatches(gqlDepNotFound, res.error)) { - return ; - } - - return ( - ( - - )} - /> - ); -} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/RemoteRow.tsx similarity index 80% rename from web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx rename to web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/RemoteRow.tsx index 11ee6531..b666c260 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemoteRow.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/RemoteRow.tsx @@ -2,14 +2,16 @@ import { RemoteFragment } from "@gen/graphql-types"; import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; import { Button } from "@dolthub/react-components"; import { FaRegTrashAlt } from "@react-icons/all-files/fa/FaRegTrashAlt"; +import { DatabaseParams } from "@lib/params"; import css from "./index.module.css"; type Props = { remote: RemoteFragment; - onDeleteClicked: (r: RemoteFragment) => void; + onDeleteClicked: () => void; + params: DatabaseParams; }; -export default function RemoteRow({ remote, onDeleteClicked }: Props) { +export default function RemoteRow({ remote, onDeleteClicked, params }: Props) { return ( {remote.name} @@ -23,7 +25,7 @@ export default function RemoteRow({ remote, onDeleteClicked }: Props) { ))} - + ; + if (errorMatches(gqlDepNotFound, res.error)) { + return ; + } + + return ( + ( + + )} + /> + ); +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/useRemoteList.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/useRemoteList.ts similarity index 100% rename from web/renderer/components/pageComponents/DatabasePage/ForRemotes/useRemoteList.ts rename to web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/useRemoteList.ts diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx index 72fac016..d9736312 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx @@ -3,8 +3,8 @@ import NotDoltWrapper from "@components/util/NotDoltWrapper"; import { DatabaseParams } from "@lib/params"; import { remotes } from "@lib/urls"; import ForDefaultBranch from "../ForDefaultBranch"; -import RemotesPage from "./RemotesPage"; import AddRemotePage from "./AddRemotePage"; +import RemotesPage from "./RemotesPage"; type Props = { params: DatabaseParams; diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts index db1f0212..e364604d 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts @@ -16,3 +16,23 @@ export const REMOTES_FOR_REMOTES_PAGE_QUERY = gql` } } `; + +export const ADD_REMOTE = gql` + mutation AddRemote( + $databaseName: String! + $remoteName: String! + $remoteUrl: String! + ) { + addRemote( + databaseName: $databaseName + remoteName: $remoteName + remoteUrl: $remoteUrl + ) + } +`; + +export const DELETE_REMOTE = gql` + mutation DeleteRemote($remoteName: String!, $databaseName: String!) { + deleteRemote(remoteName: $remoteName, databaseName: $databaseName) + } +`; diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index fb5964b3..58f209f5 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -1197,6 +1197,16 @@ export type DeleteTagMutationVariables = Exact<{ export type DeleteTagMutation = { __typename?: 'Mutation', deleteTag: boolean }; +export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }; + +export type RemoteListQueryVariables = Exact<{ + databaseName: Scalars['String']['input']; + offset?: InputMaybe; +}>; + + +export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }> } }; + export type AddRemoteMutationVariables = Exact<{ databaseName: Scalars['String']['input']; remoteName: Scalars['String']['input']; @@ -1214,16 +1224,6 @@ export type DeleteRemoteMutationVariables = Exact<{ export type DeleteRemoteMutation = { __typename?: 'Mutation', deleteRemote: boolean }; -export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }; - -export type RemoteListQueryVariables = Exact<{ - databaseName: Scalars['String']['input']; - offset?: InputMaybe; -}>; - - -export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }> } }; - export type LoadDataMutationVariables = Exact<{ databaseName: Scalars['String']['input']; refName: Scalars['String']['input']; @@ -3518,6 +3518,50 @@ export function useDeleteTagMutation(baseOptions?: Apollo.MutationHookOptions; export type DeleteTagMutationResult = Apollo.MutationResult; export type DeleteTagMutationOptions = Apollo.BaseMutationOptions; +export const RemoteListDocument = gql` + query RemoteList($databaseName: String!, $offset: Int) { + remotes(databaseName: $databaseName, offset: $offset) { + list { + ...Remote + } + nextOffset + } +} + ${RemoteFragmentDoc}`; + +/** + * __useRemoteListQuery__ + * + * To run a query within a React component, call `useRemoteListQuery` and pass it any options that fit your needs. + * When your component renders, `useRemoteListQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useRemoteListQuery({ + * variables: { + * databaseName: // value for 'databaseName' + * offset: // value for 'offset' + * }, + * }); + */ +export function useRemoteListQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: RemoteListQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(RemoteListDocument, options); + } +export function useRemoteListLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(RemoteListDocument, options); + } +export function useRemoteListSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(RemoteListDocument, options); + } +export type RemoteListQueryHookResult = ReturnType; +export type RemoteListLazyQueryHookResult = ReturnType; +export type RemoteListSuspenseQueryHookResult = ReturnType; +export type RemoteListQueryResult = Apollo.QueryResult; export const AddRemoteDocument = gql` mutation AddRemote($databaseName: String!, $remoteName: String!, $remoteUrl: String!) { addRemote( @@ -3587,50 +3631,6 @@ export function useDeleteRemoteMutation(baseOptions?: Apollo.MutationHookOptions export type DeleteRemoteMutationHookResult = ReturnType; export type DeleteRemoteMutationResult = Apollo.MutationResult; export type DeleteRemoteMutationOptions = Apollo.BaseMutationOptions; -export const RemoteListDocument = gql` - query RemoteList($databaseName: String!, $offset: Int) { - remotes(databaseName: $databaseName, offset: $offset) { - list { - ...Remote - } - nextOffset - } -} - ${RemoteFragmentDoc}`; - -/** - * __useRemoteListQuery__ - * - * To run a query within a React component, call `useRemoteListQuery` and pass it any options that fit your needs. - * When your component renders, `useRemoteListQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useRemoteListQuery({ - * variables: { - * databaseName: // value for 'databaseName' - * offset: // value for 'offset' - * }, - * }); - */ -export function useRemoteListQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: RemoteListQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(RemoteListDocument, options); - } -export function useRemoteListLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(RemoteListDocument, options); - } -export function useRemoteListSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(RemoteListDocument, options); - } -export type RemoteListQueryHookResult = ReturnType; -export type RemoteListLazyQueryHookResult = ReturnType; -export type RemoteListSuspenseQueryHookResult = ReturnType; -export type RemoteListQueryResult = Apollo.QueryResult; export const LoadDataDocument = gql` mutation LoadData($databaseName: String!, $refName: String!, $schemaName: String, $tableName: String!, $importOp: ImportOperation!, $fileType: FileType!, $file: Upload!, $modifier: LoadDataModifier) { loadDataFile( From 40d89cb323e4ec2980f1b2584ff88bad5275763c Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 3 Dec 2024 16:21:13 -0800 Subject: [PATCH 13/18] pagination --- .../queryFactory/dolt/doltEntityManager.ts | 14 +-- graphql-server/src/queryFactory/dolt/index.ts | 4 +- .../src/queryFactory/doltgres/index.ts | 4 +- graphql-server/src/queryFactory/index.ts | 2 +- .../src/queryFactory/mysql/index.ts | 2 +- graphql-server/src/queryFactory/types.ts | 6 +- graphql-server/src/remotes/remote.model.ts | 15 ++- graphql-server/src/remotes/remote.resolver.ts | 18 +--- .../AddRemotePage/AddRemoteForm.tsx | 4 +- .../ForRemotes/AddRemotePage/queries.ts | 15 +++ .../ForRemotes/RemotesPage/RemoteRow.tsx | 9 +- .../ForRemotes/RemotesPage/useRemoteList.ts | 12 +-- .../DatabasePage/ForRemotes/index.tsx | 3 +- .../DatabasePage/ForRemotes/queries.ts | 14 --- web/renderer/gen/graphql-types.tsx | 92 +++++++++---------- .../database/[databaseName]/remotes/new.tsx | 6 +- 16 files changed, 104 insertions(+), 116 deletions(-) create mode 100644 web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/queries.ts diff --git a/graphql-server/src/queryFactory/dolt/doltEntityManager.ts b/graphql-server/src/queryFactory/dolt/doltEntityManager.ts index 678036aa..fe617fb4 100644 --- a/graphql-server/src/queryFactory/dolt/doltEntityManager.ts +++ b/graphql-server/src/queryFactory/dolt/doltEntityManager.ts @@ -139,10 +139,12 @@ export async function getDoltTags(em: EntityManager): t.PR { .getRawMany(); } -export async function getDoltRemotes(em: EntityManager): t.PR { - return em - .createQueryBuilder() - .select("*") - .from("dolt_remotes", "") - .getRawMany(); +export async function getDoltRemotesPaginated( + em: EntityManager, + args: t.ListRemotesArgs, +): t.PR { + let sel = em.createQueryBuilder().select("*").from("dolt_remotes", ""); + sel = sel.offset(args.offset); + + return sel.limit(ROW_LIMIT + 1).getRawMany(); } diff --git a/graphql-server/src/queryFactory/dolt/index.ts b/graphql-server/src/queryFactory/dolt/index.ts index 9d61b3cd..234372e2 100644 --- a/graphql-server/src/queryFactory/dolt/index.ts +++ b/graphql-server/src/queryFactory/dolt/index.ts @@ -435,9 +435,9 @@ export class DoltQueryFactory ); } - async getRemotes(args: t.DBArgs): t.PR { + async getRemotes(args: t.ListRemotesArgs): t.PR { return this.queryForBuilder( - async em => dem.getDoltRemotes(em), + async em => dem.getDoltRemotesPaginated(em, args), args.databaseName, ); } diff --git a/graphql-server/src/queryFactory/doltgres/index.ts b/graphql-server/src/queryFactory/doltgres/index.ts index b5fa4485..bb841132 100644 --- a/graphql-server/src/queryFactory/doltgres/index.ts +++ b/graphql-server/src/queryFactory/doltgres/index.ts @@ -426,9 +426,9 @@ export class DoltgresQueryFactory ); } - async getRemotes(args: t.DBArgs): t.PR { + async getRemotes(args: t.ListRemotesArgs): t.PR { return this.queryForBuilder( - async em => dem.getDoltRemotes(em), + async em => dem.getDoltRemotesPaginated(em, args), args.databaseName, ); } diff --git a/graphql-server/src/queryFactory/index.ts b/graphql-server/src/queryFactory/index.ts index d1b7554b..0ce739b7 100644 --- a/graphql-server/src/queryFactory/index.ts +++ b/graphql-server/src/queryFactory/index.ts @@ -145,7 +145,7 @@ export declare class QueryFactory { restoreAllTables(args: t.RefArgs): t.PR; - getRemotes(args: t.DBArgs): t.PR; + getRemotes(args: t.ListRemotesArgs): t.PR; addRemote(args: t.AddRemoteArgs): t.PR; diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index 01c635d2..9c8bcb81 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -302,7 +302,7 @@ export class MySQLQueryFactory throw notDoltError("restore all tables"); } - async getRemotes(_args: t.DBArgs): t.PR { + async getRemotes(_args: t.ListRemotesArgs): t.PR { throw notDoltError("get remotes"); } diff --git a/graphql-server/src/queryFactory/types.ts b/graphql-server/src/queryFactory/types.ts index 46533448..60db548b 100644 --- a/graphql-server/src/queryFactory/types.ts +++ b/graphql-server/src/queryFactory/types.ts @@ -7,8 +7,8 @@ export type RefArgs = DBArgs & { refName: string }; export type RefSchemaArgs = RefArgs & { schemaName: string }; export type RefMaybeSchemaArgs = RefArgs & { schemaName?: string }; export type BranchArgs = DBArgs & { branchName: string }; -export type AddRemoteArgs = DBArgs & { remoteName: string; remoteUrl: string }; export type RemoteArgs = DBArgs & { remoteName: string }; +export type AddRemoteArgs = RemoteArgs & { remoteUrl: string }; export type TagArgs = DBArgs & { tagName: string }; export type TableArgs = RefArgs & { tableName: string }; export type TableMaybeSchemaArgs = TableArgs & { schemaName?: string }; @@ -42,6 +42,10 @@ export type RowDiffArgs = DBArgs & { filterByRowType?: DiffRowType; }; +export type ListRemotesArgs = DBArgs & { + offset: number; +}; + export type RawRow = Record; export type RawRows = RawRow[]; export type PR = Promise; diff --git a/graphql-server/src/remotes/remote.model.ts b/graphql-server/src/remotes/remote.model.ts index 1920a9ab..b9732505 100644 --- a/graphql-server/src/remotes/remote.model.ts +++ b/graphql-server/src/remotes/remote.model.ts @@ -1,7 +1,8 @@ import { Field, ID, ObjectType } from "@nestjs/graphql"; import { __Type } from "graphql"; +import { getNextOffset, ROW_LIMIT } from "../utils"; import { RawRow } from "../queryFactory/types"; -import { ListOffsetRes } from "../utils/commonTypes"; +import { DBArgsWithOffset, ListOffsetRes } from "../utils/commonTypes"; @ObjectType() export class Remote { @@ -32,3 +33,15 @@ export function fromDoltRemotesRow(databaseName: string, r: RawRow): Remote { fetchSpecs: r.fetch_specs, }; } + +export function getRemoteListRes( + remotes: RawRow[], + args: DBArgsWithOffset, +): RemoteList { + return { + list: remotes + .slice(0, ROW_LIMIT) + .map(l => fromDoltRemotesRow(args.databaseName, l)), + nextOffset: getNextOffset(remotes.length, args.offset ?? 0), + }; +} diff --git a/graphql-server/src/remotes/remote.resolver.ts b/graphql-server/src/remotes/remote.resolver.ts index bcaf9f57..9184d747 100644 --- a/graphql-server/src/remotes/remote.resolver.ts +++ b/graphql-server/src/remotes/remote.resolver.ts @@ -8,9 +8,7 @@ import { } from "@nestjs/graphql"; import { ConnectionProvider } from "../connections/connection.provider"; import { DBArgs, DBArgsWithOffset, RemoteArgs } from "../utils/commonTypes"; -import { RawRow } from "../queryFactory/types"; -import { getNextOffset, ROW_LIMIT } from "../utils"; -import { fromDoltRemotesRow, Remote, RemoteList } from "./remote.model"; +import { getRemoteListRes, Remote, RemoteList } from "./remote.model"; @ArgsType() export class AddRemoteArgs extends DBArgs { @@ -29,7 +27,7 @@ export class RemoteResolver { async remotes(@Args() args: DBArgsWithOffset): Promise { const conn = this.conn.connection(); - const res = await conn.getRemotes(args); + const res = await conn.getRemotes({ ...args, offset: args.offset ?? 0 }); return getRemoteListRes(res, args); } @@ -47,15 +45,3 @@ export class RemoteResolver { return true; } } - -function getRemoteListRes( - remotes: RawRow[], - args: DBArgsWithOffset, -): RemoteList { - return { - list: remotes - .slice(0, ROW_LIMIT) - .map(l => fromDoltRemotesRow(args.databaseName, l)), - nextOffset: getNextOffset(remotes.length, args.offset ?? 0), - }; -} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx index 042242f2..51497c8c 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx @@ -8,7 +8,7 @@ import { useReactiveWidth } from "@dolthub/react-hooks"; import { useAddRemoteMutation } from "@gen/graphql-types"; import useMutation from "@hooks/useMutation"; import { DatabaseParams } from "@lib/params"; -import { refetchBranchQueries } from "@lib/refetchQueries"; +import { refetchRemoteQueries } from "@lib/refetchQueries"; import { remotes } from "@lib/urls"; import { useRouter } from "next/router"; import { SyntheticEvent, useState } from "react"; @@ -28,7 +28,7 @@ export default function AddRemoteForm(props: Props): JSX.Element { loading, } = useMutation({ hook: useAddRemoteMutation, - refetchQueries: refetchBranchQueries(props.params), + refetchQueries: refetchRemoteQueries(props.params), }); const { isMobile } = useReactiveWidth(); diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/queries.ts new file mode 100644 index 00000000..343c8c44 --- /dev/null +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/queries.ts @@ -0,0 +1,15 @@ +import { gql } from "@apollo/client"; + +export const ADD_REMOTE = gql` + mutation AddRemote( + $databaseName: String! + $remoteName: String! + $remoteUrl: String! + ) { + addRemote( + databaseName: $databaseName + remoteName: $remoteName + remoteUrl: $remoteUrl + ) + } +`; diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/RemoteRow.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/RemoteRow.tsx index b666c260..38b59b10 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/RemoteRow.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/RemoteRow.tsx @@ -16,14 +16,7 @@ export default function RemoteRow({ remote, onDeleteClicked, params }: Props) { {remote.name} {remote.url} - - {remote.fetchSpecs?.map((fs, i) => ( - - {fs} - {i < (remote.fetchSpecs?.length ?? 0) - 1 ? ", " : ""} - - ))} - + {remote.fetchSpecs?.join(",")} Promise; }; export function useRemoteList(params: DatabaseParams): ReturnType { @@ -31,15 +30,6 @@ export function useRemoteList(params: DatabaseParams): ReturnType { const [offset, setOffset] = useState(data?.remotes.nextOffset); const [lastOffset, setLastOffset] = useState>(undefined); - const refetch = async () => { - try { - const newRes = await res.refetch(params); - setRemotes(newRes.data.remotes.list); - } catch (e) { - handleCaughtApolloError(e, setErr); - } - }; - useEffect(() => { setRemotes(data?.remotes.list); setOffset(data?.remotes.nextOffset); @@ -70,5 +60,5 @@ export function useRemoteList(params: DatabaseParams): ReturnType { const hasMore = offset !== undefined && offset !== null && offset !== lastOffset; - return { ...res, error: err, remotes, loadMore, hasMore, refetch }; + return { ...res, error: err, remotes, loadMore, hasMore }; } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx index d9736312..7ea410c3 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/index.tsx @@ -12,8 +12,7 @@ type Props = { }; export default function ForRemotes({ params, newRemote }: Props): JSX.Element { - const feature = newRemote ? "Creating remotes" : "Viewing Remotes"; - console.log("ForRemotes", params, newRemote); + const feature = newRemote ? "Creating remotes" : "Viewing remotes"; return ( | null }; - -export type RemoteListQueryVariables = Exact<{ +export type AddRemoteMutationVariables = Exact<{ databaseName: Scalars['String']['input']; - offset?: InputMaybe; + remoteName: Scalars['String']['input']; + remoteUrl: Scalars['String']['input']; }>; -export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }> } }; +export type AddRemoteMutation = { __typename?: 'Mutation', addRemote: string }; -export type AddRemoteMutationVariables = Exact<{ +export type RemoteFragment = { __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }; + +export type RemoteListQueryVariables = Exact<{ databaseName: Scalars['String']['input']; - remoteName: Scalars['String']['input']; - remoteUrl: Scalars['String']['input']; + offset?: InputMaybe; }>; -export type AddRemoteMutation = { __typename?: 'Mutation', addRemote: string }; +export type RemoteListQuery = { __typename?: 'Query', remotes: { __typename?: 'RemoteList', nextOffset?: number | null, list: Array<{ __typename?: 'Remote', _id: string, name: string, url: string, fetchSpecs?: Array | null }> } }; export type DeleteRemoteMutationVariables = Exact<{ remoteName: Scalars['String']['input']; @@ -3518,6 +3518,43 @@ export function useDeleteTagMutation(baseOptions?: Apollo.MutationHookOptions; export type DeleteTagMutationResult = Apollo.MutationResult; export type DeleteTagMutationOptions = Apollo.BaseMutationOptions; +export const AddRemoteDocument = gql` + mutation AddRemote($databaseName: String!, $remoteName: String!, $remoteUrl: String!) { + addRemote( + databaseName: $databaseName + remoteName: $remoteName + remoteUrl: $remoteUrl + ) +} + `; +export type AddRemoteMutationFn = Apollo.MutationFunction; + +/** + * __useAddRemoteMutation__ + * + * To run a mutation, you first call `useAddRemoteMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useAddRemoteMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [addRemoteMutation, { data, loading, error }] = useAddRemoteMutation({ + * variables: { + * databaseName: // value for 'databaseName' + * remoteName: // value for 'remoteName' + * remoteUrl: // value for 'remoteUrl' + * }, + * }); + */ +export function useAddRemoteMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(AddRemoteDocument, options); + } +export type AddRemoteMutationHookResult = ReturnType; +export type AddRemoteMutationResult = Apollo.MutationResult; +export type AddRemoteMutationOptions = Apollo.BaseMutationOptions; export const RemoteListDocument = gql` query RemoteList($databaseName: String!, $offset: Int) { remotes(databaseName: $databaseName, offset: $offset) { @@ -3562,43 +3599,6 @@ export type RemoteListQueryHookResult = ReturnType; export type RemoteListLazyQueryHookResult = ReturnType; export type RemoteListSuspenseQueryHookResult = ReturnType; export type RemoteListQueryResult = Apollo.QueryResult; -export const AddRemoteDocument = gql` - mutation AddRemote($databaseName: String!, $remoteName: String!, $remoteUrl: String!) { - addRemote( - databaseName: $databaseName - remoteName: $remoteName - remoteUrl: $remoteUrl - ) -} - `; -export type AddRemoteMutationFn = Apollo.MutationFunction; - -/** - * __useAddRemoteMutation__ - * - * To run a mutation, you first call `useAddRemoteMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useAddRemoteMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [addRemoteMutation, { data, loading, error }] = useAddRemoteMutation({ - * variables: { - * databaseName: // value for 'databaseName' - * remoteName: // value for 'remoteName' - * remoteUrl: // value for 'remoteUrl' - * }, - * }); - */ -export function useAddRemoteMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(AddRemoteDocument, options); - } -export type AddRemoteMutationHookResult = ReturnType; -export type AddRemoteMutationResult = Apollo.MutationResult; -export type AddRemoteMutationOptions = Apollo.BaseMutationOptions; export const DeleteRemoteDocument = gql` mutation DeleteRemote($remoteName: String!, $databaseName: String!) { deleteRemote(remoteName: $remoteName, databaseName: $databaseName) diff --git a/web/renderer/pages/database/[databaseName]/remotes/new.tsx b/web/renderer/pages/database/[databaseName]/remotes/new.tsx index c8d555b4..48f825f1 100644 --- a/web/renderer/pages/database/[databaseName]/remotes/new.tsx +++ b/web/renderer/pages/database/[databaseName]/remotes/new.tsx @@ -7,8 +7,8 @@ type Props = { params: DatabaseParams; }; -const DatabaseRemotesPage: NextPage = ({ params }) => ( - +const DatabaseNewRemotePage: NextPage = ({ params }) => ( + ); @@ -25,4 +25,4 @@ export const getServerSideProps: GetServerSideProps = async ({ }; // #!endif -export default DatabaseRemotesPage; +export default DatabaseNewRemotePage; From 74ce44a4a74adc0ced4ff90c3b932028cc22db77 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Wed, 4 Dec 2024 11:38:53 -0800 Subject: [PATCH 14/18] add description --- .../ForRemotes/AddRemotePage/AddRemoteForm.tsx | 10 ++++++++++ .../ForRemotes/AddRemotePage/index.module.css | 4 ++++ .../DatabasePage/ForRemotes/AddRemotePage/index.tsx | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx index 51497c8c..caaea79d 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx @@ -12,6 +12,7 @@ import { refetchRemoteQueries } from "@lib/refetchQueries"; import { remotes } from "@lib/urls"; import { useRouter } from "next/router"; import { SyntheticEvent, useState } from "react"; +import Link from "@components/links/Link"; import css from "./index.module.css"; type Props = { @@ -64,6 +65,7 @@ export default function AddRemoteForm(props: Props): JSX.Element { value={remoteUrl} onChangeString={setRemoteUrl} label="Add remote url" + placeholder="i.e. https://url-of-remote.com" className={css.input} /> +

    + A remote is a [Dolt|Doltgres] database in another location, usually + on a different, network accessible host. To learn more about + configuring a remote for your database, see our{" "} + + documentation + +

    diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.module.css b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.module.css index 432eeb1b..df39b339 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.module.css +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.module.css @@ -16,3 +16,7 @@ } } } + +.text { + @apply text-sm text-stone-500 mb-5 max-w-xl mt-4; +} diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.tsx index 6070c9c5..3bbd582a 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/index.tsx @@ -9,7 +9,7 @@ type Props = { export default function AddRemotePage(props: Props): JSX.Element { return (
    -

    Add Remote

    +

    New Remote

    ); From 37c6e4003d2c708d7e911de5ba3685773eb97e9f Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Wed, 4 Dec 2024 14:02:21 -0800 Subject: [PATCH 15/18] database type --- .../AddRemotePage/AddRemoteForm.tsx | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx index caaea79d..aaed920e 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx @@ -5,7 +5,10 @@ import { Loader, } from "@dolthub/react-components"; import { useReactiveWidth } from "@dolthub/react-hooks"; -import { useAddRemoteMutation } from "@gen/graphql-types"; +import { + useAddRemoteMutation, + useDoltDatabaseDetailsQuery, +} from "@gen/graphql-types"; import useMutation from "@hooks/useMutation"; import { DatabaseParams } from "@lib/params"; import { refetchRemoteQueries } from "@lib/refetchQueries"; @@ -13,6 +16,7 @@ import { remotes } from "@lib/urls"; import { useRouter } from "next/router"; import { SyntheticEvent, useState } from "react"; import Link from "@components/links/Link"; +import { getDatabaseType } from "@components/DatabaseTypeLabel"; import css from "./index.module.css"; type Props = { @@ -21,6 +25,12 @@ type Props = { export default function AddRemoteForm(props: Props): JSX.Element { const router = useRouter(); + const { data: databaseDetails, loading: databaseDetailsLoading } = + useDoltDatabaseDetailsQuery(); + const type = getDatabaseType( + databaseDetails?.doltDatabaseDetails.type ?? undefined, + !!databaseDetails?.doltDatabaseDetails.isDolt, + ); const [remoteName, setRemoteName] = useState(""); const [remoteUrl, setRemoteUrl] = useState(""); const { @@ -79,15 +89,15 @@ export default function AddRemoteForm(props: Props): JSX.Element {

    - A remote is a [Dolt|Doltgres] database in another location, usually - on a different, network accessible host. To learn more about - configuring a remote for your database, see our{" "} + A remote is a {type} database in another location, usually on a + different, network accessible host. To learn more about configuring + a remote for your database, see our{" "} documentation

    - +
    ); From c09f1944101ee65c00c26c564288db32e1c1f345 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Wed, 4 Dec 2024 14:09:50 -0800 Subject: [PATCH 16/18] link --- .../AddRemotePage/AddRemoteForm.tsx | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx index aaed920e..dc174da0 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx @@ -6,6 +6,7 @@ import { } from "@dolthub/react-components"; import { useReactiveWidth } from "@dolthub/react-hooks"; import { + DoltDatabaseDetails, useAddRemoteMutation, useDoltDatabaseDetailsQuery, } from "@gen/graphql-types"; @@ -17,6 +18,8 @@ import { useRouter } from "next/router"; import { SyntheticEvent, useState } from "react"; import Link from "@components/links/Link"; import { getDatabaseType } from "@components/DatabaseTypeLabel"; +import DoltLink from "@components/links/DoltLink"; +import DoltgresLink from "@components/links/DoltgresLink"; import css from "./index.module.css"; type Props = { @@ -27,10 +30,6 @@ export default function AddRemoteForm(props: Props): JSX.Element { const router = useRouter(); const { data: databaseDetails, loading: databaseDetailsLoading } = useDoltDatabaseDetailsQuery(); - const type = getDatabaseType( - databaseDetails?.doltDatabaseDetails.type ?? undefined, - !!databaseDetails?.doltDatabaseDetails.isDolt, - ); const [remoteName, setRemoteName] = useState(""); const [remoteUrl, setRemoteUrl] = useState(""); const { @@ -89,9 +88,10 @@ export default function AddRemoteForm(props: Props): JSX.Element {

    - A remote is a {type} database in another location, usually on a - different, network accessible host. To learn more about configuring - a remote for your database, see our{" "} + A remote is a {getDbLink(databaseDetails?.doltDatabaseDetails)}{" "} + database in another location, usually on a different, network + accessible host. To learn more about configuring a remote for your + database, see our{" "} documentation @@ -102,3 +102,17 @@ export default function AddRemoteForm(props: Props): JSX.Element {

    ); } + +function getDbLink(dbDetails?: DoltDatabaseDetails): JSX.Element { + const type = getDatabaseType( + dbDetails?.type ?? undefined, + !!dbDetails?.isDolt, + ); + if (type === "Dolt") { + return ; + } + if (type === "DoltgreSQL") { + return ; + } + return {type}; +} From 75532cae9921c60655b1d07ab4d3d8fae033d877 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Wed, 4 Dec 2024 14:16:10 -0800 Subject: [PATCH 17/18] place holder --- .../AddRemotePage/AddRemoteForm.tsx | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx index dc174da0..7eaddec7 100644 --- a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx +++ b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/AddRemotePage/AddRemoteForm.tsx @@ -30,6 +30,9 @@ export default function AddRemoteForm(props: Props): JSX.Element { const router = useRouter(); const { data: databaseDetails, loading: databaseDetailsLoading } = useDoltDatabaseDetailsQuery(); + const { dbLink, urlPlaceHolder } = getDbNameAndLink( + databaseDetails?.doltDatabaseDetails, + ); const [remoteName, setRemoteName] = useState(""); const [remoteUrl, setRemoteUrl] = useState(""); const { @@ -74,7 +77,7 @@ export default function AddRemoteForm(props: Props): JSX.Element { value={remoteUrl} onChangeString={setRemoteUrl} label="Add remote url" - placeholder="i.e. https://url-of-remote.com" + placeholder={urlPlaceHolder} className={css.input} />

    - A remote is a {getDbLink(databaseDetails?.doltDatabaseDetails)}{" "} - database in another location, usually on a different, network - accessible host. To learn more about configuring a remote for your - database, see our{" "} + A remote is a {dbLink} database in another location, usually on a + different, network accessible host. To learn more about configuring + a remote for your database, see our{" "} documentation @@ -103,16 +105,25 @@ export default function AddRemoteForm(props: Props): JSX.Element { ); } -function getDbLink(dbDetails?: DoltDatabaseDetails): JSX.Element { +type ReturnType = { + dbLink: JSX.Element; + urlPlaceHolder: string; +}; + +function getDbNameAndLink(dbDetails?: DoltDatabaseDetails): ReturnType { const type = getDatabaseType( dbDetails?.type ?? undefined, !!dbDetails?.isDolt, ); + const universalUrl = "i.e. https://url-of-remote.com"; if (type === "Dolt") { - return ; + return { + dbLink: , + urlPlaceHolder: "i.e. https://doltremoteapi.dolthub.com/owner/repo", + }; } if (type === "DoltgreSQL") { - return ; + return { dbLink: , urlPlaceHolder: universalUrl }; } - return {type}; + return { dbLink: {type}, urlPlaceHolder: universalUrl }; } From f067008a761638a2e53a6d028812c39c556f5524 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Wed, 4 Dec 2024 14:24:38 -0800 Subject: [PATCH 18/18] return chained, queries --- .../src/queryFactory/dolt/doltEntityManager.ts | 11 +++++++---- .../ForRemotes/{ => RemotesPage}/queries.ts | 0 2 files changed, 7 insertions(+), 4 deletions(-) rename web/renderer/components/pageComponents/DatabasePage/ForRemotes/{ => RemotesPage}/queries.ts (100%) diff --git a/graphql-server/src/queryFactory/dolt/doltEntityManager.ts b/graphql-server/src/queryFactory/dolt/doltEntityManager.ts index fe617fb4..538893e5 100644 --- a/graphql-server/src/queryFactory/dolt/doltEntityManager.ts +++ b/graphql-server/src/queryFactory/dolt/doltEntityManager.ts @@ -143,8 +143,11 @@ export async function getDoltRemotesPaginated( em: EntityManager, args: t.ListRemotesArgs, ): t.PR { - let sel = em.createQueryBuilder().select("*").from("dolt_remotes", ""); - sel = sel.offset(args.offset); - - return sel.limit(ROW_LIMIT + 1).getRawMany(); + return em + .createQueryBuilder() + .select("*") + .from("dolt_remotes", "") + .offset(args.offset) + .limit(ROW_LIMIT + 1) + .getRawMany(); } diff --git a/web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts b/web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/queries.ts similarity index 100% rename from web/renderer/components/pageComponents/DatabasePage/ForRemotes/queries.ts rename to web/renderer/components/pageComponents/DatabasePage/ForRemotes/RemotesPage/queries.ts