From 3779062064fde2ac9a537faa68fa3d0ae97fc95f Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 11:11:30 -0800 Subject: [PATCH 01/13] graphql, web: Progress on pull page --- packages/graphql-server/schema.gql | 4 +- .../src/rowDiffs/rowDiff.queries.ts | 3 + .../src/rowDiffs/rowDiff.resolver.ts | 58 ++++++++++++--- .../src/schemaDiffs/schemaDiff.resolver.ts | 12 +-- packages/web/components/DatabaseNav/index.tsx | 2 +- packages/web/components/DatabaseNav/utils.ts | 5 +- .../BranchSelectForm/BranchSelect.tsx | 30 ++++++++ .../BranchSelectForm/index.module.css | 15 ++++ .../DiffSelector/BranchSelectForm/index.tsx | 73 +++++++++++++++++++ .../web/components/DiffSelector/ForPull.tsx | 10 +++ .../web/components/DiffSelector/index.tsx | 2 + packages/web/components/DiffStat/index.tsx | 12 ++- .../components/DiffTable/DataDiff/Table.tsx | 6 +- .../DiffTable/DataDiff/ViewSqlLink.tsx | 14 ++-- .../components/DiffTable/DataDiff/index.tsx | 11 ++- .../DiffTable/DataDiff/useRowDiffs.ts | 15 ++-- .../DiffTable/DiffTableStats/index.tsx | 11 ++- .../DiffTable/DiffTableStats/mocks.ts | 8 +- .../DiffTable/DiffTableStats/utils.test.ts | 17 ++++- .../DiffTable/DiffTableStats/utils.ts | 17 +++-- packages/web/components/DiffTable/index.tsx | 12 +-- packages/web/components/DiffTable/queries.ts | 18 +++-- .../components/DiffTableNav/BackButton.tsx | 7 +- .../DiffTableNav/DiffTableStats/ListItem.tsx | 13 +--- .../DiffTableNav/DiffTableStats/TableStat.tsx | 9 ++- .../components/DiffTableNav/ForCommits.tsx | 13 +--- .../web/components/DiffTableNav/ForPull.tsx | 47 ++++++++++++ .../components/DiffTableNav/ForWorking.tsx | 10 +-- .../web/components/DiffTableNav/component.tsx | 7 +- .../components/DiffTableNav/index.module.css | 7 +- .../web/components/DiffTableNav/index.tsx | 2 + .../components/FormSelect/index.module.css | 4 +- .../components/SqlDataTable/WorkingDiff.tsx | 6 +- .../breadcrumbs/PullsBreadcrumbs.tsx | 19 +++++ .../breadcrumbs/breadcrumbDetails.tsx | 11 +++ .../ForCommits/DiffPage/component.tsx | 4 +- .../DatabasePage/ForPulls/index.tsx | 63 ++++++++++++++++ .../DatabasePage/ForReleases/index.tsx | 5 +- .../pageComponents/DatabasePage/index.tsx | 2 + packages/web/contexts/diff/index.tsx | 22 ++++-- packages/web/contexts/diff/queries.ts | 10 ++- packages/web/gen/graphql-types.tsx | 58 ++++++++------- packages/web/lib/params.ts | 12 +++ packages/web/lib/refetchQueries.ts | 14 ++-- packages/web/lib/urls.ts | 9 +++ .../database/[databaseName]/pulls/index.tsx | 46 ++++++++++++ 46 files changed, 590 insertions(+), 165 deletions(-) create mode 100644 packages/web/components/DiffSelector/BranchSelectForm/BranchSelect.tsx create mode 100644 packages/web/components/DiffSelector/BranchSelectForm/index.module.css create mode 100644 packages/web/components/DiffSelector/BranchSelectForm/index.tsx create mode 100644 packages/web/components/DiffSelector/ForPull.tsx create mode 100644 packages/web/components/DiffTableNav/ForPull.tsx create mode 100644 packages/web/components/breadcrumbs/PullsBreadcrumbs.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx create mode 100644 packages/web/pages/database/[databaseName]/pulls/index.tsx diff --git a/packages/graphql-server/schema.gql b/packages/graphql-server/schema.gql index eb5b247b..c5b1a71c 100644 --- a/packages/graphql-server/schema.gql +++ b/packages/graphql-server/schema.gql @@ -238,9 +238,9 @@ type Query { diffSummaries(databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, type: CommitDiffType, tableName: String): [DiffSummary!]! docs(databaseName: String!, refName: String!): DocList! docOrDefaultDoc(refName: String!, databaseName: String!, docType: DocType): Doc - rowDiffs(offset: Int, databaseName: String!, fromCommitId: String!, toCommitId: String!, refName: String, tableName: String!, filterByRowType: DiffRowType): RowDiffList! + rowDiffs(offset: Int, databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, filterByRowType: DiffRowType, type: CommitDiffType): RowDiffList! rows(refName: String!, databaseName: String!, tableName: String!, offset: Int): RowList! - schemaDiff(databaseName: String!, fromCommitId: String!, toCommitId: String!, refName: String, tableName: String!): SchemaDiff + schemaDiff(databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, type: CommitDiffType): SchemaDiff doltSchemas(databaseName: String!, refName: String!): [SchemaItem!]! views(databaseName: String!, refName: String!): [SchemaItem!]! doltProcedures(databaseName: String!, refName: String!): [SchemaItem!]! diff --git a/packages/graphql-server/src/rowDiffs/rowDiff.queries.ts b/packages/graphql-server/src/rowDiffs/rowDiff.queries.ts index 649784b0..8b50f9e5 100644 --- a/packages/graphql-server/src/rowDiffs/rowDiff.queries.ts +++ b/packages/graphql-server/src/rowDiffs/rowDiff.queries.ts @@ -15,6 +15,9 @@ export const getRowsQueryAsOf = ( export const tableColsQueryAsOf = `DESCRIBE ?? AS OF ?`; +export const hashOf = `SELECT HASHOF(?)`; +export const mergeBase = `SELECT DOLT_MERGE_BASE(?, ?)`; + export function getTableCommitDiffQuery( cols: RawRows, hasFilter = false, diff --git a/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts b/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts index 6695293e..500f9ab2 100644 --- a/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts +++ b/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts @@ -1,7 +1,10 @@ import { Args, ArgsType, Field, Query, Resolver } from "@nestjs/graphql"; import * as column from "../columns/column.model"; import { DataSourceService, ParQuery } from "../dataSources/dataSource.service"; -import { TableDiffType } from "../diffSummaries/diffSummary.enums"; +import { + CommitDiffType, + TableDiffType, +} from "../diffSummaries/diffSummary.enums"; import { getDiffSummaries } from "../diffSummaries/diffSummary.resolver"; import { ListRowsArgs } from "../rows/row.resolver"; import { ROW_LIMIT } from "../utils"; @@ -17,18 +20,19 @@ import { import { getRowsQueryAsOf, getTableCommitDiffQuery, + hashOf, + mergeBase, tableColsQueryAsOf, } from "./rowDiff.queries"; import { unionCols } from "./utils"; @ArgsType() class ListRowDiffsArgs extends DBArgsWithOffset { - // Uses resolved commits @Field() - fromCommitId: string; + fromRefName: string; @Field() - toCommitId: string; + toRefName: string; @Field({ nullable: true }) refName?: string; @@ -38,6 +42,9 @@ class ListRowDiffsArgs extends DBArgsWithOffset { @Field(_type => DiffRowType, { nullable: true }) filterByRowType?: DiffRowType; + + @Field(_type => CommitDiffType, { nullable: true }) + type?: CommitDiffType; } @Resolver(_of => RowDiff) @@ -57,20 +64,30 @@ export class RowDiffResolver { const ds = await getDiffSummaries(query, { ...dbArgs, tableName, - fromRefName: args.fromCommitId, - toRefName: args.toCommitId, + fromRefName: args.fromRefName, + toRefName: args.toRefName, + type: args.type, }); if (!ds.length) { throw new Error(`Could not get summary for table "${tableName}"`); } - const { tableType, fromTableName, toTableName } = ds[0]; + const { fromCommitId, toCommitId } = await resolveRefs( + query, + args.fromRefName, + args.toRefName, + args.type, + ); + const { tableType, fromTableName, toTableName } = ds[0]; + console.log("from", args.fromRefName, "to", args.toRefName); + console.log("DIFF TYPE", ds[0]); if (tableType === TableDiffType.Dropped) { + // console.log("dropped", tableName, args.fromRefName); const rows = await getRowsForDiff(query, { ...dbArgs, tableName, - refName: args.fromCommitId, + refName: args.toRefName, }); return fromOneSidedTable(rows, "dropped", args.filterByRowType); } @@ -78,18 +95,18 @@ export class RowDiffResolver { const rows = await getRowsForDiff(query, { ...dbArgs, tableName, - refName: args.toCommitId, + refName: args.fromRefName, }); return fromOneSidedTable(rows, "added", args.filterByRowType); } const oldCols = await query(tableColsQueryAsOf, [ fromTableName, - args.fromCommitId, + fromCommitId, ]); const newCols = await query(tableColsQueryAsOf, [ toTableName, - args.toCommitId, + toCommitId, ]); const colsUnion = unionCols( @@ -98,7 +115,7 @@ export class RowDiffResolver { ); const diffType = convertToStringForQuery(args.filterByRowType); - const refArgs = [args.fromCommitId, args.toCommitId, tableName]; + const refArgs = [fromCommitId, toCommitId, tableName]; const pageArgs = [ROW_LIMIT + 1, offset]; const diffs = await query( getTableCommitDiffQuery(colsUnion, !!diffType), @@ -131,3 +148,20 @@ async function getRowsForDiff(query: ParQuery, args: ListRowsArgs) { ]); return fromDoltListRowWithColsRes(rows, columns, offset, args.tableName); } + +async function resolveRefs( + query: ParQuery, + fromRefName: string, + toRefName: string, + type?: CommitDiffType, +): Promise<{ fromCommitId: string; toCommitId: string }> { + if (type === CommitDiffType.ThreeDot) { + const fromCommitId = await query(hashOf, [fromRefName]); + const toCommitId = await query(mergeBase, [toRefName, fromRefName]); + return { + fromCommitId: Object.values(fromCommitId[0])[0], + toCommitId: Object.values(toCommitId[0])[0], + }; + } + return { fromCommitId: fromRefName, toCommitId: toRefName }; +} diff --git a/packages/graphql-server/src/schemaDiffs/schemaDiff.resolver.ts b/packages/graphql-server/src/schemaDiffs/schemaDiff.resolver.ts index e6e1abc1..97bf58cb 100644 --- a/packages/graphql-server/src/schemaDiffs/schemaDiff.resolver.ts +++ b/packages/graphql-server/src/schemaDiffs/schemaDiff.resolver.ts @@ -1,23 +1,26 @@ import { Args, ArgsType, Field, Query, Resolver } from "@nestjs/graphql"; import { DataSourceService } from "../dataSources/dataSource.service"; +import { CommitDiffType } from "../diffSummaries/diffSummary.enums"; import { DBArgs } from "../utils/commonTypes"; import { SchemaDiff } from "./schemaDiff.model"; import { schemaDiffQuery, schemaPatchQuery } from "./schemaDiff.queries"; @ArgsType() class SchemaDiffArgs extends DBArgs { - // Uses resolved commits @Field() - fromCommitId: string; + fromRefName: string; @Field() - toCommitId: string; + toRefName: string; @Field({ nullable: true }) refName?: string; @Field() tableName: string; + + @Field(_type => CommitDiffType, { nullable: true }) + type?: CommitDiffType; } @Resolver(_of => SchemaDiff) @@ -28,10 +31,9 @@ export class SchemaDiffResolver { async schemaDiff( @Args() args: SchemaDiffArgs, ): Promise { - const commitArgs = [args.fromCommitId, args.toCommitId, args.tableName]; - return this.dss.query( async query => { + const commitArgs = [args.fromRefName, args.toRefName, args.tableName]; const res = await query(schemaPatchQuery, commitArgs); const schemaPatch = res.map(r => r.statement); diff --git a/packages/web/components/DatabaseNav/index.tsx b/packages/web/components/DatabaseNav/index.tsx index 51af3278..71492578 100644 --- a/packages/web/components/DatabaseNav/index.tsx +++ b/packages/web/components/DatabaseNav/index.tsx @@ -23,7 +23,7 @@ type QueryProps = Props & { }; }; -const tabs = ["Database", "About", "Commit Log", "Releases"]; +const tabs = ["Database", "About", "Commit Log", "Releases", "Pull Requests"]; export default function DatabaseNav(props: Props) { const { isDolt } = useIsDolt(); diff --git a/packages/web/components/DatabaseNav/utils.ts b/packages/web/components/DatabaseNav/utils.ts index 7dc75af6..a33e43f7 100644 --- a/packages/web/components/DatabaseNav/utils.ts +++ b/packages/web/components/DatabaseNav/utils.ts @@ -4,6 +4,7 @@ import { database, DatabaseUrl, defaultDoc, + pulls, ref, RefUrl, releases, @@ -20,8 +21,8 @@ function getUrlFromName(name: string): [DatabaseUrl, RefUrl?] { return [database, commitLog]; case "Releases": return [releases]; - // case "Pull Requests": - // return [pulls]; + case "Pull Requests": + return [pulls]; default: return [database, ref]; } diff --git a/packages/web/components/DiffSelector/BranchSelectForm/BranchSelect.tsx b/packages/web/components/DiffSelector/BranchSelectForm/BranchSelect.tsx new file mode 100644 index 00000000..25289169 --- /dev/null +++ b/packages/web/components/DiffSelector/BranchSelectForm/BranchSelect.tsx @@ -0,0 +1,30 @@ +import FormSelect from "@components/FormSelect"; +import { BranchFragment } from "@gen/graphql-types"; +import css from "./index.module.css"; + +type Props = { + branchList: BranchFragment[]; + currentBranchName: string; + onChange: (b: string) => void; + label: string; +}; + +export default function BranchSelect(props: Props) { + return ( + { + return { + value: b.branchName, + label: b.branchName, + }; + })} + val={props.currentBranchName} + onChangeValue={props.onChange} + hideSelectedOptions + className={css.selector} + label={props.label} + small + horizontal + /> + ); +} diff --git a/packages/web/components/DiffSelector/BranchSelectForm/index.module.css b/packages/web/components/DiffSelector/BranchSelectForm/index.module.css new file mode 100644 index 00000000..2ce9538d --- /dev/null +++ b/packages/web/components/DiffSelector/BranchSelectForm/index.module.css @@ -0,0 +1,15 @@ +.container { + @apply mx-4; +} + +.selectors { + @apply flex flex-col items-start mb-10; +} + +.selector { + @apply min-w-[225px]; +} + +.arrow { + @apply text-2xl mx-6 my-3 rotate-90; +} diff --git a/packages/web/components/DiffSelector/BranchSelectForm/index.tsx b/packages/web/components/DiffSelector/BranchSelectForm/index.tsx new file mode 100644 index 00000000..307ba859 --- /dev/null +++ b/packages/web/components/DiffSelector/BranchSelectForm/index.tsx @@ -0,0 +1,73 @@ +import QueryHandler from "@components/util/QueryHandler"; +import { BranchFragment, useBranchListQuery } from "@gen/graphql-types"; +import { PullParams } from "@lib/params"; +import { pulls } from "@lib/urls"; +import { BsArrowLeft } from "@react-icons/all-files/bs/BsArrowLeft"; +import { useRouter } from "next/router"; +import BranchSelect from "./BranchSelect"; +import css from "./index.module.css"; + +type Props = { + params: PullParams; +}; + +type InnerProps = Props & { + branches: BranchFragment[]; +}; + +function Inner(props: InnerProps) { + const router = useRouter(); + + return ( +
+ {props.branches.length ? ( +
+
+
+ { + const p = pulls({ ...props.params, toBranchName: b }); + router + .push(p.href, p.as, { shallow: true }) + .catch(console.error); + }} + /> +
+
+ +
+
+ { + const p = pulls({ ...props.params, fromBranchName: b }); + router + .push(p.href, p.as, { shallow: true }) + .catch(console.error); + }} + /> +
+
+
+ ) : ( + Database must have branches to view pull request. + )} +
+ ); +} + +export default function BranchSelectForm(props: Props) { + const branchRes = useBranchListQuery({ variables: props.params }); + + return ( + } + /> + ); +} diff --git a/packages/web/components/DiffSelector/ForPull.tsx b/packages/web/components/DiffSelector/ForPull.tsx new file mode 100644 index 00000000..0332adb8 --- /dev/null +++ b/packages/web/components/DiffSelector/ForPull.tsx @@ -0,0 +1,10 @@ +import { PullParams } from "@lib/params"; +import BranchSelectForm from "./BranchSelectForm"; + +type Props = { + params: PullParams; +}; + +export default function ForPull(props: Props) { + return ; +} diff --git a/packages/web/components/DiffSelector/index.tsx b/packages/web/components/DiffSelector/index.tsx index 7bb85608..e5873c57 100644 --- a/packages/web/components/DiffSelector/index.tsx +++ b/packages/web/components/DiffSelector/index.tsx @@ -1,6 +1,8 @@ import DiffSelector from "./component"; import ForBranch from "./ForBranch"; +import ForPull from "./ForPull"; export default Object.assign(DiffSelector, { ForBranch, + ForPull, }); diff --git a/packages/web/components/DiffStat/index.tsx b/packages/web/components/DiffStat/index.tsx index 88478a50..484f02c9 100644 --- a/packages/web/components/DiffStat/index.tsx +++ b/packages/web/components/DiffStat/index.tsx @@ -1,7 +1,11 @@ import { ApolloError } from "@apollo/client"; import ErrorMsg from "@components/ErrorMsg"; import { useDiffContext } from "@contexts/diff"; -import { DiffStatForDiffsFragment, useDiffStatQuery } from "@gen/graphql-types"; +import { + CommitDiffType, + DiffStatForDiffsFragment, + useDiffStatQuery, +} from "@gen/graphql-types"; import { gqlErrorPrimaryKeyChange } from "@lib/errors/graphql"; import { errorMatches } from "@lib/errors/helpers"; import { DiffParamsWithRefs } from "@lib/params"; @@ -44,8 +48,12 @@ function Inner(props: InnerProps) { } export default function DiffStat(props: Props) { + const { forPull } = useDiffContext(); const { data, loading, error } = useDiffStatQuery({ - variables: props.params, + variables: { + ...props.params, + type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, + }, }); return ( diff --git a/packages/web/components/DiffTable/DataDiff/Table.tsx b/packages/web/components/DiffTable/DataDiff/Table.tsx index f8240bb5..2632e23b 100644 --- a/packages/web/components/DiffTable/DataDiff/Table.tsx +++ b/packages/web/components/DiffTable/DataDiff/Table.tsx @@ -6,7 +6,7 @@ import { } from "@lib/doltSystemTables"; import { gqlNoRefFoundErr } from "@lib/errors/graphql"; import { errorMatches } from "@lib/errors/helpers"; -import { DiffParams } from "@lib/params"; +import { TableParams } from "@lib/params"; import cx from "classnames"; import { useState } from "react"; import Body from "./Body"; @@ -23,9 +23,7 @@ type Props = { state: RowDiffState; setHiddenColIndexes: SetHiddenColIndexes; hiddenColIndexes: HiddenColIndexes; - params: DiffParams & { - tableName: string; - }; + params: TableParams; hideCellButtons?: boolean; refName: string; error?: ApolloError; diff --git a/packages/web/components/DiffTable/DataDiff/ViewSqlLink.tsx b/packages/web/components/DiffTable/DataDiff/ViewSqlLink.tsx index fdc230ef..3b5a109c 100644 --- a/packages/web/components/DiffTable/DataDiff/ViewSqlLink.tsx +++ b/packages/web/components/DiffTable/DataDiff/ViewSqlLink.tsx @@ -1,22 +1,24 @@ -import { AiOutlineConsoleSql } from "@react-icons/all-files/ai/AiOutlineConsoleSql"; +import { DropdownItem } from "@components/DatabaseOptionsDropdown"; +import SmallLoader from "@components/SmallLoader"; +import Link from "@components/links/Link"; import { ColumnForDataTableFragment, useDataTableQuery, } from "@gen/graphql-types"; -import { DiffParams } from "@lib/params"; +import { RequiredRefsParams } from "@lib/params"; import { sqlQuery } from "@lib/urls"; -import { DropdownItem } from "@components/DatabaseOptionsDropdown"; -import Link from "@components/links/Link"; -import SmallLoader from "@components/SmallLoader"; +import { AiOutlineConsoleSql } from "@react-icons/all-files/ai/AiOutlineConsoleSql"; import { getDoltCommitDiffQuery } from "../DiffTableStats/utils"; import css from "./index.module.css"; import { HiddenColIndexes } from "./utils"; type Props = { - params: Required & { + params: RequiredRefsParams & { + refName: string; tableName: string; }; hiddenColIndexes: HiddenColIndexes; + forPull?: boolean; }; type InnerProps = Props & { diff --git a/packages/web/components/DiffTable/DataDiff/index.tsx b/packages/web/components/DiffTable/DataDiff/index.tsx index 8e6eaf0d..297fb58a 100644 --- a/packages/web/components/DiffTable/DataDiff/index.tsx +++ b/packages/web/components/DiffTable/DataDiff/index.tsx @@ -8,7 +8,7 @@ import { useDiffContext } from "@contexts/diff"; import { DiffRowType } from "@gen/graphql-types"; import useFocus from "@hooks/useFocus"; import { ApolloErrorType } from "@lib/errors/types"; -import { DiffParams } from "@lib/params"; +import { RequiredRefsParams } from "@lib/params"; import InfiniteScroll from "react-infinite-scroller"; import DiffMsg from "./DiffMsg"; import FilterByType from "./FilterByType"; @@ -24,8 +24,9 @@ import { HiddenColIndexes, SetHiddenColIndexes, getIsPKTable } from "./utils"; type Props = { hiddenColIndexes: HiddenColIndexes; setHiddenColIndexes: SetHiddenColIndexes; - params: Required & { + params: RequiredRefsParams & { tableName: string; + refName: string; }; hideCellButtons?: boolean; }; @@ -54,7 +55,7 @@ function Inner(props: InnerProps) { // For diff tables we want to use `refName` from `useDiffContext`, which is either the `fromBranchName` // for PR diffs or the current ref for commit diffs - const { refName } = useDiffContext(); + const { refName, forPull } = useDiffContext(); const res = useDataTableContext(); return ( @@ -65,7 +66,7 @@ function Inner(props: InnerProps) { showingHideUnchangedCol={hideUnchangedCols} className={css.optionButton} > - + @@ -123,8 +124,10 @@ function Inner(props: InnerProps) { } export default function DataDiff(props: Props) { + const { forPull } = useDiffContext(); const { state, fetchMore, setFilter, hasMore, loading } = useRowDiffs( props.params, + forPull, ); if (loading) return ; diff --git a/packages/web/components/DiffTable/DataDiff/useRowDiffs.ts b/packages/web/components/DiffTable/DataDiff/useRowDiffs.ts index c35b76cf..6a7bc320 100644 --- a/packages/web/components/DiffTable/DataDiff/useRowDiffs.ts +++ b/packages/web/components/DiffTable/DataDiff/useRowDiffs.ts @@ -1,4 +1,5 @@ import { + CommitDiffType, DiffRowType, RowDiffForTableListFragment, RowDiffsDocument, @@ -11,7 +12,7 @@ import useSetState from "@hooks/useSetState"; import Maybe from "@lib/Maybe"; import { handleCaughtApolloError } from "@lib/errors/helpers"; import { ApolloErrorType } from "@lib/errors/types"; -import { RequiredCommitsParams } from "@lib/params"; +import { RequiredRefsParams } from "@lib/params"; import { useEffect, useState } from "react"; import { RowDiffState, getDefaultState } from "./state"; @@ -24,13 +25,17 @@ type ReturnType = { error?: ApolloErrorType; }; -type Params = RequiredCommitsParams & { +type Params = RequiredRefsParams & { tableName: string; }; -export default function useRowDiffs(params: Params): ReturnType { +export default function useRowDiffs( + params: Params, + forPull = false, +): ReturnType { + const type = forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot; const { data, client, loading, error } = useRowDiffsQuery({ - variables: params, + variables: { ...params, type }, }); const [state, setState] = useSetState(getDefaultState(data?.rowDiffs)); const [lastOffset, setLastOffset] = useState>(undefined); @@ -54,7 +59,7 @@ export default function useRowDiffs(params: Params): ReturnType { try { const res = await client.query({ query: RowDiffsDocument, - variables: { ...params, offset, filterByRowType }, + variables: { ...params, type, offset, filterByRowType }, }); setRowDiffs(res.data.rowDiffs.list); setState({ offset: res.data.rowDiffs.nextOffset }); diff --git a/packages/web/components/DiffTable/DiffTableStats/index.tsx b/packages/web/components/DiffTable/DiffTableStats/index.tsx index 5e469598..1b5c9f09 100644 --- a/packages/web/components/DiffTable/DiffTableStats/index.tsx +++ b/packages/web/components/DiffTable/DiffTableStats/index.tsx @@ -1,7 +1,11 @@ import ErrorMsg from "@components/ErrorMsg"; import SmallLoader from "@components/SmallLoader"; import { useDiffContext } from "@contexts/diff"; -import { DiffSummaryFragment, useDiffStatQuery } from "@gen/graphql-types"; +import { + CommitDiffType, + DiffSummaryFragment, + useDiffStatQuery, +} from "@gen/graphql-types"; import { gqlErrorPrimaryKeyChange } from "@lib/errors/graphql"; import { errorMatches } from "@lib/errors/helpers"; import cx from "classnames"; @@ -14,14 +18,13 @@ type Props = { }; export default function DiffTableStats(props: Props) { - const { params, refName } = useDiffContext(); + const { params, refName, forPull } = useDiffContext(); const { data, loading, error } = useDiffStatQuery({ variables: { ...params, refName, - fromRefName: params.fromCommitId, - toRefName: params.toCommitId, tableName: props.diffSummary.tableName, + type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, }, }); diff --git a/packages/web/components/DiffTable/DiffTableStats/mocks.ts b/packages/web/components/DiffTable/DiffTableStats/mocks.ts index 72c2016d..8fa0f9a4 100644 --- a/packages/web/components/DiffTable/DiffTableStats/mocks.ts +++ b/packages/web/components/DiffTable/DiffTableStats/mocks.ts @@ -1,8 +1,8 @@ import { fakeCommitId } from "@components/CustomFormSelect/mocks"; import { ColumnForDataTableFragment } from "@gen/graphql-types"; -import { DiffParams, TableParams } from "@lib/params"; +import { RequiredRefsParams, TableParams } from "@lib/params"; -type Params = Required & { tableName: string }; +type Params = RequiredRefsParams & { tableName: string; refName: string }; const tableParams: TableParams = { databaseName: "dbname", @@ -12,8 +12,8 @@ const tableParams: TableParams = { export const params: Params = { ...tableParams, - fromCommitId: fakeCommitId(), - toCommitId: fakeCommitId(), + fromRefName: fakeCommitId(), + toRefName: fakeCommitId(), }; export const tableCols: ColumnForDataTableFragment[] = [ diff --git a/packages/web/components/DiffTable/DiffTableStats/utils.test.ts b/packages/web/components/DiffTable/DiffTableStats/utils.test.ts index 2c36f9a5..cf04973e 100644 --- a/packages/web/components/DiffTable/DiffTableStats/utils.test.ts +++ b/packages/web/components/DiffTable/DiffTableStats/utils.test.ts @@ -10,7 +10,7 @@ describe("test getDoltCommitDiffQuery for diff tables", () => { hiddenColIndexes: [], }), ).toEqual( - `SELECT diff_type, \`from_id\`, \`to_id\`, \`from_name\`, \`to_name\`, from_commit, from_commit_date, to_commit, to_commit_date FROM \`dolt_commit_diff_${params.tableName}\` WHERE from_commit="${params.fromCommitId}" AND to_commit="${params.toCommitId}"`, + `SELECT diff_type, \`from_id\`, \`to_id\`, \`from_name\`, \`to_name\`, from_commit, from_commit_date, to_commit, to_commit_date FROM \`dolt_commit_diff_${params.tableName}\` WHERE from_commit="${params.fromRefName}" AND to_commit="${params.toRefName}"`, ); }); @@ -22,7 +22,20 @@ describe("test getDoltCommitDiffQuery for diff tables", () => { hiddenColIndexes: [1], }), ).toEqual( - `SELECT diff_type, \`from_id\`, \`to_id\`, from_commit, from_commit_date, to_commit, to_commit_date FROM \`dolt_commit_diff_${params.tableName}\` WHERE from_commit="${params.fromCommitId}" AND to_commit="${params.toCommitId}"`, + `SELECT diff_type, \`from_id\`, \`to_id\`, from_commit, from_commit_date, to_commit, to_commit_date FROM \`dolt_commit_diff_${params.tableName}\` WHERE from_commit="${params.fromRefName}" AND to_commit="${params.toRefName}"`, + ); + }); + + it("returns query for no diff tags and removed columns for pull", () => { + expect( + getDoltCommitDiffQuery({ + params, + columns: tableCols, + hiddenColIndexes: [1], + forPull: true, + }), + ).toEqual( + `SELECT diff_type, \`from_id\`, \`to_id\`, from_commit, from_commit_date, to_commit, to_commit_date FROM \`dolt_commit_diff_${params.tableName}\` WHERE from_commit="${params.fromRefName}" AND to_commit=DOLT_MERGE_BASE("${params.toRefName}", "${params.fromRefName}")`, ); }); }); diff --git a/packages/web/components/DiffTable/DiffTableStats/utils.ts b/packages/web/components/DiffTable/DiffTableStats/utils.ts index 4b5e843e..2c17089e 100644 --- a/packages/web/components/DiffTable/DiffTableStats/utils.ts +++ b/packages/web/components/DiffTable/DiffTableStats/utils.ts @@ -1,12 +1,14 @@ -import { ColumnForDataTableFragment } from "@gen/graphql-types"; -import { CommitsParams, DiffParams } from "@lib/params"; import { getAllSelectColumns } from "@components/CellButtons/queryHelpers"; +import { ColumnForDataTableFragment } from "@gen/graphql-types"; +import { RefsParams, RequiredRefsParams } from "@lib/params"; import { isHiddenColumn } from "../DataDiff/utils"; type Props = { - params: Required & { + params: RequiredRefsParams & { + refName: string; tableName: string; }; + forPull?: boolean; columns: ColumnForDataTableFragment[]; hiddenColIndexes: number[]; }; @@ -23,11 +25,14 @@ export function getDoltCommitDiffQuery(props: Props): string { const cols = getAllSelectColumns(colsWithNamesAndVals); return `SELECT ${cols} FROM \`dolt_commit_diff_${ props.params.tableName - }\`${getWhereClause(props.params)}`; + }\`${getWhereClause(props.params, props.forPull)}`; } -function getWhereClause(params: CommitsParams): string { - return ` WHERE from_commit="${params.fromCommitId}" AND to_commit="${params.toCommitId}"`; +function getWhereClause(params: RefsParams, forPull = false): string { + const toCommit = forPull + ? `DOLT_MERGE_BASE("${params.toRefName}", "${params.fromRefName}")` + : `"${params.toRefName}"`; + return ` WHERE from_commit="${params.fromRefName}" AND to_commit=${toCommit}`; } // Get names and values for every column based on row value and dolt_commit_diff table diff --git a/packages/web/components/DiffTable/index.tsx b/packages/web/components/DiffTable/index.tsx index 8fd203ed..4c3276f3 100644 --- a/packages/web/components/DiffTable/index.tsx +++ b/packages/web/components/DiffTable/index.tsx @@ -1,7 +1,7 @@ import StatusWithOptions from "@components/StatusWithOptions"; import { useDiffContext } from "@contexts/diff"; import { DiffSummaryFragment, TableDiffType } from "@gen/graphql-types"; -import { DatabaseParams, RequiredCommitsParams } from "@lib/params"; +import { DatabaseParams, RequiredRefsParams } from "@lib/params"; import { useEffect, useState } from "react"; import DataSection from "./DataSection"; import DiffTableStats from "./DiffTableStats"; @@ -80,11 +80,11 @@ export default function DiffTable(props: Props) { return ; } -function isShowingUncommittedChanges(params: RequiredCommitsParams): boolean { +function isShowingUncommittedChanges(params: RequiredRefsParams): boolean { return ( - params.fromCommitId === "WORKING" || - params.toCommitId === "WORKING" || - params.fromCommitId === "STAGED" || - params.toCommitId === "STAGED" + params.fromRefName === "WORKING" || + params.toRefName === "WORKING" || + params.fromRefName === "STAGED" || + params.toRefName === "STAGED" ); } diff --git a/packages/web/components/DiffTable/queries.ts b/packages/web/components/DiffTable/queries.ts index d2dd89f1..4728cacb 100644 --- a/packages/web/components/DiffTable/queries.ts +++ b/packages/web/components/DiffTable/queries.ts @@ -37,20 +37,22 @@ export const ROW_DIFFS = gql` query RowDiffs( $databaseName: String! $tableName: String! - $fromCommitId: String! - $toCommitId: String! + $fromRefName: String! + $toRefName: String! $refName: String $offset: Int $filterByRowType: DiffRowType + $type: CommitDiffType ) { rowDiffs( databaseName: $databaseName tableName: $tableName - fromCommitId: $fromCommitId - toCommitId: $toCommitId + fromRefName: $fromRefName + toRefName: $toRefName refName: $refName offset: $offset filterByRowType: $filterByRowType + type: $type ) { ...RowDiffListWithCols } @@ -71,15 +73,15 @@ export const SCHEMA_DIFF = gql` query SchemaDiff( $databaseName: String! $tableName: String! - $fromCommitId: String! - $toCommitId: String! + $fromRefName: String! + $toRefName: String! $refName: String ) { schemaDiff( databaseName: $databaseName tableName: $tableName - fromCommitId: $fromCommitId - toCommitId: $toCommitId + fromRefName: $fromRefName + toRefName: $toRefName refName: $refName ) { ...SchemaDiff diff --git a/packages/web/components/DiffTableNav/BackButton.tsx b/packages/web/components/DiffTableNav/BackButton.tsx index aab2ff09..a6aafe9a 100644 --- a/packages/web/components/DiffTableNav/BackButton.tsx +++ b/packages/web/components/DiffTableNav/BackButton.tsx @@ -14,16 +14,15 @@ type Params = DatabaseParams & { type Props = { params: Params; open: boolean; + forPull?: boolean; }; export default function BackButton(props: Props) { const { defaultBranchName, loading } = useDefaultBranch(props.params); + if (props.forPull) return
; return (
diff --git a/packages/web/components/DiffTableNav/DiffTableStats/ListItem.tsx b/packages/web/components/DiffTableNav/DiffTableStats/ListItem.tsx index 2828ea70..821e9d70 100644 --- a/packages/web/components/DiffTableNav/DiffTableStats/ListItem.tsx +++ b/packages/web/components/DiffTableNav/DiffTableStats/ListItem.tsx @@ -1,5 +1,5 @@ import { DiffSummaryFragment } from "@gen/graphql-types"; -import { RequiredCommitsParams } from "@lib/params"; +import { RequiredRefsParams } from "@lib/params"; import cx from "classnames"; import StatIcon from "./StatIcon"; import TableName from "./TableName"; @@ -8,7 +8,7 @@ import css from "./index.module.css"; type Props = { diffSummary: DiffSummaryFragment; - params: RequiredCommitsParams & { refName: string }; + params: RequiredRefsParams & { refName: string }; isActive: boolean; }; @@ -26,14 +26,7 @@ export default function ListItem(props: Props) { - + ); } diff --git a/packages/web/components/DiffTableNav/DiffTableStats/TableStat.tsx b/packages/web/components/DiffTableNav/DiffTableStats/TableStat.tsx index 194934ee..64034b94 100644 --- a/packages/web/components/DiffTableNav/DiffTableStats/TableStat.tsx +++ b/packages/web/components/DiffTableNav/DiffTableStats/TableStat.tsx @@ -1,7 +1,9 @@ import SummaryStat from "@components/DiffStat/SummaryStat"; import ErrorMsg from "@components/ErrorMsg"; import SmallLoader from "@components/SmallLoader"; +import { useDiffContext } from "@contexts/diff"; import { + CommitDiffType, DiffStatForDiffsFragment, DiffSummaryFragment, TableDiffType, @@ -76,8 +78,13 @@ function Inner({ diffStat, diffSummary, loading, error }: InnerProps) { } export default function TableStat(props: Props) { + const { forPull } = useDiffContext(); const res = useDiffStatQuery({ - variables: { ...props.params, tableName: props.diffSummary.tableName }, + variables: { + ...props.params, + tableName: props.diffSummary.tableName, + type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, + }, }); return (
diff --git a/packages/web/components/DiffTableNav/ForCommits.tsx b/packages/web/components/DiffTableNav/ForCommits.tsx index 833ccbfd..1e38f4fc 100644 --- a/packages/web/components/DiffTableNav/ForCommits.tsx +++ b/packages/web/components/DiffTableNav/ForCommits.tsx @@ -14,21 +14,14 @@ export default function ForCommits(props: Props) { return ( - } + diffStat={} diffSelector={ } diff --git a/packages/web/components/DiffTableNav/ForPull.tsx b/packages/web/components/DiffTableNav/ForPull.tsx new file mode 100644 index 00000000..0bd53cfb --- /dev/null +++ b/packages/web/components/DiffTableNav/ForPull.tsx @@ -0,0 +1,47 @@ +import DiffSelector from "@components/DiffSelector"; +import DiffStat from "@components/DiffStat"; +import { PullParams } from "@lib/params"; +import DiffTableStats from "./DiffTableStats"; +import DiffTableNav from "./component"; +import css from "./index.module.css"; + +type Props = { + params: PullParams; + tableName?: string; +}; + +export default function ForPull(props: Props) { + const selector = ; + if (!props.params.fromBranchName || !props.params.toBranchName) { + return ( + + Select branches to view diff +

+ } + diffTables={null} + forPull + /> + ); + } + return ( + + } + diffTables={} + forPull + /> + ); +} diff --git a/packages/web/components/DiffTableNav/ForWorking.tsx b/packages/web/components/DiffTableNav/ForWorking.tsx index bc9d7726..a8e70eba 100644 --- a/packages/web/components/DiffTableNav/ForWorking.tsx +++ b/packages/web/components/DiffTableNav/ForWorking.tsx @@ -1,11 +1,11 @@ import DiffStat from "@components/DiffStat"; -import { RequiredCommitsParams } from "@lib/params"; +import { RequiredRefsParams } from "@lib/params"; import cx from "classnames"; import DiffTableStats from "./DiffTableStats"; import css from "./index.module.css"; type Props = { - params: RequiredCommitsParams & { refName: string }; + params: RequiredRefsParams & { refName: string }; }; export default function ForWorking(props: Props) { @@ -16,11 +16,7 @@ export default function ForWorking(props: Props) {

Working Changes

diff --git a/packages/web/components/DiffTableNav/component.tsx b/packages/web/components/DiffTableNav/component.tsx index 581a6258..ffa21c4a 100644 --- a/packages/web/components/DiffTableNav/component.tsx +++ b/packages/web/components/DiffTableNav/component.tsx @@ -15,6 +15,7 @@ type Props = { diffSelector?: ReactNode; diffTables?: ReactNode; white?: boolean; + forPull?: boolean; }; export default function DiffTableNav({ white = false, ...props }: Props) { @@ -33,7 +34,11 @@ export default function DiffTableNav({ white = false, ...props }: Props) { > {!!props.diffSelector && (
- + diff --git a/packages/web/components/breadcrumbs/PullsBreadcrumbs.tsx b/packages/web/components/breadcrumbs/PullsBreadcrumbs.tsx new file mode 100644 index 00000000..b0d64385 --- /dev/null +++ b/packages/web/components/breadcrumbs/PullsBreadcrumbs.tsx @@ -0,0 +1,19 @@ +import { DatabaseParams } from "@lib/params"; +import Breadcrumbs from "."; +import { pullsBreadcrumbs } from "./breadcrumbDetails"; + +type Props = { + params: DatabaseParams; + className?: string; +}; + +export default function PullsBreadcrumbs({ params, ...props }: Props) { + return ( + + ); +} diff --git a/packages/web/components/breadcrumbs/breadcrumbDetails.tsx b/packages/web/components/breadcrumbs/breadcrumbDetails.tsx index da021116..7638b071 100644 --- a/packages/web/components/breadcrumbs/breadcrumbDetails.tsx +++ b/packages/web/components/breadcrumbs/breadcrumbDetails.tsx @@ -223,3 +223,14 @@ export function commitDiffBreadcrumbDetails( }, ]; } + +export function pullsBreadcrumbs(params: DatabaseParams): BreadcrumbDetails[] { + return [ + ...databaseBreadcrumbs(params), + { + child: pull requests, + name: BreadcrumbName.DBPulls, + type: BreadcrumbType.Text, + }, + ]; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForCommits/DiffPage/component.tsx b/packages/web/components/pageComponents/DatabasePage/ForCommits/DiffPage/component.tsx index fed1f881..2ac11915 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForCommits/DiffPage/component.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForCommits/DiffPage/component.tsx @@ -50,8 +50,8 @@ export default function DiffPage(props: Props) { {...props} params={{ ...props.params, - fromCommitId: props.initialFromCommitId, - toCommitId: props.initialToCommitId, + fromRefName: props.initialFromCommitId, + toRefName: props.initialToCommitId, }} initialTableName={props.tableName} > diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx new file mode 100644 index 00000000..882bf620 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx @@ -0,0 +1,63 @@ +import DiffTable from "@components/DiffTable"; +import DiffTableNav from "@components/DiffTableNav"; +import PullsBreadcrumbs from "@components/breadcrumbs/PullsBreadcrumbs"; +import NotDoltWrapper from "@components/util/NotDoltWrapper"; +import { DiffProvider } from "@contexts/diff"; +import { PullParams } from "@lib/params"; +import { pulls } from "@lib/urls"; +import ForDefaultBranch from "../ForDefaultBranch"; + +type Props = { + params: PullParams; + tableName?: string; +}; + +export default function ForPulls(props: Props) { + if (!props.params.fromBranchName || !props.params.toBranchName) { + return ( + } + initialSmallHeader + leftTableNav={} + wide + hideDefaultTable + > + +
Select branches to view pull request
+
+
+ ); + } + + return ( + + } + initialSmallHeader + leftTableNav={} + wide + hideDefaultTable + > + + + + + + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForReleases/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForReleases/index.tsx index 0334238e..277ca088 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForReleases/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForReleases/index.tsx @@ -15,10 +15,7 @@ export default function ForReleases(props: Props): JSX.Element { const feature = props.newRelease ? "Creating releases" : "Viewing releases"; return ( void; refName: string; setRefName: (r: string) => void; stayWithinPage: boolean; // Changing tables within diff doesn't change URL + forPull: boolean; }; export const DiffContext = createCustomContext("DiffContext"); @@ -33,13 +39,17 @@ export function DiffProvider({ children, initialTableName, stayWithinPage = false, + forPull = false, }: Props): JSX.Element { const [activeTableName, setActiveTableName] = useState( initialTableName ?? "", ); const [refName, setRefName] = useState(params.refName ?? ""); const { data, error, loading } = useDiffSummariesQuery({ - variables: params, + variables: { + ...params, + type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, + }, }); useEffect(() => { @@ -59,6 +69,7 @@ export function DiffProvider({ refName, setRefName, stayWithinPage, + forPull, }; }, [ data, @@ -70,6 +81,7 @@ export function DiffProvider({ refName, setRefName, stayWithinPage, + forPull, ]); return {children}; diff --git a/packages/web/contexts/diff/queries.ts b/packages/web/contexts/diff/queries.ts index 4507e417..63b24b25 100644 --- a/packages/web/contexts/diff/queries.ts +++ b/packages/web/contexts/diff/queries.ts @@ -12,15 +12,17 @@ export const DIFF_SUMMARIES = gql` } query DiffSummaries( $databaseName: String! - $fromCommitId: String! - $toCommitId: String! + $fromRefName: String! + $toRefName: String! $refName: String + $type: CommitDiffType ) { diffSummaries( databaseName: $databaseName - fromRefName: $fromCommitId - toRefName: $toCommitId + fromRefName: $fromRefName + toRefName: $toRefName refName: $refName + type: $type ) { ...DiffSummary } diff --git a/packages/web/gen/graphql-types.tsx b/packages/web/gen/graphql-types.tsx index f44e722a..cabf81f9 100644 --- a/packages/web/gen/graphql-types.tsx +++ b/packages/web/gen/graphql-types.tsx @@ -364,11 +364,12 @@ export type QueryDoltSchemasArgs = { export type QueryRowDiffsArgs = { databaseName: Scalars['String']['input']; filterByRowType?: InputMaybe; - fromCommitId: Scalars['String']['input']; + fromRefName: Scalars['String']['input']; offset?: InputMaybe; refName?: InputMaybe; tableName: Scalars['String']['input']; - toCommitId: Scalars['String']['input']; + toRefName: Scalars['String']['input']; + type?: InputMaybe; }; @@ -382,10 +383,11 @@ export type QueryRowsArgs = { export type QuerySchemaDiffArgs = { databaseName: Scalars['String']['input']; - fromCommitId: Scalars['String']['input']; + fromRefName: Scalars['String']['input']; refName?: InputMaybe; tableName: Scalars['String']['input']; - toCommitId: Scalars['String']['input']; + toRefName: Scalars['String']['input']; + type?: InputMaybe; }; @@ -675,11 +677,12 @@ export type RowDiffListWithColsFragment = { __typename?: 'RowDiffList', nextOffs export type RowDiffsQueryVariables = Exact<{ databaseName: Scalars['String']['input']; tableName: Scalars['String']['input']; - fromCommitId: Scalars['String']['input']; - toCommitId: Scalars['String']['input']; + fromRefName: Scalars['String']['input']; + toRefName: Scalars['String']['input']; refName?: InputMaybe; offset?: InputMaybe; filterByRowType?: InputMaybe; + type?: InputMaybe; }>; @@ -692,8 +695,8 @@ export type SchemaDiffFragment = { __typename?: 'SchemaDiff', schemaPatch?: Arra export type SchemaDiffQueryVariables = Exact<{ databaseName: Scalars['String']['input']; tableName: Scalars['String']['input']; - fromCommitId: Scalars['String']['input']; - toCommitId: Scalars['String']['input']; + fromRefName: Scalars['String']['input']; + toRefName: Scalars['String']['input']; refName?: InputMaybe; }>; @@ -947,9 +950,10 @@ export type DiffSummaryFragment = { __typename?: 'DiffSummary', _id: string, fro export type DiffSummariesQueryVariables = Exact<{ databaseName: Scalars['String']['input']; - fromCommitId: Scalars['String']['input']; - toCommitId: Scalars['String']['input']; + fromRefName: Scalars['String']['input']; + toRefName: Scalars['String']['input']; refName?: InputMaybe; + type?: InputMaybe; }>; @@ -1721,15 +1725,16 @@ export type DiffStatQueryHookResult = ReturnType; export type DiffStatLazyQueryHookResult = ReturnType; export type DiffStatQueryResult = Apollo.QueryResult; export const RowDiffsDocument = gql` - query RowDiffs($databaseName: String!, $tableName: String!, $fromCommitId: String!, $toCommitId: String!, $refName: String, $offset: Int, $filterByRowType: DiffRowType) { + query RowDiffs($databaseName: String!, $tableName: String!, $fromRefName: String!, $toRefName: String!, $refName: String, $offset: Int, $filterByRowType: DiffRowType, $type: CommitDiffType) { rowDiffs( databaseName: $databaseName tableName: $tableName - fromCommitId: $fromCommitId - toCommitId: $toCommitId + fromRefName: $fromRefName + toRefName: $toRefName refName: $refName offset: $offset filterByRowType: $filterByRowType + type: $type ) { ...RowDiffListWithCols } @@ -1750,11 +1755,12 @@ export const RowDiffsDocument = gql` * variables: { * databaseName: // value for 'databaseName' * tableName: // value for 'tableName' - * fromCommitId: // value for 'fromCommitId' - * toCommitId: // value for 'toCommitId' + * fromRefName: // value for 'fromRefName' + * toRefName: // value for 'toRefName' * refName: // value for 'refName' * offset: // value for 'offset' * filterByRowType: // value for 'filterByRowType' + * type: // value for 'type' * }, * }); */ @@ -1770,12 +1776,12 @@ export type RowDiffsQueryHookResult = ReturnType; export type RowDiffsLazyQueryHookResult = ReturnType; export type RowDiffsQueryResult = Apollo.QueryResult; export const SchemaDiffDocument = gql` - query SchemaDiff($databaseName: String!, $tableName: String!, $fromCommitId: String!, $toCommitId: String!, $refName: String) { + query SchemaDiff($databaseName: String!, $tableName: String!, $fromRefName: String!, $toRefName: String!, $refName: String) { schemaDiff( databaseName: $databaseName tableName: $tableName - fromCommitId: $fromCommitId - toCommitId: $toCommitId + fromRefName: $fromRefName + toRefName: $toRefName refName: $refName ) { ...SchemaDiff @@ -1797,8 +1803,8 @@ export const SchemaDiffDocument = gql` * variables: { * databaseName: // value for 'databaseName' * tableName: // value for 'tableName' - * fromCommitId: // value for 'fromCommitId' - * toCommitId: // value for 'toCommitId' + * fromRefName: // value for 'fromRefName' + * toRefName: // value for 'toRefName' * refName: // value for 'refName' * }, * }); @@ -2734,12 +2740,13 @@ export type RowsForDataTableQueryHookResult = ReturnType; export type RowsForDataTableQueryQueryResult = Apollo.QueryResult; export const DiffSummariesDocument = gql` - query DiffSummaries($databaseName: String!, $fromCommitId: String!, $toCommitId: String!, $refName: String) { + query DiffSummaries($databaseName: String!, $fromRefName: String!, $toRefName: String!, $refName: String, $type: CommitDiffType) { diffSummaries( databaseName: $databaseName - fromRefName: $fromCommitId - toRefName: $toCommitId + fromRefName: $fromRefName + toRefName: $toRefName refName: $refName + type: $type ) { ...DiffSummary } @@ -2759,9 +2766,10 @@ export const DiffSummariesDocument = gql` * const { data, loading, error } = useDiffSummariesQuery({ * variables: { * databaseName: // value for 'databaseName' - * fromCommitId: // value for 'fromCommitId' - * toCommitId: // value for 'toCommitId' + * fromRefName: // value for 'fromRefName' + * toRefName: // value for 'toRefName' * refName: // value for 'refName' + * type: // value for 'type' * }, * }); */ diff --git a/packages/web/lib/params.ts b/packages/web/lib/params.ts index ce274079..721e3ac1 100644 --- a/packages/web/lib/params.ts +++ b/packages/web/lib/params.ts @@ -49,6 +49,13 @@ export type CommitsParams = { export type RequiredCommitsParams = DatabaseParams & Required; +export type RefsParams = { + fromRefName: string; + toRefName: string; +}; + +export type RequiredRefsParams = DatabaseParams & RefsParams; + export type DiffParams = RefParams & CommitsParams; export type UploadParams = DatabaseParams & { @@ -63,3 +70,8 @@ export type DiffParamsWithRefs = DatabaseParams & { fromRefName: string; toRefName: string; }; + +export type PullParams = OptionalRefParams & { + fromBranchName?: string; + toBranchName?: string; +}; diff --git a/packages/web/lib/refetchQueries.ts b/packages/web/lib/refetchQueries.ts index d5f176a8..e82d5344 100644 --- a/packages/web/lib/refetchQueries.ts +++ b/packages/web/lib/refetchQueries.ts @@ -9,7 +9,7 @@ import * as gen from "@gen/graphql-types"; import { DatabaseParams, RefParams, - RequiredCommitsParams, + RequiredRefsParams, TableParams, } from "./params"; @@ -47,20 +47,16 @@ export const refetchResetChangesQueries = ( variables: RefParams, isDolt = false, ): RefetchQueries => { - const diffVariables: RequiredCommitsParams = { + const diffVariables: RequiredRefsParams = { ...variables, - fromCommitId: "HEAD", - toCommitId: "WORKING", + fromRefName: "HEAD", + toRefName: "WORKING", }; return [ ...(isDolt ? [{ query: gen.GetStatusDocument, variables }] : []), { query: gen.DiffStatDocument, - variables: { - ...variables, - fromRefName: diffVariables.fromCommitId, - toRefName: diffVariables.toCommitId, - }, + variables: diffVariables, }, { query: gen.DiffSummariesDocument, diff --git a/packages/web/lib/urls.ts b/packages/web/lib/urls.ts index bce608c9..bcba5f72 100644 --- a/packages/web/lib/urls.ts +++ b/packages/web/lib/urls.ts @@ -83,6 +83,15 @@ function getDiffRange(p: ps.DiffParams): string { export const releases = (p: ps.OptionalRefParams): Route => database(p).addStatic("releases").withQuery({ refName: p.refName }); +export const pulls = (p: ps.PullParams): Route => + database(p) + .addStatic("pulls") + .withQuery({ + refName: p.refName, + from: p.fromBranchName, + to: p.toBranchName, + }); + export const newRelease = (p: ps.OptionalRefParams): Route => releases(p).addStatic("new").withQuery({ refName: p.refName }); diff --git a/packages/web/pages/database/[databaseName]/pulls/index.tsx b/packages/web/pages/database/[databaseName]/pulls/index.tsx new file mode 100644 index 00000000..5d205b0a --- /dev/null +++ b/packages/web/pages/database/[databaseName]/pulls/index.tsx @@ -0,0 +1,46 @@ +import Page from "@components/util/Page"; +import Maybe from "@lib/Maybe"; +import { DatabaseParams, MaybeRefParams } from "@lib/params"; +import DatabasePage from "@pageComponents/DatabasePage"; +import { GetServerSideProps, NextPage } from "next"; + +type Props = { + params: MaybeRefParams & { + from?: Maybe; + to?: Maybe; + }; + tableName?: Maybe; +}; + +const PullsPage: NextPage = ({ params, tableName }) => ( + + + +); + +export const getServerSideProps: GetServerSideProps = async ({ + params, + query, +}) => { + return { + props: { + params: { + ...(params as DatabaseParams), + refName: query.refName ? String(query.refName) : null, + from: query.from ? String(query.from) : null, + to: query.to ? String(query.to) : null, + }, + tableName: query.tableName ? String(query.tableName) : null, + }, + }; +}; + +export default PullsPage; From fc1fc07b8f35892377f9770d17154b205ea2b4bc Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 11:23:52 -0800 Subject: [PATCH 02/13] graphql,web: Fix schema diffs --- .../src/rowDiffs/rowDiff.resolver.ts | 7 ++-- .../src/schemaDiffs/schemaDiff.model.ts | 23 +++++++++++++ .../src/schemaDiffs/schemaDiff.queries.ts | 4 +++ .../src/schemaDiffs/schemaDiff.resolver.ts | 34 ++++++++++--------- .../components/DiffTable/SchemaSection.tsx | 4 ++- packages/web/components/DiffTable/queries.ts | 2 ++ packages/web/gen/graphql-types.tsx | 5 ++- 7 files changed, 56 insertions(+), 23 deletions(-) diff --git a/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts b/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts index 500f9ab2..e18696cc 100644 --- a/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts +++ b/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts @@ -80,14 +80,11 @@ export class RowDiffResolver { ); const { tableType, fromTableName, toTableName } = ds[0]; - console.log("from", args.fromRefName, "to", args.toRefName); - console.log("DIFF TYPE", ds[0]); if (tableType === TableDiffType.Dropped) { - // console.log("dropped", tableName, args.fromRefName); const rows = await getRowsForDiff(query, { ...dbArgs, tableName, - refName: args.toRefName, + refName: toCommitId, }); return fromOneSidedTable(rows, "dropped", args.filterByRowType); } @@ -95,7 +92,7 @@ export class RowDiffResolver { const rows = await getRowsForDiff(query, { ...dbArgs, tableName, - refName: args.fromRefName, + refName: fromCommitId, }); return fromOneSidedTable(rows, "added", args.filterByRowType); } diff --git a/packages/graphql-server/src/schemaDiffs/schemaDiff.model.ts b/packages/graphql-server/src/schemaDiffs/schemaDiff.model.ts index 75697cff..5913fc07 100644 --- a/packages/graphql-server/src/schemaDiffs/schemaDiff.model.ts +++ b/packages/graphql-server/src/schemaDiffs/schemaDiff.model.ts @@ -1,4 +1,5 @@ import { Field, Int, ObjectType } from "@nestjs/graphql"; +import { RawRows } from "../utils/commonTypes"; @ObjectType() export class TextDiff { @@ -20,3 +21,25 @@ export class SchemaDiff { @Field(_type => Int, { nullable: true }) numChangedSchemas?: number; } + +function fromSchemaPatchRows(res: RawRows): string[] { + return res.map(r => r.statement); +} + +function fromSchemaDiffRows(res: RawRows): TextDiff | undefined { + if (!res.length) return undefined; + return { + leftLines: res[0].from_create_statement, + rightLines: res[0].to_create_statement, + }; +} + +export function fromDoltSchemaDiffRows( + patch: RawRows, + diff: RawRows, +): SchemaDiff { + return { + schemaDiff: fromSchemaDiffRows(diff), + schemaPatch: fromSchemaPatchRows(patch), + }; +} diff --git a/packages/graphql-server/src/schemaDiffs/schemaDiff.queries.ts b/packages/graphql-server/src/schemaDiffs/schemaDiff.queries.ts index 45eda8c0..a4dfdee2 100644 --- a/packages/graphql-server/src/schemaDiffs/schemaDiff.queries.ts +++ b/packages/graphql-server/src/schemaDiffs/schemaDiff.queries.ts @@ -1,3 +1,7 @@ export const schemaPatchQuery = `SELECT * FROM DOLT_PATCH(?, ?, ?) WHERE diff_type="schema"`; +export const threeDotSchemaPatchQuery = `SELECT * FROM DOLT_PATCH(?, ?) WHERE diff_type="schema"`; + export const schemaDiffQuery = `SELECT * FROM DOLT_SCHEMA_DIFF(?, ?, ?)`; + +export const threeDotSchemaDiffQuery = `SELECT * FROM DOLT_SCHEMA_DIFF(?, ?)`; diff --git a/packages/graphql-server/src/schemaDiffs/schemaDiff.resolver.ts b/packages/graphql-server/src/schemaDiffs/schemaDiff.resolver.ts index 97bf58cb..5addbe89 100644 --- a/packages/graphql-server/src/schemaDiffs/schemaDiff.resolver.ts +++ b/packages/graphql-server/src/schemaDiffs/schemaDiff.resolver.ts @@ -2,8 +2,12 @@ import { Args, ArgsType, Field, Query, Resolver } from "@nestjs/graphql"; import { DataSourceService } from "../dataSources/dataSource.service"; import { CommitDiffType } from "../diffSummaries/diffSummary.enums"; import { DBArgs } from "../utils/commonTypes"; -import { SchemaDiff } from "./schemaDiff.model"; -import { schemaDiffQuery, schemaPatchQuery } from "./schemaDiff.queries"; +import { SchemaDiff, fromDoltSchemaDiffRows } from "./schemaDiff.model"; +import { + schemaDiffQuery, + schemaPatchQuery, + threeDotSchemaPatchQuery, +} from "./schemaDiff.queries"; @ArgsType() class SchemaDiffArgs extends DBArgs { @@ -33,22 +37,20 @@ export class SchemaDiffResolver { ): Promise { return this.dss.query( async query => { - const commitArgs = [args.fromRefName, args.toRefName, args.tableName]; - const res = await query(schemaPatchQuery, commitArgs); - const schemaPatch = res.map(r => r.statement); + if (args.type === CommitDiffType.ThreeDot) { + const commitArgs = [ + `${args.toRefName}...${args.fromRefName}`, + args.tableName, + ]; + const patchRes = await query(threeDotSchemaPatchQuery, commitArgs); + const diffRes = await query(schemaDiffQuery, commitArgs); + return fromDoltSchemaDiffRows(patchRes, diffRes); + } + const commitArgs = [args.fromRefName, args.toRefName, args.tableName]; + const patchRes = await query(schemaPatchQuery, commitArgs); const diffRes = await query(schemaDiffQuery, commitArgs); - const schemaDiff = diffRes.length - ? { - leftLines: diffRes[0].from_create_statement, - rightLines: diffRes[0].to_create_statement, - } - : undefined; - - return { - schemaDiff, - schemaPatch, - }; + return fromDoltSchemaDiffRows(patchRes, diffRes); }, args.databaseName, args.refName, diff --git a/packages/web/components/DiffTable/SchemaSection.tsx b/packages/web/components/DiffTable/SchemaSection.tsx index 4d89b15e..40d78e50 100644 --- a/packages/web/components/DiffTable/SchemaSection.tsx +++ b/packages/web/components/DiffTable/SchemaSection.tsx @@ -1,6 +1,7 @@ import QueryHandler from "@components/util/QueryHandler"; import { useDiffContext } from "@contexts/diff"; import { + CommitDiffType, DiffSummaryFragment, SchemaDiffFragment, useSchemaDiffQuery, @@ -36,11 +37,12 @@ function Inner({ schemaDiff }: InnerProps) { } export default function SchemaSection(props: Props) { - const { params } = useDiffContext(); + const { params, forPull } = useDiffContext(); const res = useSchemaDiffQuery({ variables: { ...params, tableName: props.diffSummary.tableName, + type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, }, }); return ( diff --git a/packages/web/components/DiffTable/queries.ts b/packages/web/components/DiffTable/queries.ts index 4728cacb..475aeb99 100644 --- a/packages/web/components/DiffTable/queries.ts +++ b/packages/web/components/DiffTable/queries.ts @@ -76,6 +76,7 @@ export const SCHEMA_DIFF = gql` $fromRefName: String! $toRefName: String! $refName: String + $type: CommitDiffType ) { schemaDiff( databaseName: $databaseName @@ -83,6 +84,7 @@ export const SCHEMA_DIFF = gql` fromRefName: $fromRefName toRefName: $toRefName refName: $refName + type: $type ) { ...SchemaDiff } diff --git a/packages/web/gen/graphql-types.tsx b/packages/web/gen/graphql-types.tsx index cabf81f9..d67c72dc 100644 --- a/packages/web/gen/graphql-types.tsx +++ b/packages/web/gen/graphql-types.tsx @@ -698,6 +698,7 @@ export type SchemaDiffQueryVariables = Exact<{ fromRefName: Scalars['String']['input']; toRefName: Scalars['String']['input']; refName?: InputMaybe; + type?: InputMaybe; }>; @@ -1776,13 +1777,14 @@ export type RowDiffsQueryHookResult = ReturnType; export type RowDiffsLazyQueryHookResult = ReturnType; export type RowDiffsQueryResult = Apollo.QueryResult; export const SchemaDiffDocument = gql` - query SchemaDiff($databaseName: String!, $tableName: String!, $fromRefName: String!, $toRefName: String!, $refName: String) { + query SchemaDiff($databaseName: String!, $tableName: String!, $fromRefName: String!, $toRefName: String!, $refName: String, $type: CommitDiffType) { schemaDiff( databaseName: $databaseName tableName: $tableName fromRefName: $fromRefName toRefName: $toRefName refName: $refName + type: $type ) { ...SchemaDiff } @@ -1806,6 +1808,7 @@ export const SchemaDiffDocument = gql` * fromRefName: // value for 'fromRefName' * toRefName: // value for 'toRefName' * refName: // value for 'refName' + * type: // value for 'type' * }, * }); */ From aba6a2e85ea4efc7628ff333843408fb3bc1f2ae Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 11:55:40 -0800 Subject: [PATCH 03/13] web,graphql: Prettier, correct commits --- .../graphql-server/src/rowDiffs/rowDiff.resolver.ts | 10 +++++----- packages/web/lib/urls.ts | 12 +++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts b/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts index e18696cc..271772e2 100644 --- a/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts +++ b/packages/graphql-server/src/rowDiffs/rowDiff.resolver.ts @@ -84,7 +84,7 @@ export class RowDiffResolver { const rows = await getRowsForDiff(query, { ...dbArgs, tableName, - refName: toCommitId, + refName: fromCommitId, }); return fromOneSidedTable(rows, "dropped", args.filterByRowType); } @@ -92,7 +92,7 @@ export class RowDiffResolver { const rows = await getRowsForDiff(query, { ...dbArgs, tableName, - refName: fromCommitId, + refName: toCommitId, }); return fromOneSidedTable(rows, "added", args.filterByRowType); } @@ -153,10 +153,10 @@ async function resolveRefs( type?: CommitDiffType, ): Promise<{ fromCommitId: string; toCommitId: string }> { if (type === CommitDiffType.ThreeDot) { - const fromCommitId = await query(hashOf, [fromRefName]); - const toCommitId = await query(mergeBase, [toRefName, fromRefName]); + const toCommitId = await query(hashOf, [fromRefName]); + const mergeBaseCommit = await query(mergeBase, [toRefName, fromRefName]); return { - fromCommitId: Object.values(fromCommitId[0])[0], + fromCommitId: Object.values(mergeBaseCommit[0])[0], toCommitId: Object.values(toCommitId[0])[0], }; } diff --git a/packages/web/lib/urls.ts b/packages/web/lib/urls.ts index bcba5f72..87685ee8 100644 --- a/packages/web/lib/urls.ts +++ b/packages/web/lib/urls.ts @@ -84,13 +84,11 @@ export const releases = (p: ps.OptionalRefParams): Route => database(p).addStatic("releases").withQuery({ refName: p.refName }); export const pulls = (p: ps.PullParams): Route => - database(p) - .addStatic("pulls") - .withQuery({ - refName: p.refName, - from: p.fromBranchName, - to: p.toBranchName, - }); + database(p).addStatic("pulls").withQuery({ + refName: p.refName, + from: p.fromBranchName, + to: p.toBranchName, + }); export const newRelease = (p: ps.OptionalRefParams): Route => releases(p).addStatic("new").withQuery({ refName: p.refName }); From 3fb2eb16d6314901f9da9867ed6768af0ff51568 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 12:11:30 -0800 Subject: [PATCH 04/13] web: Clean up --- .../DiffSelector/BranchSelectForm/index.tsx | 8 ++----- packages/web/components/DiffStat/index.tsx | 13 +++--------- .../DiffTable/DataDiff/ViewSqlLink.tsx | 3 ++- .../components/DiffTable/DataDiff/index.tsx | 8 +++---- .../DiffTable/DataDiff/useRowDiffs.ts | 3 +-- .../DiffTable/DiffTableStats/index.tsx | 10 +++------ .../DiffTable/DiffTableStats/utils.test.ts | 3 ++- .../DiffTable/DiffTableStats/utils.ts | 21 ++++++++++++------- .../components/DiffTable/SchemaSection.tsx | 5 ++--- .../DiffTableNav/DiffTableStats/TableStat.tsx | 5 ++--- .../DiffTableStats/index.module.css | 2 +- packages/web/contexts/diff/index.tsx | 12 +++++------ 12 files changed, 40 insertions(+), 53 deletions(-) diff --git a/packages/web/components/DiffSelector/BranchSelectForm/index.tsx b/packages/web/components/DiffSelector/BranchSelectForm/index.tsx index 307ba859..f83dfe59 100644 --- a/packages/web/components/DiffSelector/BranchSelectForm/index.tsx +++ b/packages/web/components/DiffSelector/BranchSelectForm/index.tsx @@ -30,9 +30,7 @@ function Inner(props: InnerProps) { label="Base branch" onChange={b => { const p = pulls({ ...props.params, toBranchName: b }); - router - .push(p.href, p.as, { shallow: true }) - .catch(console.error); + router.push(p.href, p.as).catch(console.error); }} />
@@ -46,9 +44,7 @@ function Inner(props: InnerProps) { label="From branch" onChange={b => { const p = pulls({ ...props.params, fromBranchName: b }); - router - .push(p.href, p.as, { shallow: true }) - .catch(console.error); + router.push(p.href, p.as).catch(console.error); }} />
diff --git a/packages/web/components/DiffStat/index.tsx b/packages/web/components/DiffStat/index.tsx index 484f02c9..68577530 100644 --- a/packages/web/components/DiffStat/index.tsx +++ b/packages/web/components/DiffStat/index.tsx @@ -1,11 +1,7 @@ import { ApolloError } from "@apollo/client"; import ErrorMsg from "@components/ErrorMsg"; import { useDiffContext } from "@contexts/diff"; -import { - CommitDiffType, - DiffStatForDiffsFragment, - useDiffStatQuery, -} from "@gen/graphql-types"; +import { DiffStatForDiffsFragment, useDiffStatQuery } from "@gen/graphql-types"; import { gqlErrorPrimaryKeyChange } from "@lib/errors/graphql"; import { errorMatches } from "@lib/errors/helpers"; import { DiffParamsWithRefs } from "@lib/params"; @@ -48,12 +44,9 @@ function Inner(props: InnerProps) { } export default function DiffStat(props: Props) { - const { forPull } = useDiffContext(); + const { type } = useDiffContext(); const { data, loading, error } = useDiffStatQuery({ - variables: { - ...props.params, - type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, - }, + variables: { ...props.params, type }, }); return ( diff --git a/packages/web/components/DiffTable/DataDiff/ViewSqlLink.tsx b/packages/web/components/DiffTable/DataDiff/ViewSqlLink.tsx index 3b5a109c..5f9457a0 100644 --- a/packages/web/components/DiffTable/DataDiff/ViewSqlLink.tsx +++ b/packages/web/components/DiffTable/DataDiff/ViewSqlLink.tsx @@ -3,6 +3,7 @@ import SmallLoader from "@components/SmallLoader"; import Link from "@components/links/Link"; import { ColumnForDataTableFragment, + CommitDiffType, useDataTableQuery, } from "@gen/graphql-types"; import { RequiredRefsParams } from "@lib/params"; @@ -18,7 +19,7 @@ type Props = { tableName: string; }; hiddenColIndexes: HiddenColIndexes; - forPull?: boolean; + type?: CommitDiffType; }; type InnerProps = Props & { diff --git a/packages/web/components/DiffTable/DataDiff/index.tsx b/packages/web/components/DiffTable/DataDiff/index.tsx index 297fb58a..b18e26f4 100644 --- a/packages/web/components/DiffTable/DataDiff/index.tsx +++ b/packages/web/components/DiffTable/DataDiff/index.tsx @@ -55,7 +55,7 @@ function Inner(props: InnerProps) { // For diff tables we want to use `refName` from `useDiffContext`, which is either the `fromBranchName` // for PR diffs or the current ref for commit diffs - const { refName, forPull } = useDiffContext(); + const { refName, type } = useDiffContext(); const res = useDataTableContext(); return ( @@ -66,7 +66,7 @@ function Inner(props: InnerProps) { showingHideUnchangedCol={hideUnchangedCols} className={css.optionButton} > - +
@@ -124,10 +124,10 @@ function Inner(props: InnerProps) { } export default function DataDiff(props: Props) { - const { forPull } = useDiffContext(); + const { type } = useDiffContext(); const { state, fetchMore, setFilter, hasMore, loading } = useRowDiffs( props.params, - forPull, + type, ); if (loading) return ; diff --git a/packages/web/components/DiffTable/DataDiff/useRowDiffs.ts b/packages/web/components/DiffTable/DataDiff/useRowDiffs.ts index 6a7bc320..93406a77 100644 --- a/packages/web/components/DiffTable/DataDiff/useRowDiffs.ts +++ b/packages/web/components/DiffTable/DataDiff/useRowDiffs.ts @@ -31,9 +31,8 @@ type Params = RequiredRefsParams & { export default function useRowDiffs( params: Params, - forPull = false, + type: CommitDiffType, ): ReturnType { - const type = forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot; const { data, client, loading, error } = useRowDiffsQuery({ variables: { ...params, type }, }); diff --git a/packages/web/components/DiffTable/DiffTableStats/index.tsx b/packages/web/components/DiffTable/DiffTableStats/index.tsx index 1b5c9f09..fbc67cb6 100644 --- a/packages/web/components/DiffTable/DiffTableStats/index.tsx +++ b/packages/web/components/DiffTable/DiffTableStats/index.tsx @@ -1,11 +1,7 @@ import ErrorMsg from "@components/ErrorMsg"; import SmallLoader from "@components/SmallLoader"; import { useDiffContext } from "@contexts/diff"; -import { - CommitDiffType, - DiffSummaryFragment, - useDiffStatQuery, -} from "@gen/graphql-types"; +import { DiffSummaryFragment, useDiffStatQuery } from "@gen/graphql-types"; import { gqlErrorPrimaryKeyChange } from "@lib/errors/graphql"; import { errorMatches } from "@lib/errors/helpers"; import cx from "classnames"; @@ -18,13 +14,13 @@ type Props = { }; export default function DiffTableStats(props: Props) { - const { params, refName, forPull } = useDiffContext(); + const { params, refName, type } = useDiffContext(); const { data, loading, error } = useDiffStatQuery({ variables: { ...params, refName, tableName: props.diffSummary.tableName, - type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, + type, }, }); diff --git a/packages/web/components/DiffTable/DiffTableStats/utils.test.ts b/packages/web/components/DiffTable/DiffTableStats/utils.test.ts index cf04973e..2b111d4e 100644 --- a/packages/web/components/DiffTable/DiffTableStats/utils.test.ts +++ b/packages/web/components/DiffTable/DiffTableStats/utils.test.ts @@ -1,3 +1,4 @@ +import { CommitDiffType } from "@gen/graphql-types"; import { params, tableCols } from "./mocks"; import { getDoltCommitDiffQuery } from "./utils"; @@ -32,7 +33,7 @@ describe("test getDoltCommitDiffQuery for diff tables", () => { params, columns: tableCols, hiddenColIndexes: [1], - forPull: true, + type: CommitDiffType.ThreeDot, }), ).toEqual( `SELECT diff_type, \`from_id\`, \`to_id\`, from_commit, from_commit_date, to_commit, to_commit_date FROM \`dolt_commit_diff_${params.tableName}\` WHERE from_commit="${params.fromRefName}" AND to_commit=DOLT_MERGE_BASE("${params.toRefName}", "${params.fromRefName}")`, diff --git a/packages/web/components/DiffTable/DiffTableStats/utils.ts b/packages/web/components/DiffTable/DiffTableStats/utils.ts index 2c17089e..fd0d1d1d 100644 --- a/packages/web/components/DiffTable/DiffTableStats/utils.ts +++ b/packages/web/components/DiffTable/DiffTableStats/utils.ts @@ -1,5 +1,5 @@ import { getAllSelectColumns } from "@components/CellButtons/queryHelpers"; -import { ColumnForDataTableFragment } from "@gen/graphql-types"; +import { ColumnForDataTableFragment, CommitDiffType } from "@gen/graphql-types"; import { RefsParams, RequiredRefsParams } from "@lib/params"; import { isHiddenColumn } from "../DataDiff/utils"; @@ -8,7 +8,7 @@ type Props = { refName: string; tableName: string; }; - forPull?: boolean; + type?: CommitDiffType; columns: ColumnForDataTableFragment[]; hiddenColIndexes: number[]; }; @@ -25,14 +25,19 @@ export function getDoltCommitDiffQuery(props: Props): string { const cols = getAllSelectColumns(colsWithNamesAndVals); return `SELECT ${cols} FROM \`dolt_commit_diff_${ props.params.tableName - }\`${getWhereClause(props.params, props.forPull)}`; + }\`${getWhereClause(props.params, props.type)}`; } -function getWhereClause(params: RefsParams, forPull = false): string { - const toCommit = forPull - ? `DOLT_MERGE_BASE("${params.toRefName}", "${params.fromRefName}")` - : `"${params.toRefName}"`; - return ` WHERE from_commit="${params.fromRefName}" AND to_commit=${toCommit}`; +function getWhereClause(params: RefsParams, type?: CommitDiffType): string { + const fromCommit = + type === CommitDiffType.ThreeDot + ? `DOLT_MERGE_BASE("${params.toRefName}", "${params.fromRefName}")` + : `"${params.fromRefName}"`; + const toCommit = + type === CommitDiffType.ThreeDot + ? `HASHOF("${params.fromRefName}")` + : `"${params.toRefName}"`; + return ` WHERE from_commit=${fromCommit} AND to_commit=${toCommit}`; } // Get names and values for every column based on row value and dolt_commit_diff table diff --git a/packages/web/components/DiffTable/SchemaSection.tsx b/packages/web/components/DiffTable/SchemaSection.tsx index 40d78e50..7a410e16 100644 --- a/packages/web/components/DiffTable/SchemaSection.tsx +++ b/packages/web/components/DiffTable/SchemaSection.tsx @@ -1,7 +1,6 @@ import QueryHandler from "@components/util/QueryHandler"; import { useDiffContext } from "@contexts/diff"; import { - CommitDiffType, DiffSummaryFragment, SchemaDiffFragment, useSchemaDiffQuery, @@ -37,12 +36,12 @@ function Inner({ schemaDiff }: InnerProps) { } export default function SchemaSection(props: Props) { - const { params, forPull } = useDiffContext(); + const { params, type } = useDiffContext(); const res = useSchemaDiffQuery({ variables: { ...params, tableName: props.diffSummary.tableName, - type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, + type, }, }); return ( diff --git a/packages/web/components/DiffTableNav/DiffTableStats/TableStat.tsx b/packages/web/components/DiffTableNav/DiffTableStats/TableStat.tsx index 64034b94..b00b8d3c 100644 --- a/packages/web/components/DiffTableNav/DiffTableStats/TableStat.tsx +++ b/packages/web/components/DiffTableNav/DiffTableStats/TableStat.tsx @@ -3,7 +3,6 @@ import ErrorMsg from "@components/ErrorMsg"; import SmallLoader from "@components/SmallLoader"; import { useDiffContext } from "@contexts/diff"; import { - CommitDiffType, DiffStatForDiffsFragment, DiffSummaryFragment, TableDiffType, @@ -78,12 +77,12 @@ function Inner({ diffStat, diffSummary, loading, error }: InnerProps) { } export default function TableStat(props: Props) { - const { forPull } = useDiffContext(); + const { type } = useDiffContext(); const res = useDiffStatQuery({ variables: { ...props.params, tableName: props.diffSummary.tableName, - type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, + type, }, }); return ( diff --git a/packages/web/components/DiffTableNav/DiffTableStats/index.module.css b/packages/web/components/DiffTableNav/DiffTableStats/index.module.css index 677cf8d7..bf93f789 100644 --- a/packages/web/components/DiffTableNav/DiffTableStats/index.module.css +++ b/packages/web/components/DiffTableNav/DiffTableStats/index.module.css @@ -1,5 +1,5 @@ .list { - @apply mb-8 lg:mb-20; + @apply mb-8 lg:mb-40; } .tableInfo { diff --git a/packages/web/contexts/diff/index.tsx b/packages/web/contexts/diff/index.tsx index ffa2d274..125fb30a 100644 --- a/packages/web/contexts/diff/index.tsx +++ b/packages/web/contexts/diff/index.tsx @@ -28,7 +28,7 @@ type DiffContextType = { refName: string; setRefName: (r: string) => void; stayWithinPage: boolean; // Changing tables within diff doesn't change URL - forPull: boolean; + type: CommitDiffType; }; export const DiffContext = createCustomContext("DiffContext"); @@ -41,15 +41,13 @@ export function DiffProvider({ stayWithinPage = false, forPull = false, }: Props): JSX.Element { + const type = forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot; const [activeTableName, setActiveTableName] = useState( initialTableName ?? "", ); const [refName, setRefName] = useState(params.refName ?? ""); const { data, error, loading } = useDiffSummariesQuery({ - variables: { - ...params, - type: forPull ? CommitDiffType.ThreeDot : CommitDiffType.TwoDot, - }, + variables: { ...params, type }, }); useEffect(() => { @@ -69,7 +67,7 @@ export function DiffProvider({ refName, setRefName, stayWithinPage, - forPull, + type, }; }, [ data, @@ -81,7 +79,7 @@ export function DiffProvider({ refName, setRefName, stayWithinPage, - forPull, + type, ]); return {children}; From 44609ae34336b46035857072b193c5cff11539a5 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 13:06:32 -0800 Subject: [PATCH 05/13] web,graphql: Add pull commits --- packages/graphql-server/schema.gql | 2 +- .../src/commits/commit.queries.ts | 2 + .../src/commits/commit.resolver.ts | 39 +++++++------ .../BranchSelectForm/index.module.css | 2 +- .../web/components/DiffStat/index.module.css | 4 ++ packages/web/components/DiffStat/index.tsx | 5 ++ .../DiffTableStats/index.module.css | 6 +- .../web/components/DiffTableNav/ForPull.tsx | 18 +++--- .../DiffTableNav/PullCommits/index.module.css | 20 +++++++ .../DiffTableNav/PullCommits/index.tsx | 58 +++++++++++++++++++ .../DiffTableNav/PullCommits/queries.ts | 20 +++++++ .../web/components/DiffTableNav/component.tsx | 2 + packages/web/gen/graphql-types.tsx | 55 ++++++++++++++++++ 13 files changed, 203 insertions(+), 30 deletions(-) create mode 100644 packages/web/components/DiffTableNav/PullCommits/index.module.css create mode 100644 packages/web/components/DiffTableNav/PullCommits/index.tsx create mode 100644 packages/web/components/DiffTableNav/PullCommits/queries.ts diff --git a/packages/graphql-server/schema.gql b/packages/graphql-server/schema.gql index c5b1a71c..8c6a9b7a 100644 --- a/packages/graphql-server/schema.gql +++ b/packages/graphql-server/schema.gql @@ -229,7 +229,7 @@ type Query { branchOrDefault(databaseName: String!, branchName: String): Branch branches(databaseName: String!, sortBy: SortBranchesBy): BranchNamesList! defaultBranch(databaseName: String!): Branch - commits(offset: Int, databaseName: String!, refName: String, afterCommitId: String): CommitList! + commits(offset: Int, databaseName: String!, refName: String, afterCommitId: String, twoDot: Boolean, excludingCommitsFromRefName: String): CommitList! currentDatabase: String hasDatabaseEnv: Boolean! databases: [String!]! diff --git a/packages/graphql-server/src/commits/commit.queries.ts b/packages/graphql-server/src/commits/commit.queries.ts index 72f0a8a5..32227ac8 100644 --- a/packages/graphql-server/src/commits/commit.queries.ts +++ b/packages/graphql-server/src/commits/commit.queries.ts @@ -1 +1,3 @@ export const doltLogsQuery = `SELECT * FROM DOLT_LOG(?, '--parents') LIMIT ? OFFSET ?`; + +export const twoDotDoltLogsQuery = `SELECT * FROM DOLT_LOG(?, '--parents')`; diff --git a/packages/graphql-server/src/commits/commit.resolver.ts b/packages/graphql-server/src/commits/commit.resolver.ts index 9ce0aaf1..0fbb9fbd 100644 --- a/packages/graphql-server/src/commits/commit.resolver.ts +++ b/packages/graphql-server/src/commits/commit.resolver.ts @@ -3,7 +3,7 @@ import { DataSourceService } from "../dataSources/dataSource.service"; import { ROW_LIMIT, getNextOffset } from "../utils"; import { DBArgsWithOffset, RawRow } from "../utils/commonTypes"; import { Commit, CommitList, fromDoltLogRow } from "./commit.model"; -import { doltLogsQuery } from "./commit.queries"; +import { doltLogsQuery, twoDotDoltLogsQuery } from "./commit.queries"; @ArgsType() export class ListCommitsArgs extends DBArgsWithOffset { @@ -14,14 +14,11 @@ export class ListCommitsArgs extends DBArgsWithOffset { @Field({ nullable: true }) afterCommitId?: string; - // @Field(_type => Boolean, { nullable: true }) - // twoDot?: boolean; + @Field(_type => Boolean, { nullable: true }) + twoDot?: boolean; - // @Field({ nullable: true }) - // excludingCommitsFromRefName?: string; - - // @Field(_type => Boolean, { nullable: true }) - // resolveBranchNames?: boolean; + @Field({ nullable: true }) + excludingCommitsFromRefName?: string; } @Resolver(_of => Commit) @@ -38,6 +35,12 @@ export class CommitResolver { const refName = args.refName ?? args.afterCommitId ?? ""; const offset = args.offset ?? 0; return this.dss.query(async query => { + if (args.twoDot && args.excludingCommitsFromRefName) { + const logs = await query(twoDotDoltLogsQuery, [ + `${args.excludingCommitsFromRefName}..${refName}`, + ]); + return getCommitListRes(logs, args); + } const logs = await query(doltLogsQuery, [refName, ROW_LIMIT + 1, offset]); return getCommitListRes(logs, args); }, args.databaseName); @@ -64,15 +67,15 @@ function handleArgsErr(args: ListCommitsArgs): Error | undefined { "cannot supply both `refName` and `afterCommitId` when listing commits", ); } - // if (args.twoDot && !args.excludingCommitsFromRefName) { - // return new Error( - // "must supply `excludingCommitsFromRefName` if twoDot is true", - // ); - // } - // if (!args.twoDot && args.excludingCommitsFromRefName) { - // return new Error( - // "cannot supply `excludingCommitsFromRefName` if twoDot is not provided or false", - // ); - // } + if (args.twoDot && !args.excludingCommitsFromRefName) { + return new Error( + "must supply `excludingCommitsFromRefName` if twoDot is true", + ); + } + if (!args.twoDot && args.excludingCommitsFromRefName) { + return new Error( + "cannot supply `excludingCommitsFromRefName` if twoDot is not provided or false", + ); + } return undefined; } diff --git a/packages/web/components/DiffSelector/BranchSelectForm/index.module.css b/packages/web/components/DiffSelector/BranchSelectForm/index.module.css index 2ce9538d..eb846566 100644 --- a/packages/web/components/DiffSelector/BranchSelectForm/index.module.css +++ b/packages/web/components/DiffSelector/BranchSelectForm/index.module.css @@ -3,7 +3,7 @@ } .selectors { - @apply flex flex-col items-start mb-10; + @apply flex flex-col items-start mb-12; } .selector { diff --git a/packages/web/components/DiffStat/index.module.css b/packages/web/components/DiffStat/index.module.css index efa2fa9e..9fc71a1b 100644 --- a/packages/web/components/DiffStat/index.module.css +++ b/packages/web/components/DiffStat/index.module.css @@ -34,3 +34,7 @@ .primaryKeyChange { @apply text-primary font-normal; } + +.noChanges { + @apply mx-3 mt-4; +} diff --git a/packages/web/components/DiffStat/index.tsx b/packages/web/components/DiffStat/index.tsx index 68577530..5beae2a5 100644 --- a/packages/web/components/DiffStat/index.tsx +++ b/packages/web/components/DiffStat/index.tsx @@ -24,6 +24,11 @@ type InnerProps = Props & { function Inner(props: InnerProps) { const { diffSummaries } = useDiffContext(); const isPrimaryKeyChange = errorMatches(gqlErrorPrimaryKeyChange, props.err); + + if (!diffSummaries.length) { + return

No changes to show

; + } + return (
); } + + const params = { + ...props.params, + fromRefName: props.params.fromBranchName, + toRefName: props.params.toBranchName, + }; return ( - } + diffStat={} diffTables={} + diffCommits={} forPull /> ); diff --git a/packages/web/components/DiffTableNav/PullCommits/index.module.css b/packages/web/components/DiffTableNav/PullCommits/index.module.css new file mode 100644 index 00000000..3487c47b --- /dev/null +++ b/packages/web/components/DiffTableNav/PullCommits/index.module.css @@ -0,0 +1,20 @@ +.container { + @apply mx-3; + + h4, + p { + @apply my-4; + } + + li { + @apply mb-5; + } +} + +.hash { + @apply text-sm block font-mono text-ld-darkgrey; +} + +.message { + @apply text-sm; +} diff --git a/packages/web/components/DiffTableNav/PullCommits/index.tsx b/packages/web/components/DiffTableNav/PullCommits/index.tsx new file mode 100644 index 00000000..7d4bb9d5 --- /dev/null +++ b/packages/web/components/DiffTableNav/PullCommits/index.tsx @@ -0,0 +1,58 @@ +import QueryHandler from "@components/util/QueryHandler"; +import { + CommitForHistoryFragment, + usePullCommitsQuery, +} from "@gen/graphql-types"; +import excerpt from "@lib/excerpt"; +import { DiffParamsWithRefs } from "@lib/params"; +import css from "./index.module.css"; + +type Props = { + params: DiffParamsWithRefs & { refName?: string }; +}; + +type InnerProps = Props & { + commits: CommitForHistoryFragment[]; +}; + +function Inner(props: InnerProps) { + return ( +
+ {props.commits.length ? ( +
    + {props.commits.map(c => ( +
  • + {c.commitId} + {excerpt(c.message, 100)} +
  • + ))} +
+ ) : ( +

+ {props.params.toRefName} is up to date with commits from{" "} + {props.params.fromRefName} +

+ )} +
+ ); +} + +export default function PullCommits(props: Props) { + const res = usePullCommitsQuery({ + variables: { + ...props.params, + refName: props.params.fromRefName, + excludingCommitsFromRefName: props.params.toRefName, + }, + }); + + return ( +
+

Commits

+ } + /> +
+ ); +} diff --git a/packages/web/components/DiffTableNav/PullCommits/queries.ts b/packages/web/components/DiffTableNav/PullCommits/queries.ts new file mode 100644 index 00000000..2fec6ed6 --- /dev/null +++ b/packages/web/components/DiffTableNav/PullCommits/queries.ts @@ -0,0 +1,20 @@ +import { gql } from "@apollo/client"; + +export const PULL_COMMITS = gql` + query PullCommits( + $databaseName: String! + $refName: String! + $excludingCommitsFromRefName: String! + ) { + commits( + databaseName: $databaseName + refName: $refName + excludingCommitsFromRefName: $excludingCommitsFromRefName + twoDot: true + ) { + list { + ...CommitForHistory + } + } + } +`; diff --git a/packages/web/components/DiffTableNav/component.tsx b/packages/web/components/DiffTableNav/component.tsx index ffa21c4a..f63528ab 100644 --- a/packages/web/components/DiffTableNav/component.tsx +++ b/packages/web/components/DiffTableNav/component.tsx @@ -16,6 +16,7 @@ type Props = { diffTables?: ReactNode; white?: boolean; forPull?: boolean; + diffCommits?: ReactNode; }; export default function DiffTableNav({ white = false, ...props }: Props) { @@ -53,6 +54,7 @@ export default function DiffTableNav({ white = false, ...props }: Props) { {props.diffStat}
{props.diffTables} + {props.diffCommits}
); diff --git a/packages/web/gen/graphql-types.tsx b/packages/web/gen/graphql-types.tsx index d67c72dc..32138290 100644 --- a/packages/web/gen/graphql-types.tsx +++ b/packages/web/gen/graphql-types.tsx @@ -306,8 +306,10 @@ export type QueryBranchesArgs = { export type QueryCommitsArgs = { afterCommitId?: InputMaybe; databaseName: Scalars['String']['input']; + excludingCommitsFromRefName?: InputMaybe; offset?: InputMaybe; refName?: InputMaybe; + twoDot?: InputMaybe; }; @@ -704,6 +706,15 @@ export type SchemaDiffQueryVariables = Exact<{ export type SchemaDiffQuery = { __typename?: 'Query', schemaDiff?: { __typename?: 'SchemaDiff', schemaPatch?: Array | null, schemaDiff?: { __typename?: 'TextDiff', leftLines: string, rightLines: string } | null } | null }; +export type PullCommitsQueryVariables = Exact<{ + databaseName: Scalars['String']['input']; + refName: Scalars['String']['input']; + excludingCommitsFromRefName: Scalars['String']['input']; +}>; + + +export type PullCommitsQuery = { __typename?: 'Query', commits: { __typename?: 'CommitList', list: Array<{ __typename?: 'Commit', _id: string, message: string, commitId: string, committedAt: any, parents: Array, committer: { __typename?: 'DoltWriter', _id: string, username?: string | null, displayName: string, emailAddress: string } }> } }; + export type ColumnsListForTableListFragment = { __typename?: 'IndexColumn', name: string, sqlType?: string | null }; export type IndexForTableListFragment = { __typename?: 'Index', name: string, type: string, comment: string, columns: Array<{ __typename?: 'IndexColumn', name: string, sqlType?: string | null }> }; @@ -1823,6 +1834,50 @@ export function useSchemaDiffLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions export type SchemaDiffQueryHookResult = ReturnType; export type SchemaDiffLazyQueryHookResult = ReturnType; export type SchemaDiffQueryResult = Apollo.QueryResult; +export const PullCommitsDocument = gql` + query PullCommits($databaseName: String!, $refName: String!, $excludingCommitsFromRefName: String!) { + commits( + databaseName: $databaseName + refName: $refName + excludingCommitsFromRefName: $excludingCommitsFromRefName + twoDot: true + ) { + list { + ...CommitForHistory + } + } +} + ${CommitForHistoryFragmentDoc}`; + +/** + * __usePullCommitsQuery__ + * + * To run a query within a React component, call `usePullCommitsQuery` and pass it any options that fit your needs. + * When your component renders, `usePullCommitsQuery` 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 } = usePullCommitsQuery({ + * variables: { + * databaseName: // value for 'databaseName' + * refName: // value for 'refName' + * excludingCommitsFromRefName: // value for 'excludingCommitsFromRefName' + * }, + * }); + */ +export function usePullCommitsQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(PullCommitsDocument, options); + } +export function usePullCommitsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(PullCommitsDocument, options); + } +export type PullCommitsQueryHookResult = ReturnType; +export type PullCommitsLazyQueryHookResult = ReturnType; +export type PullCommitsQueryResult = Apollo.QueryResult; export const TableListForSchemasDocument = gql` query TableListForSchemas($databaseName: String!, $refName: String!) { tables(databaseName: $databaseName, refName: $refName, filterSystemTables: true) { From d7d59331dfba760b4ee1ac08defac7f0a1de52c8 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 13:09:14 -0800 Subject: [PATCH 06/13] web: Fix test --- packages/web/components/DiffTable/DiffTableStats/utils.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/components/DiffTable/DiffTableStats/utils.test.ts b/packages/web/components/DiffTable/DiffTableStats/utils.test.ts index 2b111d4e..a13c2c1a 100644 --- a/packages/web/components/DiffTable/DiffTableStats/utils.test.ts +++ b/packages/web/components/DiffTable/DiffTableStats/utils.test.ts @@ -36,7 +36,7 @@ describe("test getDoltCommitDiffQuery for diff tables", () => { type: CommitDiffType.ThreeDot, }), ).toEqual( - `SELECT diff_type, \`from_id\`, \`to_id\`, from_commit, from_commit_date, to_commit, to_commit_date FROM \`dolt_commit_diff_${params.tableName}\` WHERE from_commit="${params.fromRefName}" AND to_commit=DOLT_MERGE_BASE("${params.toRefName}", "${params.fromRefName}")`, + `SELECT diff_type, \`from_id\`, \`to_id\`, from_commit, from_commit_date, to_commit, to_commit_date FROM \`dolt_commit_diff_${params.tableName}\` WHERE from_commit=DOLT_MERGE_BASE("${params.toRefName}", "${params.fromRefName}") AND to_commit=HASHOF("${params.fromRefName}")`, ); }); }); From e519f483bb0e4ab3b8a9216ccc9705c376d1f28e Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 14:32:01 -0800 Subject: [PATCH 07/13] web,graphql: Separate pull and diff pages --- packages/graphql-server/package.json | 1 + packages/graphql-server/schema.gql | 37 +++++ .../src/pullDetails/getPullDetails.ts | 90 +++++++++++ .../src/pullDetails/pullDetail.model.ts | 60 +++++++ .../src/pullSummaries/pullSummary.model.ts | 21 +++ .../graphql-server/src/pulls/pull.enums.ts | 9 ++ .../graphql-server/src/pulls/pull.model.ts | 37 +++++ .../graphql-server/src/pulls/pull.resolver.ts | 31 ++++ packages/graphql-server/src/resolvers.ts | 2 + packages/web/codegen.yml | 7 +- .../BranchSelectForm/index.module.css | 15 -- .../web/components/DiffSelector/ForPull.tsx | 13 +- .../components/DiffTableNav/BackButton.tsx | 40 +++-- .../web/components/DiffTableNav/ForPull.tsx | 6 +- .../web/components/DiffTableNav/component.tsx | 2 - .../PullStateLabel/index.module.css | 14 ++ .../components/PullStateLabel/index.test.tsx | 24 +++ .../web/components/PullStateLabel/index.tsx | 20 +++ packages/web/components/links/PullLink.tsx | 17 ++ .../DatabasePage/ForPullDiff/index.tsx | 43 +++++ .../BranchSelectForm/BranchSelect.tsx | 1 - .../BranchSelectForm/index.module.css | 11 ++ .../ForPulls}/BranchSelectForm/index.tsx | 2 +- .../ForPulls/PullCommit/index.module.css | 83 ++++++++++ .../ForPulls/PullCommit/index.tsx | 50 ++++++ .../PullCommitSummary/index.module.css | 28 ++++ .../ForPulls/PullCommitSummary/index.tsx | 25 +++ .../ForPulls/PullDetailsList/index.module.css | 19 +++ .../ForPulls/PullDetailsList/index.tsx | 55 +++++++ .../DatabasePage/ForPulls/index.module.css | 7 + .../DatabasePage/ForPulls/index.tsx | 141 +++++++++++------ .../DatabasePage/ForPulls/queries.ts | 46 ++++++ .../pageComponents/DatabasePage/index.tsx | 2 + packages/web/gen/fragmentTypes.json | 8 + packages/web/gen/graphql-types.tsx | 148 ++++++++++++++++++ packages/web/lib/apollo.tsx | 3 +- packages/web/lib/enumKeys.test.ts | 18 +++ packages/web/lib/enumKeys.ts | 26 +++ packages/web/lib/params.ts | 10 ++ packages/web/lib/urls.ts | 11 +- packages/web/package.json | 1 + .../[fromBranchName]/[toBranchName]/index.tsx | 43 +++++ .../database/[databaseName]/pulls/index.tsx | 5 +- yarn.lock | 14 ++ 44 files changed, 1148 insertions(+), 98 deletions(-) create mode 100644 packages/graphql-server/src/pullDetails/getPullDetails.ts create mode 100644 packages/graphql-server/src/pullDetails/pullDetail.model.ts create mode 100644 packages/graphql-server/src/pullSummaries/pullSummary.model.ts create mode 100644 packages/graphql-server/src/pulls/pull.enums.ts create mode 100644 packages/graphql-server/src/pulls/pull.model.ts create mode 100644 packages/graphql-server/src/pulls/pull.resolver.ts delete mode 100644 packages/web/components/DiffSelector/BranchSelectForm/index.module.css create mode 100644 packages/web/components/PullStateLabel/index.module.css create mode 100644 packages/web/components/PullStateLabel/index.test.tsx create mode 100644 packages/web/components/PullStateLabel/index.tsx create mode 100644 packages/web/components/links/PullLink.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx rename packages/web/components/{DiffSelector => pageComponents/DatabasePage/ForPulls}/BranchSelectForm/BranchSelect.tsx (98%) create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.module.css rename packages/web/components/{DiffSelector => pageComponents/DatabasePage/ForPulls}/BranchSelectForm/index.tsx (98%) create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommit/index.module.css create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommit/index.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommitSummary/index.module.css create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommitSummary/index.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/queries.ts create mode 100644 packages/web/gen/fragmentTypes.json create mode 100644 packages/web/lib/enumKeys.test.ts create mode 100644 packages/web/lib/enumKeys.ts create mode 100644 packages/web/pages/database/[databaseName]/pulls/compare/[fromBranchName]/[toBranchName]/index.tsx diff --git a/packages/graphql-server/package.json b/packages/graphql-server/package.json index ab60b700..5ea12cc4 100644 --- a/packages/graphql-server/package.json +++ b/packages/graphql-server/package.json @@ -41,6 +41,7 @@ "mysql2": "^3.1.0", "reflect-metadata": "^0.1.13", "rxjs": "^7.5.4", + "timeago.js": "^4.0.2", "typeorm": "^0.3.12" }, "devDependencies": { diff --git a/packages/graphql-server/schema.gql b/packages/graphql-server/schema.gql index 8c6a9b7a..757301c9 100644 --- a/packages/graphql-server/schema.gql +++ b/packages/graphql-server/schema.gql @@ -149,6 +149,42 @@ type DocList { list: [Doc!]! } +type PullSummary { + _id: ID! + commits: CommitList! +} + +type PullWithDetails { + _id: ID! + state: PullState! + summary: PullSummary + details: [PullDetails!] +} + +enum PullState { + Open + Merged + Unspecified +} + +union PullDetails = PullDetailSummary | PullDetailCommit + +type PullDetailSummary { + _id: ID! + username: String! + createdAt: Timestamp! + numCommits: Float! +} + +type PullDetailCommit { + _id: ID! + username: String! + message: String! + createdAt: Timestamp! + commitId: String! + parentCommitId: String +} + type RowDiff { added: Row deleted: Row @@ -238,6 +274,7 @@ type Query { diffSummaries(databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, type: CommitDiffType, tableName: String): [DiffSummary!]! docs(databaseName: String!, refName: String!): DocList! docOrDefaultDoc(refName: String!, databaseName: String!, docType: DocType): Doc + pullWithDetails(databaseName: String!, fromBranchName: String!, toBranchName: String!): PullWithDetails! rowDiffs(offset: Int, databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, filterByRowType: DiffRowType, type: CommitDiffType): RowDiffList! rows(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/packages/graphql-server/src/pullDetails/getPullDetails.ts b/packages/graphql-server/src/pullDetails/getPullDetails.ts new file mode 100644 index 00000000..b87d902d --- /dev/null +++ b/packages/graphql-server/src/pullDetails/getPullDetails.ts @@ -0,0 +1,90 @@ +import { format } from "timeago.js"; +import { Commit } from "../commits/commit.model"; +import { PullSummary } from "../pullSummaries/pullSummary.model"; +import { + PullDetailCommit, + PullDetails, + PullDetailSummary, + PullDetailUnion, +} from "./pullDetail.model"; + +type PullDetail = typeof PullDetailUnion; + +export default function getPullDetails(summary?: PullSummary): PullDetails { + const details: PullDetails = []; + if (!summary) { + return details; + } + // Add commits to details + summary.commits.list.forEach(c => details.push(getCommit(c))); + // Get commit summaries from sorted commits + const sorted = details.sort(sortByTimestampDesc); + const summaries = getSummaries(sorted); + return sorted.concat(summaries).sort(sortByTimestampDesc) as PullDetails; +} + +function sortByTimestampDesc(a: PullDetail, b: PullDetail) { + return a.createdAt.valueOf() - b.createdAt.valueOf(); +} + +function getCommit(c: Commit): PullDetailCommit { + const parentCommitId = c.parents.length ? c.parents[0] : undefined; + return { + ...c, + username: c.committer.username ?? c.committer.displayName, + createdAt: c.committedAt, + parentCommitId, + }; +} + +const initialSummary: PullDetailSummary = { + _id: "", + username: "", + createdAt: new Date(0), + numCommits: 0, +}; + +function getSummaries(sorted: PullDetail[]): PullDetailSummary[] { + const summaries: PullDetailSummary[] = []; + let summary = { ...initialSummary }; + + sorted.forEach(d => { + // Only update summary for commits + if ("commitId" in d) { + const timeagosEqual = format(d.createdAt) === format(summary.createdAt); + const needToUpdate = d.username !== summary.username || !timeagosEqual; + + if (needToUpdate) { + // Push last summary if it has commit info + if (summary.numCommits > 0) { + summaries.push({ ...summary }); + } + // Update summary with changed information + summary = { + ...summary, + _id: `${d.username}/${d.createdAt.valueOf()}`, + username: d.username, + numCommits: 0, + // Ensure that the summary shows up before first commit + createdAt: new Date(d.createdAt.valueOf() - 1), + }; + } + // Update number of commits every time + summary.numCommits += 1; + } else { + // If not commit, push last summary + if (summary.numCommits > 0) { + summaries.push({ ...summary }); + } + // And start fresh + summary = { ...initialSummary }; + } + }); + + // If last summary not pushed yet, push + if (summary.numCommits > 0) { + summaries.push({ ...summary }); + } + + return summaries; +} diff --git a/packages/graphql-server/src/pullDetails/pullDetail.model.ts b/packages/graphql-server/src/pullDetails/pullDetail.model.ts new file mode 100644 index 00000000..65308f53 --- /dev/null +++ b/packages/graphql-server/src/pullDetails/pullDetail.model.ts @@ -0,0 +1,60 @@ +import { + Field, + GraphQLTimestamp, + ID, + ObjectType, + createUnionType, +} from "@nestjs/graphql"; + +@ObjectType() +export class PullDetailCommit { + @Field(_type => ID) + _id: string; + + @Field() + username: string; + + @Field() + message: string; + + @Field(_type => GraphQLTimestamp) + createdAt: Date; + + @Field() + commitId: string; + + @Field({ nullable: true }) + parentCommitId?: string; +} + +@ObjectType() +export class PullDetailSummary { + @Field(_type => ID) + _id: string; + + @Field() + username: string; + + @Field(_type => GraphQLTimestamp) + createdAt: Date; + + @Field() + numCommits: number; +} + +export const PullDetailUnion = createUnionType({ + name: "PullDetails", + types: () => [PullDetailSummary, PullDetailCommit], + resolveType: value => { + if ("commitId" in value) { + return PullDetailCommit; + } + if ("numCommits" in value) { + return PullDetailSummary; + } + return undefined; + }, +}); + +export type PullDetail = typeof PullDetailUnion; +export type PullDetails = PullDetail[]; diff --git a/packages/graphql-server/src/pullSummaries/pullSummary.model.ts b/packages/graphql-server/src/pullSummaries/pullSummary.model.ts new file mode 100644 index 00000000..6c0d0b87 --- /dev/null +++ b/packages/graphql-server/src/pullSummaries/pullSummary.model.ts @@ -0,0 +1,21 @@ +import { Field, ID, ObjectType } from "@nestjs/graphql"; +import * as commit from "../commits/commit.model"; + +@ObjectType() +export class PullSummary { + @Field(_type => ID) + _id: string; + + @Field(_type => commit.CommitList) + commits: commit.CommitList; +} + +export function fromAPISummary( + _pullId: string, + commits: commit.Commit[], +): PullSummary { + return { + _id: `${_pullId}/summary`, + commits: { list: commits }, + }; +} diff --git a/packages/graphql-server/src/pulls/pull.enums.ts b/packages/graphql-server/src/pulls/pull.enums.ts new file mode 100644 index 00000000..0d9f8b14 --- /dev/null +++ b/packages/graphql-server/src/pulls/pull.enums.ts @@ -0,0 +1,9 @@ +import { registerEnumType } from "@nestjs/graphql"; + +export enum PullState { + Open, + Merged, + Unspecified, +} + +registerEnumType(PullState, { name: "PullState" }); diff --git a/packages/graphql-server/src/pulls/pull.model.ts b/packages/graphql-server/src/pulls/pull.model.ts new file mode 100644 index 00000000..6bc462c5 --- /dev/null +++ b/packages/graphql-server/src/pulls/pull.model.ts @@ -0,0 +1,37 @@ +import { Field, ID, ObjectType } from "@nestjs/graphql"; +import { Commit } from "../commits/commit.model"; +import getPullDetails from "../pullDetails/getPullDetails"; +import { PullDetailUnion, PullDetails } from "../pullDetails/pullDetail.model"; +import { + PullSummary, + fromAPISummary, +} from "../pullSummaries/pullSummary.model"; +import { PullState } from "./pull.enums"; + +@ObjectType() +export class PullWithDetails { + @Field(_type => ID) + _id: string; + + @Field(_type => PullState) + state: PullState; + + @Field(_type => PullSummary, { nullable: true }) + summary?: PullSummary; + + @Field(_type => [PullDetailUnion], { nullable: true }) + details?: PullDetails; +} + +export function fromAPIModelPullWithDetails( + pullId: string, + commits: Commit[] = [], +): PullWithDetails { + const summary = fromAPISummary(pullId, commits); + return { + _id: `${pullId}/pullWithDetails`, + state: commits.length ? PullState.Open : PullState.Merged, + summary, + details: getPullDetails(summary), + }; +} diff --git a/packages/graphql-server/src/pulls/pull.resolver.ts b/packages/graphql-server/src/pulls/pull.resolver.ts new file mode 100644 index 00000000..e86cef08 --- /dev/null +++ b/packages/graphql-server/src/pulls/pull.resolver.ts @@ -0,0 +1,31 @@ +import { Args, ArgsType, Field, Query, Resolver } from "@nestjs/graphql"; +import { CommitResolver } from "../commits/commit.resolver"; +import { DBArgs } from "../utils/commonTypes"; +import { PullWithDetails, fromAPIModelPullWithDetails } from "./pull.model"; + +@ArgsType() +class PullArgs extends DBArgs { + @Field() + fromBranchName: string; + + @Field() + toBranchName: string; +} + +@Resolver(_of => PullWithDetails) +export class PullResolver { + constructor(private readonly commitResolver: CommitResolver) {} + + @Query(_returns => PullWithDetails) + async pullWithDetails(@Args() args: PullArgs): Promise { + const name = `databases/${args.databaseName}/pulls/${args.fromBranchName}/${args.toBranchName}`; + const commits = await this.commitResolver.commits({ + ...args, + refName: args.fromBranchName, + excludingCommitsFromRefName: args.toBranchName, + twoDot: true, + }); + + return fromAPIModelPullWithDetails(name, commits.list); + } +} diff --git a/packages/graphql-server/src/resolvers.ts b/packages/graphql-server/src/resolvers.ts index f2414ce4..f92ffd35 100644 --- a/packages/graphql-server/src/resolvers.ts +++ b/packages/graphql-server/src/resolvers.ts @@ -4,6 +4,7 @@ import { DatabaseResolver } from "./databases/database.resolver"; import { DiffStatResolver } from "./diffStats/diffStat.resolver"; import { DiffSummaryResolver } from "./diffSummaries/diffSummary.resolver"; import { DocsResolver } from "./docs/doc.resolver"; +import { PullResolver } from "./pulls/pull.resolver"; import { RowDiffResolver } from "./rowDiffs/rowDiff.resolver"; import { RowResolver } from "./rows/row.resolver"; import { SchemaDiffResolver } from "./schemaDiffs/schemaDiff.resolver"; @@ -22,6 +23,7 @@ const resolvers = [ DiffSummaryResolver, DocsResolver, FileUploadResolver, + PullResolver, RowDiffResolver, RowResolver, SchemaDiffResolver, diff --git a/packages/web/codegen.yml b/packages/web/codegen.yml index 2eefd523..63c22d1f 100644 --- a/packages/web/codegen.yml +++ b/packages/web/codegen.yml @@ -12,4 +12,9 @@ generates: - "typescript" - "typescript-operations" - "typescript-react-apollo" - + gen/fragmentTypes.json: + plugins: + - "fragment-matcher" + config: + apolloClientVersion: 3 + \ No newline at end of file diff --git a/packages/web/components/DiffSelector/BranchSelectForm/index.module.css b/packages/web/components/DiffSelector/BranchSelectForm/index.module.css deleted file mode 100644 index eb846566..00000000 --- a/packages/web/components/DiffSelector/BranchSelectForm/index.module.css +++ /dev/null @@ -1,15 +0,0 @@ -.container { - @apply mx-4; -} - -.selectors { - @apply flex flex-col items-start mb-12; -} - -.selector { - @apply min-w-[225px]; -} - -.arrow { - @apply text-2xl mx-6 my-3 rotate-90; -} diff --git a/packages/web/components/DiffSelector/ForPull.tsx b/packages/web/components/DiffSelector/ForPull.tsx index 0332adb8..d98043e6 100644 --- a/packages/web/components/DiffSelector/ForPull.tsx +++ b/packages/web/components/DiffSelector/ForPull.tsx @@ -1,10 +1,15 @@ -import { PullParams } from "@lib/params"; -import BranchSelectForm from "./BranchSelectForm"; +import { PullDiffParams } from "@lib/params"; +import DiffSelector from "./component"; type Props = { - params: PullParams; + params: PullDiffParams; }; export default function ForPull(props: Props) { - return ; + return ( + + Viewing changes between {props.params.fromBranchName} and{" "} + {props.params.toBranchName} + + ); } diff --git a/packages/web/components/DiffTableNav/BackButton.tsx b/packages/web/components/DiffTableNav/BackButton.tsx index a6aafe9a..44b9f1a3 100644 --- a/packages/web/components/DiffTableNav/BackButton.tsx +++ b/packages/web/components/DiffTableNav/BackButton.tsx @@ -1,6 +1,7 @@ import Button from "@components/Button"; import Loader from "@components/Loader"; import CommitLogLink from "@components/links/CommitLogLink"; +import PullLink from "@components/links/PullLink"; import useDefaultBranch from "@hooks/useDefaultBranch"; import { DatabaseParams } from "@lib/params"; import { FaChevronLeft } from "@react-icons/all-files/fa/FaChevronLeft"; @@ -9,6 +10,8 @@ import css from "./index.module.css"; type Params = DatabaseParams & { refName?: string; + fromBranchName?: string; + toBranchName?: string; }; type Props = { @@ -19,24 +22,33 @@ type Props = { export default function BackButton(props: Props) { const { defaultBranchName, loading } = useDefaultBranch(props.params); - if (props.forPull) return
; return (
- - - - + {props.forPull ? ( + + + + ) : ( + + + + )}
); } diff --git a/packages/web/components/DiffTableNav/ForPull.tsx b/packages/web/components/DiffTableNav/ForPull.tsx index 3e34c2d9..c5bd3e4e 100644 --- a/packages/web/components/DiffTableNav/ForPull.tsx +++ b/packages/web/components/DiffTableNav/ForPull.tsx @@ -1,13 +1,12 @@ import DiffSelector from "@components/DiffSelector"; import DiffStat from "@components/DiffStat"; -import { PullParams } from "@lib/params"; +import { PullDiffParams } from "@lib/params"; import DiffTableStats from "./DiffTableStats"; -import PullCommits from "./PullCommits"; import DiffTableNav from "./component"; import css from "./index.module.css"; type Props = { - params: PullParams; + params: PullDiffParams; tableName?: string; }; @@ -40,7 +39,6 @@ export default function ForPull(props: Props) { diffSelector={selector} diffStat={} diffTables={} - diffCommits={} forPull /> ); diff --git a/packages/web/components/DiffTableNav/component.tsx b/packages/web/components/DiffTableNav/component.tsx index f63528ab..ffa21c4a 100644 --- a/packages/web/components/DiffTableNav/component.tsx +++ b/packages/web/components/DiffTableNav/component.tsx @@ -16,7 +16,6 @@ type Props = { diffTables?: ReactNode; white?: boolean; forPull?: boolean; - diffCommits?: ReactNode; }; export default function DiffTableNav({ white = false, ...props }: Props) { @@ -54,7 +53,6 @@ export default function DiffTableNav({ white = false, ...props }: Props) { {props.diffStat}
{props.diffTables} - {props.diffCommits} ); diff --git a/packages/web/components/PullStateLabel/index.module.css b/packages/web/components/PullStateLabel/index.module.css new file mode 100644 index 00000000..77c660fe --- /dev/null +++ b/packages/web/components/PullStateLabel/index.module.css @@ -0,0 +1,14 @@ +.state { + @apply inline-block rounded-full text-sm text-center mb-1 py-0.5 uppercase; + width: 4.5rem; +} + +.Open { + @apply text-acc-green; + background-color: #d8f5e6; +} + +.Merged { + @apply text-acc-pink; + background-color: #fae9fa; +} diff --git a/packages/web/components/PullStateLabel/index.test.tsx b/packages/web/components/PullStateLabel/index.test.tsx new file mode 100644 index 00000000..b1500663 --- /dev/null +++ b/packages/web/components/PullStateLabel/index.test.tsx @@ -0,0 +1,24 @@ +import { PullState } from "@gen/graphql-types"; +import enumKeys from "@lib/enumKeys"; +import { render, screen } from "@testing-library/react"; +import PullStateLabel from "."; + +const className = "some-class-name"; +const defaultState = PullState.Open; + +describe("test PullStateLabel", () => { + enumKeys(PullState).forEach(key => { + it(`displays the "${key}" pull state`, () => { + const state = PullState[key]; + render(); + // getByText will throw if the Pull State text is missing + screen.getByText(key); + }); + }); + + it("applies the given className", async () => { + render(); + const span = screen.getByText(defaultState); + expect(span).toHaveClass(className); + }); +}); diff --git a/packages/web/components/PullStateLabel/index.tsx b/packages/web/components/PullStateLabel/index.tsx new file mode 100644 index 00000000..c8193662 --- /dev/null +++ b/packages/web/components/PullStateLabel/index.tsx @@ -0,0 +1,20 @@ +import { PullState } from "@gen/graphql-types"; +import cx from "classnames"; +import css from "./index.module.css"; + +type Props = { + state?: PullState; + className?: string; +}; + +export default function PullStateLabel({ state, className }: Props) { + if (!state) return null; + return ( + + {state} + + ); +} diff --git a/packages/web/components/links/PullLink.tsx b/packages/web/components/links/PullLink.tsx new file mode 100644 index 00000000..16a72b53 --- /dev/null +++ b/packages/web/components/links/PullLink.tsx @@ -0,0 +1,17 @@ +import { PullParams } from "@lib/params"; +import { pulls } from "@lib/urls"; +import { ReactNode } from "react"; +import Link, { LinkProps } from "./Link"; + +type Props = LinkProps & { + children: ReactNode; + params: PullParams; +}; + +export default function PullLink({ children, ...props }: Props) { + return ( + + {children} + + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx new file mode 100644 index 00000000..5e7881de --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx @@ -0,0 +1,43 @@ +import DiffTable from "@components/DiffTable"; +import DiffTableNav from "@components/DiffTableNav"; +import PullsBreadcrumbs from "@components/breadcrumbs/PullsBreadcrumbs"; +import NotDoltWrapper from "@components/util/NotDoltWrapper"; +import { DiffProvider } from "@contexts/diff"; +import { RequiredPullDiffParams } from "@lib/params"; +import { pulls } from "@lib/urls"; +import ForDefaultBranch from "../ForDefaultBranch"; + +type Props = { + params: RequiredPullDiffParams & { refName?: string }; + tableName?: string; +}; + +export default function ForPullDiff(props: Props) { + return ( + + } + initialSmallHeader + leftTableNav={} + wide + hideDefaultTable + > + + + + + + ); +} diff --git a/packages/web/components/DiffSelector/BranchSelectForm/BranchSelect.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/BranchSelect.tsx similarity index 98% rename from packages/web/components/DiffSelector/BranchSelectForm/BranchSelect.tsx rename to packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/BranchSelect.tsx index 25289169..4d20133c 100644 --- a/packages/web/components/DiffSelector/BranchSelectForm/BranchSelect.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/BranchSelect.tsx @@ -23,7 +23,6 @@ export default function BranchSelect(props: Props) { hideSelectedOptions className={css.selector} label={props.label} - small horizontal /> ); diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.module.css new file mode 100644 index 00000000..85d20bc1 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.module.css @@ -0,0 +1,11 @@ +.selectors { + @apply flex items-center; +} + +.selector { + @apply min-w-[225px]; +} + +.arrow { + @apply text-2xl mx-6; +} diff --git a/packages/web/components/DiffSelector/BranchSelectForm/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.tsx similarity index 98% rename from packages/web/components/DiffSelector/BranchSelectForm/index.tsx rename to packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.tsx index f83dfe59..c9f40a38 100644 --- a/packages/web/components/DiffSelector/BranchSelectForm/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.tsx @@ -19,7 +19,7 @@ function Inner(props: InnerProps) { const router = useRouter(); return ( -
+
{props.branches.length ? (
diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommit/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommit/index.module.css new file mode 100644 index 00000000..07d1c57b --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommit/index.module.css @@ -0,0 +1,83 @@ +.commit { + @apply text-sm flex flex-col; + @screen lg { + @apply pl-14 justify-between pr-2 flex-row; + } + svg { + @apply min-w-[1.5rem] w-4 h-4 text-ld-darkgrey; + } +} + +.left { + @apply flex ml-4 lg:ml-0; + div { + @apply lg:my-0; + } +} + +.commitIcon { + @screen lg { + @apply hidden; + } +} + +.bull { + @apply text-acc-grey text-lg leading-tight; + @screen lg { + @apply hidden ml-[0.65rem]; + } + svg { + @apply inline w-6 h-5 mr-4; + } +} + +.desktopBull { + @apply hidden relative; + @screen lg { + @apply flex flex-col text-lg mr-4 leading-tight; + svg { + @apply inline h-12; + } + } +} + +.verticalLine { + @apply ml-3 border-l w-0 h-full; +} + +.mobileVerticalLine { + @apply -ml-1 mr-7 border-l w-0; + @screen lg { + @apply hidden; + } +} + +.message { + @apply font-mono text-xs mt-2 lg:mt-0; + /* break long line such as urls without breaking words*/ + -ms-word-break: break-all; + word-break: break-all; + /* Non standard for webkit */ + word-break: break-word; +} + +.date { + @apply block mt-2 text-ld-darkgrey font-mono text-xs whitespace-nowrap; +} + +.hash { + @apply text-ld-darkgrey font-normal text-xs font-mono; + @screen lg { + @apply ml-6 min-w-[4rem]; + } + &:hover { + @apply text-acc-linkblue; + } +} + +.desktop { + @apply hidden; + @screen lg { + @apply block; + } +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommit/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommit/index.tsx new file mode 100644 index 00000000..2490ca97 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommit/index.tsx @@ -0,0 +1,50 @@ +import Link from "@components/links/Link"; +import { PullDetailCommitFragment } from "@gen/graphql-types"; +import { longDateTimeString } from "@lib/dateConversions"; +import { PullDiffParams } from "@lib/params"; +import { diff } from "@lib/urls"; +import { IoGitCommitOutline } from "@react-icons/all-files/io5/IoGitCommitOutline"; +import cx from "classnames"; +import css from "./index.module.css"; + +type Props = { + commit: PullDetailCommitFragment; + params: PullDiffParams; +}; + +export default function PullCommit({ commit, params }: Props) { + const commitLink = diff({ + ...params, + refName: params.fromBranchName, + fromCommitId: commit.parentCommitId || "", + toCommitId: commit.commitId, + }); + const date = new Date(commit.createdAt); + + return ( +
  • + + + + {commit.commitId.substring(0, 7)} + + +
    +
    + + +
    + +
    + + {commit.message} + + {longDateTimeString(date)} +
    +
    + + {commit.commitId.substring(0, 7)} + +
  • + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommitSummary/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommitSummary/index.module.css new file mode 100644 index 00000000..1cf0a20f --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommitSummary/index.module.css @@ -0,0 +1,28 @@ +.summary { + @apply relative flex items-start text-sm text-ld-darkgrey pr-4; + @screen lg { + @apply ml-[3.25rem] pr-12; + } +} + +.right { + @apply inline-block leading-7 ml-4; +} + +.icon { + @apply w-7 h-7 inline-block rounded-full text-lg bg-ld-lightgrey flex-shrink-0 p-[0.35rem] md:p-[0.4rem]; + svg { + @apply w-4 h-4 text-ld-darkgrey; + } +} + +.user { + @apply mr-1 font-semibold; +} + +.mobileVerticalLine { + @apply left-3 h-full border-l w-0 -z-10 absolute; + @screen lg { + @apply hidden; + } +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommitSummary/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommitSummary/index.tsx new file mode 100644 index 00000000..b7d62e4e --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullCommitSummary/index.tsx @@ -0,0 +1,25 @@ +import { PullDetailSummaryFragment } from "@gen/graphql-types"; +import { pluralize } from "@lib/pluralize"; +import { RiGitRepositoryCommitsFill } from "@react-icons/all-files/ri/RiGitRepositoryCommitsFill"; +import TimeAgo from "react-timeago"; +import css from "./index.module.css"; + +type Props = { + summary: PullDetailSummaryFragment; +}; + +export default function PullCommitSummary({ summary }: Props) { + return ( +
  • + + + +
    +
    + {summary.username} added{" "} + {summary.numCommits} {pluralize(summary.numCommits, "commit")}{" "} + +
    +
  • + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css new file mode 100644 index 00000000..5b0fca19 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css @@ -0,0 +1,19 @@ +.list { + @apply max-w-3xl mx-0 break-words; + + li { + @apply my-0; + } + + @screen lg { + @apply mb-0 mx-auto border-b; + } +} + +.empty { + @apply text-center font-semibold; +} + +.verticalLine { + @apply border-l w-0 h-8 ml-3 lg:ml-[4.25rem]; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.tsx new file mode 100644 index 00000000..f075e41c --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.tsx @@ -0,0 +1,55 @@ +import ErrorMsg from "@components/ErrorMsg"; +import { + PullDetailCommitFragment, + PullDetailSummaryFragment, + PullDetailsFragment, +} from "@gen/graphql-types"; +import { PullDiffParams } from "@lib/params"; +import PullCommit from "../PullCommit"; +import PullCommitSummary from "../PullCommitSummary"; +import css from "./index.module.css"; + +type Props = { + params: PullDiffParams; +}; + +type InnerProps = Props & { + pullDetails: PullDetailsFragment; +}; + +export default function PullDetailsList({ pullDetails, params }: InnerProps) { + return pullDetails.details?.length ? ( +
      +
      + {pullDetails.details.map(c => ( + <> +
      {" "} + + + ))} +
      +
    + ) : ( +

    No details to display

    + ); +} + +type PullDetail = PullDetailCommitFragment | PullDetailSummaryFragment; + +type ListItemProps = { + item: PullDetail; + params: PullDiffParams; +}; + +function ListItem({ item, params }: ListItemProps) { + switch (item.__typename) { + case "PullDetailCommit": + return ; + case "PullDetailSummary": + return ; + default: + return ( + + ); + } +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css new file mode 100644 index 00000000..55d04ef7 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css @@ -0,0 +1,7 @@ +.top { + @apply flex justify-between items-center py-10 ml-6 mr-10 border-b; + + button { + @apply ml-6; + } +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx index 882bf620..77ce93a4 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx @@ -1,63 +1,104 @@ -import DiffTable from "@components/DiffTable"; -import DiffTableNav from "@components/DiffTableNav"; +import Button from "@components/Button"; +import PullStateLabel from "@components/PullStateLabel"; import PullsBreadcrumbs from "@components/breadcrumbs/PullsBreadcrumbs"; +import Link from "@components/links/Link"; import NotDoltWrapper from "@components/util/NotDoltWrapper"; -import { DiffProvider } from "@contexts/diff"; -import { PullParams } from "@lib/params"; -import { pulls } from "@lib/urls"; +import QueryHandler from "@components/util/QueryHandler"; +import { + PullState, + usePullDetailsForPullDetailsQuery, +} from "@gen/graphql-types"; +import { PullDiffParams, PullParams } from "@lib/params"; +import { pullDiff, pulls } from "@lib/urls"; +import { useEffect, useState } from "react"; import ForDefaultBranch from "../ForDefaultBranch"; +import BranchSelectForm from "./BranchSelectForm"; +import PullDetailsList from "./PullDetailsList"; +import css from "./index.module.css"; type Props = { params: PullParams; - tableName?: string; }; -export default function ForPulls(props: Props) { - if (!props.params.fromBranchName || !props.params.toBranchName) { - return ( - } - initialSmallHeader - leftTableNav={} - wide - hideDefaultTable - > - -
    Select branches to view pull request
    -
    -
    - ); - } +type BranchesProps = { + params: PullDiffParams; + setPullState: (s: PullState) => void; +}; + +function ForBranches(props: BranchesProps) { + const res = usePullDetailsForPullDetailsQuery({ variables: props.params }); + + console.log(res); + useEffect(() => { + if (!res.data) return; + props.setPullState(res.data.pullWithDetails.state); + }); + + return ( + ( + + )} + /> + ); +} + +function Inner(props: Props) { + const [pullState, setPullState] = useState(); + return ( +
    +
    + +
    + + {props.params.fromBranchName && props.params.toBranchName && ( + + + + )} +
    +
    + + {props.params.fromBranchName && props.params.toBranchName ? ( + + ) : ( +

    Select branches

    + )} +
    + ); +} + +export default function ForPulls(props: Props) { return ( - } + hideDefaultTable > - } - initialSmallHeader - leftTableNav={} - wide - hideDefaultTable - > - - - - - + + + + ); } diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/queries.ts b/packages/web/components/pageComponents/DatabasePage/ForPulls/queries.ts new file mode 100644 index 00000000..5ef87916 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/queries.ts @@ -0,0 +1,46 @@ +import { gql } from "@apollo/client"; + +export const PULL_DETAILS_FOR_PULL_DETAILS = gql` + fragment PullDetailCommit on PullDetailCommit { + _id + username + message + createdAt + commitId + parentCommitId + } + fragment PullDetailSummary on PullDetailSummary { + _id + username + createdAt + numCommits + } + fragment PullDetailsForPullDetails on PullDetails { + ... on PullDetailCommit { + ...PullDetailCommit + } + ... on PullDetailSummary { + ...PullDetailSummary + } + } + fragment PullDetails on PullWithDetails { + _id + state + details { + ...PullDetailsForPullDetails + } + } + query PullDetailsForPullDetails( + $databaseName: String! + $fromBranchName: String! + $toBranchName: String! + ) { + pullWithDetails( + databaseName: $databaseName + fromBranchName: $fromBranchName + toBranchName: $toBranchName + ) { + ...PullDetails + } + } +`; diff --git a/packages/web/components/pageComponents/DatabasePage/index.tsx b/packages/web/components/pageComponents/DatabasePage/index.tsx index 1334f28e..ed61fb11 100644 --- a/packages/web/components/pageComponents/DatabasePage/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/index.tsx @@ -4,6 +4,7 @@ import ForCommits from "./ForCommits"; import ForCreateTable from "./ForCreateTable"; import ForDefaultBranch from "./ForDefaultBranch"; import ForDocs from "./ForDocs"; +import ForPullDiff from "./ForPullDiff"; import ForPulls from "./ForPulls"; import ForQuery from "./ForQuery"; import ForRef from "./ForRef"; @@ -21,6 +22,7 @@ export default Object.assign(DatabasePage, { ForDocs, ForQuery, ForPulls, + ForPullDiff, ForRef, ForReleases, ForSchema, diff --git a/packages/web/gen/fragmentTypes.json b/packages/web/gen/fragmentTypes.json new file mode 100644 index 00000000..5cafff37 --- /dev/null +++ b/packages/web/gen/fragmentTypes.json @@ -0,0 +1,8 @@ +{ + "possibleTypes": { + "PullDetails": [ + "PullDetailCommit", + "PullDetailSummary" + ] + } +} \ No newline at end of file diff --git a/packages/web/gen/graphql-types.tsx b/packages/web/gen/graphql-types.tsx index 32138290..10bf5b02 100644 --- a/packages/web/gen/graphql-types.tsx +++ b/packages/web/gen/graphql-types.tsx @@ -253,6 +253,46 @@ export type MutationLoadDataFileArgs = { tableName: Scalars['String']['input']; }; +export type PullDetailCommit = { + __typename?: 'PullDetailCommit'; + _id: Scalars['ID']['output']; + commitId: Scalars['String']['output']; + createdAt: Scalars['Timestamp']['output']; + message: Scalars['String']['output']; + parentCommitId?: Maybe; + username: Scalars['String']['output']; +}; + +export type PullDetailSummary = { + __typename?: 'PullDetailSummary'; + _id: Scalars['ID']['output']; + createdAt: Scalars['Timestamp']['output']; + numCommits: Scalars['Float']['output']; + username: Scalars['String']['output']; +}; + +export type PullDetails = PullDetailCommit | PullDetailSummary; + +export enum PullState { + Merged = 'Merged', + Open = 'Open', + Unspecified = 'Unspecified' +} + +export type PullSummary = { + __typename?: 'PullSummary'; + _id: Scalars['ID']['output']; + commits: CommitList; +}; + +export type PullWithDetails = { + __typename?: 'PullWithDetails'; + _id: Scalars['ID']['output']; + details?: Maybe>; + state: PullState; + summary?: Maybe; +}; + export type Query = { __typename?: 'Query'; branch?: Maybe; @@ -270,6 +310,7 @@ export type Query = { doltProcedures: Array; doltSchemas: Array; hasDatabaseEnv: Scalars['Boolean']['output']; + pullWithDetails: PullWithDetails; rowDiffs: RowDiffList; rows: RowList; schemaDiff?: Maybe; @@ -363,6 +404,13 @@ export type QueryDoltSchemasArgs = { }; +export type QueryPullWithDetailsArgs = { + databaseName: Scalars['String']['input']; + fromBranchName: Scalars['String']['input']; + toBranchName: Scalars['String']['input']; +}; + + export type QueryRowDiffsArgs = { databaseName: Scalars['String']['input']; filterByRowType?: InputMaybe; @@ -884,6 +932,27 @@ export type DocPageQueryNoBranchQueryVariables = Exact<{ export type DocPageQueryNoBranchQuery = { __typename?: 'Query', branchOrDefault?: { __typename?: 'Branch', _id: string, branchName: string } | null }; +export type PullDetailCommitFragment = { __typename?: 'PullDetailCommit', _id: string, username: string, message: string, createdAt: any, commitId: string, parentCommitId?: string | null }; + +export type PullDetailSummaryFragment = { __typename?: 'PullDetailSummary', _id: string, username: string, createdAt: any, numCommits: number }; + +type PullDetailsForPullDetails_PullDetailCommit_Fragment = { __typename?: 'PullDetailCommit', _id: string, username: string, message: string, createdAt: any, commitId: string, parentCommitId?: string | null }; + +type PullDetailsForPullDetails_PullDetailSummary_Fragment = { __typename?: 'PullDetailSummary', _id: string, username: string, createdAt: any, numCommits: number }; + +export type PullDetailsForPullDetailsFragment = PullDetailsForPullDetails_PullDetailCommit_Fragment | PullDetailsForPullDetails_PullDetailSummary_Fragment; + +export type PullDetailsFragment = { __typename?: 'PullWithDetails', _id: string, state: PullState, details?: Array<{ __typename?: 'PullDetailCommit', _id: string, username: string, message: string, createdAt: any, commitId: string, parentCommitId?: string | null } | { __typename?: 'PullDetailSummary', _id: string, username: string, createdAt: any, numCommits: number }> | null }; + +export type PullDetailsForPullDetailsQueryVariables = Exact<{ + databaseName: Scalars['String']['input']; + fromBranchName: Scalars['String']['input']; + toBranchName: Scalars['String']['input']; +}>; + + +export type PullDetailsForPullDetailsQuery = { __typename?: 'Query', pullWithDetails: { __typename?: 'PullWithDetails', _id: string, state: PullState, details?: Array<{ __typename?: 'PullDetailCommit', _id: string, username: string, message: string, createdAt: any, commitId: string, parentCommitId?: string | null } | { __typename?: 'PullDetailSummary', _id: string, username: string, createdAt: any, numCommits: number }> | null } }; + export type RefPageQueryVariables = Exact<{ refName: Scalars['String']['input']; databaseName: Scalars['String']['input']; @@ -1282,6 +1351,44 @@ export const DocColumnValuesForDocPageFragmentDoc = gql` } } `; +export const PullDetailCommitFragmentDoc = gql` + fragment PullDetailCommit on PullDetailCommit { + _id + username + message + createdAt + commitId + parentCommitId +} + `; +export const PullDetailSummaryFragmentDoc = gql` + fragment PullDetailSummary on PullDetailSummary { + _id + username + createdAt + numCommits +} + `; +export const PullDetailsForPullDetailsFragmentDoc = gql` + fragment PullDetailsForPullDetails on PullDetails { + ... on PullDetailCommit { + ...PullDetailCommit + } + ... on PullDetailSummary { + ...PullDetailSummary + } +} + ${PullDetailCommitFragmentDoc} +${PullDetailSummaryFragmentDoc}`; +export const PullDetailsFragmentDoc = gql` + fragment PullDetails on PullWithDetails { + _id + state + details { + ...PullDetailsForPullDetails + } +} + ${PullDetailsForPullDetailsFragmentDoc}`; export const ColumnForDataTableFragmentDoc = gql` fragment ColumnForDataTable on Column { name @@ -2513,6 +2620,47 @@ export function useDocPageQueryNoBranchLazyQuery(baseOptions?: Apollo.LazyQueryH export type DocPageQueryNoBranchHookResult = ReturnType; export type DocPageQueryNoBranchLazyQueryHookResult = ReturnType; export type DocPageQueryNoBranchQueryResult = Apollo.QueryResult; +export const PullDetailsForPullDetailsDocument = gql` + query PullDetailsForPullDetails($databaseName: String!, $fromBranchName: String!, $toBranchName: String!) { + pullWithDetails( + databaseName: $databaseName + fromBranchName: $fromBranchName + toBranchName: $toBranchName + ) { + ...PullDetails + } +} + ${PullDetailsFragmentDoc}`; + +/** + * __usePullDetailsForPullDetailsQuery__ + * + * To run a query within a React component, call `usePullDetailsForPullDetailsQuery` and pass it any options that fit your needs. + * When your component renders, `usePullDetailsForPullDetailsQuery` 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 } = usePullDetailsForPullDetailsQuery({ + * variables: { + * databaseName: // value for 'databaseName' + * fromBranchName: // value for 'fromBranchName' + * toBranchName: // value for 'toBranchName' + * }, + * }); + */ +export function usePullDetailsForPullDetailsQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(PullDetailsForPullDetailsDocument, options); + } +export function usePullDetailsForPullDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(PullDetailsForPullDetailsDocument, options); + } +export type PullDetailsForPullDetailsQueryHookResult = ReturnType; +export type PullDetailsForPullDetailsLazyQueryHookResult = ReturnType; +export type PullDetailsForPullDetailsQueryResult = Apollo.QueryResult; export const RefPageQueryDocument = gql` query RefPageQuery($refName: String!, $databaseName: String!, $filterSystemTables: Boolean) { branch(databaseName: $databaseName, branchName: $refName) { diff --git a/packages/web/lib/apollo.tsx b/packages/web/lib/apollo.tsx index 330ffaef..ff7528dc 100644 --- a/packages/web/lib/apollo.tsx +++ b/packages/web/lib/apollo.tsx @@ -4,6 +4,7 @@ import { InMemoryCache, NormalizedCacheObject, } from "@apollo/client"; +import fragmentTypes from "@gen/fragmentTypes.json"; import { createUploadLink } from "apollo-upload-client"; import { IncomingMessage } from "http"; import fetch from "isomorphic-unfetch"; @@ -22,7 +23,7 @@ export function createApolloClient( }; const cache = new InMemoryCache({ - // possibleTypes: fragmentTypes.possibleTypes, + possibleTypes: fragmentTypes.possibleTypes, }).restore(initialState || {}); return new ApolloClient({ diff --git a/packages/web/lib/enumKeys.test.ts b/packages/web/lib/enumKeys.test.ts new file mode 100644 index 00000000..a444c7c5 --- /dev/null +++ b/packages/web/lib/enumKeys.test.ts @@ -0,0 +1,18 @@ +import enumKeys from "./enumKeys"; + +describe("test enumKeys", () => { + it("iterates through all keys in an enum", () => { + enum TestEnum { + Key1 = "value1", + Key2 = "value2", + Key3 = "value3", + } + + const keys = enumKeys(TestEnum); + const t = keys.map(k => TestEnum[k]); + + expect(t).toContain(TestEnum.Key1); + expect(t).toContain(TestEnum.Key2); + expect(t).toContain(TestEnum.Key3); + }); +}); diff --git a/packages/web/lib/enumKeys.ts b/packages/web/lib/enumKeys.ts new file mode 100644 index 00000000..4692455d --- /dev/null +++ b/packages/web/lib/enumKeys.ts @@ -0,0 +1,26 @@ +/** + * enumKeys takes an enum and returns an array of strongly typed keys. Useful to iterate over string enums. + * @param obj The enum + * @returns An array of strong typed keys + * @example + * + * enum MyEnum { + * Key1 = "value1", + * Key2 = "value2", + * Key3 = "value3" + * } + * + * // ks's type is ("Key1" || "Key2" || "Key3")[] + * const ks = enumKeys(MyEnum); + * + * // keys' type is MyEnum[] + * // Unfortunately, we can't do this inside enumKeys because there is no generic type constraint for enums. + * const keys = ks.map(k => MyEnum[k]) + */ +function enumKeys(obj: O): K[] { + return Object.keys(obj) + .filter(k => Number.isNaN(+k)) + .map(k => k as K); +} + +export default enumKeys; diff --git a/packages/web/lib/params.ts b/packages/web/lib/params.ts index 721e3ac1..248e1888 100644 --- a/packages/web/lib/params.ts +++ b/packages/web/lib/params.ts @@ -75,3 +75,13 @@ export type PullParams = OptionalRefParams & { fromBranchName?: string; toBranchName?: string; }; + +export type RequiredPullDiffParams = DatabaseParams & { + fromBranchName: string; + toBranchName: string; +}; + +export type PullDiffParams = RequiredPullDiffParams & { + refName?: string; + tableName?: string; +}; diff --git a/packages/web/lib/urls.ts b/packages/web/lib/urls.ts index 87685ee8..c49c13b5 100644 --- a/packages/web/lib/urls.ts +++ b/packages/web/lib/urls.ts @@ -83,13 +83,22 @@ function getDiffRange(p: ps.DiffParams): string { export const releases = (p: ps.OptionalRefParams): Route => database(p).addStatic("releases").withQuery({ refName: p.refName }); +const staticPulls = (p: ps.DatabaseParams) => database(p).addStatic("pulls"); + export const pulls = (p: ps.PullParams): Route => - database(p).addStatic("pulls").withQuery({ + staticPulls(p).withQuery({ refName: p.refName, from: p.fromBranchName, to: p.toBranchName, }); +export const pullDiff = (p: ps.PullDiffParams): Route => + staticPulls(p) + .addStatic("compare") + .addDynamic("fromBranchName", p.fromBranchName, ENCODE) + .addDynamic("toBranchName", p.toBranchName, ENCODE) + .withQuery({ refName: p.refName, tableName: p.tableName }); + export const newRelease = (p: ps.OptionalRefParams): Route => releases(p).addStatic("new").withQuery({ refName: p.refName }); diff --git a/packages/web/package.json b/packages/web/package.json index edcf6176..c26bdd42 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -58,6 +58,7 @@ }, "devDependencies": { "@graphql-codegen/cli": "^5.0.0", + "@graphql-codegen/fragment-matcher": "^5.0.0", "@graphql-codegen/typescript-operations": "^4.0.1", "@graphql-codegen/typescript-react-apollo": "^4.0.0", "@testing-library/dom": "^9.3.3", diff --git a/packages/web/pages/database/[databaseName]/pulls/compare/[fromBranchName]/[toBranchName]/index.tsx b/packages/web/pages/database/[databaseName]/pulls/compare/[fromBranchName]/[toBranchName]/index.tsx new file mode 100644 index 00000000..d7655a71 --- /dev/null +++ b/packages/web/pages/database/[databaseName]/pulls/compare/[fromBranchName]/[toBranchName]/index.tsx @@ -0,0 +1,43 @@ +import Page from "@components/util/Page"; +import Maybe from "@lib/Maybe"; +import { RequiredPullDiffParams } from "@lib/params"; +import DatabasePage from "@pageComponents/DatabasePage"; +import { GetServerSideProps, NextPage } from "next"; + +type Props = { + params: RequiredPullDiffParams & { + refName?: Maybe; + }; + tableName?: Maybe; +}; + +const PullDiffPage: NextPage = ({ params, tableName }) => ( + + + +); + +export const getServerSideProps: GetServerSideProps = async ({ + params, + query, +}) => { + return { + props: { + params: { + ...(params as RequiredPullDiffParams), + refName: query.refName ? String(query.refName) : null, + }, + tableName: query.tableName ? String(query.tableName) : null, + }, + }; +}; + +export default PullDiffPage; diff --git a/packages/web/pages/database/[databaseName]/pulls/index.tsx b/packages/web/pages/database/[databaseName]/pulls/index.tsx index 5d205b0a..abc32dba 100644 --- a/packages/web/pages/database/[databaseName]/pulls/index.tsx +++ b/packages/web/pages/database/[databaseName]/pulls/index.tsx @@ -9,10 +9,9 @@ type Props = { from?: Maybe; to?: Maybe; }; - tableName?: Maybe; }; -const PullsPage: NextPage = ({ params, tableName }) => ( +const PullsPage: NextPage = ({ params }) => ( = ({ params, tableName }) => ( fromBranchName: params.from ?? undefined, toBranchName: params.to ?? undefined, }} - tableName={tableName ?? undefined} /> ); @@ -38,7 +36,6 @@ export const getServerSideProps: GetServerSideProps = async ({ from: query.from ? String(query.from) : null, to: query.to ? String(query.to) : null, }, - tableName: query.tableName ? String(query.tableName) : null, }, }; }; diff --git a/yarn.lock b/yarn.lock index b4621c7f..f0115378 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1591,6 +1591,7 @@ __metadata: reflect-metadata: ^0.1.13 rxjs: ^7.5.4 supertest: ^6.3.3 + timeago.js: ^4.0.2 ts-jest: ^29.1.1 ts-loader: ^9.4.2 ts-node: ^10.5.0 @@ -1607,6 +1608,7 @@ __metadata: dependencies: "@apollo/client": ^3.7.0 "@graphql-codegen/cli": ^5.0.0 + "@graphql-codegen/fragment-matcher": ^5.0.0 "@graphql-codegen/typescript-operations": ^4.0.1 "@graphql-codegen/typescript-react-apollo": ^4.0.0 "@react-icons/all-files": ^4.1.0 @@ -2011,6 +2013,18 @@ __metadata: languageName: node linkType: hard +"@graphql-codegen/fragment-matcher@npm:^5.0.0": + version: 5.0.0 + resolution: "@graphql-codegen/fragment-matcher@npm:5.0.0" + dependencies: + "@graphql-codegen/plugin-helpers": ^5.0.0 + tslib: ~2.5.0 + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 897781e44697f769c34dbbc738192723e5c2cafc6883c0a30ac44d0c7cdaa327a2824c7d6a315aa865809c49b3f33c8600b3ebcd0f7c6bb342120740b0caebac + languageName: node + linkType: hard + "@graphql-codegen/plugin-helpers@npm:^2.7.2": version: 2.7.2 resolution: "@graphql-codegen/plugin-helpers@npm:2.7.2" From b8777fb7cbcff6e41c89903d9a4a6c5e6be20bd9 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 15:10:23 -0800 Subject: [PATCH 08/13] graphql,web: Add pull actions --- packages/graphql-server/schema.gql | 1 + .../graphql-server/src/pulls/pull.queries.ts | 1 + .../graphql-server/src/pulls/pull.resolver.ts | 44 ++++++- .../breadcrumbs/PullDiffBreadcrumbs.tsx | 19 +++ .../breadcrumbs/breadcrumbDetails.tsx | 33 +++++ .../DatabasePage/ForPullDiff/index.tsx | 4 +- .../PullActions/DeleteBranch/index.module.css | 35 ++++++ .../PullActions/DeleteBranch/index.test.tsx | 93 ++++++++++++++ .../PullActions/DeleteBranch/index.tsx | 115 ++++++++++++++++++ .../PullActions/DeleteBranch/mocks.ts | 88 ++++++++++++++ .../PullActions/DeleteBranch/queries.ts | 9 ++ .../MergeConflictsDirections.tsx | 67 ++++++++++ .../ErrorsWithDirections/index.module.css | 23 ++++ .../Merge/ErrorsWithDirections/index.tsx | 39 ++++++ .../Merge/ErrorsWithDirections/utils.ts | 38 ++++++ .../PullActions/Merge/MergeButton.tsx | 86 +++++++++++++ .../PullActions/Merge/MergeMessage.tsx | 22 ++++ .../PullActions/Merge/MergeMessageTitle.tsx | 27 ++++ .../PullActions/Merge/index.module.css | 105 ++++++++++++++++ .../ForPulls/PullActions/Merge/index.tsx | 12 ++ .../ForPulls/PullActions/Merge/queries.ts | 15 +++ .../ForPulls/PullActions/Merge/utils.ts | 6 + .../ForPulls/PullActions/index.tsx | 17 +++ .../ForPulls/PullDetailsList/index.module.css | 4 +- .../ForPulls/PullDetailsList/index.tsx | 2 +- .../DatabasePage/ForPulls/index.module.css | 18 +++ .../DatabasePage/ForPulls/index.tsx | 49 +++++--- packages/web/gen/graphql-types.tsx | 98 +++++++++++++++ packages/web/lib/refetchQueries.ts | 18 +++ 29 files changed, 1063 insertions(+), 25 deletions(-) create mode 100644 packages/graphql-server/src/pulls/pull.queries.ts create mode 100644 packages/web/components/breadcrumbs/PullDiffBreadcrumbs.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.module.css create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.test.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/mocks.ts create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/queries.ts create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/MergeConflictsDirections.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/index.module.css create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/index.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/utils.ts create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeMessage.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeMessageTitle.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.module.css create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.tsx create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/queries.ts create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/utils.ts create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/index.tsx diff --git a/packages/graphql-server/schema.gql b/packages/graphql-server/schema.gql index 757301c9..f57c9602 100644 --- a/packages/graphql-server/schema.gql +++ b/packages/graphql-server/schema.gql @@ -322,6 +322,7 @@ type Mutation { createDatabase(databaseName: String!): Boolean! resetDatabase: Boolean! loadDataFile(tableName: String!, refName: String!, databaseName: String!, importOp: ImportOperation!, fileType: FileType!, file: Upload!, modifier: LoadDataModifier): Boolean! + mergePull(databaseName: String!, fromBranchName: String!, toBranchName: String!): Boolean! createTag(tagName: String!, databaseName: String!, message: String, fromRefName: String!): Tag! deleteTag(databaseName: String!, tagName: String!): Boolean! } diff --git a/packages/graphql-server/src/pulls/pull.queries.ts b/packages/graphql-server/src/pulls/pull.queries.ts new file mode 100644 index 00000000..237d3952 --- /dev/null +++ b/packages/graphql-server/src/pulls/pull.queries.ts @@ -0,0 +1 @@ +export const callMerge = `CALL DOLT_MERGE(?, "--no-ff", "-m", ?)`; diff --git a/packages/graphql-server/src/pulls/pull.resolver.ts b/packages/graphql-server/src/pulls/pull.resolver.ts index e86cef08..ea73c078 100644 --- a/packages/graphql-server/src/pulls/pull.resolver.ts +++ b/packages/graphql-server/src/pulls/pull.resolver.ts @@ -1,7 +1,16 @@ -import { Args, ArgsType, Field, Query, Resolver } from "@nestjs/graphql"; +import { + Args, + ArgsType, + Field, + Mutation, + Query, + Resolver, +} from "@nestjs/graphql"; import { CommitResolver } from "../commits/commit.resolver"; +import { DataSourceService } from "../dataSources/dataSource.service"; import { DBArgs } from "../utils/commonTypes"; import { PullWithDetails, fromAPIModelPullWithDetails } from "./pull.model"; +import { callMerge } from "./pull.queries"; @ArgsType() class PullArgs extends DBArgs { @@ -14,7 +23,10 @@ class PullArgs extends DBArgs { @Resolver(_of => PullWithDetails) export class PullResolver { - constructor(private readonly commitResolver: CommitResolver) {} + constructor( + private readonly dss: DataSourceService, + private readonly commitResolver: CommitResolver, + ) {} @Query(_returns => PullWithDetails) async pullWithDetails(@Args() args: PullArgs): Promise { @@ -28,4 +40,32 @@ export class PullResolver { return fromAPIModelPullWithDetails(name, commits.list); } + + @Mutation(_returns => Boolean) + async mergePull(@Args() args: PullArgs): Promise { + return this.dss.query( + async query => { + await query("BEGIN"); + + const res = await query(callMerge, [ + args.fromBranchName, + `Merge branch ${args.fromBranchName}`, + // commitAuthor: { + // name: currentUser.username, + // email: currentUser.emailAddressesList[0].address, + // }, + ]); + + if (res.length && res[0].conflicts !== "0") { + await query("ROLLBACK"); + throw new Error("Merge conflict detected"); + } + + await query("COMMIT"); + return true; + }, + args.databaseName, + args.toBranchName, + ); + } } diff --git a/packages/web/components/breadcrumbs/PullDiffBreadcrumbs.tsx b/packages/web/components/breadcrumbs/PullDiffBreadcrumbs.tsx new file mode 100644 index 00000000..2154ac08 --- /dev/null +++ b/packages/web/components/breadcrumbs/PullDiffBreadcrumbs.tsx @@ -0,0 +1,19 @@ +import { PullDiffParams } from "@lib/params"; +import Breadcrumbs from "."; +import { pullDiffBreadcrumbDetails } from "./breadcrumbDetails"; + +type Props = { + params: PullDiffParams; + className?: string; +}; + +export default function PullDiffBreadcrumbs({ params, ...props }: Props) { + return ( + + ); +} diff --git a/packages/web/components/breadcrumbs/breadcrumbDetails.tsx b/packages/web/components/breadcrumbs/breadcrumbDetails.tsx index 7638b071..2b1bb4af 100644 --- a/packages/web/components/breadcrumbs/breadcrumbDetails.tsx +++ b/packages/web/components/breadcrumbs/breadcrumbDetails.tsx @@ -1,9 +1,11 @@ import DatabasesDropdown from "@components/DatabasesDropdown"; import CommitLogLink from "@components/links/CommitLogLink"; import Link from "@components/links/Link"; +import PullLink from "@components/links/PullLink"; import { DatabaseParams, DiffRangeParams, + PullDiffParams, RefParams, SqlQueryParams, TableParams, @@ -234,3 +236,34 @@ export function pullsBreadcrumbs(params: DatabaseParams): BreadcrumbDetails[] { }, ]; } + +export function pullDiffBreadcrumbDetails( + params: PullDiffParams, +): BreadcrumbDetails[] { + const pullLink = pull request; + const pullDiffText = diff; + const commitDiffText = ( + + {params.toBranchName}...{params.fromBranchName} + + ); + + return [ + ...databaseBreadcrumbs(params), + { + child: pullLink, + name: BreadcrumbName.DBPull, + type: BreadcrumbType.Link, + }, + { + child: pullDiffText, + name: BreadcrumbName.DBPullDiff, + type: BreadcrumbType.Text, + }, + { + child: commitDiffText, + name: BreadcrumbName.DBPullDiffRange, + type: BreadcrumbType.Text, + }, + ]; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx index 5e7881de..71359166 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx @@ -1,6 +1,6 @@ import DiffTable from "@components/DiffTable"; import DiffTableNav from "@components/DiffTableNav"; -import PullsBreadcrumbs from "@components/breadcrumbs/PullsBreadcrumbs"; +import PullDiffBreadcrumbs from "@components/breadcrumbs/PullDiffBreadcrumbs"; import NotDoltWrapper from "@components/util/NotDoltWrapper"; import { DiffProvider } from "@contexts/diff"; import { RequiredPullDiffParams } from "@lib/params"; @@ -28,7 +28,7 @@ export default function ForPullDiff(props: Props) { params={props.params} routeRefChangeTo={pulls} title="pulls" - smallHeaderBreadcrumbs={} + smallHeaderBreadcrumbs={} initialSmallHeader leftTableNav={} wide diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.module.css new file mode 100644 index 00000000..c2fb4241 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.module.css @@ -0,0 +1,35 @@ +.container { + @apply flex flex-col justify-between rounded-lg bg-ld-lightpurple max-w-[46rem] mx-auto p-2 pb-4 my-6 border; + + @screen lg { + @apply mb-0 flex-row pb-2; + } +} + +.mergedContainer { + @apply border-acc-pink; +} + +.deleteMsg { + @apply flex mx-3 my-1; +} + +.success { + @apply font-semibold mb-1; +} + +.deleteBtn { + @apply px-4 h-8 mt-3 mx-2 min-w-[150px]; +} + +.merged { + @apply bg-acc-pink; +} + +.err { + @apply mx-auto max-w-3xl text-center font-semibold; +} + +.modal { + @apply max-w-xl; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.test.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.test.tsx new file mode 100644 index 00000000..65e1b4b9 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.test.tsx @@ -0,0 +1,93 @@ +import { MockedProvider, MockedResponse } from "@apollo/client/testing"; +import { DeploymentRole } from "@gen/graphql-types"; +import { mocksForDepRoleHook } from "@hooks/useDeploymentRole/mocks"; +import { fakeDeploymentParams } from "@hosted/fakers"; +import { DatabaseParams } from "@lib/params"; +import { providerNoCacheOptions } from "@lib/queryUtils"; +import { setup } from "@lib/testUtils.test"; +import { screen, waitFor } from "@testing-library/react"; +import DeleteBranch from "."; +import { pullDetailsMock } from "../../mocks"; +import * as mocks from "./mocks"; + +const params: DatabaseParams = { + ...fakeDeploymentParams(), + databaseName: "test", +}; + +async function renderWithProvider( + mockRes: MockedResponse[], + showButton: boolean, + fromBranchName = mocks.pull.fromBranchName, +) { + const { user } = setup( + + + , + ); + + if (showButton) { + expect(await screen.findByText(fromBranchName)).toBeVisible(); + } else { + expect(screen.queryByText("Delete Branch")).not.toBeInTheDocument(); + expect(screen.queryByText(fromBranchName)).not.toBeInTheDocument(); + } + + return user; +} + +describe("test DeleteBranch", () => { + it("renders nothing for no write perms", async () => { + await renderWithProvider( + [ + mocks.branchExistsMock(), + ...mocksForDepRoleHook(params, DeploymentRole.Reader), + ], + false, + ); + }); + + it("renders nothing for master from branch", async () => { + await renderWithProvider( + [ + mocks.branchExistsMock("master"), + ...mocksForDepRoleHook(params, DeploymentRole.Admin), + ], + false, + "master", + ); + }); + + it("renders delete branch button and errors on delete", async () => { + const user = await renderWithProvider( + [ + mocks.branchExistsMock(), + mocks.deleteBranchErrorMock, + ...mocksForDepRoleHook(mocks.pullParams, DeploymentRole.Admin), + ], + true, + ); + + expect(mocks.deleteBranchNewData).not.toHaveBeenCalled(); + await user.click(screen.getByText("Delete Branch")); + expect(await screen.findByText(mocks.errorMessage)).toBeVisible(); + expect(mocks.deleteBranchNewData).not.toHaveBeenCalled(); + }); + + it("renders delete branch button for branch that exists", async () => { + const user = await renderWithProvider( + [ + mocks.branchExistsMock(), + mocks.deleteBranchMock(), + mocks.branchNotExistsMock, + pullDetailsMock(mocks.pullParams), + ...mocksForDepRoleHook(mocks.pullParams, DeploymentRole.Admin), + ], + true, + ); + + expect(mocks.deleteBranchNewData).not.toHaveBeenCalled(); + await user.click(screen.getByText("Delete Branch")); + await waitFor(() => expect(mocks.deleteBranchNewData).toHaveBeenCalled()); + }); +}); diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx new file mode 100644 index 00000000..fe9fee7a --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx @@ -0,0 +1,115 @@ +import Button from "@components/Button"; +import ErrorMsg from "@components/ErrorMsg"; +import Loader from "@components/Loader"; +import HideForNoWritesWrapper from "@components/util/HideForNoWritesWrapper"; +import { + PullDetailsFragment, + PullState, + useDeleteBranchMutation, + useGetBranchForPullQuery, +} from "@gen/graphql-types"; +import useDefaultBranch from "@hooks/useDefaultBranch"; +import useMutation from "@hooks/useMutation"; +import { BranchParams, DatabaseParams, PullDiffParams } from "@lib/params"; +import { refetchDeletedBranch } from "@lib/refetchQueries"; +import cx from "classnames"; +import css from "./index.module.css"; + +type Props = { + params: PullDiffParams; + pullDetails: PullDetailsFragment; +}; + +type InnerProps = Props & { + branchExists: boolean; +}; + +function Inner(props: InnerProps) { + const params: DatabaseParams = { + databaseName: props.params.databaseName, + }; + const branchParams: BranchParams = { + ...params, + branchName: props.params.fromBranchName, + }; + + const { defaultBranchName, loading: branchLoading } = + useDefaultBranch(params); + + const { + mutateFn: deleteBranch, + err, + setErr, + loading, + } = useMutation({ + hook: useDeleteBranchMutation, + refetchQueries: refetchDeletedBranch(props.params), + }); + + const onClick = async () => { + setErr(undefined); + await deleteBranch({ variables: branchParams }); + }; + + if (branchLoading) return ; + + if ( + !props.branchExists || + props.params.fromBranchName === defaultBranchName + ) { + return null; + } + + const isMerged = props.pullDetails.state === PullState.Merged; + + return ( + +
    +
    +
    +
    +
    + {isMerged + ? `Pull request successfully merged` + : "Closed with unmerged commits"} +
    + {isMerged && ( +

    + The branch {props.params.fromBranchName} can + safely be deleted. +

    + )} +
    +
    + +
    + + +
    +
    + ); +} + +export default function DeleteBranch(props: Props) { + const res = useGetBranchForPullQuery({ + variables: { + databaseName: props.params.databaseName, + branchName: props.params.fromBranchName, + }, + }); + if (res.loading) return ; + return ; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/mocks.ts b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/mocks.ts new file mode 100644 index 00000000..5a91bfec --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/mocks.ts @@ -0,0 +1,88 @@ +import { ApolloError } from "@apollo/client"; +import { MockedResponse } from "@apollo/client/testing"; +import { + DeleteBranchDocument, + GetBranchForPullDocument, + PullForPullDetailsFragment, + PullState, +} from "@gen/graphql-types"; +import { fakeDeploymentParams, fakeTimestamp } from "@hosted/fakers"; +import { BranchUtils, PullUtils } from "@hosted/resource-utils"; +import { BranchParams, PullParams } from "@lib/params"; + +export const pullParams: PullParams = { + ...fakeDeploymentParams(), + databaseName: "test", + pullId: "5", +}; + +const pullId = PullUtils.rn.fromParams(pullParams); + +export const pull: PullForPullDetailsFragment = { + ...pullParams, + __typename: "Pull", + _id: pullId, + title: "Pull Title", + description: "", + state: PullState.Merged, + creatorName: "taylor", + fromBranchName: "taylor/feature-branch", + toBranchName: "master", + createdAt: fakeTimestamp(), +}; + +const branchParams: BranchParams = { + ownerName: pull.ownerName, + deploymentName: pull.deploymentName, + branchName: pull.fromBranchName, + databaseName: pull.databaseName, +}; + +export const branchExistsMock = ( + branchName = pull.fromBranchName, +): MockedResponse => { + const params = { ...branchParams, branchName }; + return { + request: { + query: GetBranchForPullDocument, + variables: params, + }, + result: { + data: { + branch: { + __typename: "Branch", + _id: BranchUtils.rn.fromParams(params), + }, + }, + }, + }; +}; + +export const branchNotExistsMock: MockedResponse = { + request: { query: GetBranchForPullDocument, variables: branchParams }, + result: { + data: { branch: undefined }, + }, +}; + +export const deleteBranchNewData = jest.fn(() => { + return { data: { deleteBranch: true } }; +}); + +export const deleteBranchMock = ( + branchName = pull.fromBranchName, +): MockedResponse => { + return { + request: { + query: DeleteBranchDocument, + variables: { ...branchParams, branchName }, + }, + newData: deleteBranchNewData, + }; +}; + +export const errorMessage = "error deleting branch"; +export const deleteBranchErrorMock: MockedResponse = { + request: { query: DeleteBranchDocument, variables: branchParams }, + error: new ApolloError({ errorMessage }), +}; diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/queries.ts b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/queries.ts new file mode 100644 index 00000000..4857bfcb --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/queries.ts @@ -0,0 +1,9 @@ +import { gql } from "@apollo/client"; + +export const GET_BRANCH_FOR_PULL = gql` + query GetBranchForPull($branchName: String!, $databaseName: String!) { + branch(branchName: $branchName, databaseName: $databaseName) { + _id + } + } +`; diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/MergeConflictsDirections.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/MergeConflictsDirections.tsx new file mode 100644 index 00000000..b0ba783f --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/MergeConflictsDirections.tsx @@ -0,0 +1,67 @@ +import CodeBlock from "@components/CodeBlock"; +import DocsLink from "@components/links/DocsLink"; +import { PullDiffParams } from "@lib/params"; +import { getMergeCommands } from "../utils"; +import css from "./index.module.css"; + +type Props = { + params: PullDiffParams; +}; + +export default function MergeConflictsDirections({ params }: Props) { + return ( +
    +

    Merge and Resolve Conflicts

    +
    +

    + Conflicts cannot be resolved on the web and must be resolved in a SQL + shell. +

    +

    + + Merge + {" "} + pull request: +

    + +

    + View{" "} + + all conflicts + + : +

    + +

    + View conflicts for{" "} + + each table + + : +

    + +

    + + Resolve conflicts + + : +

    + +

    + + Commit + {" "} + the merge: +

    + +

    + Learn more about merging and resolving conflicts with SQL{" "} + here + . +

    +
    +
    + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/index.module.css new file mode 100644 index 00000000..310c4831 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/index.module.css @@ -0,0 +1,23 @@ +.errContainer { + @apply block w-full mt-2; +} + +.red { + @apply text-acc-red; +} + +.err { + @apply max-w-2xl pt-0 mx-6 font-semibold; +} + +.innerModal { + @apply max-w-2xl mx-auto pb-4; + + p { + @apply text-left text-base mb-2; + } +} + +.bold { + @apply font-semibold; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/index.tsx new file mode 100644 index 00000000..cf94bac0 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/index.tsx @@ -0,0 +1,39 @@ +import ErrorMsg from "@components/ErrorMsg"; +import { ApolloErrorType } from "@lib/errors/types"; +import cx from "classnames"; +import { useEffect } from "react"; +import css from "./index.module.css"; +import { improveError } from "./utils"; + +type Props = { + mergeErr?: ApolloErrorType; + setShowDirections: (s: boolean) => void; +}; + +export default function ErrorsWithDirections({ + mergeErr, + setShowDirections, +}: Props) { + const mergeErrs = improveError(mergeErr); + + useEffect(() => { + if (!mergeErr) return; + setShowDirections(true); + }, [mergeErr, setShowDirections]); + + return ( +
    + + {mergeErrs.isTimeoutErr && ( +
    + Timed out merging pull request. Try merging using SQL. +
    + )} + {mergeErrs.isConflictsErr && ( +
    + Cannot merge due to conflicts. Please resolve and try again. +
    + )} +
    + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/utils.ts b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/utils.ts new file mode 100644 index 00000000..ef69bc40 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/ErrorsWithDirections/utils.ts @@ -0,0 +1,38 @@ +import { gqlPullHasConflicts } from "@lib/errors/graphql"; +import { errorMatches, isTimeoutError } from "@lib/errors/helpers"; +import { ApolloErrorType } from "@lib/errors/types"; + +type MergeError = { + isConflictsErr: boolean; + isTimeoutErr: boolean; + improvedErr: string | undefined; +}; + +export function improveError(err?: ApolloErrorType): MergeError { + if (!err) { + return { + isConflictsErr: false, + isTimeoutErr: false, + improvedErr: undefined, + }; + } + if (errorMatches(gqlPullHasConflicts, err)) { + return { + isConflictsErr: true, + isTimeoutErr: false, + improvedErr: undefined, + }; + } + if (isTimeoutError(err.message)) { + return { + isConflictsErr: false, + isTimeoutErr: true, + improvedErr: undefined, + }; + } + return { + isConflictsErr: false, + isTimeoutErr: false, + improvedErr: err.message, + }; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx new file mode 100644 index 00000000..bae19d53 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx @@ -0,0 +1,86 @@ +import Button from "@components/Button"; +import { + PullDetailsForPullDetailsDocument, + PullDetailsFragment, + useMergePullMutation, +} from "@gen/graphql-types"; +import useMutation from "@hooks/useMutation"; +import { gqlPullHasConflicts } from "@lib/errors/graphql"; +import { errorMatches } from "@lib/errors/helpers"; +import { PullDiffParams } from "@lib/params"; +import { FiGitPullRequest } from "@react-icons/all-files/fi/FiGitPullRequest"; +import cx from "classnames"; +import { useState } from "react"; +import ErrorsWithDirections from "./ErrorsWithDirections"; +import MergeConflictsDirections from "./ErrorsWithDirections/MergeConflictsDirections"; +import MergeMessage from "./MergeMessage"; +import MergeMessageTitle from "./MergeMessageTitle"; +import css from "./index.module.css"; + +type Props = { + params: PullDiffParams; + pullDetails: PullDetailsFragment; +}; + +export default function MergeButton(props: Props) { + // const { setState } = usePullDetailsContext(); + const [showDirections, setShowDirections] = useState(false); + const { mutateFn: merge, ...res } = useMutation({ + hook: useMergePullMutation, + refetchQueries: [ + { query: PullDetailsForPullDetailsDocument, variables: props.params }, + ], + }); + + const hasConflicts = errorMatches(gqlPullHasConflicts, res.err); + const disabled = hasConflicts; + + const red = hasConflicts; + + const onClick = async () => { + await merge({ variables: props.params }); + // setState({ isMerging: true }); + }; + + return ( +
    + + + + {/* */} +
    +
    + +
    + +
    + {res.err && ( + + )} +
    +
    + + + View{" "} + setShowDirections(!showDirections)}> + merge instructions + + . + + {showDirections && } +
    +
    +
    + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeMessage.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeMessage.tsx new file mode 100644 index 00000000..1a91275e --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeMessage.tsx @@ -0,0 +1,22 @@ +import css from "./index.module.css"; + +type Props = { + hasConflicts: boolean; +}; + +export default function MergeMessage(props: Props) { + if (props.hasConflicts) { + return ( + + This branch has conflicts with the base branch. + + ); + } + + return ( +

    + Please note: there may be conflicts. You must attempt a merge to see + conflicts. +

    + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeMessageTitle.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeMessageTitle.tsx new file mode 100644 index 00000000..3a1e1d97 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeMessageTitle.tsx @@ -0,0 +1,27 @@ +import { FiCheck } from "@react-icons/all-files/fi/FiCheck"; +import { IoMdClose } from "@react-icons/all-files/io/IoMdClose"; +import css from "./index.module.css"; + +type Props = { + hasConflicts: boolean; +}; + +export default function MergeMessageTitle(props: Props) { + if (props.hasConflicts) { + return ( +
    + +
    + Has conflicts. +
    +
    + ); + } + + return ( +
    + + Ready to merge. +
    + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.module.css new file mode 100644 index 00000000..4882a2da --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.module.css @@ -0,0 +1,105 @@ +.outer { + @apply mx-auto max-w-3xl flex flex-col; + + h3 { + @apply text-center mt-4 mb-4; + } + + @screen lg { + @apply mt-6 flex-row; + } +} + +.container { + @apply w-full mb-4 rounded-xl min-w-[15rem]; + @screen lg { + @apply mx-3 mb-0; + } +} + +.top { + @apply bg-[#E6F6EE] pl-4 pr-4 py-2 border border-acc-green flex justify-between items-start rounded-t-xl flex-wrap w-full; + + @screen lg { + @apply items-center pl-6; + } +} + +.picContainer { + @apply w-7 h-7 mb-4 mr-1 text-white relative rounded-full bg-acc-green flex-shrink-0; + + @screen lg { + @apply mb-0 mt-3 ml-2; + } + svg { + @apply text-white mt-1 ml-1 w-5 h-5; + } +} + +.redIcon { + @apply bg-acc-red; +} + +.merge { + @apply mx-2; + @screen lg { + @apply mx-0; + } +} + +.msg { + @apply px-6 py-2 border-x border-b rounded-b-xl bg-white border-acc-green; +} + +.note { + @apply font-normal text-ld-darkgrey mt-0.5 py-1 block; +} + +.icon { + @apply mr-2 mt-0.5; +} + +.green { + @apply text-acc-green; +} + +.mergeStatusIcon { + @apply inline-block mr-2 text-2xl; +} + +.red { + @apply text-acc-red flex border-acc-red bg-[#FDEEED]; +} + +.msgRed { + @apply border-acc-red; +} + +.popup { + @apply p-4 text-primary; + + h4, + p { + @apply text-sm mb-2; + } + + code { + @apply text-xs; + } +} + +.conflicts { + @apply min-w-[500px]; +} + +.button { + @apply text-acc-hoverlinkblue px-0 no-underline; +} + +.down { + @apply w-2 h-2 p-0 bg-white absolute rounded-sm top-[-3.68rem] left-4 border-r-0 border-b-0 border-l border-t border-ld-lightgrey rotate-45; +} + +.toggle { + @apply font-normal text-ld-darkgrey border-none px-3 text-sm hidden lg:contents; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.tsx new file mode 100644 index 00000000..ff90756a --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.tsx @@ -0,0 +1,12 @@ +import { PullDetailsFragment } from "@gen/graphql-types"; +import { PullDiffParams } from "@lib/params"; +import MergeButton from "./MergeButton"; + +type Props = { + params: PullDiffParams; + pullDetails: PullDetailsFragment; +}; + +export default function Merge(props: Props) { + return ; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/queries.ts b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/queries.ts new file mode 100644 index 00000000..0c13522f --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/queries.ts @@ -0,0 +1,15 @@ +import { gql } from "@apollo/client"; + +export const MERGE_PULL = gql` + mutation MergePull( + $databaseName: String! + $fromBranchName: String! + $toBranchName: String! + ) { + mergePull( + databaseName: $databaseName + fromBranchName: $fromBranchName + toBranchName: $toBranchName + ) + } +`; diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/utils.ts b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/utils.ts new file mode 100644 index 00000000..216d626e --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/utils.ts @@ -0,0 +1,6 @@ +import { PullDiffParams } from "@lib/params"; + +export function getMergeCommands(params: PullDiffParams): string { + return `CALL DOLT_CHECKOUT("${params.toBranchName}"); +CALL DOLT_MERGE("${params.fromBranchName}");`; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/index.tsx new file mode 100644 index 00000000..bcf95c47 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/index.tsx @@ -0,0 +1,17 @@ +import { PullDetailsFragment, PullState } from "@gen/graphql-types"; +import { PullDiffParams } from "@lib/params"; +import DeleteBranch from "./DeleteBranch"; +import Merge from "./Merge"; + +type Props = { + params: PullDiffParams; + pullDetails: PullDetailsFragment; +}; + +export default function PullActions(props: Props) { + if (props.pullDetails.state === PullState.Merged) { + return ; + } + + return ; +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css index 5b0fca19..0d6e008b 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css @@ -1,5 +1,5 @@ .list { - @apply max-w-3xl mx-0 break-words; + @apply max-w-4xl mx-0 break-words; li { @apply my-0; @@ -11,7 +11,7 @@ } .empty { - @apply text-center font-semibold; + @apply text-center font-semibold my-10; } .verticalLine { diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.tsx index f075e41c..2bb68530 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.tsx @@ -30,7 +30,7 @@ export default function PullDetailsList({ pullDetails, params }: InnerProps) {
    ) : ( -

    No details to display

    +

    Branches are up to date. No details to display.

    ); } diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css index 55d04ef7..27a7d55b 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css @@ -5,3 +5,21 @@ @apply ml-6; } } + +.inner { + @apply mb-20; +} + +.selectBranches { + @apply text-center font-semibold my-10; +} + +.viewDiffButton { + button { + @apply w-32 px-3 mt-2 mb-4 lg:my-0; + } + + svg { + @apply inline-block ml-2 mb-1; + } +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx index 77ce93a4..567e0f5f 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx @@ -10,9 +10,11 @@ import { } from "@gen/graphql-types"; import { PullDiffParams, PullParams } from "@lib/params"; import { pullDiff, pulls } from "@lib/urls"; +import { FaChevronRight } from "@react-icons/all-files/fa/FaChevronRight"; import { useEffect, useState } from "react"; import ForDefaultBranch from "../ForDefaultBranch"; import BranchSelectForm from "./BranchSelectForm"; +import PullActions from "./PullActions"; import PullDetailsList from "./PullDetailsList"; import css from "./index.module.css"; @@ -28,8 +30,6 @@ type BranchesProps = { function ForBranches(props: BranchesProps) { const res = usePullDetailsForPullDetailsQuery({ variables: props.params }); - console.log(res); - useEffect(() => { if (!res.data) return; props.setPullState(res.data.pullWithDetails.state); @@ -39,10 +39,16 @@ function ForBranches(props: BranchesProps) { ( - +
    + + +
    )} /> ); @@ -56,17 +62,22 @@ function Inner(props: Props) {
    - {props.params.fromBranchName && props.params.toBranchName && ( - - - - )} + {props.params.fromBranchName && + props.params.toBranchName && + pullState === PullState.Open && ( + + + + )}
    @@ -80,7 +91,9 @@ function Inner(props: Props) { setPullState={setPullState} /> ) : ( -

    Select branches

    +

    + Select branches to view pull request +

    )}
    ); diff --git a/packages/web/gen/graphql-types.tsx b/packages/web/gen/graphql-types.tsx index 10bf5b02..36f51ade 100644 --- a/packages/web/gen/graphql-types.tsx +++ b/packages/web/gen/graphql-types.tsx @@ -200,6 +200,7 @@ export type Mutation = { deleteBranch: Scalars['Boolean']['output']; deleteTag: Scalars['Boolean']['output']; loadDataFile: Scalars['Boolean']['output']; + mergePull: Scalars['Boolean']['output']; resetDatabase: Scalars['Boolean']['output']; }; @@ -253,6 +254,13 @@ export type MutationLoadDataFileArgs = { tableName: Scalars['String']['input']; }; + +export type MutationMergePullArgs = { + databaseName: Scalars['String']['input']; + fromBranchName: Scalars['String']['input']; + toBranchName: Scalars['String']['input']; +}; + export type PullDetailCommit = { __typename?: 'PullDetailCommit'; _id: Scalars['ID']['output']; @@ -932,6 +940,23 @@ export type DocPageQueryNoBranchQueryVariables = Exact<{ export type DocPageQueryNoBranchQuery = { __typename?: 'Query', branchOrDefault?: { __typename?: 'Branch', _id: string, branchName: string } | null }; +export type GetBranchForPullQueryVariables = Exact<{ + branchName: Scalars['String']['input']; + databaseName: Scalars['String']['input']; +}>; + + +export type GetBranchForPullQuery = { __typename?: 'Query', branch?: { __typename?: 'Branch', _id: string } | null }; + +export type MergePullMutationVariables = Exact<{ + databaseName: Scalars['String']['input']; + fromBranchName: Scalars['String']['input']; + toBranchName: Scalars['String']['input']; +}>; + + +export type MergePullMutation = { __typename?: 'Mutation', mergePull: boolean }; + export type PullDetailCommitFragment = { __typename?: 'PullDetailCommit', _id: string, username: string, message: string, createdAt: any, commitId: string, parentCommitId?: string | null }; export type PullDetailSummaryFragment = { __typename?: 'PullDetailSummary', _id: string, username: string, createdAt: any, numCommits: number }; @@ -2620,6 +2645,79 @@ export function useDocPageQueryNoBranchLazyQuery(baseOptions?: Apollo.LazyQueryH export type DocPageQueryNoBranchHookResult = ReturnType; export type DocPageQueryNoBranchLazyQueryHookResult = ReturnType; export type DocPageQueryNoBranchQueryResult = Apollo.QueryResult; +export const GetBranchForPullDocument = gql` + query GetBranchForPull($branchName: String!, $databaseName: String!) { + branch(branchName: $branchName, databaseName: $databaseName) { + _id + } +} + `; + +/** + * __useGetBranchForPullQuery__ + * + * To run a query within a React component, call `useGetBranchForPullQuery` and pass it any options that fit your needs. + * When your component renders, `useGetBranchForPullQuery` 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 } = useGetBranchForPullQuery({ + * variables: { + * branchName: // value for 'branchName' + * databaseName: // value for 'databaseName' + * }, + * }); + */ +export function useGetBranchForPullQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetBranchForPullDocument, options); + } +export function useGetBranchForPullLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetBranchForPullDocument, options); + } +export type GetBranchForPullQueryHookResult = ReturnType; +export type GetBranchForPullLazyQueryHookResult = ReturnType; +export type GetBranchForPullQueryResult = Apollo.QueryResult; +export const MergePullDocument = gql` + mutation MergePull($databaseName: String!, $fromBranchName: String!, $toBranchName: String!) { + mergePull( + databaseName: $databaseName + fromBranchName: $fromBranchName + toBranchName: $toBranchName + ) +} + `; +export type MergePullMutationFn = Apollo.MutationFunction; + +/** + * __useMergePullMutation__ + * + * To run a mutation, you first call `useMergePullMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useMergePullMutation` 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 [mergePullMutation, { data, loading, error }] = useMergePullMutation({ + * variables: { + * databaseName: // value for 'databaseName' + * fromBranchName: // value for 'fromBranchName' + * toBranchName: // value for 'toBranchName' + * }, + * }); + */ +export function useMergePullMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(MergePullDocument, options); + } +export type MergePullMutationHookResult = ReturnType; +export type MergePullMutationResult = Apollo.MutationResult; +export type MergePullMutationOptions = Apollo.BaseMutationOptions; export const PullDetailsForPullDetailsDocument = gql` query PullDetailsForPullDetails($databaseName: String!, $fromBranchName: String!, $toBranchName: String!) { pullWithDetails( diff --git a/packages/web/lib/refetchQueries.ts b/packages/web/lib/refetchQueries.ts index e82d5344..bf870558 100644 --- a/packages/web/lib/refetchQueries.ts +++ b/packages/web/lib/refetchQueries.ts @@ -8,6 +8,7 @@ import { import * as gen from "@gen/graphql-types"; import { DatabaseParams, + PullDiffParams, RefParams, RequiredRefsParams, TableParams, @@ -85,6 +86,23 @@ export const refetchTableUploadQueries = ( ...refetchTableQueries(variables), ]; +export const refetchDeletedBranch = ( + params: PullDiffParams, +): RefetchQueries => [ + { + query: gen.GetBranchForPullDocument, + variables: { + databaseName: params.databaseName, + branchName: params.fromBranchName, + }, + }, + { + query: gen.PullDetailsForPullDetailsDocument, + variables: params, + }, + ...refetchBranchQueries(params), +]; + export const refetchSqlUpdateQueriesCacheEvict: RefetchOptions = { updateCache(cache: TCacheShape) { [ From c5a18b453a958e456e8edccdc5dee79c96f62391 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 16:11:34 -0800 Subject: [PATCH 09/13] web: Simplify pull refs, fix test --- .../web/components/DiffSelector/ForPull.tsx | 2 +- .../web/components/DiffTableNav/ForPull.tsx | 4 +- .../breadcrumbs/breadcrumbDetails.tsx | 2 +- .../DatabasePage/ForPullDiff/index.tsx | 4 +- .../ForPulls/BranchSelectForm/index.tsx | 4 +- .../PullActions/DeleteBranch/index.test.tsx | 50 ++++------------- .../PullActions/DeleteBranch/mocks.ts | 55 ++++++++++--------- .../PullActions/Merge/MergeButton.tsx | 7 +-- .../ForPulls/PullActions/Merge/utils.ts | 2 +- .../ForPulls/PullDetailsList/index.module.css | 4 ++ .../DatabasePage/ForPulls/index.module.css | 2 +- .../DatabasePage/ForPulls/index.tsx | 12 ++-- packages/web/lib/params.ts | 5 +- packages/web/lib/testUtils.test.ts | 5 -- packages/web/lib/urls.ts | 5 +- .../[fromBranchName]}/index.tsx | 12 +--- .../database/[databaseName]/pulls/index.tsx | 3 - 17 files changed, 70 insertions(+), 108 deletions(-) rename packages/web/pages/database/[databaseName]/pulls/compare/{[fromBranchName]/[toBranchName] => [refName]/[fromBranchName]}/index.tsx (74%) diff --git a/packages/web/components/DiffSelector/ForPull.tsx b/packages/web/components/DiffSelector/ForPull.tsx index d98043e6..d2c77035 100644 --- a/packages/web/components/DiffSelector/ForPull.tsx +++ b/packages/web/components/DiffSelector/ForPull.tsx @@ -9,7 +9,7 @@ export default function ForPull(props: Props) { return ( Viewing changes between {props.params.fromBranchName} and{" "} - {props.params.toBranchName} + {props.params.refName} ); } diff --git a/packages/web/components/DiffTableNav/ForPull.tsx b/packages/web/components/DiffTableNav/ForPull.tsx index c5bd3e4e..13e9a64e 100644 --- a/packages/web/components/DiffTableNav/ForPull.tsx +++ b/packages/web/components/DiffTableNav/ForPull.tsx @@ -12,7 +12,7 @@ type Props = { export default function ForPull(props: Props) { const selector = ; - if (!props.params.fromBranchName || !props.params.toBranchName) { + if (!props.params.fromBranchName || !props.params.refName) { return ( diff; const commitDiffText = ( - {params.toBranchName}...{params.fromBranchName} + {params.refName}...{params.fromBranchName} ); diff --git a/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx index 71359166..563831c8 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx @@ -8,7 +8,7 @@ import { pulls } from "@lib/urls"; import ForDefaultBranch from "../ForDefaultBranch"; type Props = { - params: RequiredPullDiffParams & { refName?: string }; + params: RequiredPullDiffParams; tableName?: string; }; @@ -18,7 +18,7 @@ export default function ForPullDiff(props: Props) { params={{ ...props.params, fromRefName: props.params.fromBranchName, - toRefName: props.params.toBranchName, + toRefName: props.params.refName, }} initialTableName={props.tableName} forPull diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.tsx index c9f40a38..c6926cfa 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/BranchSelectForm/index.tsx @@ -26,10 +26,10 @@ function Inner(props: InnerProps) {
    { - const p = pulls({ ...props.params, toBranchName: b }); + const p = pulls({ ...props.params, refName: b }); router.push(p.href, p.as).catch(console.error); }} /> diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.test.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.test.tsx index 65e1b4b9..75082931 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.test.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.test.tsx @@ -1,28 +1,20 @@ import { MockedProvider, MockedResponse } from "@apollo/client/testing"; -import { DeploymentRole } from "@gen/graphql-types"; -import { mocksForDepRoleHook } from "@hooks/useDeploymentRole/mocks"; -import { fakeDeploymentParams } from "@hosted/fakers"; -import { DatabaseParams } from "@lib/params"; -import { providerNoCacheOptions } from "@lib/queryUtils"; import { setup } from "@lib/testUtils.test"; import { screen, waitFor } from "@testing-library/react"; import DeleteBranch from "."; -import { pullDetailsMock } from "../../mocks"; import * as mocks from "./mocks"; -const params: DatabaseParams = { - ...fakeDeploymentParams(), - databaseName: "test", -}; - async function renderWithProvider( mockRes: MockedResponse[], showButton: boolean, - fromBranchName = mocks.pull.fromBranchName, + fromBranchName = mocks.pullParams.fromBranchName, ) { const { user } = setup( - - + + , ); @@ -37,34 +29,13 @@ async function renderWithProvider( } describe("test DeleteBranch", () => { - it("renders nothing for no write perms", async () => { - await renderWithProvider( - [ - mocks.branchExistsMock(), - ...mocksForDepRoleHook(params, DeploymentRole.Reader), - ], - false, - ); - }); - - it("renders nothing for master from branch", async () => { - await renderWithProvider( - [ - mocks.branchExistsMock("master"), - ...mocksForDepRoleHook(params, DeploymentRole.Admin), - ], - false, - "master", - ); + it("renders nothing for main from branch", async () => { + await renderWithProvider([mocks.branchExistsMock("main")], false, "main"); }); it("renders delete branch button and errors on delete", async () => { const user = await renderWithProvider( - [ - mocks.branchExistsMock(), - mocks.deleteBranchErrorMock, - ...mocksForDepRoleHook(mocks.pullParams, DeploymentRole.Admin), - ], + [mocks.branchExistsMock(), mocks.deleteBranchErrorMock], true, ); @@ -80,8 +51,7 @@ describe("test DeleteBranch", () => { mocks.branchExistsMock(), mocks.deleteBranchMock(), mocks.branchNotExistsMock, - pullDetailsMock(mocks.pullParams), - ...mocksForDepRoleHook(mocks.pullParams, DeploymentRole.Admin), + mocks.pullDetailsMock(mocks.pullParams), ], true, ); diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/mocks.ts b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/mocks.ts index 5a91bfec..b55dc430 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/mocks.ts +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/mocks.ts @@ -3,43 +3,48 @@ import { MockedResponse } from "@apollo/client/testing"; import { DeleteBranchDocument, GetBranchForPullDocument, - PullForPullDetailsFragment, + PullDetailsForPullDetailsDocument, + PullDetailsFragment, PullState, } from "@gen/graphql-types"; -import { fakeDeploymentParams, fakeTimestamp } from "@hosted/fakers"; -import { BranchUtils, PullUtils } from "@hosted/resource-utils"; import { BranchParams, PullParams } from "@lib/params"; -export const pullParams: PullParams = { - ...fakeDeploymentParams(), +export const pullParams: Required = { databaseName: "test", - pullId: "5", + refName: "main", + fromBranchName: "taylor/feature-branch", }; -const pullId = PullUtils.rn.fromParams(pullParams); +export const pullWithDetails = ( + params: Required, +): PullDetailsFragment => { + return { + __typename: "PullWithDetails", + state: PullState.Merged, + _id: `databases/${params.databaseName}/pulls/${params.refName}/${params.fromBranchName}`, + details: [], + }; +}; -export const pull: PullForPullDetailsFragment = { - ...pullParams, - __typename: "Pull", - _id: pullId, - title: "Pull Title", - description: "", - state: PullState.Merged, - creatorName: "taylor", - fromBranchName: "taylor/feature-branch", - toBranchName: "master", - createdAt: fakeTimestamp(), +export const pullDetailsMock = ( + params: Required, +): MockedResponse => { + return { + request: { + query: PullDetailsForPullDetailsDocument, + variables: { ...params, toBranchName: params.refName }, + }, + result: { data: { pullWithDetails } }, + }; }; const branchParams: BranchParams = { - ownerName: pull.ownerName, - deploymentName: pull.deploymentName, - branchName: pull.fromBranchName, - databaseName: pull.databaseName, + branchName: pullParams.fromBranchName, + databaseName: pullParams.databaseName, }; export const branchExistsMock = ( - branchName = pull.fromBranchName, + branchName = pullParams.fromBranchName, ): MockedResponse => { const params = { ...branchParams, branchName }; return { @@ -51,7 +56,7 @@ export const branchExistsMock = ( data: { branch: { __typename: "Branch", - _id: BranchUtils.rn.fromParams(params), + _id: `databases/${params.databaseName}/branches/${params.branchName}`, }, }, }, @@ -70,7 +75,7 @@ export const deleteBranchNewData = jest.fn(() => { }); export const deleteBranchMock = ( - branchName = pull.fromBranchName, + branchName = pullParams.fromBranchName, ): MockedResponse => { return { request: { diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx index bae19d53..cfec60ec 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx @@ -25,11 +25,10 @@ type Props = { export default function MergeButton(props: Props) { // const { setState } = usePullDetailsContext(); const [showDirections, setShowDirections] = useState(false); + const variables = { ...props.params, toBranchName: props.params.refName }; const { mutateFn: merge, ...res } = useMutation({ hook: useMergePullMutation, - refetchQueries: [ - { query: PullDetailsForPullDetailsDocument, variables: props.params }, - ], + refetchQueries: [{ query: PullDetailsForPullDetailsDocument, variables }], }); const hasConflicts = errorMatches(gqlPullHasConflicts, res.err); @@ -38,7 +37,7 @@ export default function MergeButton(props: Props) { const red = hasConflicts; const onClick = async () => { - await merge({ variables: props.params }); + await merge({ variables }); // setState({ isMerging: true }); }; diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/utils.ts b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/utils.ts index 216d626e..d4d5a09c 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/utils.ts +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/utils.ts @@ -1,6 +1,6 @@ import { PullDiffParams } from "@lib/params"; export function getMergeCommands(params: PullDiffParams): string { - return `CALL DOLT_CHECKOUT("${params.toBranchName}"); + return `CALL DOLT_CHECKOUT("${params.refName}"); CALL DOLT_MERGE("${params.fromBranchName}");`; } diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css index 0d6e008b..cc389b1a 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullDetailsList/index.module.css @@ -16,4 +16,8 @@ .verticalLine { @apply border-l w-0 h-8 ml-3 lg:ml-[4.25rem]; + + &:last-of-type { + @apply h-14; + } } diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css index 27a7d55b..594f2802 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.module.css @@ -1,5 +1,5 @@ .top { - @apply flex justify-between items-center py-10 ml-6 mr-10 border-b; + @apply flex justify-between items-center flex-wrap py-10 ml-6 mr-10 border-b; button { @apply ml-6; diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx index 567e0f5f..364b6c5e 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/index.tsx @@ -28,7 +28,9 @@ type BranchesProps = { }; function ForBranches(props: BranchesProps) { - const res = usePullDetailsForPullDetailsQuery({ variables: props.params }); + const res = usePullDetailsForPullDetailsQuery({ + variables: { ...props.params, toBranchName: props.params.refName }, + }); useEffect(() => { if (!res.data) return; @@ -63,13 +65,13 @@ function Inner(props: Props) {
    {props.params.fromBranchName && - props.params.toBranchName && + props.params.refName && pullState === PullState.Open && ( @@ -81,12 +83,12 @@ function Inner(props: Props) {
    - {props.params.fromBranchName && props.params.toBranchName ? ( + {props.params.fromBranchName && props.params.refName ? ( diff --git a/packages/web/lib/params.ts b/packages/web/lib/params.ts index 248e1888..6022be7f 100644 --- a/packages/web/lib/params.ts +++ b/packages/web/lib/params.ts @@ -73,15 +73,12 @@ export type DiffParamsWithRefs = DatabaseParams & { export type PullParams = OptionalRefParams & { fromBranchName?: string; - toBranchName?: string; }; -export type RequiredPullDiffParams = DatabaseParams & { +export type RequiredPullDiffParams = RefParams & { fromBranchName: string; - toBranchName: string; }; export type PullDiffParams = RequiredPullDiffParams & { - refName?: string; tableName?: string; }; diff --git a/packages/web/lib/testUtils.test.ts b/packages/web/lib/testUtils.test.ts index 3fb6c6ff..31da2f59 100644 --- a/packages/web/lib/testUtils.test.ts +++ b/packages/web/lib/testUtils.test.ts @@ -49,8 +49,3 @@ export function setup(jsx: React.ReactElement) { ...render(jsx), }; } - -// Need to place the above functions in a .test.tsx file, so there needs to be at least one test in the file -describe("utils test", () => { - it("works", () => {}); -}); diff --git a/packages/web/lib/urls.ts b/packages/web/lib/urls.ts index c49c13b5..8cf6d52a 100644 --- a/packages/web/lib/urls.ts +++ b/packages/web/lib/urls.ts @@ -89,15 +89,14 @@ export const pulls = (p: ps.PullParams): Route => staticPulls(p).withQuery({ refName: p.refName, from: p.fromBranchName, - to: p.toBranchName, }); export const pullDiff = (p: ps.PullDiffParams): Route => staticPulls(p) .addStatic("compare") + .addDynamic("refName", p.refName, ENCODE) .addDynamic("fromBranchName", p.fromBranchName, ENCODE) - .addDynamic("toBranchName", p.toBranchName, ENCODE) - .withQuery({ refName: p.refName, tableName: p.tableName }); + .withQuery({ tableName: p.tableName }); export const newRelease = (p: ps.OptionalRefParams): Route => releases(p).addStatic("new").withQuery({ refName: p.refName }); diff --git a/packages/web/pages/database/[databaseName]/pulls/compare/[fromBranchName]/[toBranchName]/index.tsx b/packages/web/pages/database/[databaseName]/pulls/compare/[refName]/[fromBranchName]/index.tsx similarity index 74% rename from packages/web/pages/database/[databaseName]/pulls/compare/[fromBranchName]/[toBranchName]/index.tsx rename to packages/web/pages/database/[databaseName]/pulls/compare/[refName]/[fromBranchName]/index.tsx index d7655a71..09a72cb0 100644 --- a/packages/web/pages/database/[databaseName]/pulls/compare/[fromBranchName]/[toBranchName]/index.tsx +++ b/packages/web/pages/database/[databaseName]/pulls/compare/[refName]/[fromBranchName]/index.tsx @@ -5,9 +5,7 @@ import DatabasePage from "@pageComponents/DatabasePage"; import { GetServerSideProps, NextPage } from "next"; type Props = { - params: RequiredPullDiffParams & { - refName?: Maybe; - }; + params: RequiredPullDiffParams; tableName?: Maybe; }; @@ -17,8 +15,7 @@ const PullDiffPage: NextPage = ({ params, tableName }) => ( params={{ databaseName: params.databaseName, fromBranchName: params.fromBranchName, - toBranchName: params.toBranchName, - refName: params.refName ?? undefined, + refName: params.refName, }} tableName={tableName ?? undefined} /> @@ -31,10 +28,7 @@ export const getServerSideProps: GetServerSideProps = async ({ }) => { return { props: { - params: { - ...(params as RequiredPullDiffParams), - refName: query.refName ? String(query.refName) : null, - }, + params: params as RequiredPullDiffParams, tableName: query.tableName ? String(query.tableName) : null, }, }; diff --git a/packages/web/pages/database/[databaseName]/pulls/index.tsx b/packages/web/pages/database/[databaseName]/pulls/index.tsx index abc32dba..1701f925 100644 --- a/packages/web/pages/database/[databaseName]/pulls/index.tsx +++ b/packages/web/pages/database/[databaseName]/pulls/index.tsx @@ -7,7 +7,6 @@ import { GetServerSideProps, NextPage } from "next"; type Props = { params: MaybeRefParams & { from?: Maybe; - to?: Maybe; }; }; @@ -18,7 +17,6 @@ const PullsPage: NextPage = ({ params }) => ( databaseName: params.databaseName, refName: params.refName ?? undefined, fromBranchName: params.from ?? undefined, - toBranchName: params.to ?? undefined, }} /> @@ -34,7 +32,6 @@ export const getServerSideProps: GetServerSideProps = async ({ ...(params as DatabaseParams), refName: query.refName ? String(query.refName) : null, from: query.from ? String(query.from) : null, - to: query.to ? String(query.to) : null, }, }, }; From 056a2695ad4ab28952b6eedb29e857daef04a346 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 16:27:21 -0800 Subject: [PATCH 10/13] web: Cleanup --- .../web/components/DiffSelector/ForPull.tsx | 4 +- .../components/DiffSelector/index.module.css | 6 +- .../web/components/DiffTableNav/ForPull.tsx | 20 +------ .../DiffTableNav/PullCommits/index.module.css | 20 ------- .../DiffTableNav/PullCommits/index.tsx | 58 ------------------- .../DiffTableNav/PullCommits/queries.ts | 20 ------- .../DatabasePage/ForPullDiff/index.tsx | 4 +- .../ForPulls/PullActions/Merge/Arrow.tsx | 15 +++++ .../PullActions/Merge/MergeButton.tsx | 3 +- .../PullActions/Merge/index.module.css | 23 ++++++++ packages/web/gen/graphql-types.tsx | 53 ----------------- packages/web/lib/params.ts | 8 +-- packages/web/lib/urls.ts | 3 +- .../[refName]/[fromBranchName]/index.tsx | 6 +- 14 files changed, 55 insertions(+), 188 deletions(-) delete mode 100644 packages/web/components/DiffTableNav/PullCommits/index.module.css delete mode 100644 packages/web/components/DiffTableNav/PullCommits/index.tsx delete mode 100644 packages/web/components/DiffTableNav/PullCommits/queries.ts create mode 100644 packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/Arrow.tsx diff --git a/packages/web/components/DiffSelector/ForPull.tsx b/packages/web/components/DiffSelector/ForPull.tsx index d2c77035..e0308bfe 100644 --- a/packages/web/components/DiffSelector/ForPull.tsx +++ b/packages/web/components/DiffSelector/ForPull.tsx @@ -8,8 +8,8 @@ type Props = { export default function ForPull(props: Props) { return ( - Viewing changes between {props.params.fromBranchName} and{" "} - {props.params.refName} + Viewing changes between {props.params.refName} and{" "} + {props.params.fromBranchName} ); } diff --git a/packages/web/components/DiffSelector/index.module.css b/packages/web/components/DiffSelector/index.module.css index e423cac5..e3b88bfb 100644 --- a/packages/web/components/DiffSelector/index.module.css +++ b/packages/web/components/DiffSelector/index.module.css @@ -1,5 +1,9 @@ .selector { - @apply mx-3 py-3 text-primary; + @apply mx-3 py-3 text-primary break-words; + + code { + @apply text-sm; + } } .branch { diff --git a/packages/web/components/DiffTableNav/ForPull.tsx b/packages/web/components/DiffTableNav/ForPull.tsx index 13e9a64e..b0086afd 100644 --- a/packages/web/components/DiffTableNav/ForPull.tsx +++ b/packages/web/components/DiffTableNav/ForPull.tsx @@ -3,7 +3,6 @@ import DiffStat from "@components/DiffStat"; import { PullDiffParams } from "@lib/params"; import DiffTableStats from "./DiffTableStats"; import DiffTableNav from "./component"; -import css from "./index.module.css"; type Props = { params: PullDiffParams; @@ -11,23 +10,6 @@ type Props = { }; export default function ForPull(props: Props) { - const selector = ; - if (!props.params.fromBranchName || !props.params.refName) { - return ( - - Select branches to view diff -

    - } - diffTables={null} - forPull - /> - ); - } - const params = { ...props.params, fromRefName: props.params.fromBranchName, @@ -36,7 +18,7 @@ export default function ForPull(props: Props) { return ( } diffStat={} diffTables={} forPull diff --git a/packages/web/components/DiffTableNav/PullCommits/index.module.css b/packages/web/components/DiffTableNav/PullCommits/index.module.css deleted file mode 100644 index 3487c47b..00000000 --- a/packages/web/components/DiffTableNav/PullCommits/index.module.css +++ /dev/null @@ -1,20 +0,0 @@ -.container { - @apply mx-3; - - h4, - p { - @apply my-4; - } - - li { - @apply mb-5; - } -} - -.hash { - @apply text-sm block font-mono text-ld-darkgrey; -} - -.message { - @apply text-sm; -} diff --git a/packages/web/components/DiffTableNav/PullCommits/index.tsx b/packages/web/components/DiffTableNav/PullCommits/index.tsx deleted file mode 100644 index 7d4bb9d5..00000000 --- a/packages/web/components/DiffTableNav/PullCommits/index.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import QueryHandler from "@components/util/QueryHandler"; -import { - CommitForHistoryFragment, - usePullCommitsQuery, -} from "@gen/graphql-types"; -import excerpt from "@lib/excerpt"; -import { DiffParamsWithRefs } from "@lib/params"; -import css from "./index.module.css"; - -type Props = { - params: DiffParamsWithRefs & { refName?: string }; -}; - -type InnerProps = Props & { - commits: CommitForHistoryFragment[]; -}; - -function Inner(props: InnerProps) { - return ( -
    - {props.commits.length ? ( -
      - {props.commits.map(c => ( -
    • - {c.commitId} - {excerpt(c.message, 100)} -
    • - ))} -
    - ) : ( -

    - {props.params.toRefName} is up to date with commits from{" "} - {props.params.fromRefName} -

    - )} -
    - ); -} - -export default function PullCommits(props: Props) { - const res = usePullCommitsQuery({ - variables: { - ...props.params, - refName: props.params.fromRefName, - excludingCommitsFromRefName: props.params.toRefName, - }, - }); - - return ( -
    -

    Commits

    - } - /> -
    - ); -} diff --git a/packages/web/components/DiffTableNav/PullCommits/queries.ts b/packages/web/components/DiffTableNav/PullCommits/queries.ts deleted file mode 100644 index 2fec6ed6..00000000 --- a/packages/web/components/DiffTableNav/PullCommits/queries.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { gql } from "@apollo/client"; - -export const PULL_COMMITS = gql` - query PullCommits( - $databaseName: String! - $refName: String! - $excludingCommitsFromRefName: String! - ) { - commits( - databaseName: $databaseName - refName: $refName - excludingCommitsFromRefName: $excludingCommitsFromRefName - twoDot: true - ) { - list { - ...CommitForHistory - } - } - } -`; diff --git a/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx index 563831c8..700cb094 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPullDiff/index.tsx @@ -3,12 +3,12 @@ import DiffTableNav from "@components/DiffTableNav"; import PullDiffBreadcrumbs from "@components/breadcrumbs/PullDiffBreadcrumbs"; import NotDoltWrapper from "@components/util/NotDoltWrapper"; import { DiffProvider } from "@contexts/diff"; -import { RequiredPullDiffParams } from "@lib/params"; +import { PullDiffParams } from "@lib/params"; import { pulls } from "@lib/urls"; import ForDefaultBranch from "../ForDefaultBranch"; type Props = { - params: RequiredPullDiffParams; + params: PullDiffParams; tableName?: string; }; diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/Arrow.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/Arrow.tsx new file mode 100644 index 00000000..3c812e69 --- /dev/null +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/Arrow.tsx @@ -0,0 +1,15 @@ +import cx from "classnames"; +import css from "./index.module.css"; + +export function Arrow(props: { red?: boolean; green?: boolean }) { + return ( +
    +
    +
    + ); +} diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx index cfec60ec..b786fa17 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/MergeButton.tsx @@ -11,6 +11,7 @@ import { PullDiffParams } from "@lib/params"; import { FiGitPullRequest } from "@react-icons/all-files/fi/FiGitPullRequest"; import cx from "classnames"; import { useState } from "react"; +import { Arrow } from "./Arrow"; import ErrorsWithDirections from "./ErrorsWithDirections"; import MergeConflictsDirections from "./ErrorsWithDirections/MergeConflictsDirections"; import MergeMessage from "./MergeMessage"; @@ -46,7 +47,7 @@ export default function MergeButton(props: Props) { - {/* */} +
    diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.module.css b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.module.css index 4882a2da..d0ac96a2 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.module.css +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/Merge/index.module.css @@ -103,3 +103,26 @@ .toggle { @apply font-normal text-ld-darkgrey border-none px-3 text-sm hidden lg:contents; } + +.arrow { + @apply relative z-10; +} + +.arrowGrey { + @apply border-ld-lightgrey bg-ld-lightpurple; +} + +.arrowRed { + @apply border-acc-red bg-[#FDEEED]; +} + +.arrowGreen { + @apply bg-[#E6F6EE] border-acc-green; +} + +.arrowLeft { + @apply w-4 h-4 absolute rounded-sm rotate-45 border-l border-t -top-2 left-3; + @screen lg { + @apply border-b border-t-0 left-[0.3rem] top-[1.2rem]; + } +} diff --git a/packages/web/gen/graphql-types.tsx b/packages/web/gen/graphql-types.tsx index 36f51ade..9c2b646c 100644 --- a/packages/web/gen/graphql-types.tsx +++ b/packages/web/gen/graphql-types.tsx @@ -762,15 +762,6 @@ export type SchemaDiffQueryVariables = Exact<{ export type SchemaDiffQuery = { __typename?: 'Query', schemaDiff?: { __typename?: 'SchemaDiff', schemaPatch?: Array | null, schemaDiff?: { __typename?: 'TextDiff', leftLines: string, rightLines: string } | null } | null }; -export type PullCommitsQueryVariables = Exact<{ - databaseName: Scalars['String']['input']; - refName: Scalars['String']['input']; - excludingCommitsFromRefName: Scalars['String']['input']; -}>; - - -export type PullCommitsQuery = { __typename?: 'Query', commits: { __typename?: 'CommitList', list: Array<{ __typename?: 'Commit', _id: string, message: string, commitId: string, committedAt: any, parents: Array, committer: { __typename?: 'DoltWriter', _id: string, username?: string | null, displayName: string, emailAddress: string } }> } }; - export type ColumnsListForTableListFragment = { __typename?: 'IndexColumn', name: string, sqlType?: string | null }; export type IndexForTableListFragment = { __typename?: 'Index', name: string, type: string, comment: string, columns: Array<{ __typename?: 'IndexColumn', name: string, sqlType?: string | null }> }; @@ -1966,50 +1957,6 @@ export function useSchemaDiffLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions export type SchemaDiffQueryHookResult = ReturnType; export type SchemaDiffLazyQueryHookResult = ReturnType; export type SchemaDiffQueryResult = Apollo.QueryResult; -export const PullCommitsDocument = gql` - query PullCommits($databaseName: String!, $refName: String!, $excludingCommitsFromRefName: String!) { - commits( - databaseName: $databaseName - refName: $refName - excludingCommitsFromRefName: $excludingCommitsFromRefName - twoDot: true - ) { - list { - ...CommitForHistory - } - } -} - ${CommitForHistoryFragmentDoc}`; - -/** - * __usePullCommitsQuery__ - * - * To run a query within a React component, call `usePullCommitsQuery` and pass it any options that fit your needs. - * When your component renders, `usePullCommitsQuery` 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 } = usePullCommitsQuery({ - * variables: { - * databaseName: // value for 'databaseName' - * refName: // value for 'refName' - * excludingCommitsFromRefName: // value for 'excludingCommitsFromRefName' - * }, - * }); - */ -export function usePullCommitsQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(PullCommitsDocument, options); - } -export function usePullCommitsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(PullCommitsDocument, options); - } -export type PullCommitsQueryHookResult = ReturnType; -export type PullCommitsLazyQueryHookResult = ReturnType; -export type PullCommitsQueryResult = Apollo.QueryResult; export const TableListForSchemasDocument = gql` query TableListForSchemas($databaseName: String!, $refName: String!) { tables(databaseName: $databaseName, refName: $refName, filterSystemTables: true) { diff --git a/packages/web/lib/params.ts b/packages/web/lib/params.ts index 6022be7f..ae8d915d 100644 --- a/packages/web/lib/params.ts +++ b/packages/web/lib/params.ts @@ -75,10 +75,4 @@ export type PullParams = OptionalRefParams & { fromBranchName?: string; }; -export type RequiredPullDiffParams = RefParams & { - fromBranchName: string; -}; - -export type PullDiffParams = RequiredPullDiffParams & { - tableName?: string; -}; +export type PullDiffParams = Required; diff --git a/packages/web/lib/urls.ts b/packages/web/lib/urls.ts index 8cf6d52a..f92a634e 100644 --- a/packages/web/lib/urls.ts +++ b/packages/web/lib/urls.ts @@ -95,8 +95,7 @@ export const pullDiff = (p: ps.PullDiffParams): Route => staticPulls(p) .addStatic("compare") .addDynamic("refName", p.refName, ENCODE) - .addDynamic("fromBranchName", p.fromBranchName, ENCODE) - .withQuery({ tableName: p.tableName }); + .addDynamic("fromBranchName", p.fromBranchName, ENCODE); export const newRelease = (p: ps.OptionalRefParams): Route => releases(p).addStatic("new").withQuery({ refName: p.refName }); diff --git a/packages/web/pages/database/[databaseName]/pulls/compare/[refName]/[fromBranchName]/index.tsx b/packages/web/pages/database/[databaseName]/pulls/compare/[refName]/[fromBranchName]/index.tsx index 09a72cb0..71e7df67 100644 --- a/packages/web/pages/database/[databaseName]/pulls/compare/[refName]/[fromBranchName]/index.tsx +++ b/packages/web/pages/database/[databaseName]/pulls/compare/[refName]/[fromBranchName]/index.tsx @@ -1,11 +1,11 @@ import Page from "@components/util/Page"; import Maybe from "@lib/Maybe"; -import { RequiredPullDiffParams } from "@lib/params"; +import { PullDiffParams } from "@lib/params"; import DatabasePage from "@pageComponents/DatabasePage"; import { GetServerSideProps, NextPage } from "next"; type Props = { - params: RequiredPullDiffParams; + params: PullDiffParams; tableName?: Maybe; }; @@ -28,7 +28,7 @@ export const getServerSideProps: GetServerSideProps = async ({ }) => { return { props: { - params: params as RequiredPullDiffParams, + params: params as PullDiffParams, tableName: query.tableName ? String(query.tableName) : null, }, }; From 3ba06aa6976223fbf499ab7b7b14584f24598ec2 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 16:36:45 -0800 Subject: [PATCH 11/13] web: Fix test --- packages/web/jest.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/web/jest.config.js b/packages/web/jest.config.js index 01636e49..982984a9 100644 --- a/packages/web/jest.config.js +++ b/packages/web/jest.config.js @@ -23,7 +23,11 @@ const customJestConfig = { "@hooks/(.*)": "/hooks/$1", "@lib/(.*)": "/lib/$1", }, - testPathIgnorePatterns: ["/.next/", "/node_modules/"], + testPathIgnorePatterns: [ + "/.next/", + "/node_modules/", + "/lib/testUtils.test.ts", + ], moduleFileExtensions: ["ts", "tsx", "js", "jsx"], collectCoverage: false, }; From 99a6cf65f7f241f4c3de9a8d590c0e5f08d1dbb2 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 16:42:02 -0800 Subject: [PATCH 12/13] web: Hide delete branch for same branch selected --- .../DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx index fe9fee7a..59021c1b 100644 --- a/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx +++ b/packages/web/components/pageComponents/DatabasePage/ForPulls/PullActions/DeleteBranch/index.tsx @@ -55,7 +55,8 @@ function Inner(props: InnerProps) { if ( !props.branchExists || - props.params.fromBranchName === defaultBranchName + props.params.fromBranchName === defaultBranchName || + props.params.fromBranchName === props.params.refName ) { return null; } From 798360ff7bf64d11a88c482f465399912d663300 Mon Sep 17 00:00:00 2001 From: Taylor Bantle Date: Wed, 8 Nov 2023 16:49:53 -0800 Subject: [PATCH 13/13] web: Css fix --- packages/web/components/DiffTable/index.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/components/DiffTable/index.module.css b/packages/web/components/DiffTable/index.module.css index 4550395f..5652f31e 100644 --- a/packages/web/components/DiffTable/index.module.css +++ b/packages/web/components/DiffTable/index.module.css @@ -23,7 +23,7 @@ } .buttons { - @apply w-full mx-2 text-acc-hoverlinkblue; + @apply mx-2 text-acc-hoverlinkblue; button { @apply pb-2 mr-4 px-6 font-semibold;