Skip to content

Commit

Permalink
feat: Split dependencies table into two tables
Browse files Browse the repository at this point in the history
One table for dev deps and another for deps
  • Loading branch information
botmaster committed Mar 2, 2024
1 parent d5459ff commit 36103be
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 164 deletions.
162 changes: 162 additions & 0 deletions components/app/DepsTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<script setup lang="ts">
interface Props {
dependencies: Record<string, string>
}
const props = defineProps<Props>();
const latestVersions = ref<Record<string, string>>({});
async function fetchLatestVersion(pkgName: string) {
try {
const response = await fetch(`https://unpkg.com/${pkgName}/package.json`);
const data = await response.json();
return data.version;
}
catch (error) {
console.error(`Failed to fetch version for package ${pkgName}:`, error);
return null;
}
}
async function fetchLatestVersions() {
// fetch latest versions in parallel
const promises = Object.keys(props.dependencies).map(async (pkgName) => {
latestVersions.value[pkgName] = 'loading';
try {
latestVersions.value[pkgName] = await fetchLatestVersion(pkgName);
}
catch (error) {
latestVersions.value[pkgName] = 'error';
}
});
await Promise.all(promises);
}
const depsTarget = ref<HTMLElement | null>(null);
if (process.client) {
useIntersectionObserver(depsTarget, ([{ isIntersecting }]) => {
if (isIntersecting) {
// If latest versions are not yet fetched, fetch them
if (Object.keys(latestVersions.value).length === 0)
fetchLatestVersions();
}
});
}
</script>

<template>
<table ref="depsTarget" class="deps-table">
<thead>
<tr>
<th class="" />
<th class="" />
<th class="autowidth" />
<th class="" />
<th class="" />
</tr>
</thead>
<tbody>
<tr v-for="(value, key) in dependencies" :key="key">
<td>{{ key }}</td>
<template v-if="latestVersions[key] === 'error'">
<td colspan="4" class="right">
<span title="Failed to fetch latest version">
<Icon
name="ic:baseline-error"
class="text-aurora-nord-11"
/>
</span>
</td>
</template>

<template v-else-if="latestVersions[key] === 'loading'">
<td colspan="4" class="right">
<span title="Loading">
<Icon
name="eos-icons:three-dots-loading"
class="text-primary"
/>
</span>
</td>
</template>

<template
v-else-if="
latestVersions[key]
&& latestVersions[key] !== value.replace('^', '').trim()
"
>
<td class="right">
{{ value }}
</td>
<td class="text-center">
<Icon name="mdi:arrow-right-thin" />
</td>
<td class="right">
{{ latestVersions[key] }}
</td>
<td>
<span title="Update available"><Icon
name="material-symbols:arrow-circle-up"
class="text-base text-aurora-nord-14"
/></span>
</td>
</template>

<template v-else-if="latestVersions[key]">
<td colspan="3" class="right">
{{ value }}
</td>
<td>
<span title="Up to date"><Icon
name="material-symbols:check-box-rounded"
class="text-base text-primary"
/></span>
</td>
</template>

<template v-else>
<td colspan="4" class="right">
{{ value }}
</td>
</template>
</tr>
</tbody>
</table>
</template>

