Skip to content

Commit

Permalink
feat(First Listed At): Support sorting by firstListedAt (#211)
Browse files Browse the repository at this point in the history
* feat: Sort by first listed at

* chore: Update commons

* chore: Master package files

* chore: Update commons

* chore: Master package files

* chore: Update commons

* fix: Tests

* chore: Master package files

* chore: Update commons

* chore: Test getCollectionsQuery

* chore: Test fromCollectionFragment

* chore: Test getItemQuery

* chore: Test fromItemFragment

* chore: Use SortDirection instead of strings
  • Loading branch information
fzavalia authored Jan 31, 2023
1 parent d89dcdc commit 781bce4
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 27 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"printWidth": 80
},
"dependencies": {
"@dcl/schemas": "^6.5.0",
"@dcl/schemas": "^6.6.0",
"@types/sqlite3": "^3.1.7",
"@well-known-components/env-config-provider": "^1.2.0",
"@well-known-components/http-server": "^1.1.6",
Expand Down
1 change: 1 addition & 0 deletions src/adapters/sources/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function createCollectionsSource(
[CollectionSortBy.RECENTLY_REVIEWED]: result.reviewedAt,
[CollectionSortBy.NAME]: result.name,
[CollectionSortBy.SIZE]: result.size,
[CollectionSortBy.RECENTLY_LISTED]: result.firstListedAt,
},
}))
}
Expand Down
1 change: 1 addition & 0 deletions src/adapters/sources/items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function createItemsSource(
[ItemSortBy.RECENTLY_SOLD]: result.soldAt,
[ItemSortBy.NAME]: result.name,
[ItemSortBy.CHEAPEST]: result.available > 0 ? +result.price : null,
[ItemSortBy.RECENTLY_LISTED]: result.firstListedAt,
},
}))
}
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ async function initComponents(): Promise<AppComponents> {
[ItemSortBy.RECENTLY_SOLD]: SortDirection.DESC,
[ItemSortBy.NAME]: SortDirection.ASC,
[ItemSortBy.CHEAPEST]: SortDirection.ASC,
[ItemSortBy.RECENTLY_LISTED]: SortDirection.DESC,
},
maxCount: 1000,
})
Expand Down Expand Up @@ -589,6 +590,7 @@ async function initComponents(): Promise<AppComponents> {
[CollectionSortBy.NEWEST]: SortDirection.DESC,
[CollectionSortBy.RECENTLY_REVIEWED]: SortDirection.DESC,
[CollectionSortBy.SIZE]: SortDirection.DESC,
[CollectionSortBy.RECENTLY_LISTED]: SortDirection.DESC,
},
maxCount: 1000,
})
Expand Down
1 change: 1 addition & 0 deletions src/ports/collections/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export type CollectionFragment = {
createdAt: string
updatedAt: string
reviewedAt: string
firstListedAt: string | null
}
78 changes: 78 additions & 0 deletions src/ports/collections/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { ChainId, CollectionSortBy, Network } from '@dcl/schemas'
import { CollectionFragment } from './types'
import { fromCollectionFragment, getCollectionsQuery } from './utils'

describe('#getCollectionsQuery', () => {
describe('when sortBy is CollectionSortBy.RECENTLY_LISTED', () => {
let query: string

beforeEach(() => {
query = getCollectionsQuery({
sortBy: CollectionSortBy.RECENTLY_LISTED,
})
})

it('should add firstListedAt_not: null where filter', () => {
expect(query.includes('firstListedAt_not: null')).toBeTruthy()
})

it('should add firstListedAt as orderBy', () => {
expect(query.includes('orderBy: firstListedAt')).toBeTruthy()
})

it('should add desc as orderDirection', () => {
expect(query.includes('orderDirection: desc')).toBeTruthy()
})
})
})

describe('#fromCollectionFragment', () => {
let collectionFragment: CollectionFragment

beforeEach(() => {
collectionFragment = {
id: 'id',
urn: 'urn',
name: 'name',
creator: 'creator',
searchIsStoreMinter: false,
itemsCount: 100,
createdAt: '100',
updatedAt: '200',
reviewedAt: '300',
firstListedAt: null,
}
})

describe('when fragment firstListedAt is null', () => {
beforeEach(() => {
collectionFragment.firstListedAt = null
})

it('should return a Collection with firstListedAt as null', () => {
const collection = fromCollectionFragment(
collectionFragment,
Network.MATIC,
ChainId.MATIC_MUMBAI
)

expect(collection.firstListedAt).toBeNull()
})
})

describe('when fragment firstListedAt is "100"', () => {
beforeEach(() => {
collectionFragment.firstListedAt = '100'
})

it('should return a Collection with firstListedAt as 100000', () => {
const collection = fromCollectionFragment(
collectionFragment,
Network.MATIC,
ChainId.MATIC_MUMBAI
)

expect(collection.firstListedAt).toBe(100000)
})
})
})
26 changes: 21 additions & 5 deletions src/ports/collections/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CollectionSortBy,
Network,
} from '@dcl/schemas'
import { SortDirection } from '../merger/types'
import { CollectionFragment } from './types'

