deploy
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
# Base URL of the backend HTTP API.
|
||||
VITE_API_BASE=https://localhost:3000
|
||||
VITE_API_BASE=http://localhost:3000
|
||||
|
||||
# Base URL of the backend websocket. Optional: when omitted it is derived
|
||||
# from VITE_API_BASE by swapping the protocol (https -> wss).
|
||||
VITE_WS_BASE=wss://localhost:3000
|
||||
VITE_WS_BASE=ws://localhost:3000
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Build and Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: |
|
||||
git clone ${{ github.server_url }}/${{ github.repository }}.git .
|
||||
git checkout ${{ github.sha }}
|
||||
|
||||
- name: Login to Gitea Registry
|
||||
run: |
|
||||
echo "${{ secrets.REGISTRY_PASSWORD }}" | \
|
||||
docker login https://gitea.johannesbot.de -u ${{ secrets.REGISTRY_USER }} --password-stdin
|
||||
|
||||
- name: Build Image
|
||||
run: docker build -t gitea.johannesbot.de/johannesbot/mc-computer-craft-api-frontend:latest .
|
||||
|
||||
- name: Push Image
|
||||
run: docker push gitea.johannesbot.de/johannesbot/mc-computer-craft-api-frontend:latest
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create deployment directory
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: ${{ secrets.SSH_HOST }}
|
||||
username: ${{ secrets.SSH_USER }}
|
||||
password: ${{ secrets.SSH_PASSWORD }}
|
||||
port: ${{ secrets.SSH_PORT || 22 }}
|
||||
script: mkdir -p /home/${{ secrets.SSH_USER }}/mc-computer-craft-api-frontend
|
||||
|
||||
- name: Deploy via SSH
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: ${{ secrets.SSH_HOST }}
|
||||
username: ${{ secrets.SSH_USER }}
|
||||
password: ${{ secrets.SSH_PASSWORD }}
|
||||
port: ${{ secrets.SSH_PORT || 22 }}
|
||||
script: |
|
||||
cd /home/${{ secrets.SSH_USER }}/mc-computer-craft-api
|
||||
# Login as root/sudo to ensure we can pull
|
||||
echo "${{ secrets.REGISTRY_PASSWORD }}" | sudo docker login https://gitea.johannesbot.de -u ${{ secrets.REGISTRY_USER }} --password-stdin
|
||||
sudo docker compose pull
|
||||
sudo docker compose up -d --remove-orphans
|
||||
sudo docker image prune -f
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ export interface LiveItem {
|
||||
mod: string;
|
||||
amount: number;
|
||||
updatedAt: string;
|
||||
/** Optional icon URL served by the backend (e.g. "/api/icon/minecraft/iron_ingot.png"). */
|
||||
icon?: string | null;
|
||||
}
|
||||
|
||||
export interface ModInfo {
|
||||
|
||||
@@ -49,6 +49,7 @@ function onModChange(event: Event): void {
|
||||
function toggleOrder(): void {
|
||||
emit('update', { order: props.filters.order === 'asc' ? 'desc' : 'asc' });
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="filter-bar panel">
|
||||
|
||||
@@ -68,7 +68,7 @@ function buildConfig(): ChartConfiguration<'line'> {
|
||||
bodyColor: '#2fd4c4',
|
||||
padding: 10,
|
||||
callbacks: {
|
||||
label: (ctx) => ` ${fullNumber(ctx.parsed.y)}`,
|
||||
label: (ctx) => ` ${fullNumber(ctx.parsed.y ?? 0)}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vue-router';
|
||||
import type { LiveItem } from '../api/types.js';
|
||||
import { abbreviateNumber, fullNumber } from '../utils/format.js';
|
||||
|
||||
defineProps<{
|
||||
items: LiveItem[];
|
||||
}>();
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
function openItem(item: LiveItem): void {
|
||||
router.push({ name: 'item', params: { name: item.name } });
|
||||
}
|
||||
|
||||
function label(item: LiveItem): string {
|
||||
return item.displayName ?? item.name;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="table-wrap panel">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="table__col-item">Item</th>
|
||||
<th class="table__col-mod">Mod</th>
|
||||
<th class="table__col-amount">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="item in items"
|
||||
:key="item.name"
|
||||
class="table__row"
|
||||
tabindex="0"
|
||||
@click="openItem(item)"
|
||||
@keydown.enter="openItem(item)"
|
||||
>
|
||||
<td class="table__col-item">
|
||||
<span class="table__name">{{ label(item) }}</span>
|
||||
<span class="table__id mono">{{ item.name }}</span>
|
||||
</td>
|
||||
<td class="table__col-mod">
|
||||
<span class="tag mono">{{ item.mod }}</span>
|
||||
</td>
|
||||
<td class="table__col-amount mono" :title="fullNumber(item.amount)">
|
||||
{{ abbreviateNumber(item.amount) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="items.length === 0">
|
||||
<td colspan="3" class="table__empty">No items match the current filters.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.table-wrap {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.table th {
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-dim);
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--bg-panel-2);
|
||||
}
|
||||
|
||||
.table__col-amount {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.table__row {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.12s ease;
|
||||
}
|
||||
|
||||
.table__row td {
|
||||
padding: 11px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.table__row:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.table__row:hover,
|
||||
.table__row:focus {
|
||||
background: var(--accent-soft);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.table__name {
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.table__id {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
border: 1px solid var(--border-bright);
|
||||
border-radius: 5px;
|
||||
color: var(--accent);
|
||||
background: var(--accent-soft);
|
||||
}
|
||||
|
||||
.table__col-amount {
|
||||
font-size: 15px;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.table__empty {
|
||||
text-align: center;
|
||||
color: var(--text-dim);
|
||||
padding: 28px 16px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import FilterBar from '../components/FilterBar.vue';
|
||||
import ItemTable from '../components/ItemTable.vue';
|
||||
import ItemGrid from '../components/ItemGrid.vue';
|
||||
import { useLiveData } from '../composables/useLiveData.js';
|
||||
import type { LiveFilters } from '../api/types.js';
|
||||
import { abbreviateNumber, formatRelative } from '../utils/format.js';
|
||||
@@ -53,7 +53,7 @@ function onFilterUpdate(value: Partial<LiveFilters>): void {
|
||||
<span v-else>Waiting for first update…</span>
|
||||
</p>
|
||||
|
||||
<ItemTable :items="items" />
|
||||
<ItemGrid :items="items" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user