Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# build stage
FROM --platform=$BUILDPLATFORM node:lts-alpine AS build-stage
# Set environment variables for non-interactive npm installs
ENV NPM_CONFIG_LOGLEVEL warn
ENV CI true
ENV NPM_CONFIG_LOGLEVEL=warn
ENV CI=true

RUN apk add --update python3 make g++\
&& rm -rf /var/cache/apk/*
Expand All @@ -13,12 +13,12 @@ RUN npm install -g pnpm && pnpm i --ignore-scripts --frozen-lockfile
COPY . .
ARG BASE_URL
ENV BASE_URL=${BASE_URL}
ENV VITE_VERCEL_ENV production
ENV VITE_VERCEL_ENV=production
RUN pnpm build

# production stage
FROM nginxinc/nginx-unprivileged:stable-alpine AS production-stage
ENV VITE_VERCEL_ENV production
ENV VITE_VERCEL_ENV=production
ARG BASE_URL
ENV BASE_URL=${BASE_URL}
COPY --from=build-stage /app/dist /usr/share/nginx/html
Expand Down
4,254 changes: 2,344 additions & 1,910 deletions locales/ar.yml

Large diffs are not rendered by default.

4,396 changes: 2,381 additions & 2,015 deletions locales/da.yml

Large diffs are not rendered by default.

5,256 changes: 2,832 additions & 2,424 deletions locales/de.yml

Large diffs are not rendered by default.

5,256 changes: 2,834 additions & 2,422 deletions locales/el.yml

Large diffs are not rendered by default.

165 changes: 125 additions & 40 deletions locales/en.yml

Large diffs are not rendered by default.

4,993 changes: 2,674 additions & 2,319 deletions locales/es.yml

Large diffs are not rendered by default.

5,171 changes: 2,677 additions & 2,494 deletions locales/fr.yml

Large diffs are not rendered by default.

4,851 changes: 2,623 additions & 2,228 deletions locales/ga.yml

Large diffs are not rendered by default.

4,951 changes: 2,657 additions & 2,294 deletions locales/it.yml

Large diffs are not rendered by default.

3,446 changes: 1,899 additions & 1,547 deletions locales/ko.yml

Large diffs are not rendered by default.

4,692 changes: 2,522 additions & 2,170 deletions locales/nl.yml

Large diffs are not rendered by default.

4,598 changes: 2,495 additions & 2,103 deletions locales/no.yml

Large diffs are not rendered by default.

4,674 changes: 2,535 additions & 2,139 deletions locales/pl.yml

Large diffs are not rendered by default.

4,847 changes: 2,626 additions & 2,221 deletions locales/pt.yml

Large diffs are not rendered by default.

4,773 changes: 2,592 additions & 2,181 deletions locales/ru.yml

Large diffs are not rendered by default.

4,580 changes: 2,453 additions & 2,127 deletions locales/tr.yml

Large diffs are not rendered by default.

4,688 changes: 2,548 additions & 2,140 deletions locales/uk.yml

Large diffs are not rendered by default.

4,671 changes: 2,580 additions & 2,091 deletions locales/vi.yml

Large diffs are not rendered by default.

256 changes: 169 additions & 87 deletions locales/zh.yml

Large diffs are not rendered by default.

71 changes: 45 additions & 26 deletions src/components/CollapsibleToolMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import { useStorage } from '@vueuse/core';
import { useThemeVars } from 'naive-ui';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import MenuIconItem from './MenuIconItem.vue';
import MenuItemWithTooltip from './MenuItemTooltip.vue';
import type { Tool, ToolCategory } from '@/tools/tools.types';

const { t } = useI18n();
const props = withDefaults(defineProps<{ toolsByCategory?: ToolCategory[] }>(), { toolsByCategory: () => [] });

Check failure on line 11 in src/components/CollapsibleToolMenu.vue

View workflow job for this annotation

GitHub Actions / ci

defineProps should be the first statement in `<script setup>` (after any potential import statements or type definitions)
const { toolsByCategory } = toRefs(props);
const route = useRoute();

Expand All @@ -21,8 +23,8 @@
{
deep: true,
serializer: {
read: v => (v ? JSON.parse(v) : null),
write: v => JSON.stringify(v),
read: (v) => (v ? JSON.parse(v) : null),

Check failure on line 26 in src/components/CollapsibleToolMenu.vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected parentheses around single function argument having a body with no curly braces
write: (v) => JSON.stringify(v),

Check failure on line 27 in src/components/CollapsibleToolMenu.vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected parentheses around single function argument having a body with no curly braces
},
},
);
Expand Down Expand Up @@ -52,9 +54,7 @@
}

const areAllCollapsed = computed(() => {
return toolsByCategory.value.every(({ name }) =>
collapsedCategories.value[name] !== false,
);
return toolsByCategory.value.every(({ name }) => collapsedCategories.value[name] !== false);
});

async function toggleAllCategories() {
Expand Down Expand Up @@ -82,12 +82,12 @@
const baseDuration = 250;
const durationIncrement = 5;

return baseDuration + (Math.min(itemCount, 30) * durationIncrement);
return baseDuration + Math.min(itemCount, 30) * durationIncrement;
}

// Function to check if any tool in the category is active
function isCategoryActive(components: Tool[]): boolean {
return components.some(tool => tool.path === route.path);
return components.some((tool) => tool.path === route.path);

Check failure on line 90 in src/components/CollapsibleToolMenu.vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected parentheses around single function argument having a body with no curly braces
}

const menuOptions = computed(() =>
Expand All @@ -96,7 +96,7 @@
isCollapsed: collapsedCategories.value[name],
isActive: isCategoryActive(components),
animationDuration: getAnimationDuration(components.length),
tools: components.map(tool => ({
tools: components.map((tool) => ({

Check failure on line 99 in src/components/CollapsibleToolMenu.vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected parentheses around single function argument having a body with no curly braces
label: makeLabel(tool),
icon: makeIcon(tool),
key: tool.path,
Expand All @@ -105,16 +105,14 @@
);

async function scrollToActiveItem() {
const activeCategory = toolsByCategory.value.find(({ components }) =>
isCategoryActive(components),
);
const activeCategory = toolsByCategory.value.find(({ components }) => isCategoryActive(components));

if (activeCategory) {
// Expand the active category
collapsedCategories.value[activeCategory.name] = false;

// Wait for the entire animation to complete
await new Promise(resolve => setTimeout(resolve, getAnimationDuration(activeCategory.components.length) + 50));
await new Promise((resolve) => setTimeout(resolve, getAnimationDuration(activeCategory.components.length) + 50));

Check failure on line 115 in src/components/CollapsibleToolMenu.vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected parentheses around single function argument having a body with no curly braces

// Scroll to the active menu item
const menuContainer = menuContainerRefs.value[activeCategory.name];
Expand All @@ -131,9 +129,12 @@
scrollToActiveItem();
});

watch(() => route.path, () => {
scrollToActiveItem();
});
watch(
() => route.path,
() => {
scrollToActiveItem();
},
);

const themeVars = useThemeVars();
</script>
Expand All @@ -142,22 +143,36 @@
<div class="top-controls" mb-12px ml-12px>
<c-button :disabled="isToggling" @click="toggleAllCategories">
<span v-if="isToggling">
{{ areAllCollapsed ? 'Expanding...' : 'Collapsing...' }}
{{ areAllCollapsed ? t('home.expanding') : t('home.collapsing') }}
</span>
<span v-else>
{{ areAllCollapsed ? 'Expand All Tools' : 'Collapse All Tools' }}
{{ areAllCollapsed ? t('home.expandAllTools') : t('home.collapseAllTools') }}
</span>
</c-button>
</div>

<div v-for="{ name, tools, isCollapsed, isActive, animationDuration } of menuOptions" :key="name" class="category-container">
<div
v-for="{ name, tools, isCollapsed, isActive, animationDuration } of menuOptions"
:key="name"
class="category-container"
>
<button
class="category-button"
:class="{ 'category-active': isActive }"
flex cursor-pointer items-center op-60
flex
cursor-pointer
items-center
op-60
@click="toggleCategoryCollapse({ name })"
>
<span :class="{ 'rotate-0': isCollapsed, 'rotate-90': !isCollapsed }" text-16px lh-1 op-50 transition-transform duration-200>
<span
:class="{ 'rotate-0': isCollapsed, 'rotate-90': !isCollapsed }"
text-16px
lh-1
op-50
transition-transform
duration-200
>
<icon-mdi-chevron-right />
</span>

Expand All @@ -167,7 +182,11 @@
</button>

<div
:ref="el => { if (el) menuContainerRefs[name] = el as HTMLElement }"
:ref="
(el) => {
if (el) menuContainerRefs[name] = el as HTMLElement;
}
"
class="menu-container"
:class="{ collapsed: isCollapsed }"
:style="{ '--animation-duration': `${animationDuration}ms` }"
Expand Down Expand Up @@ -215,11 +234,11 @@
}
}
.category-container {
.menu-container {
display: grid;
grid-template-rows: 1fr;
transition: grid-template-rows var(--animation-duration, 250ms) ease-out;
will-change: grid-template-rows;
.menu-container {
display: grid;
grid-template-rows: 1fr;
transition: grid-template-rows var(--animation-duration, 250ms) ease-out;
will-change: grid-template-rows;

&.collapsed {
grid-template-rows: 0fr;
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/i18n.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { get } from '@vueuse/core';
import type { Plugin } from 'vue';
import { createI18n } from 'vue-i18n';

const DEFAULT_LOCALE = String(import.meta.env.VITE_LANGUAGE || 'en');
const DEFAULT_LOCALE = String(import.meta.env.VITE_LANGUAGE || 'zh');

const i18n = createI18n({
legacy: false,
Expand Down
2 changes: 1 addition & 1 deletion src/tools/date-time-converter/date-time-converter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ function formatDateInTimezone(date: Date | undefined, timezone: string): string
}

return withDefaultOnError(() => {
return formatInTimeZone(date, timezone, 'yyyy-MM-dd\'T\'HH:mm:ssXXX');
return formatInTimeZone(date, timezone, 'yyyy-MM-dd HH:mm:ss XXX');
}, '');
}
</script>
Expand Down
47 changes: 26 additions & 21 deletions src/tools/docker-pangolin-labels/docker-pangolin-labels.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<script setup lang="ts">
import yaml from 'yaml';
import { blueprintToLabels, extractPangolinLabelsFromCompose, pangolinLabelsToBlueprint } from './docker-pangolin-labels.service';
import { useI18n } from 'vue-i18n';
import {
blueprintToLabels,
extractPangolinLabelsFromCompose,
pangolinLabelsToBlueprint,
} from './docker-pangolin-labels.service';

const { t } = useI18n();

const composeInput = ref('');
const blueprintOutput = ref('');
Expand All @@ -18,15 +25,14 @@
try {
const compose = yaml.parse(composeInput.value) as any;
if (!compose?.services) {
throw new Error('Invalid docker-compose.yml');
throw new Error(t('tools.docker-pangolin-labels.texts.error-invalid-compose'));
}

const labels = extractPangolinLabelsFromCompose(compose);
const blueprint = pangolinLabelsToBlueprint(labels);

blueprintOutput.value = yaml.stringify(blueprint);
}
catch (err: any) {
} catch (err: any) {

Check failure on line 35 in src/tools/docker-pangolin-labels/docker-pangolin-labels.vue

View workflow job for this annotation

GitHub Actions / ci

Closing curly brace appears on the same line as the subsequent block
error.value = err.toString();
}
}
Expand All @@ -41,14 +47,13 @@
try {
const blueprint = yaml.parse(blueprintInput.value) as any;
if (!blueprint || typeof blueprint !== 'object') {
throw new Error('Invalid blueprint YAML');
throw new Error(t('tools.docker-pangolin-labels.texts.error-invalid-blueprint'));
}

const labels = blueprintToLabels(blueprint, labelsAsArray.value ? 'array' : 'object');

labelsOutput.value = yaml.stringify(labels);
}
catch (err: any) {
} catch (err: any) {

Check failure on line 56 in src/tools/docker-pangolin-labels/docker-pangolin-labels.vue

View workflow job for this annotation

GitHub Actions / ci

Closing curly brace appears on the same line as the subsequent block
error.value = err?.message ?? String(err);
}
}
Expand All @@ -58,19 +63,19 @@
<div>
<n-tabs type="segment">
<!-- COMPOSE → BLUEPRINT -->
<n-tab-pane name="compose-to-blueprint" tab="Compose → Blueprint">
<n-tab-pane name="compose-to-blueprint" :tab="t('tools.docker-pangolin-labels.texts.tab-compose-to-blueprint')">
<c-input-text
v-model:value="composeInput"
label="Docker Compose YAML:"
:label="t('tools.docker-pangolin-labels.texts.label-docker-compose-yaml')"
multiline
rows="10"
placeholder="Paste full docker-compose.yml here…"
:placeholder="t('tools.docker-pangolin-labels.texts.placeholder-docker-compose-yaml')"
mb-2
/>

<n-space justify="center" mb-2>
<n-button type="primary" @click="convertComposeToBlueprint">
Extract Pangolin Blueprint
{{ t('tools.docker-pangolin-labels.texts.button-extract-blueprint') }}
</n-button>
</n-space>

Expand All @@ -81,48 +86,48 @@
<textarea-copyable
v-if="blueprintOutput"
v-model:value="blueprintOutput"
label="Generated Blueprint:"
:label="t('tools.docker-pangolin-labels.texts.label-generated-blueprint')"
language="yaml"
readonly
placeholder="Blueprint YAML will appear here…"
:placeholder="t('tools.docker-pangolin-labels.texts.placeholder-generated-blueprint')"
/>
</n-tab-pane>

<!-- BLUEPRINT → LABELS -->
<n-tab-pane name="blueprint-to-labels" tab="Blueprint → Labels">
<n-tab-pane name="blueprint-to-labels" :tab="t('tools.docker-pangolin-labels.texts.tab-blueprint-to-labels')">
<c-input-text
v-model:value="blueprintInput"
label="Blueprint YAML:"
:label="t('tools.docker-pangolin-labels.texts.label-blueprint-yaml')"
multiline
rows="5"
placeholder="Paste Pangolin blueprint YAML here…"
:placeholder="t('tools.docker-pangolin-labels.texts.placeholder-blueprint-yaml')"
mb-2
/>

<n-space justify="center" mb-2>
<n-switch v-model:value="labelsAsArray">
<template #checked>
Array (- key=value)
{{ t('tools.docker-pangolin-labels.texts.switch-array-format') }}
</template>
<template #unchecked>
Object (key: value)
{{ t('tools.docker-pangolin-labels.texts.switch-object-format') }}
</template>
</n-switch>
</n-space>

<n-space justify="center" mb-2>
<n-button type="primary" @click="convertBlueprintToLabels">
Convert to Docker Labels
{{ t('tools.docker-pangolin-labels.texts.button-convert-to-labels') }}
</n-button>
</n-space>

<textarea-copyable
v-if="labelsOutput"
v-model:value="labelsOutput"
label="Generated Docker labels:"
:label="t('tools.docker-pangolin-labels.texts.label-generated-docker-labels')"
rows="16"
language="yaml"
placeholder="Docker labels will appear here..."
:placeholder="t('tools.docker-pangolin-labels.texts.placeholder-generated-docker-labels')"
/>
</n-tab-pane>
</n-tabs>
Expand Down
Loading
Loading