Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add (record|remove)ArtworkView mutations #6323

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 30 additions & 14 deletions _schemaV2.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -14057,10 +14057,16 @@ type Mutation {
input: MyCollectionUpdateArtworkInput!
): MyCollectionUpdateArtworkPayload
publishViewingRoom(input: PublishViewingRoomInput!): PublishViewingRoomPayload

# Record an artwork view.
recordArtworkView(
# Parameters for RecordArtworkView
input: RecordArtworkViewInput!
): RecordArtworkViewPayload
input: RecordArtworkViewMutationInput!
): RecordArtworkViewMutationPayload

# Remove an artwork view.
removeArtworkView(
input: RemoveArtworkViewMutationInput!
): RemoveArtworkViewMutationPayload
removeAssetFromConsignmentSubmission(
# Parameters for RemoveAssetFromConsignmentSubmission
input: RemoveAssetFromConsignmentSubmissionInput!
Expand Down Expand Up @@ -17717,23 +17723,18 @@ type RecentlySoldArtworkTypeEdge {
node: RecentlySoldArtworkType
}

# Autogenerated input type of RecordArtworkView
input RecordArtworkViewInput {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a cool thingy @mzikherman taught me - if not sure whether schema will add a breaking change - copy new schema to clients and run yarn relay. I did it in Force and Eigen. Force doesn't complain, but Eigen does:

[ERROR] Error: ✖︎ Unknown type 'RecordArtworkViewInput'. Did you mean `RecordArtworkViewMutationInput`?

  src/app/Scenes/Artwork/Artwork.tsx:261:59
  260 
  261 │         mutation ArtworkMarkAsRecentlyViewedQuery($input: RecordArtworkViewInput!) {
      │                                                           ^^^^^^^^^^^^^^^^^^^^^^
  262 │           recordArtworkView(input: $input) {

[ERROR] Compilation failed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!! Yeah, this will cause a compilation error for sure because Eigen is explicitly referencing RecordArtworkViewInput which has been removed in this diff. I wonder though if this would also cause a runtime error? Will check on that... if this doesn't cause any runtime backwards-incompatibility, I think we could merge this in (with type name changes) and follow-up with an Eigen PR to address the compilation error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't quote me on this - but I think changing the name like that, if a Relay client explicitly references the name - will indeed cause a runtime error if you merge the schema update. Give it a whirl to confirm (and we start to increase our mental model of how to think about these kinds of changes with our clients).

input RecordArtworkViewMutationInput {
# ID of artwork.
artwork_id: String!

# A unique identifier for the client performing the mutation.
clientMutationId: String
}

# Autogenerated return type of RecordArtworkView
type RecordArtworkViewPayload {
# Id of viewed artwork
type RecordArtworkViewMutationPayload {
# ID of viewed artwork.
artworkId: String!

# Id of viewed artwork
artwork_id: String! @deprecated(reason: "Use artworkId")

# A unique identifier for the client performing the mutation.
# ID of viewed artwork.
artwork_id: String! @deprecated(reason: "Use artworkId.")
clientMutationId: String
}

Expand Down Expand Up @@ -17761,6 +17762,21 @@ type RelatedArtworkGrid implements ArtworkContextGrid {
title: String
}

input RemoveArtworkViewMutationInput {
# ID of artwork.
artwork_id: String!
clientMutationId: String
}

type RemoveArtworkViewMutationPayload {
# ID of viewed artwork.
artworkId: String!

# ID of viewed artwork.
artwork_id: String! @deprecated(reason: "Use artworkId.")
clientMutationId: String
}

# Autogenerated input type of RemoveAssetFromConsignmentSubmission
input RemoveAssetFromConsignmentSubmissionInput {
assetID: String
Expand Down
10 changes: 10 additions & 0 deletions src/lib/loaders/loaders_with_authentication/gravity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ export default (accessToken, userID, opts) => {
{},
{ method: "POST" }
),
createArtworkViewLoader: gravityLoader(
(artworkID) => `artwork/${artworkID}/view`,
{},
{ method: "POST" }
),
createCommerceOptInEligibleArtworksReportLoader: gravityLoader(
(id) => `partner/${id}/commerce_opt_in_eligible_artworks_report`,
{},
Expand Down Expand Up @@ -215,6 +220,11 @@ export default (accessToken, userID, opts) => {
{},
{ method: "DELETE" }
),
deleteArtworkViewLoader: gravityLoader(
(artworkID) => `artwork/${artworkID}/view`,
{},
{ method: "DELETE" }
),
deleteBankAccountLoader: gravityLoader(
(id) => `me/bank_account/${id}`,
{},
Expand Down
3 changes: 3 additions & 0 deletions src/lib/stitching/gravity/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const executableGravitySchema = () => {
excludedMutations.push("updateViewingRoomArtworks")
excludedMutations.push("updateViewingRoomSubsections")
}
excludedMutations.push("recordArtworkView")

// Types which come from Gravity that are not (yet) needed in MP.
// In the future, these can be removed from this list as they are needed.
Expand All @@ -96,6 +97,8 @@ export const executableGravitySchema = () => {
"LotEvent",
"RefundCommissionExemptionInput",
"RefundCommissionExemptionPayload",
"RecordArtworkViewInput",
"RecordArtworkViewPayload",
]

// Return the new modified schema
Expand Down
25 changes: 25 additions & 0 deletions src/schema/v2/__tests__/recordArtworkViewMutation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* eslint-disable promise/always-return */
import { runAuthenticatedQuery } from "schema/v2/test/utils"

describe("recording an artwork view", () => {
const query = `
mutation {
recordArtworkView(input: { artwork_id: "artwork-id" }) {
artworkId
}
}
`

const context = {
createArtworkViewLoader: (id) => Promise.resolve({ artwork_id: id }),
}

it("records an artwork view", async () => {
const data = await runAuthenticatedQuery(query, context)
expect(data).toEqual({
recordArtworkView: {
artworkId: "artwork-id",
},
})
})
})
25 changes: 25 additions & 0 deletions src/schema/v2/__tests__/removeArtworkViewMutation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* eslint-disable promise/always-return */
import { runAuthenticatedQuery } from "schema/v2/test/utils"

describe("removing an artwork view", () => {
const query = `
mutation {
removeArtworkView(input: { artwork_id: "artwork-id" }) {
artworkId
}
}
`

const context = {
deleteArtworkViewLoader: (id) => Promise.resolve({ artwork_id: id }),
}

it("removes an artwork view", async () => {
const data = await runAuthenticatedQuery(query, context)
expect(data).toEqual({
removeArtworkView: {
artworkId: "artwork-id",
},
})
})
})
8 changes: 1 addition & 7 deletions src/schema/v2/me/__tests__/recentlyViewedArtworks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe("RecentlyViewedArtworks", () => {
context = {
meLoader: async () => me,
artworksLoader: async () => artworks,
recordArtworkViewLoader: jest.fn(async () => me),
createArtworkViewLoader: jest.fn(async (id) => ({ artwork_id: id })),
}
})

Expand Down Expand Up @@ -213,12 +213,6 @@ describe("RecentlyViewedArtworks", () => {

const data = await runAuthenticatedQuery(mutation, context)

// The graphQL API
expect(mockFetch).toBeCalledWith(
"https://api.artsy.test/api/graphql",
expect.anything()
)

const artworkID = data!.recordArtworkView.artwork_id
expect(artworkID).toEqual("percy")
})
Expand Down
43 changes: 43 additions & 0 deletions src/schema/v2/recordArtworkView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { GraphQLNonNull, GraphQLString } from "graphql"
import { mutationWithClientMutationId } from "graphql-relay"
import { ResolverContext } from "types/graphql"
import { GraphQLError } from "graphql"

export interface RecordArtworkViewMutationInput {
artwork_id: string
}

export const recordArtworkViewMutation = mutationWithClientMutationId<
RecordArtworkViewMutationInput,
any,
ResolverContext
>({
name: "RecordArtworkViewMutation",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering, if you omit Mutation here - will it produce the schema without changes that break relay (RecordArtworkViewInput -> RecordArtworkViewMutationInput)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, now that I look closer it seems like we're a bit inconsistent with suffixing these names with Mutation in the file itself... I wonder if relay adds Mutation anyway but I'll check.

description: "Record an artwork view.",
inputFields: {
artwork_id: {
type: new GraphQLNonNull(GraphQLString),
description: "ID of artwork.",
},
},
outputFields: {
artwork_id: {
description: "ID of viewed artwork.",
type: new GraphQLNonNull(GraphQLString),
deprecationReason: "Use artworkId.",
},
artworkId: {
description: "ID of viewed artwork.",
type: new GraphQLNonNull(GraphQLString),
},
},
mutateAndGetPayload: async ({ artwork_id }, { createArtworkViewLoader }) => {
try {
const response = await createArtworkViewLoader(artwork_id)

return { artwork_id: response.artwork_id, artworkId: response.artwork_id }
} catch (error) {
throw new GraphQLError(`RecordArtworkViewMutation error: ${error}`)
}
},
})
43 changes: 43 additions & 0 deletions src/schema/v2/removeArtworkView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { GraphQLNonNull, GraphQLString } from "graphql"
import { mutationWithClientMutationId } from "graphql-relay"
import { ResolverContext } from "types/graphql"
import { GraphQLError } from "graphql"

export interface RemoveArtworkViewMutationInput {
artwork_id: string
}

export const removeArtworkViewMutation = mutationWithClientMutationId<
RemoveArtworkViewMutationInput,
any,
ResolverContext
>({
name: "RemoveArtworkViewMutation",
description: "Remove an artwork view.",
inputFields: {
artwork_id: {
type: new GraphQLNonNull(GraphQLString),
description: "ID of artwork.",
},
},
outputFields: {
artwork_id: {
description: "ID of viewed artwork.",
type: new GraphQLNonNull(GraphQLString),
deprecationReason: "Use artworkId.",
},
artworkId: {
description: "ID of viewed artwork.",
type: new GraphQLNonNull(GraphQLString),
},
},
mutateAndGetPayload: async ({ artwork_id }, { deleteArtworkViewLoader }) => {
try {
const response = await deleteArtworkViewLoader(artwork_id)

return { artworkId: response.artwork_id }
} catch (error) {
throw new GraphQLError(`RemoveArtworkViewMutation error: ${error}`)
}
},
})
4 changes: 4 additions & 0 deletions src/schema/v2/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ import { unpublishViewingRoomMutation } from "./viewingRooms/mutations/unpublish
import { updateViewingRoomArtworksMutation } from "./viewingRooms/mutations/updateViewingRoomArtworks"
import { updateViewingRoomSubsectionsMutation } from "./viewingRooms/mutations/updateViewingRoomSubsections"
import { ViewingRoomConnection } from "./viewingRooms"
import { recordArtworkViewMutation } from "./recordArtworkView"
import { removeArtworkViewMutation } from "./removeArtworkView"

const viewingRoomUnstitchedRootField = config.USE_UNSTITCHED_VIEWING_ROOM_SCHEMA
? {
Expand Down Expand Up @@ -506,6 +508,8 @@ export default new GraphQLSchema({
myCollectionCreateArtwork: myCollectionCreateArtworkMutation,
myCollectionDeleteArtwork: myCollectionDeleteArtworkMutation,
myCollectionUpdateArtwork: myCollectionUpdateArtworkMutation,
recordArtworkView: recordArtworkViewMutation,
removeArtworkView: removeArtworkViewMutation,
requestCredentialsForAssetUpload: CreateAssetRequestLoader,
requestPriceEstimate: requestPriceEstimateMutation,
saveArtwork: saveArtworkMutation,
Expand Down