Skip to content

Commit 837483d

Browse files
authored
Get back parquet viewer (#943)
* Revert "Remove parquet viewer" This reverts commit fb9b48d. * Remove license related code * Add missing locale i18n * Remove duplicate code
1 parent 9ee35db commit 837483d

File tree

7 files changed

+257
-0
lines changed

7 files changed

+257
-0
lines changed
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
<template>
2+
<div class="flex flex-col border rounded-md p-[16px] gap-[16px]">
3+
<div class="flex justify-between gap-[16px]">
4+
<div class="flex w-[181px] h-[28px]">
5+
<SvgIcon
6+
name="parquet_viewer"
7+
width="13px"
8+
height="13px"
9+
/>
10+
<p class="ml-[8px] text-gray-900 text-lg leading-[28px]">{{ $t('all.parquet') }}</p>
11+
</div>
12+
<!-- <div class="flex items-center justify-center">
13+
<SvgIcon
14+
name="parquet_auto_converted"
15+
width="10px"
16+
height="10px"
17+
class="cursor-pointer"
18+
/>
19+
<p class="ml-[8px] text-gray-500 text-sm leading-[20px]">Auto-converted to Parquet</p>
20+
</div>
21+
<div class="flex items-center justify-center cursor-pointer px-[12px] py-[2px] border rounded-xs">
22+
<SvgIcon
23+
name="parquet_api"
24+
width="10px"
25+
height="6px"
26+
/>
27+
<p class="ml-[8px] text-xs leading-[18px] text-gray-500">
28+
API
29+
</p>
30+
</div>
31+
<div class="flex items-center justify-center cursor-pointer px-[12px] py-[2px] border rounded-xs">
32+
<SvgIcon
33+
name="parquet_api"
34+
width="10px"
35+
height="6px"
36+
/>
37+
<p class="ml-[8px] text-xs leading-[18px] text-gray-500">
38+
Go to dataset viewer
39+
</p>
40+
</div> -->
41+
</div>
42+
<div class="flex justify-between gap-[16px] text-gray-700 text-sm leading-[20px]">
43+
<div class="flex flex-col gap-[8px]">
44+
<p>Subset</p>
45+
<el-select
46+
v-model="subset"
47+
@change="changeSubsetName"
48+
placeholder="Select"
49+
size="large"
50+
class="!w-[350px] sm:!w-full">
51+
<el-option
52+
v-for="item in datasetInfo"
53+
:key="item.config_name"
54+
:label="item.config_name"
55+
:value="item.config_name" />
56+
</el-select>
57+
</div>
58+
<div v-if="splits" class="flex flex-col gap-[8px]">
59+
<p>Split {{ numSplits }}</p>
60+
<el-select
61+
v-model="split"
62+
@change="changeSplitName"
63+
placeholder="Select"
64+
size="large"
65+
class="!w-[350px] sm:!w-full">
66+
<el-option
67+
v-for="item in splits"
68+
:key="item.name"
69+
:label="item.name"
70+
:value="item.name" />
71+
</el-select>
72+
</div>
73+
</div>
74+
<!-- <div>
75+
<el-input
76+
v-model="nameFilterInput"
77+
clearable
78+
size="large"
79+
:prefix-icon="Search"
80+
placeholder="Search this dataset"
81+
@change="filterChange"
82+
class="w-full" />
83+
</div> -->
84+
<div>
85+
<el-table :data="tableData"
86+
border
87+
stripe
88+
max-height="420"
89+
@row-click="toggleRow"
90+
v-loading="previewLoading"
91+
class="w-full rounded-md mb-4"
92+
row-class-name="row-item-clamp cursor-pointer"
93+
cell-class-name="!align-top">
94+
<el-table-column v-for="column in previewData.columns"
95+
:key="column"
96+
:prop="column"
97+
:label="column"
98+
min-width="180" />
99+
</el-table>
100+
<CsgPagination
101+
:perPage="perPage"
102+
:currentPage="currentPage"
103+
@currentChange="reloadRows"
104+
:total="totalRows"
105+
/>
106+
</div>
107+
</div>
108+
</template>
109+
110+
<script setup>
111+
import { computed, onMounted, ref } from 'vue'
112+
import { ElMessage } from 'element-plus'
113+
import { Search } from '@element-plus/icons-vue'
114+
import useFetchApi from '../../packs/useFetchApi'
115+
import CsgPagination from '../shared/CsgPagination.vue'
116+
117+
const props = defineProps({
118+
datasetInfo: Object,
119+
namespacePath: String
120+
})
121+
122+
const previewLoading = ref(false)
123+
124+
const previewData = ref({ columns: [], rows: [], total: 0 })
125+
const currentPage = ref(1)
126+
const totalRows = computed(() => { return previewData.value.total });
127+
const perPage = ref(4)
128+
const nameFilterInput = ref('')
129+
// 默认subset和split的值
130+
const splits = ref(props.datasetInfo[0].splits)
131+
const subset = ref(props.datasetInfo[0].config_name)
132+
const split = ref(splits.value[0]?.name || '')
133+
const numSplits = ref(splits.value[0]?.num_examples || 0)
134+
135+
const tableData = computed(() => {
136+
if (!previewData.value?.rows || !previewData.value?.columns) {
137+
return []
138+
}
139+
140+
const { rows, columns, columns_type = [] } = previewData.value
141+
142+
return rows.map(row =>
143+
columns.reduce((obj, column, index) => {
144+
const value = row[index]
145+
obj[column] = columns_type[index] === 'string' ? value : JSON.stringify(value, null, 2)
146+
return obj
147+
}, {})
148+
)
149+
})
150+
151+
const toggleRow = (_row, _column, event) => {
152+
const row = event.target.closest('.el-table__row')
153+
row.classList.toggle('row-item-clamp')
154+
}
155+
156+
const changeSubsetName = (value) => {
157+
const filteredItem = props.datasetInfo.find(item => item.config_name === value)
158+
splits.value = filteredItem ? filteredItem.data_files: null
159+
split.value = splits.value[0].name || ''
160+
numSplits.value = splits.value[0].num_examples || 0
161+
currentPage.value = 1
162+
reloadRows()
163+
}
164+
165+
const changeSplitName = (value) => {
166+
currentPage.value = 1
167+
reloadRows()
168+
}
169+
170+
const filterChange = () => {
171+
currentPage.value = 1
172+
reloadRows()
173+
}
174+
175+
const reloadRows = (childCurrent) => {
176+
if(childCurrent){
177+
currentPage.value = childCurrent
178+
}
179+
let url = `datasets/${props.namespacePath}/dataviewer/rows`
180+
url = url + `?page=${childCurrent ? childCurrent : currentPage.value}`
181+
url = url + `&per=${perPage.value}`
182+
url = url + `&search=${nameFilterInput.value}`
183+
184+
url = url + `&namespace=${props.namespacePath.split('/')[0]}`
185+
url = url + `&config=${subset.value}`
186+
url = url + `&split=${split.value}`
187+
loadRows(url)
188+
}
189+
190+
async function loadRows(url) {
191+
previewLoading.value = true
192+
const { error, data } = await useFetchApi(url).json()
193+
if (!data.value) {
194+
ElMessage({
195+
message: error.value.msg || t('all.fetchError'),
196+
type: 'warning'
197+
})
198+
} else {
199+
previewData.value = data.value.data
200+
}
201+
previewLoading.value = false
202+
}
203+
204+
onMounted(() => {
205+
reloadRows()
206+
})
207+
</script>
208+
209+
<style scoped>
210+
:deep(.row-item-clamp .cell) {
211+
overflow: hidden;
212+
display: -webkit-box;
213+
-webkit-box-orient: vertical;
214+
-webkit-line-clamp: 2;
215+
}
216+
217+
:deep(.el-table__header-wrapper th) {
218+
background-color: #F9FAFB;
219+
}
220+
</style>

frontend/src/components/shared/RepoSummary.vue

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
<div class="flex md:px-5 md:flex-col-reverse min-h-[calc(100vh-341px)]">
33
<div class="max-w-[60%] sm:max-w-[100%] py-8 pr-6 sm:pr-0 break-words flex-1 md:border-t-0">
44
<el-skeleton v-if="loading" class="mt-4" :rows="5" animated />
5+
<ParquetViewer
6+
v-if="datasetInfo"
7+
:datasetInfo="datasetInfo"
8+
:namespacePath="namespacePath" />
59
<markdown-viewer
610
:content="readmeContent"
711
:setDefaultText="true"
@@ -52,6 +56,7 @@
5256
<script setup>
5357
import { ref, onMounted, computed, watch } from 'vue'
5458
import MarkdownViewer from '../../components/shared/viewers/MarkdownViewer.vue'
59+
import ParquetViewer from '../../components/datasets/ParquetViewer.vue'
5560
import SpaceRelationsCard from '../application_spaces/SpaceRelationsCard.vue'
5661
import PromptRelationsCard from '../prompts/PromptRelationsCard.vue';
5762
import CodeRelationsCard from '../codes/CodeRelationsCard.vue';
@@ -61,6 +66,7 @@
6166
import useFetchApi from '../../packs/useFetchApi'
6267
import resolveContent from '../../packs/resolveContent'
6368
import { ElMessage } from 'element-plus'
69+
import { useI18n } from 'vue-i18n'
6470
6571
const props = defineProps({
6672
namespacePath: String,
@@ -70,11 +76,13 @@
7076
repoType: String
7177
})
7278
79+
const { t } = useI18n()
7380
const loading = ref(true)
7481
const readmeContent = ref('')
7582
const rawReadmeContent = ref('')
7683
const relations = ref({})
7784
const endpoint = ref({})
85+
const datasetInfo = ref(null)
7886
7987
const fetchData = async () => {
8088
const url = `/${props.repoType}s/${props.namespacePath}/blob/README.md`
@@ -88,6 +96,20 @@
8896
loading.value = false
8997
}
9098
99+
const fetchCatalog = async () => {
100+
if (props.repoType !== 'dataset') return
101+
102+
const { error, data } = await useFetchApi(
103+
`datasets/${props.namespacePath}/dataviewer/catalog`
104+
).json()
105+
106+
if (data.value) {
107+
datasetInfo.value = data.value.data.dataset_info
108+
} else {
109+
ElMessage.warning(error.value.msg || t('all.fetchError'))
110+
}
111+
}
112+
91113
const fetchRepoRelations = async () => {
92114
const url = `/${props.repoType}s/${props.namespacePath}/relations`
93115
const { data } = await useFetchApi(url).json()
@@ -121,6 +143,7 @@
121143
122144
onMounted(() => {
123145
fetchData()
146+
fetchCatalog()
124147
fetchRepoRelations()
125148
if (props.repoType == 'model') {
126149
fetchEndpoint()

frontend/src/locales/en_js/all.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,5 @@ export const all = {
8686
private: "Private",
8787
loadMore: "Load more",
8888
viewMore: "View more",
89+
parquet: "Dataset Preview"
8990
}

frontend/src/locales/zh_js/all.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,5 @@ export const all = {
8686
private: "私有",
8787
loadMore:"加载更多",
8888
viewMore: "展示更多",
89+
parquet: "数据集预览"
8990
}

0 commit comments

Comments
 (0)