@abi-software/map-side-bar 2.14.1-simulation.1 → 2.14.1-simulation.3
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/dist/map-side-bar.js +17605 -13097
- package/dist/map-side-bar.umd.cjs +84 -68
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/App.vue +5 -0
- package/src/components/BadgesGroup.vue +1 -0
- package/src/components/DatasetCard.vue +416 -7
- package/src/components/DatasetExplorer.vue +161 -103
- package/src/components/FileBrowser.vue +199 -0
- package/src/components/ImageGallery.vue +11 -380
- package/src/components/SideBar.vue +8 -0
- package/src/components/scripts/utilities.js +50 -0
- package/src/components.d.ts +5 -0
|
@@ -1,108 +1,122 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
<el-card :body-style="bodyStyle" class="content-card">
|
|
3
|
+
<template #header>
|
|
4
|
+
<div class="header">
|
|
5
|
+
<div class="search-input-container" :class="{'is-focus': searchInput}">
|
|
6
|
+
<el-input
|
|
7
|
+
class="search-input"
|
|
8
|
+
placeholder="Search"
|
|
9
|
+
v-model="searchInput"
|
|
10
|
+
@keyup="searchEvent"
|
|
11
|
+
clearable
|
|
12
|
+
@clear="clearSearchClicked"
|
|
13
|
+
></el-input>
|
|
14
|
+
<el-popover
|
|
15
|
+
width="350"
|
|
16
|
+
trigger="hover"
|
|
17
|
+
popper-class="filter-help-popover"
|
|
18
|
+
>
|
|
19
|
+
<template #reference>
|
|
20
|
+
<MapSvgIcon icon="help" class="help" />
|
|
21
|
+
</template>
|
|
22
|
+
<div>
|
|
23
|
+
<strong>Search rules:</strong>
|
|
24
|
+
<ul>
|
|
25
|
+
<li>
|
|
26
|
+
<strong>Multiple Terms:</strong> Separate terms with a comma (<code>,</code>).
|
|
27
|
+
This will find datasets that match any of the terms (an "OR" search).
|
|
28
|
+
</li>
|
|
29
|
+
<li>
|
|
30
|
+
<strong>Exact Phrase:</strong> Terms within a comma block will be matched as an exact phrase.
|
|
31
|
+
</li>
|
|
32
|
+
</ul>
|
|
33
|
+
<br/>
|
|
34
|
+
<strong>Examples:</strong>
|
|
35
|
+
<ul>
|
|
36
|
+
<li>
|
|
37
|
+
<strong>To find by exact phrase:</strong>
|
|
38
|
+
Searching for <code>vagus nerve</code> will find any dataset containing <code>"vagus nerve"</code>.
|
|
39
|
+
</li>
|
|
40
|
+
<li>
|
|
41
|
+
<strong>To find by multiple terms:</strong>
|
|
42
|
+
Searching for <code>nerve, vagus</code> will find data that contains either <code>nerve</code> OR <code>vagus</code>.
|
|
43
|
+
</li>
|
|
44
|
+
</ul>
|
|
45
|
+
</div>
|
|
46
|
+
</el-popover>
|
|
47
|
+
</div>
|
|
48
|
+
<el-button
|
|
49
|
+
type="primary"
|
|
50
|
+
class="button"
|
|
51
|
+
@click="searchEvent"
|
|
52
|
+
size="large"
|
|
18
53
|
>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
<li>
|
|
30
|
-
<strong>Exact Phrase:</strong> Terms within a comma block will be matched as an exact phrase.
|
|
31
|
-
</li>
|
|
32
|
-
</ul>
|
|
33
|
-
<br/>
|
|
34
|
-
<strong>Examples:</strong>
|
|
35
|
-
<ul>
|
|
36
|
-
<li>
|
|
37
|
-
<strong>To find by exact phrase:</strong>
|
|
38
|
-
Searching for <code>vagus nerve</code> will find any dataset containing <code>"vagus nerve"</code>.
|
|
39
|
-
</li>
|
|
40
|
-
<li>
|
|
41
|
-
<strong>To find by multiple terms:</strong>
|
|
42
|
-
Searching for <code>nerve, vagus</code> will find data that contains either <code>nerve</code> OR <code>vagus</code>.
|
|
43
|
-
</li>
|
|
44
|
-
</ul>
|
|
45
|
-
</div>
|
|
46
|
-
</el-popover>
|
|
54
|
+
Search
|
|
55
|
+
</el-button>
|
|
56
|
+
<el-button
|
|
57
|
+
link
|
|
58
|
+
class="el-button-link"
|
|
59
|
+
@click="onResetClick"
|
|
60
|
+
size="large"
|
|
61
|
+
>
|
|
62
|
+
Reset
|
|
63
|
+
</el-button>
|
|
47
64
|
</div>
|
|
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
|
-
|
|
65
|
+
</template>
|
|
66
|
+
<SearchFilters
|
|
67
|
+
class="filters"
|
|
68
|
+
ref="filtersRef"
|
|
69
|
+
:entry="filterEntry"
|
|
70
|
+
:envVars="envVars"
|
|
71
|
+
@filterResults="filterUpdate"
|
|
72
|
+
@numberPerPage="numberPerPageUpdate"
|
|
73
|
+
@loading="filtersLoading"
|
|
74
|
+
@cascaderReady="cascaderReady"
|
|
75
|
+
></SearchFilters>
|
|
76
|
+
<SearchHistory
|
|
77
|
+
ref="searchHistory"
|
|
78
|
+
localStorageKey="sparc.science-dataset-search-history"
|
|
79
|
+
@search="searchHistorySearch"
|
|
80
|
+
></SearchHistory>
|
|
81
|
+
<div class="content scrollbar" v-loading="loadingCards" ref="content">
|
|
82
|
+
<div class="error-feedback" v-if="results.length === 0 && !loadingCards">
|
|
83
|
+
No results found - Please change your search / filter criteria.
|
|
84
|
+
</div>
|
|
85
|
+
<div v-for="result in results" :key="result.doi" class="step-item">
|
|
86
|
+
<DatasetCard
|
|
87
|
+
class="dataset-card"
|
|
88
|
+
:entry="result"
|
|
89
|
+
:envVars="envVars"
|
|
90
|
+
@mouseenter="hoverChanged(result)"
|
|
91
|
+
@mouseleave="hoverChanged(undefined)"
|
|
92
|
+
@openFileBrowser="openFileBrowser"
|
|
93
|
+
@fileInfoReady="fileInfoReady"
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
<el-pagination
|
|
97
|
+
class="pagination"
|
|
98
|
+
v-model:current-page="page"
|
|
99
|
+
hide-on-single-page
|
|
100
|
+
large
|
|
101
|
+
layout="prev, pager, next"
|
|
102
|
+
:page-size="numberPerPage"
|
|
103
|
+
:total="numberOfHits"
|
|
104
|
+
@current-change="pageChange"
|
|
105
|
+
></el-pagination>
|
|
84
106
|
</div>
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
107
|
+
<el-dialog
|
|
108
|
+
v-model="fileBrowserVisible"
|
|
109
|
+
title="File browser"
|
|
110
|
+
width="700"
|
|
111
|
+
top="16px"
|
|
112
|
+
>
|
|
113
|
+
<FileBrowser
|
|
114
|
+
ref="fileBrowserRef"
|
|
115
|
+
@fileActionTriggered="fileActionTriggered"
|
|
92
116
|
/>
|
|
93
|
-
</
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
v-model:current-page="page"
|
|
97
|
-
hide-on-single-page
|
|
98
|
-
large
|
|
99
|
-
layout="prev, pager, next"
|
|
100
|
-
:page-size="numberPerPage"
|
|
101
|
-
:total="numberOfHits"
|
|
102
|
-
@current-change="pageChange"
|
|
103
|
-
></el-pagination>
|
|
104
|
-
</div>
|
|
105
|
-
</el-card>
|
|
117
|
+
</el-dialog>
|
|
118
|
+
</el-card>
|
|
119
|
+
|
|
106
120
|
</template>
|
|
107
121
|
|
|
108
122
|
<script>
|
|
@@ -110,17 +124,20 @@
|
|
|
110
124
|
import {
|
|
111
125
|
ElButton as Button,
|
|
112
126
|
ElCard as Card,
|
|
127
|
+
ElDialog as Dialog,
|
|
113
128
|
ElDrawer as Drawer,
|
|
114
129
|
ElIcon as Icon,
|
|
115
130
|
ElInput as Input,
|
|
116
131
|
ElPagination as Pagination,
|
|
117
132
|
ElMessage as Message,
|
|
118
133
|
} from 'element-plus'
|
|
119
|
-
import 'element-plus/es/components/message/style/css'
|
|
134
|
+
import 'element-plus/es/components/message/style/css'
|
|
120
135
|
import SearchFilters from './SearchFilters.vue'
|
|
121
136
|
import SearchHistory from './SearchHistory.vue'
|
|
122
137
|
import DatasetCard from './DatasetCard.vue'
|
|
138
|
+
import FileBrowser from './FileBrowser.vue'
|
|
123
139
|
import EventBus from './EventBus.js'
|
|
140
|
+
import { processProtocolsData } from './scripts/utilities.js'
|
|
124
141
|
|
|
125
142
|
import { AlgoliaClient } from '../algolia/algolia.js'
|
|
126
143
|
import { getFilters, facetPropPathMapping } from '../algolia/utils.js'
|
|
@@ -158,11 +175,13 @@ var initial_state = {
|
|
|
158
175
|
|
|
159
176
|
export default {
|
|
160
177
|
components: {
|
|
161
|
-
SearchFilters,
|
|
162
178
|
DatasetCard,
|
|
179
|
+
FileBrowser,
|
|
180
|
+
SearchFilters,
|
|
163
181
|
SearchHistory,
|
|
164
182
|
Button,
|
|
165
183
|
Card,
|
|
184
|
+
Dialog,
|
|
166
185
|
Drawer,
|
|
167
186
|
Icon,
|
|
168
187
|
Input,
|
|
@@ -199,6 +218,12 @@ export default {
|
|
|
199
218
|
display: 'flex',
|
|
200
219
|
},
|
|
201
220
|
cascaderIsReady: false,
|
|
221
|
+
fileBrowserVisible: false,
|
|
222
|
+
fileSearch: {
|
|
223
|
+
onGoing: false,
|
|
224
|
+
datasetId: undefined,
|
|
225
|
+
searchTerm: undefined,
|
|
226
|
+
}
|
|
202
227
|
}
|
|
203
228
|
},
|
|
204
229
|
computed: {
|
|
@@ -216,6 +241,25 @@ export default {
|
|
|
216
241
|
},
|
|
217
242
|
},
|
|
218
243
|
methods: {
|
|
244
|
+
fileActionTriggered: function(action) {
|
|
245
|
+
this.fileBrowserVisible = false
|
|
246
|
+
EventBus.emit('PopoverActionClick', action)
|
|
247
|
+
EventBus.emit('contextUpdate', action) // Pass to mapintegratedvuer
|
|
248
|
+
},
|
|
249
|
+
fileInfoReady: function(payload) {
|
|
250
|
+
if (this.fileSearch.onGoing) {
|
|
251
|
+
if (payload.id === this.fileSearch.datasetID) {
|
|
252
|
+
payload.instance.openFileBrowser()
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
displayFileInfo: function(datasetID, fileSearch, searchTerm = "") {
|
|
257
|
+
let query = searchTerm ? searchTerm : datasetID
|
|
258
|
+
this.openSearch([], query)
|
|
259
|
+
this.fileSearch.onGoing = true
|
|
260
|
+
this.fileSearch.datasetID = datasetID
|
|
261
|
+
this.fileSearch.searchTerm = fileSearch
|
|
262
|
+
},
|
|
219
263
|
hoverChanged: function (data) {
|
|
220
264
|
const payload = data ? { ...data, tabType: 'dataset' } : { tabType: 'dataset' }
|
|
221
265
|
this.$emit('hover-changed', payload)
|
|
@@ -227,6 +271,18 @@ export default {
|
|
|
227
271
|
this.results = []
|
|
228
272
|
this.loadingCards = false
|
|
229
273
|
},
|
|
274
|
+
openFileBrowser: function(data) {
|
|
275
|
+
this.fileBrowserVisible = true
|
|
276
|
+
this.$nextTick(() => {
|
|
277
|
+
this.$refs.fileBrowserRef.setData(data.items)
|
|
278
|
+
if (this.fileSearch.onGoing) {
|
|
279
|
+
if (this.fileSearch.datasetID === data.datasetID) {
|
|
280
|
+
this.$refs.fileBrowserRef.setSearchTerm(this.fileSearch.searchTerm)
|
|
281
|
+
}
|
|
282
|
+
this.fileSearch.onGoing = false
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
},
|
|
230
286
|
openSearch: function (filter, search = '') {
|
|
231
287
|
this.searchInput = search
|
|
232
288
|
this.resetPageNavigation()
|
|
@@ -418,7 +474,7 @@ export default {
|
|
|
418
474
|
})
|
|
419
475
|
.then((data) => {
|
|
420
476
|
if (this.searchInput.toLowerCase().includes("reveal")) {
|
|
421
|
-
this.results.
|
|
477
|
+
processProtocolsData(this.results, data, this.envVars.TEST_DATA_LOCATION)
|
|
422
478
|
}
|
|
423
479
|
})
|
|
424
480
|
}
|
|
@@ -478,6 +534,8 @@ export default {
|
|
|
478
534
|
let i = this.results.findIndex((res) =>
|
|
479
535
|
element.doi ? element.doi.includes(res.doi) : false
|
|
480
536
|
)
|
|
537
|
+
|
|
538
|
+
|
|
481
539
|
// Assign scicrunch results to the object
|
|
482
540
|
Object.assign(this.results[i], element)
|
|
483
541
|
// Assign the attributes that need some processing
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
|
|
4
|
+
<el-table
|
|
5
|
+
v-if="fileLists"
|
|
6
|
+
:data="fileLists"
|
|
7
|
+
style="width: 100%;"
|
|
8
|
+
height="600"
|
|
9
|
+
:stripe="true"
|
|
10
|
+
>
|
|
11
|
+
<el-table-column type="expand">
|
|
12
|
+
<template #default="props">
|
|
13
|
+
<div class="file-details" m="4">
|
|
14
|
+
<p m="t-0 b-2" v-if="props.row.description">
|
|
15
|
+
Description: {{ props.row.description }}
|
|
16
|
+
</p>
|
|
17
|
+
<p m="t-0 b-2" v-if="props.row.protocol">
|
|
18
|
+
Protocol: {{ props.row.protocol }}
|
|
19
|
+
</p>
|
|
20
|
+
<div v-for="(val, key) in props.row.columns">
|
|
21
|
+
<p :key="key" m="t-0 b-2">Column {{ key + 1 }}: {{ val }}</p>
|
|
22
|
+
</div>
|
|
23
|
+
<p m="t-0 b-2">File path: {{ props.row.filePath }}</p>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
</el-table-column>
|
|
27
|
+
<el-table-column
|
|
28
|
+
prop="thumbnail"
|
|
29
|
+
label="Thumbnail"
|
|
30
|
+
width="170"
|
|
31
|
+
>
|
|
32
|
+
<template #default="scope">
|
|
33
|
+
<el-image
|
|
34
|
+
v-if="scope.row.thumbnail"
|
|
35
|
+
:src="scope.row.thumbnail"
|
|
36
|
+
style="max-width: 150px; max-height: 150px"
|
|
37
|
+
fit="contain"
|
|
38
|
+
lazy
|
|
39
|
+
/>
|
|
40
|
+
</template>
|
|
41
|
+
</el-table-column>
|
|
42
|
+
<el-table-column
|
|
43
|
+
prop="fileName"
|
|
44
|
+
label="File name"
|
|
45
|
+
width="200"
|
|
46
|
+
class-name="title-text"
|
|
47
|
+
/>
|
|
48
|
+
<el-table-column
|
|
49
|
+
prop="type"
|
|
50
|
+
label="Type"
|
|
51
|
+
width="100"
|
|
52
|
+
/>
|
|
53
|
+
<el-table-column
|
|
54
|
+
fixed="right"
|
|
55
|
+
>
|
|
56
|
+
<template #header>
|
|
57
|
+
<el-input v-model="search" size="small" placeholder="Type to search" />
|
|
58
|
+
</template>
|
|
59
|
+
<template #default="scope">
|
|
60
|
+
<el-button
|
|
61
|
+
size="small"
|
|
62
|
+
@click="handleView(scope.row)"
|
|
63
|
+
>
|
|
64
|
+
{{ getActionLabel(scope.row.type) }}
|
|
65
|
+
</el-button>
|
|
66
|
+
</template>
|
|
67
|
+
</el-table-column>
|
|
68
|
+
</el-table>
|
|
69
|
+
</div>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<script>
|
|
73
|
+
//provide the s3Bucket related methods and data.
|
|
74
|
+
import {
|
|
75
|
+
ElButton as Button,
|
|
76
|
+
ElImage as Image,
|
|
77
|
+
ElInput as Input,
|
|
78
|
+
ElTable as Table,
|
|
79
|
+
ElTableColumn as TableColumn
|
|
80
|
+
} from "element-plus";
|
|
81
|
+
import EventBus from './EventBus.js'
|
|
82
|
+
import { ref } from 'vue'
|
|
83
|
+
|
|
84
|
+
export default {
|
|
85
|
+
name: 'FileBrowser',
|
|
86
|
+
components: {
|
|
87
|
+
Button,
|
|
88
|
+
Image,
|
|
89
|
+
Input,
|
|
90
|
+
Table,
|
|
91
|
+
TableColumn
|
|
92
|
+
},
|
|
93
|
+
data() {
|
|
94
|
+
return {
|
|
95
|
+
category: "All",
|
|
96
|
+
search: "",
|
|
97
|
+
tableData: undefined,
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
methods: {
|
|
101
|
+
getActionLabel: function(type) {
|
|
102
|
+
if (type === "Simulations" || type === "Protocol Data") {
|
|
103
|
+
return "Run"
|
|
104
|
+
} else {
|
|
105
|
+
return "View"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
setSearchTerm: function(searchTerm) {
|
|
109
|
+
this.search = searchTerm
|
|
110
|
+
},
|
|
111
|
+
handleView: function(row) {
|
|
112
|
+
this.$emit("fileActionTriggered", row.action)
|
|
113
|
+
},
|
|
114
|
+
downloadThumbnail: async function(url, entry) {
|
|
115
|
+
const response = await fetch(url)
|
|
116
|
+
if (response.ok) {
|
|
117
|
+
let data = await response.text()
|
|
118
|
+
if (typeof data === 'string' && data.startsWith('data:')) {
|
|
119
|
+
entry.thumbnail = data
|
|
120
|
+
} else {
|
|
121
|
+
if (entry.mimetype) {
|
|
122
|
+
entry.thumbnail = `data:${entry.mimetype};base64,${data}`
|
|
123
|
+
} else {
|
|
124
|
+
entry.thumbnail = data
|
|
125
|
+
}
|
|
126
|
+
let index = this.tableData.findIndex((item) => item.filePath === entry.filePath);
|
|
127
|
+
if (index > -1) {
|
|
128
|
+
this.tableData[index] = {...entry}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
setData: function(data) {
|
|
134
|
+
this.tableData = ref([])
|
|
135
|
+
this.search = ""
|
|
136
|
+
Object.keys(data).forEach((key) => {
|
|
137
|
+
if (key !== "Dataset") {
|
|
138
|
+
data[key].forEach((item) => {
|
|
139
|
+
const entry = {
|
|
140
|
+
action: item.userData,
|
|
141
|
+
description: item.description ? item.description : "",
|
|
142
|
+
protocol: item.protocol ? item.protocol : "",
|
|
143
|
+
columns: [],
|
|
144
|
+
fileName: item.title,
|
|
145
|
+
filePath: item.filePath,
|
|
146
|
+
mimetype: item.mimetype,
|
|
147
|
+
type: key,
|
|
148
|
+
}
|
|
149
|
+
if (item.columns && item.columns.length > 0) {
|
|
150
|
+
item.columns.forEach((column) => entry.columns.push(JSON.stringify(column)))
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
this.tableData.push(entry)
|
|
154
|
+
if (item.thumbnail?.includes("encodeBase64")) {
|
|
155
|
+
this.downloadThumbnail(item.thumbnail, entry)
|
|
156
|
+
} else {
|
|
157
|
+
entry.thumbnail = item.thumbnail
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
computed: {
|
|
165
|
+
fileLists() {
|
|
166
|
+
if (!this.search) return this.tableData
|
|
167
|
+
const keys = ["fileName", "filePath", "description", "type", "protocol"]
|
|
168
|
+
const lower = this.search.toLowerCase()
|
|
169
|
+
const list = this.tableData.filter((data) => {
|
|
170
|
+
for (let key of keys) {
|
|
171
|
+
if (data[key] && data[key].toLowerCase().includes(lower)) {
|
|
172
|
+
return true
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (data.columns) {
|
|
176
|
+
for (let column of data.columns) {
|
|
177
|
+
if (column.toLowerCase().includes(lower)) {
|
|
178
|
+
return true
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
})
|
|
183
|
+
return list
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
}
|
|
187
|
+
</script>
|
|
188
|
+
|
|
189
|
+
<style lang="scss" scoped>
|
|
190
|
+
:deep(.el-table__body-wrapper) {
|
|
191
|
+
.title-text {
|
|
192
|
+
font-size: 10px;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.file-details {
|
|
197
|
+
font-size: 10px;
|
|
198
|
+
}
|
|
199
|
+
</style>
|