diff --git a/src/locales/en.json b/src/locales/en.json
index b99d3244b..5de52f7af 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -486,7 +486,7 @@
"listing_page_select_language_ch": "Simplified Chinese",
"listing_page_select_language_en": "English",
"listing_page_select_language_title": "Language",
- "listing_page_select_language_zh": "Traditional Chinese",
+ "listing_page_select_language_zh": "Chinese",
"listing_page_sorter": "Sort",
"listing_page_tag_not_found": "Tag is not found",
"Locale": {
diff --git a/src/locales/zh-Hant.json b/src/locales/zh-Hant.json
index 63721084a..013440ae2 100644
--- a/src/locales/zh-Hant.json
+++ b/src/locales/zh-Hant.json
@@ -486,7 +486,7 @@
"listing_page_select_language_ch": "簡體中文",
"listing_page_select_language_en": "英文",
"listing_page_select_language_title": "語言",
- "listing_page_select_language_zh": "繁體中文",
+ "listing_page_select_language_zh": "中文",
"listing_page_sorter": "排序",
"listing_page_tag_not_found": "找不到此標籤",
"Locale": {
diff --git a/src/pages/store/index.vue b/src/pages/store/index.vue
index 44ef16a72..ce95bbfc8 100644
--- a/src/pages/store/index.vue
+++ b/src/pages/store/index.vue
@@ -304,7 +304,7 @@
-
+
{
+ if (locale.includes(a)) return -1;
+ if (locale.includes(b)) return 1;
+ return 0;
+ });
+ return languages.map(lang => `listing-${lang}`);
+}
+
export default {
name: 'ListingPage',
mixins: [crispMixin],
@@ -560,7 +571,9 @@ export default {
try {
const fetches = [
$api.$get(fetchBookstoreCMSTags({ limit: 100 })),
- store.dispatch('lazyFetchBookstoreCMSProductsByTagId', 'listing'),
+ ...getCMSTagIdsForRecommendedBookstoreItemsByLocale(i18n.locale).map(
+ tagId => store.dispatch('lazyFetchBookstoreCMSProductsByTagId', tagId)
+ ),
store.dispatch('fetchBookstoreLatestItems'),
];
if (route.query.tag) {
@@ -613,9 +626,7 @@ export default {
href: this.canonicalLink,
},
];
- const classIds = Array.from(
- new Set(this.bookstoreItems.map(b => b.classId).flat())
- );
+ const classIds = this.uniqueBookstoreItems.map(item => item.classId);
classIds.forEach(classId =>
link.push({
rel: 'prefetch',
@@ -754,6 +765,10 @@ export default {
text: this.$t('listing_page_select_language_all'),
value: LANGUAGE_OPTIONS.ALL,
},
+ {
+ text: this.$t('listing_page_select_language_zh'),
+ value: LANGUAGE_OPTIONS.ZH,
+ },
{
text: this.$t('listing_page_select_language_en'),
value: LANGUAGE_OPTIONS.EN,
@@ -825,17 +840,37 @@ export default {
return this.$t('listing_page_header_sort', { sort: this.$t(text) });
},
- bookstoreCMSProducts() {
- return this.nftGetBookstoreCMSProductsByTagId('listing') || [];
+ recommendedBookstoreItems() {
+ // Return 100 books for each locale
+ return getCMSTagIdsForRecommendedBookstoreItemsByLocale(this.$i18n.locale)
+ .map(tagId => this.nftGetBookstoreCMSProductsByTagId(tagId))
+ .flat()
+ .map((item, index) => ({ ...item, order: index + 1 }));
},
bookstoreItems() {
- const items = this.selectedTagId
- ? this.nftGetBookstoreCMSProductsByTagId(this.selectedTagId) || []
- : [...this.bookstoreCMSProducts, ...this.nftBookstoreLatestItems];
+ if (this.selectedTagId) {
+ // Return books with particular tag from CMS
+ return this.nftGetBookstoreCMSProductsByTagId(this.selectedTagId);
+ }
+
+ if (this.selectedSorting === SORTING_OPTIONS.LATEST) {
+ // Return the latest 100 published books & fill up with recommended books from CMS
+ return this.nftBookstoreLatestItems
+ .map(item => ({
+ ...item,
+ id: item.classId, // Imitate items from CMS that have id keys
+ }))
+ .concat(this.recommendedBookstoreItems);
+ }
+
+ // Return recommended books from CMS by default
+ return this.recommendedBookstoreItems;
+ },
+ uniqueBookstoreItems() {
const uniqueIds = new Set();
const dedupedItems = [];
- items.forEach(item => {
+ this.bookstoreItems.forEach(item => {
if (!uniqueIds.has(item.classId)) {
uniqueIds.add(item.classId);
dedupedItems.push(item);
@@ -844,7 +879,7 @@ export default {
return dedupedItems;
},
filteredBookstoreItems() {
- return this.bookstoreItems
+ return this.uniqueBookstoreItems
.filter(item => {
if (this.isAppliedDRMFreeFilter) {
return item.isDRMFree;
@@ -852,11 +887,11 @@ export default {
return true;
})
.filter(item => {
- if (
- this.selectedLanguageFilter !== LANGUAGE_OPTIONS.ALL &&
- item.locales
- ) {
- return item.locales.includes(this.selectedLanguageFilter);
+ if (this.selectedLanguageFilter !== LANGUAGE_OPTIONS.ALL) {
+ if (Array.isArray(item.locales)) {
+ return item.locales.includes(this.selectedLanguageFilter);
+ }
+ return this.selectedLanguageFilter.includes(item.locale);
}
return true;
})
@@ -871,7 +906,9 @@ export default {
});
},
isFilterApplied() {
- return this.bookstoreItems.length !== this.filteredBookstoreItems.length;
+ return (
+ this.uniqueBookstoreItems.length !== this.filteredBookstoreItems.length
+ );
},
sortedBookstoreItems() {
if (this.searchQuery) {
@@ -880,18 +917,6 @@ export default {
const items = [...this.filteredBookstoreItems];
items.sort((a, b) => {
- const locale = this.selectedLanguageFilter;
- if (locale !== LANGUAGE_OPTIONS.ALL) {
- const aLocales = a.locales || [];
- const bLocales = b.locales || [];
- if (aLocales.includes(locale) && !bLocales.includes(locale)) {
- return -1;
- }
- if (!aLocales.includes(locale) && bLocales.includes(locale)) {
- return 1;
- }
- }
-
switch (this.selectedSorting) {
case SORTING_OPTIONS.RECOMMEND:
if (a.order && b.order) {
diff --git a/src/server/api/util/airtable.js b/src/server/api/util/airtable.js
index a3de2d93c..bca1fbca9 100644
--- a/src/server/api/util/airtable.js
+++ b/src/server/api/util/airtable.js
@@ -11,8 +11,10 @@ function normalizeTagIdForViewName(viewName) {
switch (viewName) {
case 'landing':
return 'Landing Page';
- case 'listing':
- return 'Listing Page';
+ case 'listing-zh':
+ return 'Listing Page (Chinese)';
+ case 'listing-en':
+ return 'Listing Page (English)';
case 'all':
return 'All';
default:
@@ -39,7 +41,7 @@ async function fetchAirtableCMSProductsByTagId(
}
);
- const normalizedRecords = results.data.records.map(({ fields }) => {
+ const normalizedRecords = results.data.records.map(({ id, fields }) => {
const classId = fields.ID;
const classIds = fields.IDs;
const title = fields.Name;
@@ -52,6 +54,7 @@ async function fetchAirtableCMSProductsByTagId(
const minPrice = fields['Min Price'];
const isMultiple = classIds && classIds.length > 1;
return {
+ id,
classId,
classIds: isMultiple ? classIds : undefined,
title,
diff --git a/src/store/modules/nft.js b/src/store/modules/nft.js
index 243e5fe96..4b5f6423f 100644
--- a/src/store/modules/nft.js
+++ b/src/store/modules/nft.js
@@ -986,8 +986,9 @@ const actions = {
const { data } = await this.$api.get(api.fetchBookstoreLatestItems());
commit(
TYPES.NFT_SET_BOOKSTORE_LATEST_ITEMS,
- data.list.map(({ hideDownload, ...item }) => ({
+ data.list.map(({ hideDownload, inLanguage, ...item }) => ({
...item,
+ locale: inLanguage,
isDRMFree: !hideDownload,
}))
);