-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgallery.js
More file actions
212 lines (178 loc) · 7.35 KB
/
gallery.js
File metadata and controls
212 lines (178 loc) · 7.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
document.addEventListener('DOMContentLoaded', () => {
const photoGrid = document.getElementById('photoGrid');
const tagItems = document.querySelectorAll('.tag-item');
const tagSelectedElement = document.querySelector('.tag-selected');
const itemCountElement = document.getElementById('item-count');
const API_BASE_URL = 'https://dia-backend.numbersprotocol.io/api/v3/assets/';
const ACCOUNT = 'kmt-studio@com.tw';
// Loading indicator
const loadingIndicator = document.createElement('div');
loadingIndicator.className = 'loading-indicator';
loadingIndicator.innerHTML = '<div class="spinner"></div><p>載入中...</p>';
// Display loading indicator initially
photoGrid.innerHTML = '';
photoGrid.appendChild(loadingIndicator);
// Fetch and display all photos initially
fetchAndDisplayPhotos('all');
// Filter photos by tag
tagItems.forEach(item => {
item.addEventListener('click', () => {
const tag = item.getAttribute('data-tag');
const tagText = item.textContent;
// Update active tag
tagItems.forEach(t => t.classList.remove('active'));
item.classList.add('active');
// Update the selected tag text
tagSelectedElement.textContent = tagText;
// Show loading indicator
photoGrid.innerHTML = '';
photoGrid.appendChild(loadingIndicator);
// Fetch and display filtered photos
fetchAndDisplayPhotos(tag);
});
});
// Fetch photos from Numbers API based on tag
async function fetchAndDisplayPhotos(tag) {
try {
let apiUrl;
if (tag === 'all') {
apiUrl = `${API_BASE_URL}?owner=${ACCOUNT}`;
} else {
const tagName = getTagQueryName(tag);
apiUrl = `${API_BASE_URL}?tag=${tagName}&owner=${ACCOUNT}`;
}
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
// Update the item count
if (data.results && data.results.length) {
itemCountElement.textContent = data.results.length;
} else {
itemCountElement.textContent = '0';
}
displayPhotos(data.results);
} catch (error) {
console.error('Error fetching photos:', error);
photoGrid.innerHTML = `
<div class="error-message">
<p>無法載入資料,請稍後再試。</p>
<p>Error: ${error.message}</p>
</div>
`;
itemCountElement.textContent = '0';
}
}
// Display photos in the grid
function displayPhotos(photos) {
photoGrid.innerHTML = '';
if (!photos || photos.length === 0) {
photoGrid.innerHTML = '<div class="no-results">沒有找到相關資料</div>';
return;
}
photos.forEach(photo => {
const photoItem = document.createElement('div');
photoItem.className = 'photo-item';
// Determine file type and create appropriate content
const mediaContent = createMediaContent(photo);
// Create Capture Eye component
photoItem.innerHTML = `
<capture-eye nid="${photo.id}">
${mediaContent}
</capture-eye>
`;
photoGrid.appendChild(photoItem);
});
}
// Create appropriate media content based on file type
function createMediaContent(asset) {
const fileType = asset.asset_file_mime_type || '';
const title = asset.headline || asset.caption || 'Document asset';
const nid = asset.id;
// Check if a thumbnail is available from the API
if (asset.asset_file_thumbnail) {
return `
<media-viewer
width="100%"
src="${asset.asset_file_thumbnail}"
alt="${title}"
>
</media-viewer>
`;
}
// For image files, use IPFS gateway
if (fileType.startsWith('image/')) {
return `
<media-viewer
width="100%"
src="https://ipfs-pin.numbersprotocol.io/ipfs/${nid}"
alt="${title}"
>
</media-viewer>
`;
}
// For PDF files
if (fileType === 'application/pdf') {
return `
<div class="file-preview pdf-preview">
<div class="file-icon" style="flex: 1; display: flex; align-items: center;">
<img src="images/PDF Preview Icon.png" alt="PDF Icon" style="max-width: 50%; max-height: 50%;">
</div>
<div class="file-info">
<div class="file-title">${title}</div>
<div class="file-type">PDF 文件</div>
</div>
</div>
`;
}
// For other document types (generic document icon)
return `
<div class="file-preview document-preview">
<div class="file-icon" style="flex: 1; display: flex; align-items: center;">
<img src="images/Document Icon.png" alt="Document Icon" style="max-width: 50%; max-height: 50%;">
</div>
<div class="file-info">
<div class="file-title">${title}</div>
<div class="file-type">${getFileTypeDisplay(fileType)}</div>
</div>
</div>
`;
}
// Helper function to display file type in a user-friendly way
function getFileTypeDisplay(mimeType) {
if (!mimeType) return '未知文件類型';
const types = {
'application/pdf': 'PDF 文件',
'application/msword': 'Word 文件',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'Word 文件',
'text/plain': '文本文件',
'audio/': '音頻文件',
'video/': '視頻文件'
};
// Check for partial matches (for audio/video types)
for (const [key, value] of Object.entries(types)) {
if (mimeType.includes(key)) {
return value;
}
}
// Return the mime type if no match
return mimeType.split('/')[1]?.toUpperCase() || '文件';
}
// Map gallery tag to API query parameter
function getTagQueryName(tag) {
const tagMap = {
'calligraphy': '國父墨跡',
'documents': '革命文獻'
};
return tagMap[tag] || tag;
}
// Map API tag to display name
function getTagDisplayName(tag) {
const tagDisplayNames = {
'國父墨跡': '國父墨跡',
'革命文獻': '革命文獻'
};
return tagDisplayNames[tag] || tag;
}
});