export const COLLECTION_DEFAULT_SORT_BY = CollectionSortBy.NAME
Expand All @@ -26,6 +27,9 @@ export function fromCollectionFragment(
size: fragment.itemsCount,
network,
chainId,
firstListedAt: fragment.firstListedAt
? +fragment.firstListedAt * 1000
: null,
}

return collection
Expand All @@ -42,6 +46,7 @@ export const getCollectionFragment = () => `
createdAt
updatedAt
reviewedAt
firstListedAt
}
`

Expand Down Expand Up @@ -87,6 +92,12 @@ export function getCollectionsQuery(
where.push(`searchText_contains: "${search.trim().toLowerCase()}"`)
}

// Sorting by a nullable field will return null values first.
// We do not want them so we filter them out.
if (sortBy === CollectionSortBy.RECENTLY_LISTED) {
where.push('firstListedAt_not: null')
}

const max = 1000
const total = isCount
? max
Expand All @@ -101,22 +112,27 @@ export function getCollectionsQuery(
switch (sortBy) {
case CollectionSortBy.NEWEST:
orderBy = 'createdAt'
orderDirection = 'desc'
orderDirection = SortDirection.DESC
break
case CollectionSortBy.RECENTLY_REVIEWED:
orderBy = 'reviewedAt'
orderDirection = 'desc'
orderDirection = SortDirection.DESC
break
case CollectionSortBy.NAME:
orderBy = 'name'
orderDirection = 'asc'
orderDirection = SortDirection.ASC
break
case CollectionSortBy.SIZE:
orderBy = 'itemsCount'
orderDirection = 'desc'
orderDirection = SortDirection.DESC
break
case CollectionSortBy.RECENTLY_LISTED:
orderBy = 'firstListedAt'
orderDirection = SortDirection.DESC
break
default:
orderBy = 'name'
orderDirection = 'asc'
orderDirection = SortDirection.ASC
}

return `
Expand Down
1 change: 1 addition & 0 deletions src/ports/items/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export type ItemFragment = {
reviewedAt: string
soldAt: string
beneficiary: string
firstListedAt: string | null
}

export interface IItemsComponent {
Expand Down
107 changes: 104 additions & 3 deletions src/ports/items/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { EmotePlayMode, GenderFilterOption } from '@dcl/schemas';
import { getItemsQuery } from './utils';
import {
ChainId,
EmoteCategory,
EmotePlayMode,
GenderFilterOption,
ItemSortBy,
Network,
Rarity,
} from '@dcl/schemas'
import { ItemFragment, FragmentItemType } from './types'
import { fromItemFragment, getItemsQuery } from './utils'

describe("#getItemsQuery", () => {
describe("when minPrice is defined", () => {
Expand Down Expand Up @@ -92,4 +101,96 @@ describe("#getItemsQuery", () => {
)
})
})
});

describe('when sortBy is ItemSortBy.RECENTLY_LISTED', () => {
let query: string

beforeEach(() => {
query = getItemsQuery({
sortBy: ItemSortBy.RECENTLY_LISTED,
})
})

it('should add firstListedAt_not: null where filter', () => {
expect(query.includes('firstListedAt_not: null')).toBeTruthy()
})

it('should add firstListedAt as orderBy', () => {
expect(query.includes('orderBy: firstListedAt')).toBeTruthy()
})

it('should add desc as orderDirection', () => {
expect(query.includes('orderDirection: desc')).toBeTruthy()
})
})
})

describe('#fromItemFragment', () => {
let itemFragment: ItemFragment

beforeEach(() => {
itemFragment = {
id: 'id',
price: 'price',
blockchainId: 'blockchainId',
image: 'image',
rarity: Rarity.COMMON,
available: 'available',
itemType: FragmentItemType.EMOTE_V1,
collection: {
id: 'collection',
creator: 'creator',
},
metadata: {
wearable: null,
emote: {
category: EmoteCategory.DANCE,
description: 'description',
loop: false,
name: 'name',
},
},
searchWearableBodyShapes: null,
searchEmoteBodyShapes: null,
searchIsStoreMinter: false,
createdAt: '100',
updatedAt: '100',
reviewedAt: '100',
soldAt: '100',
beneficiary: 'beneficiary',
firstListedAt: null,
}
})

describe('when fragment firstListedAt is null', () => {
beforeEach(() => {
itemFragment.firstListedAt = null
})

it('should return an Item with firstListedAt as null', () => {
const collection = fromItemFragment(
itemFragment,
Network.MATIC,
ChainId.MATIC_MUMBAI
)

expect(collection.firstListedAt).toBeNull()
})
})

describe('when fragment firstListedAt is "100"', () => {
beforeEach(() => {
itemFragment.firstListedAt = '100'
})

it('should return a Collection with firstListedAt as 100000', () => {
const collection = fromItemFragment(
itemFragment,
Network.MATIC,
ChainId.MATIC_MUMBAI
)

expect(collection.firstListedAt).toBe(100000)
})
})
})
Loading

0 comments on commit 781bce4

Please sign in to comment.