<style scoped lang="scss">
.deps-table {
@apply table-auto w-full font-code;
tr {
@apply text-xs lg:text-sm;
}
th,
td {
@apply text-left align-middle;
}
td {
@apply border-b border-b-snowstorm-nord-4 py-1 dark:border-b-polarnight-nord-2;
&:not(:first-child) {
@apply w-px whitespace-nowrap;
}
&:not(:first-child):not(:last-child) {
@apply px-1 lg:px-2;
}
}
td.autowidth {
@apply w-px;
}
td.right {
@apply text-right;
}
}
</style>
4 changes: 4 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"sorry": "Sorry, that page doesn't exist.",
"title": "404!"
},
"about": {
"dependencies": "Dependencies",
"devDependencies": "Dev dependencies"
},
"error": {
"intro": "It looks like something broke.",
"sorry": "Sorry about that 😕",
Expand Down
4 changes: 4 additions & 0 deletions locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"sorry": "Désolé, cette page n'existe pas.",
"title": "404 !!!"
},
"about": {
"dependencies": "Dépendances ",
"devDependencies": "Dépandances de développement"
},
"error": {
"intro": "On dirait que quelque chose s'est cassé.",
"sorry": "Désolé 😕",
Expand Down
181 changes: 17 additions & 164 deletions pages/about.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ definePageMeta({
const runtimeConfig = useRuntimeConfig();
const pkg = JSON.parse(runtimeConfig.public.pkg);
const { locale: currentLocale } = useI18n();
const { locale: currentLocale, t } = useI18n();
const { data } = await useAsyncData(`about-${currentLocale.value}`, () =>
queryContent<IPage>()
Expand All @@ -27,61 +27,16 @@ if (data?.value)
useContentHead(data as Ref<IPage>);
const dependencies = computed(() => {
const merged = {
return {
...pkg.dependencies,
...pkg.devDependencies,
};
// Sort by key alphabetically
return Object.keys(merged)
.sort()
.reduce(
(obj, key) => {
obj[key] = merged[key];
return obj;
},
{} as Record<string, string>,
);
});
const latestVersions = ref<Record<string, string>>({});
async function fetchLatestVersion(pkgName: string) {
try {
const response = await fetch(`https://unpkg.com/${pkgName}/package.json`);
const data = await response.json();
return data.version;
}
catch (error) {
console.error(`Failed to fetch version for package ${pkgName}:`, error);
return null;
}
}
async function fetchLatestVersions() {
// fetch latest versions in parallel
const promises = Object.keys(dependencies.value).map(async (pkgName) => {
latestVersions.value[pkgName] = 'loading';
try {
latestVersions.value[pkgName] = await fetchLatestVersion(pkgName);
}
catch (error) {
latestVersions.value[pkgName] = 'error';
}
});
await Promise.all(promises);
}
const depsTarget = ref<HTMLElement | null>(null);
if (process.client) {
useIntersectionObserver(depsTarget, ([{ isIntersecting }]) => {
if (isIntersecting) {
// If latest versions are not yet fetched, fetch them
if (Object.keys(latestVersions.value).length === 0)
fetchLatestVersions();
}
});
}
const devDependencies = computed(() => {
return {
...pkg.devDependencies,
};
});
</script>

<template>
Expand All @@ -98,122 +53,20 @@ if (process.client) {
v{{ pkg.version }}
</p>
</template>
<ContentRenderer class="nuxt-content" :value="data" />
<div class="nuxt-content mt-2">
<table ref="depsTarget" class="deps-table">
<thead>
<tr>
<th class="" />
<th class="" />
<th class="autowidth" />
<th class="" />
<th class="" />
</tr>
</thead>
<tbody>
<tr v-for="(value, key, index) in dependencies" :key="index">
<td>{{ key }}</td>
<template v-if="latestVersions[key] === 'error'">
<td colspan="4" class="right">
<span title="Failed to fetch latest version">
<Icon
name="ic:baseline-error"
class="text-aurora-nord-11"
/>
</span>
</td>
</template>

<template v-else-if="latestVersions[key] === 'loading'">
<td colspan="4" class="right">
<span title="Loading">
<Icon
name="eos-icons:three-dots-loading"
class="text-primary"
/>
</span>
</td>
</template>

<template
v-else-if="
latestVersions[key]
&& latestVersions[key] !== value.replace('^', '').trim()
"
>
<td class="right">
{{ value }}
</td>
<td class="text-center">
<Icon name="mdi:arrow-right-thin" />
</td>
<td class="right">
{{ latestVersions[key] }}
</td>
<td>
<span title="Update available"><Icon
name="material-symbols:arrow-circle-up"
class="text-base text-aurora-nord-14"
/></span>
</td>
</template>
<ContentRenderer class="nuxt-content" :value="data" />

<template v-else-if="latestVersions[key]">
<td colspan="3" class="right">
{{ value }}
</td>
<td>
<span title="Up to date"><Icon
name="material-symbols:check-box-rounded"
class="text-base text-primary"
/></span>
</td>
</template>
<div class="mt-2">
<p class="mb-0 font-bold">
{{ t('pages.about.dependencies') }}
</p>
<DepsTable :dependencies="dependencies" />

<template v-else>
<td colspan="4" class="right">
{{ value }}
</td>
</template>
</tr>
</tbody>
</table>
<p class="mb-0 mt-6 font-bold">
{{ t('pages.about.devDependencies') }}
</p>
<DepsTable :dependencies="devDependencies" />
</div>
</NuxtLayout>
</main>
</template>

<style scoped lang="scss">
.deps-table {
@apply table-auto w-full font-code;
tr {
@apply text-xs lg:text-sm;
}
th,
td {
@apply text-left align-middle;
}
td {
@apply border-b border-b-snowstorm-nord-4 py-1 dark:border-b-polarnight-nord-2;
&:not(:first-child) {
@apply w-px whitespace-nowrap;
}
&:not(:first-child):not(:last-child) {
@apply px-1 lg:px-2;
}
}
td.autowidth {
@apply w-px;
}
td.right {
@apply text-right;
}
}
</style>

0 comments on commit 36103be

Please sign in to comment.