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 acceptedAt sort and acceptedBy to listings #33

Open
wants to merge 2 commits into
base: dev
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
26 changes: 18 additions & 8 deletions src/Entity/Listing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,21 @@ export class Listing extends BaseEntity {

@ManyToOne(() => Objkt, objkt => objkt.listings)
objkt: Objkt

@Column()
objktId: number

@ManyToOne(() => Article, article => article.listings)
article?: Article

@Column()
articleId: number

@Field({
description: "The amount of the asset in the listing. For NFTs it will always be 1."
})
@Column({ type: "bigint" })
amount: number
amount: number

@Field({
description: "The listing price, **in mutez**"
Expand All @@ -77,7 +77,7 @@ export class Listing extends BaseEntity {
@Column({ type: "timestamptz" })
@Filter([ "gte", "lte" ], type => Date)
createdAt: Date

@Field({
nullable: true,
description: "When the listing was cancelled by the seller (if null, listing was never cancelled)",
Expand All @@ -86,7 +86,7 @@ export class Listing extends BaseEntity {
@Filter([ "gte", "lte" ], type => Date)
@Filter([ "exist" ], type => Boolean)
cancelledAt: Date

@Field({
nullable: true,
description: "When the listing was accepted by the buyer (if null, listing was never accepted)",
Expand All @@ -96,7 +96,17 @@ export class Listing extends BaseEntity {
@Filter([ "exist" ], type => Boolean)
acceptedAt: Date


@Field(type => User, {
nullable: true,
description: "The buyer that has accepted the listing",
})
@Index()
@ManyToOne(() => User, user => user.acceptedListings)
acceptedBy: User

@Column()
acceptedById: string

//
// FILTERS FOR THE GQL ENDPOINT
//
Expand All @@ -117,4 +127,4 @@ export class Listing extends BaseEntity {
asset: EListingAssetType
}

export const FiltersListing = generateFilterType(Listing)
export const FiltersListing = generateFilterType(Listing)
3 changes: 3 additions & 0 deletions src/Entity/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ export class User extends BaseEntity {
@Column({ type: "timestamptz", transformer: DateTransformer })
updatedAt: string

@OneToMany(() => Listing, listing => listing.acceptedBy)
acceptedListings: Listing[]

//
// CUSTOM FILTERS
//
Expand Down
32 changes: 18 additions & 14 deletions src/Resolver/Arguments/Sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type TSortValue = "ASC" | "DESC"
type TSortInput = Record<string, TSortValue>

/**
* Given an input sort (currentSort) and a default sort input, outputs the
* Given an input sort (currentSort) and a default sort input, outputs the
* default sort input only if the input sort is empty, otherwise outputs the
* input sort.
*/
Expand All @@ -26,11 +26,15 @@ export class ListingsSortInput {
@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
price?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
createdAt?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
acceptedAt?: "ASC" | "DESC"

// search-related sort filter
@Field(type => String, { nullable: true })
@IsIn(["DESC"])
Expand All @@ -43,7 +47,7 @@ export class OffersSortInput {
@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
price?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
createdAt?: "ASC" | "DESC"
Expand All @@ -55,11 +59,11 @@ export class ObjktsSortInput {
@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
id?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
listingPrice?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
listingCreatedAt?: "ASC" | "DESC"
Expand All @@ -75,7 +79,7 @@ export class ObjktsSortInput {
@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
iteration?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
collectedAt?: "ASC" | "DESC"
Expand All @@ -91,23 +95,23 @@ export class ObjktsSortInput {
}

@InputType()
export class GenerativeSortInput {
export class GenerativeSortInput {
@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
lockEnd?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
mintOpensAt?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
price?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
supply?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
balance?: "ASC" | "DESC"
Expand Down Expand Up @@ -193,11 +197,11 @@ export class ActionsSortInput {
}

@InputType()
export class UserSortInput {
export class UserSortInput {
@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
createdAt?: "ASC" | "DESC"

// search-related sort filter
@Field(type => String, { nullable: true })
@IsIn(["DESC"])
Expand All @@ -221,9 +225,9 @@ export class ArticleSortInput {
@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
royalties?: "ASC" | "DESC"

// search-related sort filter
@Field(type => String, { nullable: true })
@IsIn(["DESC"])
relevance?: "DESC"
}
}
34 changes: 24 additions & 10 deletions src/Resolver/ListingResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class ListingResolver {
return ctx.usersLoader.load(listing.issuerId)
}

@FieldResolver(returns => Objkt, {
@FieldResolver(returns => Objkt, {
nullable: true,
description: "The objkt associated with the listing, if any."
})
Expand All @@ -37,7 +37,7 @@ export class ListingResolver {
return ctx.objktsLoader.load(listing.objktId)
}

@FieldResolver(returns => Article, {
@FieldResolver(returns => Article, {
nullable: true,
description: "The article associated with the listing, if any."
})
Expand All @@ -49,8 +49,22 @@ export class ListingResolver {
if (listing.article) return listing.article
return ctx.articlesLoader.load(listing.articleId)
}

@Query(returns => [Listing],{

@FieldResolver(returns => User, {
nullable: true,
description: "The user who bought the listing."
})
acceptedBy(
@Root() listing: Listing,
@Ctx() ctx: RequestContext
) {
if (listing.acceptedById === null) return null
if (listing.acceptedBy) return listing.acceptedBy
return ctx.usersLoader.load(listing.acceptedById)
}


@Query(returns => [Listing],{
description: "The go-to endpoint to explore Listings on the marketplace. This endpoint both returns Listings made on the old and new marketplace contracts. **By default, only returns active listings (not accepted nor cancelled)**"
})
async listings(
Expand Down Expand Up @@ -82,7 +96,7 @@ export class ListingResolver {

// if their is a search string, we first make a request to the search engine to get results
if (filters?.searchQuery_eq) {
const searchResults = await searchIndexMarketplace.search(filters.searchQuery_eq, {
const searchResults = await searchIndexMarketplace.search(filters.searchQuery_eq, {
hitsPerPage: 5000
})

Expand All @@ -99,7 +113,7 @@ export class ListingResolver {
`(listing.id, listing.version) IN(${formatted})`
)
}

// if the sort option is relevance, we remove the sort arguments as the order
// of the search results needs to be preserved
if (sortArgs.relevance && ids.length > 1) {
Expand Down Expand Up @@ -135,7 +149,7 @@ export class ListingResolver {
query.andWhere("token.balance > 0")
}
}

// filter for author of the listing verified
if (filters?.authorVerified_eq != null) {
query.leftJoin("token.author", "author")
Expand All @@ -160,7 +174,7 @@ export class ListingResolver {
if (filters.asset_eq) {
if (filters.asset_eq === EListingAssetType.ARTICLE) {
query.andWhere("listing.articleId IS NOT NULL")
}
}
else if (filters.asset_eq === EListingAssetType.GENTK) {
query.andWhere("listing.objktId IS NOT NULL")
}
Expand All @@ -181,7 +195,7 @@ export class ListingResolver {

return query.getMany()
}

@Query(returns => [Listing], {
nullable: true,
description: "Given a list of Listing identifiers (ID + contract-version), outputs the associated listings.",
Expand All @@ -198,4 +212,4 @@ export class ListingResolver {

return query.getMany()
}
}
}
Loading