@internetarchive/collection-browser 0.0.1-alpha.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -11
- package/demo/app-root.ts +16 -92
- package/dist/demo/app-root.d.ts +3 -5
- package/dist/demo/app-root.js +13 -83
- package/dist/demo/app-root.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/src/assets/img/icons/chevron.d.ts +2 -0
- package/dist/src/assets/img/icons/chevron.js +4 -0
- package/dist/src/assets/img/icons/chevron.js.map +1 -0
- package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -2
- package/dist/src/assets/img/icons/mediatype/account.js +6 -4
- package/dist/src/assets/img/icons/mediatype/account.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/audio.js +7 -4
- package/dist/src/assets/img/icons/mediatype/audio.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/collection.js +7 -4
- package/dist/src/assets/img/icons/mediatype/collection.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -0
- package/dist/src/assets/img/icons/mediatype/data.js +15 -0
- package/dist/src/assets/img/icons/mediatype/data.js.map +1 -0
- package/dist/src/assets/img/icons/mediatype/etree.js +10 -5
- package/dist/src/assets/img/icons/mediatype/etree.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/film.js +2 -1
- package/dist/src/assets/img/icons/mediatype/film.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/images.js +9 -6
- package/dist/src/assets/img/icons/mediatype/images.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -0
- package/dist/src/assets/img/icons/mediatype/radio.js +15 -0
- package/dist/src/assets/img/icons/mediatype/radio.js.map +1 -0
- package/dist/src/assets/img/icons/mediatype/software.js +9 -6
- package/dist/src/assets/img/icons/mediatype/software.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/texts.js +9 -6
- package/dist/src/assets/img/icons/mediatype/texts.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/tv.js +10 -5
- package/dist/src/assets/img/icons/mediatype/tv.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/video.js +10 -6
- package/dist/src/assets/img/icons/mediatype/video.js.map +1 -1
- package/dist/src/assets/img/icons/mediatype/web.js +9 -6
- package/dist/src/assets/img/icons/mediatype/web.js.map +1 -1
- package/dist/src/collection-browser.d.ts +53 -31
- package/dist/src/collection-browser.js +504 -166
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/collection-facets.d.ts +28 -13
- package/dist/src/collection-facets.js +276 -160
- package/dist/src/collection-facets.js.map +1 -1
- package/dist/src/language-code-handler/language-code-handler.d.ts +37 -0
- package/dist/src/language-code-handler/language-code-handler.js +27 -0
- package/dist/src/language-code-handler/language-code-handler.js.map +1 -0
- package/dist/src/language-code-handler/language-code-mapping.d.ts +1 -0
- package/dist/src/language-code-handler/language-code-mapping.js +563 -0
- package/dist/src/language-code-handler/language-code-mapping.js.map +1 -0
- package/dist/src/mediatype/mediatype-config.d.ts +3 -0
- package/dist/src/mediatype/mediatype-config.js +86 -0
- package/dist/src/mediatype/mediatype-config.js.map +1 -0
- package/dist/src/models.d.ts +72 -13
- package/dist/src/models.js +57 -1
- package/dist/src/models.js.map +1 -1
- package/dist/src/restoration-state-handler.d.ts +38 -0
- package/dist/src/restoration-state-handler.js +204 -0
- package/dist/src/restoration-state-handler.js.map +1 -0
- package/dist/src/sort-filter-bar/alpha-bar.d.ts +1 -1
- package/dist/src/sort-filter-bar/alpha-bar.js +9 -2
- package/dist/src/sort-filter-bar/alpha-bar.js.map +1 -1
- package/dist/src/sort-filter-bar/img/compact.d.ts +1 -0
- package/dist/src/sort-filter-bar/img/compact.js +5 -0
- package/dist/src/sort-filter-bar/img/compact.js.map +1 -0
- package/dist/src/sort-filter-bar/img/list.js +1 -1
- package/dist/src/sort-filter-bar/img/list.js.map +1 -1
- package/dist/src/sort-filter-bar/img/tile.d.ts +1 -0
- package/dist/src/sort-filter-bar/img/tile.js +5 -0
- package/dist/src/sort-filter-bar/img/tile.js.map +1 -0
- package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +71 -14
- package/dist/src/sort-filter-bar/sort-filter-bar.js +499 -216
- package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
- package/dist/src/tiles/{loading-tile.d.ts → collection-browser-loading-tile.d.ts} +1 -1
- package/dist/src/tiles/collection-browser-loading-tile.js +32 -0
- package/dist/src/tiles/collection-browser-loading-tile.js.map +1 -0
- package/dist/src/tiles/grid/account-tile.d.ts +1 -1
- package/dist/src/tiles/grid/account-tile.js +5 -5
- package/dist/src/tiles/grid/account-tile.js.map +1 -1
- package/dist/src/tiles/grid/collection-tile.js +1 -2
- package/dist/src/tiles/grid/collection-tile.js.map +1 -1
- package/dist/src/tiles/grid/icons/views.d.ts +1 -1
- package/dist/src/tiles/grid/icons/views.js +2 -2
- package/dist/src/tiles/grid/icons/views.js.map +1 -1
- package/dist/src/tiles/grid/item-tile.d.ts +2 -2
- package/dist/src/tiles/grid/item-tile.js +57 -151
- package/dist/src/tiles/grid/item-tile.js.map +1 -1
- package/dist/src/tiles/item-image.d.ts +19 -0
- package/dist/src/tiles/item-image.js +204 -0
- package/dist/src/tiles/item-image.js.map +1 -0
- package/dist/src/tiles/list/account-label.d.ts +1 -0
- package/dist/src/tiles/list/account-label.js +7 -0
- package/dist/src/tiles/list/account-label.js.map +1 -0
- package/dist/src/tiles/list/date-label.d.ts +1 -0
- package/dist/src/tiles/list/date-label.js +13 -0
- package/dist/src/tiles/list/date-label.js.map +1 -0
- package/dist/src/tiles/list/tile-list-compact-header.d.ts +12 -0
- package/dist/src/tiles/list/tile-list-compact-header.js +84 -0
- package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -0
- package/dist/src/tiles/list/tile-list-compact.d.ts +12 -0
- package/dist/src/tiles/list/tile-list-compact.js +203 -6
- package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
- package/dist/src/tiles/list/tile-list.d.ts +35 -10
- package/dist/src/tiles/list/tile-list.js +368 -104
- package/dist/src/tiles/list/tile-list.js.map +1 -1
- package/dist/src/{mediatype-icon.d.ts → tiles/mediatype-icon.d.ts} +2 -2
- package/dist/src/tiles/mediatype-icon.js +78 -0
- package/dist/src/tiles/mediatype-icon.js.map +1 -0
- package/dist/src/tiles/tile-dispatcher.d.ts +11 -4
- package/dist/src/tiles/tile-dispatcher.js +56 -19
- package/dist/src/tiles/tile-dispatcher.js.map +1 -1
- package/dist/src/utils/format-date.js +2 -2
- package/dist/src/utils/format-date.js.map +1 -1
- package/dist/test/collection-browser.test.d.ts +1 -0
- package/dist/test/collection-browser.test.js +16 -2
- package/dist/test/collection-browser.test.js.map +1 -1
- package/dist/test/mediatype-config.test.d.ts +1 -0
- package/dist/test/mediatype-config.test.js +17 -0
- package/dist/test/mediatype-config.test.js.map +1 -0
- package/dist/test/utils/format-date.test.js +1 -1
- package/dist/test/utils/format-date.test.js.map +1 -1
- package/index.ts +6 -0
- package/local.archive.org.cert +86 -0
- package/local.archive.org.key +27 -0
- package/package.json +9 -5
- package/src/assets/img/icons/chevron.ts +4 -0
- package/src/assets/img/icons/mediatype/account.ts +6 -4
- package/src/assets/img/icons/mediatype/audio.ts +7 -4
- package/src/assets/img/icons/mediatype/collection.ts +7 -4
- package/src/assets/img/icons/mediatype/data.ts +15 -0
- package/src/assets/img/icons/mediatype/etree.ts +10 -5
- package/src/assets/img/icons/mediatype/film.ts +2 -1
- package/src/assets/img/icons/mediatype/images.ts +9 -6
- package/src/assets/img/icons/mediatype/radio.ts +15 -0
- package/src/assets/img/icons/mediatype/software.ts +9 -6
- package/src/assets/img/icons/mediatype/texts.ts +9 -6
- package/src/assets/img/icons/mediatype/tv.ts +10 -5
- package/src/assets/img/icons/mediatype/video.ts +10 -6
- package/src/assets/img/icons/mediatype/web.ts +9 -6
- package/src/collection-browser.ts +529 -163
- package/src/collection-facets.ts +307 -205
- package/src/language-code-handler/language-code-handler.ts +64 -0
- package/src/language-code-handler/language-code-mapping.ts +564 -0
- package/src/mediatype/mediatype-config.ts +86 -0
- package/src/models.ts +141 -13
- package/src/restoration-state-handler.ts +266 -0
- package/src/sort-filter-bar/alpha-bar.ts +9 -3
- package/src/sort-filter-bar/img/compact.ts +5 -0
- package/src/sort-filter-bar/img/list.ts +1 -1
- package/src/sort-filter-bar/img/tile.ts +5 -0
- package/src/sort-filter-bar/sort-filter-bar.ts +557 -225
- package/src/tiles/collection-browser-loading-tile.ts +29 -0
- package/src/tiles/grid/account-tile.ts +1 -1
- package/src/tiles/grid/collection-tile.ts +1 -2
- package/src/tiles/grid/icons/views.ts +2 -2
- package/src/tiles/grid/item-tile.ts +56 -163
- package/src/tiles/item-image.ts +206 -0
- package/src/tiles/list/account-label.ts +6 -0
- package/src/tiles/list/date-label.ts +12 -0
- package/src/tiles/list/tile-list-compact-header.ts +77 -0
- package/src/tiles/list/tile-list-compact.ts +218 -0
- package/src/tiles/list/tile-list.ts +412 -107
- package/src/tiles/mediatype-icon.ts +75 -0
- package/src/tiles/tile-dispatcher.ts +66 -18
- package/src/utils/format-date.ts +2 -2
- package/test/collection-browser.test.ts +20 -1
- package/test/mediatype-config.test.ts +18 -0
- package/test/utils/format-date.test.ts +1 -1
- package/web-dev-server.config.mjs +3 -1
- package/dist/src/mediatype-icon.js +0 -89
- package/dist/src/mediatype-icon.js.map +0 -1
- package/dist/src/sort-filter-bar/img/grid.d.ts +0 -1
- package/dist/src/sort-filter-bar/img/grid.js +0 -5
- package/dist/src/sort-filter-bar/img/grid.js.map +0 -1
- package/dist/src/tiles/list/tile-list-detail.d.ts +0 -7
- package/dist/src/tiles/list/tile-list-detail.js +0 -28
- package/dist/src/tiles/list/tile-list-detail.js.map +0 -1
- package/dist/src/tiles/loading-tile.js +0 -73
- package/dist/src/tiles/loading-tile.js.map +0 -1
- package/src/mediatype-icon.ts +0 -83
- package/src/sort-filter-bar/img/grid.ts +0 -5
- package/src/tiles/loading-tile.ts +0 -70
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
css,
|
|
3
|
+
html,
|
|
4
|
+
LitElement,
|
|
5
|
+
nothing,
|
|
6
|
+
PropertyValues,
|
|
7
|
+
TemplateResult,
|
|
8
|
+
} from 'lit';
|
|
9
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
10
|
+
import { join } from 'lit/directives/join.js';
|
|
11
|
+
import { map } from 'lit/directives/map.js';
|
|
12
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
|
3
13
|
import { SortParam } from '@internetarchive/search-service';
|
|
4
14
|
import DOMPurify from 'dompurify';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// - no types
|
|
10
|
-
import { CollectionDisplayMode, TileModel } from '../../models';
|
|
15
|
+
import { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
|
|
16
|
+
import { dateLabel } from './date-label';
|
|
17
|
+
import { accountLabel } from './account-label';
|
|
18
|
+
import { TileModel } from '../../models';
|
|
11
19
|
import { formatCount, NumberFormat } from '../../utils/format-count';
|
|
12
20
|
import { formatDate, DateFormat } from '../../utils/format-date';
|
|
13
|
-
import '
|
|
14
|
-
|
|
15
|
-
/*
|
|
16
|
-
at 750 creator, title trimmed
|
|
17
|
-
at 530
|
|
18
|
-
*/
|
|
21
|
+
import '../mediatype-icon';
|
|
19
22
|
|
|
20
23
|
@customElement('tile-list')
|
|
21
24
|
export class TileList extends LitElement {
|
|
@@ -23,71 +26,313 @@ export class TileList extends LitElement {
|
|
|
23
26
|
|
|
24
27
|
@property({ type: String }) baseNavigationUrl?: string;
|
|
25
28
|
|
|
29
|
+
@property({ type: Object })
|
|
30
|
+
collectionNameCache?: CollectionNameCacheInterface;
|
|
31
|
+
|
|
26
32
|
@property({ type: Number }) currentWidth?: number;
|
|
27
33
|
|
|
28
34
|
@property({ type: Number }) currentHeight?: number;
|
|
29
35
|
|
|
30
|
-
@property({ type: Object }) sortParam
|
|
36
|
+
@property({ type: Object }) sortParam: SortParam | null = null;
|
|
37
|
+
|
|
38
|
+
@property({ type: Number }) mobileBreakpoint?: number;
|
|
31
39
|
|
|
32
|
-
@
|
|
33
|
-
'list-compact';
|
|
40
|
+
@state() private collectionLinks: TemplateResult[] = [];
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
protected updated(changed: PropertyValues): void {
|
|
43
|
+
if (changed.has('model')) {
|
|
44
|
+
this.fetchCollectionNames();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private async fetchCollectionNames() {
|
|
49
|
+
if (
|
|
50
|
+
!this.model?.collections ||
|
|
51
|
+
this.model.collections.length === 0 ||
|
|
52
|
+
!this.collectionNameCache
|
|
53
|
+
) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Note: quirk of Lit: need to replace collectionLinks array,
|
|
57
|
+
// otherwise it will not re-render. Can't simply alter the array.
|
|
58
|
+
this.collectionLinks = [];
|
|
59
|
+
const newCollellectionLinks: TemplateResult[] = [];
|
|
60
|
+
const promises: Promise<void>[] = [];
|
|
61
|
+
for (const collection of this.model.collections) {
|
|
62
|
+
promises.push(
|
|
63
|
+
this.collectionNameCache?.collectionNameFor(collection).then(name => {
|
|
64
|
+
newCollellectionLinks.push(
|
|
65
|
+
this.detailsLink(collection, name ?? collection)
|
|
66
|
+
);
|
|
67
|
+
})
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
await Promise.all(promises);
|
|
71
|
+
this.collectionLinks = newCollellectionLinks;
|
|
72
|
+
}
|
|
36
73
|
|
|
37
74
|
render() {
|
|
38
75
|
return html`
|
|
39
76
|
<div id="list-line" class="${this.classSize}">
|
|
40
|
-
|
|
41
|
-
|
|
77
|
+
${this.classSize === 'mobile'
|
|
78
|
+
? this.mobileTemplate
|
|
79
|
+
: this.desktopTemplate}
|
|
80
|
+
</div>
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private get mobileTemplate() {
|
|
85
|
+
return html`
|
|
86
|
+
<div id="list-line-top">
|
|
87
|
+
<div id="list-line-left">
|
|
88
|
+
<div id="thumb">${this.imgTemplate}</div>
|
|
89
|
+
</div>
|
|
90
|
+
<div id="list-line-right">
|
|
91
|
+
<div id="title-line">
|
|
92
|
+
<div id="title">${this.titleTemplate}</div>
|
|
93
|
+
${this.iconRightTemplate}
|
|
94
|
+
</div>
|
|
42
95
|
</div>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
96
|
+
</div>
|
|
97
|
+
<div id="list-line-bottom">${this.detailsTemplate}</div>
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private get desktopTemplate() {
|
|
102
|
+
return html`
|
|
103
|
+
<div id="list-line-left">
|
|
104
|
+
<div id="thumb">${this.imgTemplate}</div>
|
|
105
|
+
</div>
|
|
106
|
+
<div id="list-line-right">
|
|
107
|
+
<div id="title-line">
|
|
108
|
+
<div id="title">${this.titleTemplate}</div>
|
|
109
|
+
${this.iconRightTemplate}
|
|
48
110
|
</div>
|
|
111
|
+
${this.detailsTemplate}
|
|
112
|
+
</div>
|
|
113
|
+
`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private get detailsTemplate() {
|
|
117
|
+
return html`
|
|
118
|
+
${this.itemLineTemplate} ${this.creatorTemplate}
|
|
119
|
+
<div id="dates-line">
|
|
120
|
+
${this.datePublishedTemplate} ${this.dateSortByTemplate}
|
|
121
|
+
</div>
|
|
122
|
+
<div id="views-line">
|
|
123
|
+
${this.viewsTemplate} ${this.ratingTemplate} ${this.reviewsTemplate}
|
|
124
|
+
</div>
|
|
125
|
+
${this.topicsTemplate} ${this.collectionsTemplate}
|
|
126
|
+
${this.descriptionTemplate}
|
|
127
|
+
`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Data templates
|
|
131
|
+
private get imgTemplate() {
|
|
132
|
+
if (!this.model?.identifier) {
|
|
133
|
+
return nothing;
|
|
134
|
+
}
|
|
135
|
+
return html` <img
|
|
136
|
+
src="${this.baseNavigationUrl}/services/img/${this.model.identifier}"
|
|
137
|
+
alt="${this.model.identifier}"
|
|
138
|
+
class=${this.model?.mediatype}
|
|
139
|
+
/>`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private get iconRightTemplate() {
|
|
143
|
+
return html`
|
|
144
|
+
<div id="icon-right">
|
|
145
|
+
<mediatype-icon
|
|
146
|
+
.mediatype=${this.model?.mediatype}
|
|
147
|
+
.collections=${this.model?.collections}
|
|
148
|
+
style="--iconCustomFillColor: ${ifDefined(this.collectionColor)}"
|
|
149
|
+
>
|
|
150
|
+
</mediatype-icon>
|
|
49
151
|
</div>
|
|
50
|
-
${this.displayMode === 'list-detail' ? this.detail() : html``}
|
|
51
152
|
`;
|
|
52
153
|
}
|
|
53
154
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
155
|
+
// Only in list, not tile
|
|
156
|
+
private get collectionColor() {
|
|
157
|
+
if (this.model?.mediatype !== 'collection') {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
return '#4666FF';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private get titleTemplate() {
|
|
164
|
+
if (!this.model?.title) {
|
|
165
|
+
return nothing;
|
|
166
|
+
}
|
|
167
|
+
return html` ${this.detailsLink(this.model.identifier, this.model.title)} `;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private get itemLineTemplate() {
|
|
171
|
+
const source = this.sourceTemplate;
|
|
172
|
+
const volume = this.volumeTemplate;
|
|
173
|
+
const issue = this.issueTemplate;
|
|
174
|
+
if (!source && !volume && !issue) {
|
|
175
|
+
return nothing;
|
|
176
|
+
}
|
|
177
|
+
return html` <div id="item-line">${source} ${volume} ${issue}</div> `;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private get sourceTemplate() {
|
|
181
|
+
if (!this.model?.source) {
|
|
182
|
+
return nothing;
|
|
183
|
+
}
|
|
184
|
+
return html`
|
|
185
|
+
<div id="source" class="metadata">
|
|
186
|
+
${this.labelTemplate('Source')}
|
|
187
|
+
${this.searchLink('source', this.model.source)}
|
|
188
|
+
</div>
|
|
189
|
+
`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private get volumeTemplate() {
|
|
193
|
+
return this.metadataTemplate(this.model?.volume, 'Volume');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private get issueTemplate() {
|
|
197
|
+
return this.metadataTemplate(this.model?.issue, 'Issue');
|
|
198
|
+
}
|
|
58
199
|
|
|
59
|
-
|
|
200
|
+
private get creatorTemplate() {
|
|
201
|
+
// "Achivist since" if account
|
|
202
|
+
if (this.model?.mediatype === 'account') {
|
|
60
203
|
return html`
|
|
61
|
-
<div id="
|
|
62
|
-
<
|
|
63
|
-
<div id="details">${descriptionHtml} ${topicHtml} ${sourceHtml}</div>
|
|
64
|
-
<div></div>
|
|
204
|
+
<div id="creator" class="metadata">
|
|
205
|
+
<span class="label"> ${accountLabel(this.model?.dateAdded)} </span>
|
|
65
206
|
</div>
|
|
66
207
|
`;
|
|
67
208
|
}
|
|
68
|
-
|
|
209
|
+
// "Creator" if not account tile
|
|
210
|
+
if (!this.model?.creators || this.model.creators.length === 0) {
|
|
211
|
+
return nothing;
|
|
212
|
+
}
|
|
213
|
+
return html`
|
|
214
|
+
<div id="creator" class="metadata">
|
|
215
|
+
${this.labelTemplate('By')}
|
|
216
|
+
${join(
|
|
217
|
+
map(this.model.creators, id => this.searchLink('creator', id)),
|
|
218
|
+
html`, `
|
|
219
|
+
)}
|
|
220
|
+
</div>
|
|
221
|
+
`;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private get datePublishedTemplate() {
|
|
225
|
+
return this.metadataTemplate(
|
|
226
|
+
formatDate(this.model?.datePublished, 'long'),
|
|
227
|
+
'Published'
|
|
228
|
+
);
|
|
69
229
|
}
|
|
70
230
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
231
|
+
// Show date label/value when sorted by date type
|
|
232
|
+
// Except datePublished which is always shown
|
|
233
|
+
private get dateSortByTemplate() {
|
|
234
|
+
if (
|
|
235
|
+
this.sortParam &&
|
|
236
|
+
(this.sortParam.field === 'addeddate' ||
|
|
237
|
+
this.sortParam.field === 'reviewdate' ||
|
|
238
|
+
this.sortParam.field === 'publicdate')
|
|
239
|
+
) {
|
|
240
|
+
return this.metadataTemplate(
|
|
241
|
+
formatDate(this.date, 'long'),
|
|
242
|
+
dateLabel(this.sortParam.field)
|
|
243
|
+
);
|
|
75
244
|
}
|
|
76
|
-
return
|
|
245
|
+
return nothing;
|
|
77
246
|
}
|
|
78
247
|
|
|
79
|
-
private
|
|
80
|
-
|
|
81
|
-
|
|
248
|
+
private get viewsTemplate() {
|
|
249
|
+
return this.metadataTemplate(
|
|
250
|
+
`${formatCount(this.model?.viewCount ?? 0, this.formatSize)}`,
|
|
251
|
+
'Views'
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private get ratingTemplate() {
|
|
256
|
+
return this.metadataTemplate(this.model?.averageRating, 'Avg Rating');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private get reviewsTemplate() {
|
|
260
|
+
return this.metadataTemplate(this.model?.commentCount, 'Reviews');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private get topicsTemplate() {
|
|
264
|
+
if (!this.model?.subjects || this.model.subjects.length === 0) {
|
|
265
|
+
return nothing;
|
|
82
266
|
}
|
|
83
|
-
return html
|
|
267
|
+
return html`
|
|
268
|
+
<div id="topics" class="metadata">
|
|
269
|
+
${this.labelTemplate('Topics')}
|
|
270
|
+
${join(
|
|
271
|
+
map(this.model.subjects, id => this.searchLink('subject', id)),
|
|
272
|
+
html`, `
|
|
273
|
+
)}
|
|
274
|
+
</div>
|
|
275
|
+
`;
|
|
84
276
|
}
|
|
85
277
|
|
|
86
|
-
private
|
|
87
|
-
if (this.
|
|
88
|
-
return
|
|
278
|
+
private get collectionsTemplate() {
|
|
279
|
+
if (!this.collectionLinks || this.collectionLinks.length === 0) {
|
|
280
|
+
return nothing;
|
|
89
281
|
}
|
|
90
|
-
return html
|
|
282
|
+
return html`
|
|
283
|
+
<div id="collections" class="metadata">
|
|
284
|
+
${this.labelTemplate('Collections')}
|
|
285
|
+
${join(this.collectionLinks, html`, `)}
|
|
286
|
+
</div>
|
|
287
|
+
`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private get descriptionTemplate() {
|
|
291
|
+
return this.metadataTemplate(
|
|
292
|
+
DOMPurify.sanitize(this.model?.description ?? ''),
|
|
293
|
+
'',
|
|
294
|
+
'description'
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Utility functions
|
|
299
|
+
private metadataTemplate(text: any, label = '', id?: string) {
|
|
300
|
+
if (!text) return nothing;
|
|
301
|
+
return html`
|
|
302
|
+
<div id=${ifDefined(id)} class="metadata">
|
|
303
|
+
${this.labelTemplate(label)} ${text}
|
|
304
|
+
</div>
|
|
305
|
+
`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
private labelTemplate(label: string) {
|
|
309
|
+
return html` ${label
|
|
310
|
+
? html`<span class="label">${label}: </span>`
|
|
311
|
+
: nothing}`;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private searchLink(field: string, searchTerm: string) {
|
|
315
|
+
if (!field || !searchTerm) {
|
|
316
|
+
return nothing;
|
|
317
|
+
}
|
|
318
|
+
const query = encodeURIComponent(`${field}:"${searchTerm}"`);
|
|
319
|
+
// No whitespace after closing tag
|
|
320
|
+
// Note: single ' for href='' to wrap " in query var gets changed back by yarn format
|
|
321
|
+
|
|
322
|
+
// eslint-disable-next-line lit/no-invalid-html
|
|
323
|
+
return html`<a href="${this.baseNavigationUrl}/search.php?query=${query}">
|
|
324
|
+
${DOMPurify.sanitize(searchTerm)}</a
|
|
325
|
+
>`;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private detailsLink(identifier: string, text?: string): TemplateResult {
|
|
329
|
+
const linkText = text ?? identifier;
|
|
330
|
+
// No whitespace after closing tag
|
|
331
|
+
// identifiers (all ASCII in their creation) should be safe to use in href, but sanitize anyway
|
|
332
|
+
return html`<a
|
|
333
|
+
href="${this.baseNavigationUrl}/details/${encodeURI(identifier)}"
|
|
334
|
+
>${DOMPurify.sanitize(linkText)}</a
|
|
335
|
+
>`;
|
|
91
336
|
}
|
|
92
337
|
|
|
93
338
|
/*
|
|
@@ -109,118 +354,178 @@ export class TileList extends LitElement {
|
|
|
109
354
|
}
|
|
110
355
|
|
|
111
356
|
private get classSize(): string {
|
|
112
|
-
|
|
357
|
+
if (
|
|
358
|
+
this.mobileBreakpoint &&
|
|
359
|
+
this.currentWidth &&
|
|
360
|
+
this.currentWidth < this.mobileBreakpoint
|
|
361
|
+
) {
|
|
362
|
+
return 'mobile';
|
|
363
|
+
}
|
|
364
|
+
return 'desktop';
|
|
113
365
|
}
|
|
114
366
|
|
|
115
367
|
private get formatSize(): DateFormat | NumberFormat {
|
|
116
|
-
|
|
368
|
+
if (
|
|
369
|
+
this.mobileBreakpoint &&
|
|
370
|
+
this.currentWidth &&
|
|
371
|
+
this.currentWidth < this.mobileBreakpoint
|
|
372
|
+
) {
|
|
373
|
+
return 'short';
|
|
374
|
+
}
|
|
375
|
+
return 'long';
|
|
117
376
|
}
|
|
118
377
|
|
|
119
378
|
static get styles() {
|
|
120
379
|
return css`
|
|
121
|
-
|
|
122
|
-
font-size:
|
|
380
|
+
html {
|
|
381
|
+
font-size: unset;
|
|
123
382
|
}
|
|
124
|
-
|
|
383
|
+
|
|
384
|
+
div {
|
|
125
385
|
font-size: 14px;
|
|
126
386
|
}
|
|
127
387
|
|
|
388
|
+
div a {
|
|
389
|
+
text-decoration: none;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.label {
|
|
393
|
+
font-weight: bold;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
#list-line.mobile {
|
|
397
|
+
--infiniteScrollerRowGap: 20px;
|
|
398
|
+
--infiniteScrollerRowHeight: auto;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
#list-line.desktop {
|
|
402
|
+
--infiniteScrollerRowGap: 30px;
|
|
403
|
+
--infiniteScrollerRowHeight: auto;
|
|
404
|
+
}
|
|
405
|
+
|
|
128
406
|
/* fields */
|
|
129
407
|
|
|
130
|
-
#
|
|
131
|
-
|
|
132
|
-
|
|
408
|
+
#thumb img {
|
|
409
|
+
object-fit: cover;
|
|
410
|
+
display: block;
|
|
133
411
|
}
|
|
134
412
|
|
|
135
|
-
#
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
#source {
|
|
139
|
-
text-overflow: ellipsis;
|
|
140
|
-
overflow: hidden;
|
|
413
|
+
.mobile #thumb img {
|
|
414
|
+
width: 90px;
|
|
415
|
+
height: 90px;
|
|
141
416
|
}
|
|
142
417
|
|
|
143
|
-
#
|
|
144
|
-
|
|
145
|
-
|
|
418
|
+
.desktop #thumb img {
|
|
419
|
+
width: 100px;
|
|
420
|
+
height: 100px;
|
|
146
421
|
}
|
|
147
422
|
|
|
148
|
-
#
|
|
149
|
-
|
|
150
|
-
|
|
423
|
+
#thumb img.collection {
|
|
424
|
+
border-radius: 8px;
|
|
425
|
+
-webkit-border-radius: 8px;
|
|
426
|
+
-moz-border-radius: 8px;
|
|
151
427
|
}
|
|
152
428
|
|
|
153
|
-
#
|
|
154
|
-
|
|
155
|
-
|
|
429
|
+
.mobile #thumb img.account {
|
|
430
|
+
border-radius: 45px;
|
|
431
|
+
-webkit-border-radius: 45px;
|
|
432
|
+
-moz-border-radius: 45px;
|
|
156
433
|
}
|
|
157
434
|
|
|
158
|
-
#
|
|
159
|
-
|
|
435
|
+
.desktop #thumb img.account {
|
|
436
|
+
border-radius: 50px;
|
|
437
|
+
-webkit-border-radius: 50px;
|
|
438
|
+
-moz-border-radius: 50px;
|
|
160
439
|
}
|
|
161
440
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
441
|
+
#icon-right {
|
|
442
|
+
width: 20px;
|
|
443
|
+
padding-top: 5px;
|
|
444
|
+
--iconHeight: 20px;
|
|
445
|
+
--iconWidth: 20px;
|
|
446
|
+
--iconTextAlign: right;
|
|
447
|
+
margin-top: -8px;
|
|
448
|
+
text-align: right;
|
|
166
449
|
}
|
|
167
450
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
font-size:
|
|
451
|
+
#title {
|
|
452
|
+
color: #4b64ff;
|
|
453
|
+
text-decoration: none;
|
|
454
|
+
font-size: 22px;
|
|
455
|
+
font-weight: bold;
|
|
456
|
+
/* align top of text with image */
|
|
457
|
+
line-height: 25px;
|
|
458
|
+
margin-top: -4px;
|
|
459
|
+
padding-bottom: 2px;
|
|
460
|
+
flex-grow: 1;
|
|
172
461
|
}
|
|
173
462
|
|
|
174
|
-
|
|
463
|
+
.metadata {
|
|
464
|
+
line-height: 20px;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
#description,
|
|
468
|
+
#creator,
|
|
469
|
+
#topics,
|
|
470
|
+
#source {
|
|
471
|
+
text-align: left;
|
|
175
472
|
overflow: hidden;
|
|
176
473
|
text-overflow: ellipsis;
|
|
177
|
-
-webkit-line-clamp: 2;
|
|
178
474
|
-webkit-box-orient: vertical;
|
|
179
475
|
display: -webkit-box;
|
|
180
476
|
word-break: break-word;
|
|
181
477
|
-webkit-line-clamp: 3; /* number of lines to show */
|
|
182
478
|
line-clamp: 3;
|
|
183
|
-
-webkit-box-orient: vertical;
|
|
184
|
-
text-align: left;
|
|
185
479
|
}
|
|
186
480
|
|
|
187
|
-
|
|
481
|
+
#icon {
|
|
482
|
+
padding-top: 5px;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
#description {
|
|
486
|
+
padding-top: 10px;
|
|
487
|
+
}
|
|
188
488
|
|
|
489
|
+
/* Top level container */
|
|
189
490
|
#list-line {
|
|
190
|
-
display:
|
|
191
|
-
column-gap: 10px;
|
|
192
|
-
line-height: 1.42857143;
|
|
193
|
-
border-top: 1px solid #ddd !important;
|
|
194
|
-
padding-top: 5px;
|
|
195
|
-
align-items: center;
|
|
491
|
+
display: flex;
|
|
196
492
|
}
|
|
197
493
|
|
|
198
494
|
#list-line.mobile {
|
|
199
|
-
|
|
495
|
+
flex-direction: column;
|
|
200
496
|
}
|
|
497
|
+
|
|
201
498
|
#list-line.desktop {
|
|
202
|
-
|
|
499
|
+
column-gap: 10px;
|
|
203
500
|
}
|
|
204
501
|
|
|
205
|
-
#list-line
|
|
206
|
-
|
|
502
|
+
#list-line-top {
|
|
503
|
+
display: flex;
|
|
504
|
+
column-gap: 7px;
|
|
207
505
|
}
|
|
208
506
|
|
|
209
|
-
|
|
507
|
+
#list-line-bottom {
|
|
508
|
+
padding-top: 4px;
|
|
509
|
+
}
|
|
210
510
|
|
|
211
|
-
#list-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
align-items: center;
|
|
511
|
+
#list-line-right,
|
|
512
|
+
#list-line-top,
|
|
513
|
+
#list-line-bottom {
|
|
514
|
+
width: 100%;
|
|
216
515
|
}
|
|
217
516
|
|
|
218
|
-
|
|
219
|
-
|
|
517
|
+
div a:hover {
|
|
518
|
+
text-decoration: underline;
|
|
220
519
|
}
|
|
221
520
|
|
|
222
|
-
|
|
223
|
-
|
|
521
|
+
/* Lines containing multiple div as row */
|
|
522
|
+
#item-line,
|
|
523
|
+
#dates-line,
|
|
524
|
+
#views-line,
|
|
525
|
+
#title-line {
|
|
526
|
+
display: flex;
|
|
527
|
+
flex-direction: row;
|
|
528
|
+
gap: 10px;
|
|
224
529
|
}
|
|
225
530
|
`;
|
|
226
531
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { css, CSSResultGroup, html, LitElement } from 'lit';
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
|
|
4
|
+
import { mediatypeConfig } from '../mediatype/mediatype-config';
|
|
5
|
+
|
|
6
|
+
@customElement('mediatype-icon')
|
|
7
|
+
export class MediatypeIcon extends LitElement {
|
|
8
|
+
@property({ type: String }) mediatype: string | undefined;
|
|
9
|
+
|
|
10
|
+
@property({ type: Array }) collections: string[] | undefined;
|
|
11
|
+
|
|
12
|
+
@property({ type: Boolean }) showText = false;
|
|
13
|
+
|
|
14
|
+
private get displayMediatype(): string {
|
|
15
|
+
const tvIdentifier = ['tvnews', 'tvarchive', 'television'];
|
|
16
|
+
const radioIdentifier = ['radio', 'radioprogram'];
|
|
17
|
+
|
|
18
|
+
if (
|
|
19
|
+
this.mediatype === 'movies' &&
|
|
20
|
+
this.collections?.some(id => tvIdentifier.indexOf(id) >= 0)
|
|
21
|
+
) {
|
|
22
|
+
return 'tv';
|
|
23
|
+
}
|
|
24
|
+
if (
|
|
25
|
+
this.mediatype === 'audio' &&
|
|
26
|
+
this.collections?.some(id => radioIdentifier.indexOf(id) >= 0)
|
|
27
|
+
) {
|
|
28
|
+
return 'radio';
|
|
29
|
+
}
|
|
30
|
+
return this.mediatype || '';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
render() {
|
|
34
|
+
const config = mediatypeConfig[this.displayMediatype];
|
|
35
|
+
if (!config) {
|
|
36
|
+
return html``;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return html`
|
|
40
|
+
<div
|
|
41
|
+
id="icon"
|
|
42
|
+
class="${this.showText ? 'show-text' : 'hide-text'}"
|
|
43
|
+
style="--iconFillColor: ${config.color}"
|
|
44
|
+
>
|
|
45
|
+
${config.icon}
|
|
46
|
+
<p class="status-text">${config.text}</p>
|
|
47
|
+
</div>
|
|
48
|
+
`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static get styles(): CSSResultGroup {
|
|
52
|
+
return css`
|
|
53
|
+
.status-text {
|
|
54
|
+
font-size: 14px;
|
|
55
|
+
color: #2c2c2c;
|
|
56
|
+
margin: auto;
|
|
57
|
+
display: block;
|
|
58
|
+
text-align: var(--iconTextAlign, center);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#icon.hide-text p {
|
|
62
|
+
display: none;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
svg {
|
|
66
|
+
height: var(--iconHeight, 10px);
|
|
67
|
+
width: var(--iconWidth, 10px);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.fill-color {
|
|
71
|
+
fill: var(--iconCustomFillColor, var(--iconFillColor, '#000000'));
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
}
|