Compare commits

...

42 Commits

Author SHA1 Message Date
0f30cdf8bb Bump version 2025-07-19 15:11:24 +02:00
a7905e4158 Add version footer 2025-07-19 15:11:17 +02:00
5c9c0cde60 Amend redirect URI 2025-07-17 17:52:24 +02:00
7713c8e4ae Add CardSetImportModal 2025-07-17 17:48:44 +02:00
9450d560c4 Update OpenAPI 2025-07-17 17:48:35 +02:00
fcd1e4c888 Bump version 2025-07-17 17:14:46 +02:00
47c468bab6 Correct callback 2025-07-17 17:14:34 +02:00
1f0b08c122 Add debug logging 2025-07-17 15:03:38 +02:00
e6ccae9af3 Amend API URL 2025-07-17 14:36:17 +02:00
b3e4f76b18 Amend API URL 2025-07-17 14:29:10 +02:00
bff0b35c5f Bump version 2025-07-17 13:56:01 +02:00
bdeaa34851 Correct nginx proxy 2025-07-17 13:55:44 +02:00
7c2c6834c2 Amend API base URL 2025-07-17 13:37:16 +02:00
7dc4c9192b Amend API base URL 2025-07-17 13:36:56 +02:00
e895602aa4 Amend port 2025-07-17 13:12:10 +02:00
9c743ed514 Update OpenAPI, amend TS issues 2025-07-17 13:11:20 +02:00
520f59a0ca Amend .gitignore 2025-07-15 20:57:52 +02:00
ad8772d112 Amend env var stubs 2025-07-15 20:57:21 +02:00
c06b75ab96 Add Compose YML 2025-07-15 20:57:05 +02:00
b0d66c9aa0 Bump version 2025-07-15 18:12:54 +02:00
6b23bfb39f Amend Upstream URL 2025-07-15 18:12:46 +02:00
202959dd9e Amend Upstream URL 2025-07-15 18:05:11 +02:00
53fc2ed8fb Amend Upstream URL 2025-07-15 17:51:54 +02:00
dfac93e1ff Amend Upstream URL 2025-07-15 17:51:02 +02:00
fc95c3fdfd Amend CORS and NGINX 2025-07-15 17:33:39 +02:00
8c9d38de35 Add missing item in Dockerfile 2025-07-15 16:21:19 +02:00
10d5edced9 Add missing item in Dockerfile 2025-07-15 16:18:48 +02:00
855996486b Bump version 2025-07-15 16:15:45 +02:00
9148bb3463 Amend CORS 2025-07-15 16:15:10 +02:00
edeffa7012 Bump version 2025-07-15 14:56:59 +02:00
3d244e5e83 Bump version 2025-07-15 14:53:59 +02:00
05f9255ef0 Amend API path 2025-07-15 14:53:43 +02:00
c942450e86 Amend API path 2025-07-15 14:45:22 +02:00
00759473f2 Correct Docker build CI/CD 2025-07-15 14:11:45 +02:00
d9acd72d7b Fix Dockerization 2025-07-15 14:09:42 +02:00
2639a5301a Add latest tag 2025-07-15 11:34:17 +02:00
460b7aee72 Add latest tag 2025-07-15 11:31:59 +02:00
3c393a1e0b Bump version 2025-07-15 11:27:03 +02:00
0189b0db15 Add Docker CI/CD 2025-07-15 11:18:30 +02:00
78b8c60329 Add Docker CI/CD 2025-07-15 11:11:39 +02:00
48bbc03a91 Add Docker CI/CD 2025-07-15 11:10:35 +02:00
d493800226 Add Docker CI/CD 2025-07-15 11:06:04 +02:00
61 changed files with 569 additions and 285 deletions

6
.dockerignore Normal file
View File

@@ -0,0 +1,6 @@
.gitignore
openapitools.json
README.md
.vscode
.idea
.gitea

View File

@@ -1,4 +1,5 @@
name: Create and Push Release
run-name: Create and Push Release
on:
workflow_dispatch:
@@ -13,6 +14,9 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get version
id: get-version
run: |
@@ -26,14 +30,16 @@ jobs:
username: ${{ secrets.CI_SERVICE_ACCOUNT }}
password: ${{ secrets.CI_SERVICE_ACCOUNT_PASSWORD }}
- name: Checkout
uses: actions/checkout@v4
- name: Build & Push Image
env:
TAG: ${{ steps.get-version.outputs.version }}
QUARKUS_CONTAINER_IMAGE_USERNAME: ${{ secrets.CI_SERVICE_ACCOUNT }}
QUARKUS_CONTAINER_IMAGE_PASSWORD: ${{ secrets.CI_SERVICE_ACCOUNT_PASSWORD }}
run: |
docker build -t $REGISTRY_URL/$IMAGE_OWNER/$IMAGE_IMAGE:$TAG .
docker push $REGISTRY_URL/$IMAGE_OWNER/$IMAGE_IMAGE:$TAG
docker build -f docker/Dockerfile \
-t $REGISTRY_URL/$IMAGE_OWNER/$IMAGE_NAME:$TAG \
-t $REGISTRY_URL/$IMAGE_OWNER/$IMAGE_NAME:latest \
.
docker push $REGISTRY_URL/$IMAGE_OWNER/$IMAGE_NAME:$TAG
docker push $REGISTRY_URL/$IMAGE_OWNER/$IMAGE_NAME:latest

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@ yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
docker/docker-compose.yml
node_modules
dist

View File

@@ -1,29 +0,0 @@
# Stage 1: Build application
FROM node:22-bookworm-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm run build
# Stage 2: Prepare static web server
FROM alpine:3.19 AS server-prep
RUN wget -O /tmp/sws.tar.gz \
https://github.com/static-web-server/static-web-server/releases/download/v2.17.0/static-web-server-v2.17.0-x86_64-unknown-linux-musl.tar.gz
RUN tar -xzf /tmp/sws.tar.gz -C /tmp \
--strip-components=1
# Stage 3: Create runtime image
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder --chown=nonroot:nonroot /app/dist /app
COPY --from=server-prep --chown=nonroot:nonroot /tmp/static-web-server /usr/local/bin/
USER nonroot
WORKDIR /app
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/static-web-server"]
CMD ["--port", "8080", "--root", "/app", "--log-level", "warn"]

36
docker/Dockerfile Normal file
View File

@@ -0,0 +1,36 @@
# Stage 1: Build application
FROM node:22-bookworm-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Create runtime image
FROM nginxinc/nginx-unprivileged:1.25-alpine AS runtime
# Create writable directories
USER root
RUN mkdir -p /runtime-config && \
chown nginx:nginx /runtime-config && \
chown -R nginx:nginx /var/cache/nginx && \
chown -R nginx:nginx /var/run
USER nginx
# Copy built assets
COPY --from=builder --chown=nginx:nginx /app/dist /usr/share/nginx/html
# Copy nginx config template
COPY --chown=nginx:nginx nginx.conf.template /etc/nginx/templates/
# Copy entrypoint script
COPY --chown=nginx:nginx docker/entrypoint.sh /entrypoint.sh
# Make entrypoint executable
USER root
RUN chmod +x /entrypoint.sh
USER nginx
EXPOSE 8080
ENTRYPOINT ["/entrypoint.sh"]

48
docker/docker-compose.yml Normal file
View File

@@ -0,0 +1,48 @@
services:
be:
image: gitea.smoothbrain.win/rak/dex:latest
ports:
- "8080:8080"
depends_on:
- db
environment:
QUARKUS_DATASOURCE_JDBC_URL:
QUARKUS_DATASOURCE_USERNAME:
QUARKUS_DATASOURCE_PASSWORD:
QUARKUS_OIDC_AUTH_SERVER_URL:
QUARKUS_OIDC_CLIENT_ID:
QUARKUS_OIDC_CREDENTIALS_SECRET:
QUARKUS_OIDC_TOKEN_AUDIENCE:
QUARKUS_OIDC_TOKEN_ISSUER:
QUARKUS_HTTP_INSECURE_REQUESTS: enabled
DEX_FILE_PATH:
networks:
- dex
frontend:
build:
context: ..
dockerfile: docker/Dockerfile
ports:
- "80:80"
depends_on:
- be
environment:
API_HOST: be
API_PORT: 8080
networks:
- dex
db:
image: postgres
restart: always
environment:
POSTGRES_PASSWORD: dex
POSTGRES_DB: dex
POSTGRES_USER: dex
networks:
- dex
networks:
dex:

18
docker/entrypoint.sh Normal file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
set -e
# Create runtime config file in writable location
#cat > /runtime-config/config.js <<EOF
#window.__APP_CONFIG__ = {
# API_HOST: "${API_HOST}",
# API_PORT: "${API_PORT}"
#};
#EOF
# Generate nginx config from template (if using)
if [ -f "/etc/nginx/templates/nginx.conf.template" ]; then
envsubst '${API_HOST} ${API_PORT}' < /etc/nginx/templates/nginx.conf.template > /etc/nginx/nginx.conf
fi
# Start Nginx
exec nginx -g "daemon off;"

88
nginx.conf.template Normal file
View File

@@ -0,0 +1,88 @@
# Main nginx configuration
worker_processes auto;
error_log /dev/stderr warn;
pid /tmp/nginx.pid; # Use writable location for PID
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
access_log /dev/stdout;
client_body_temp_path /tmp/client_temp;
proxy_temp_path /tmp/proxy_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
absolute_redirect off;
map $http_origin $cors_origin {
default "";
"~*" $http_origin;
}
resolver 127.0.0.11 valid=10s ipv6=off;
upstream backend {
server ${API_HOST}:8080;
}
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Handle client-side routing
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
# Security headers
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "DENY";
add_header Referrer-Policy "strict-origin-when-cross-origin";
}
# Serve config.js from the writable location
location = /config.js {
alias /runtime-config/config.js;
add_header Cache-Control "no-store, no-cache, must-revalidate";
access_log off;
}
location /api/ {
# Proxy to Quarkus
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Relay CORS headers from the backend
proxy_pass_header Access-Control-Allow-Origin;
proxy_pass_header Access-Control-Allow-Methods;
proxy_pass_header Access-Control-Allow-Headers;
proxy_pass_header Access-Control-Allow-Credentials;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
}
}

8
package-lock.json generated
View File

@@ -1,15 +1,16 @@
{
"name": "dex-ui-vue",
"version": "0.0.0",
"version": "0.0.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dex-ui-vue",
"version": "0.0.0",
"version": "0.0.1",
"dependencies": {
"@primeuix/themes": "^1.2.1",
"@tailwindcss/vite": "^4.1.11",
"@types/node": "^24.0.14",
"@vueuse/core": "^13.5.0",
"axios": "^1.10.0",
"oidc-client-ts": "^3.3.0",
@@ -23,7 +24,6 @@
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.20.2",
"@types/node": "^24.0.14",
"@vitejs/plugin-vue": "^6.0.0",
"@vue/tsconfig": "^0.7.0",
"typescript": "~5.7.2",
@@ -1386,7 +1386,6 @@
"version": "24.0.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.14.tgz",
"integrity": "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.8.0"
@@ -4546,7 +4545,6 @@
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
"devOptional": true,
"license": "MIT"
},
"node_modules/universalify": {

View File

@@ -1,7 +1,7 @@
{
"name": "dex-ui-vue",
"private": true,
"version": "0.0.0",
"version": "0.0.13",
"type": "module",
"scripts": {
"dev": "vite",
@@ -12,6 +12,7 @@
"dependencies": {
"@primeuix/themes": "^1.2.1",
"@tailwindcss/vite": "^4.1.11",
"@types/node": "^24.0.14",
"@vueuse/core": "^13.5.0",
"axios": "^1.10.0",
"oidc-client-ts": "^3.3.0",
@@ -25,7 +26,6 @@
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.20.2",
"@types/node": "^24.0.14",
"@vitejs/plugin-vue": "^6.0.0",
"@vue/tsconfig": "^0.7.0",
"typescript": "~5.7.2",

View File

@@ -0,0 +1,4 @@
window.__RUNTIME_CONFIG__ = {
API_HOST: "__API_HOST__",
API_PORT: "__API_PORT__"
};

View File

@@ -1,5 +1,5 @@
<template>
<div class="flex flex-col size-dvh">
<div class="flex flex-col size-full">
<!-- Navigator here -->
<Menubar
:model="items"
@@ -32,10 +32,13 @@
</div>
</template>
</Menubar>
<main class="app-main pt-[60px]">
<main class="app-main w-full pt-[60px]">
<Toast/>
<RouterView/>
</main>
<footer class="fixed bottom-0 right-0">
v{{ version }}
</footer>
</div>
</template>
@@ -44,6 +47,8 @@ import {ref} from "vue";
import {useRouter} from "vue-router";
import Toast from 'primevue/toast';
import {useAuthStore} from "./stores/auth.ts";
// noinspection ES6UnusedImports Used in template
import { version } from '../package.json'
const authStore = useAuthStore();
const router = useRouter();

View File

@@ -1,27 +0,0 @@
import axios from "axios";
import {userManager} from "../stores/auth.ts";
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:8080'
})
axiosInstance.interceptors.request.use(async (config) => {
const user = await userManager.getUser()
if (user?.access_token) {
config.headers.Authorization = `Bearer ${user.access_token}`
}
return config
})
// Handle token expiration
axiosInstance.interceptors.response.use(
response => response,
async (error) => {
if (error.response?.status === 401) {
await userManager.signinRedirect()
}
return Promise.reject(error)
}
)
export default axiosInstance;

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -6,8 +6,8 @@ All URIs are relative to *http://localhost*
|------------- | ------------- | -------------|
|[**apiSetsNameGet**](#apisetsnameget) | **GET** /api/sets/{name} | Find Set By Name|
|[**apiSetsNameNewGet**](#apisetsnamenewget) | **GET** /api/sets/{name}/new | Fetch And Persist From Upstream|
|[**apiSetsNameScrapeGet**](#apisetsnamescrapeget) | **GET** /api/sets/{name}/scrape | Scrape And Persist From Upstream|
|[**getCardSetPage**](#getcardsetpage) | **GET** /api/sets | Get a page of Card Sets with optional name query parameter|
|[**scrapeSetByName**](#scrapesetbyname) | **GET** /api/sets/{name}/scrape | Scrape a CardSet via name query parameter|
# **apiSetsNameGet**
> SetDto apiSetsNameGet()
@@ -102,56 +102,6 @@ No authorization required
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
|**200** | Set retrieved | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **apiSetsNameScrapeGet**
> apiSetsNameScrapeGet()
### Example
```typescript
import {
SetService,
Configuration
} from './api';
const configuration = new Configuration();
const apiInstance = new SetService(configuration);
let name: string; // (default to undefined)
const { status, data } = await apiInstance.apiSetsNameScrapeGet(
name
);
```
### Parameters
|Name | Type | Description | Notes|
|------------- | ------------- | ------------- | -------------|
| **name** | [**string**] | | defaults to undefined|
### Return type
void (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
@@ -215,3 +165,53 @@ No authorization required
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **scrapeSetByName**
> scrapeSetByName()
### Example
```typescript
import {
SetService,
Configuration
} from './api';
const configuration = new Configuration();
const apiInstance = new SetService(configuration);
let name: string; // (default to undefined)
const { status, data } = await apiInstance.scrapeSetByName(
name
);
```
### Parameters
|Name | Type | Description | Notes|
|------------- | ------------- | ------------- | -------------|
| **name** | [**string**] | | defaults to undefined|
### Return type
void (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
|**200** | Set retrieved | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -4,7 +4,7 @@
* dex API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.0.1
* The version of the OpenAPI document: 0.0.6
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -90,40 +90,6 @@ export const SetServiceAxiosParamCreator = function (configuration?: Configurati
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary Scrape And Persist From Upstream
* @param {string} name
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSetsNameScrapeGet: async (name: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('apiSetsNameScrapeGet', 'name', name)
const localVarPath = `/api/sets/{name}/scrape`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
@@ -169,6 +135,40 @@ export const SetServiceAxiosParamCreator = function (configuration?: Configurati
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary Scrape a CardSet via name query parameter
* @param {string} name
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
scrapeSetByName: async (name: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('scrapeSetByName', 'name', name)
const localVarPath = `/api/sets/{name}/scrape`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
@@ -214,19 +214,6 @@ export const SetServiceFp = function(configuration?: Configuration) {
const localVarOperationServerBasePath = operationServerMap['SetService.apiSetsNameNewGet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
* @summary Scrape And Persist From Upstream
* @param {string} name
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSetsNameScrapeGet(name: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.apiSetsNameScrapeGet(name, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['SetService.apiSetsNameScrapeGet']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
* @summary Get a page of Card Sets with optional name query parameter
@@ -242,6 +229,19 @@ export const SetServiceFp = function(configuration?: Configuration) {
const localVarOperationServerBasePath = operationServerMap['SetService.getCardSetPage']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
* @summary Scrape a CardSet via name query parameter
* @param {string} name
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async scrapeSetByName(name: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.scrapeSetByName(name, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['SetService.scrapeSetByName']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
}
};
@@ -272,16 +272,6 @@ export const SetServiceFactory = function (configuration?: Configuration, basePa
apiSetsNameNewGet(requestParameters: SetServiceApiSetsNameNewGetRequest, options?: RawAxiosRequestConfig): AxiosPromise<Array<SetDto>> {
return localVarFp.apiSetsNameNewGet(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
*
* @summary Scrape And Persist From Upstream
* @param {SetServiceApiSetsNameScrapeGetRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSetsNameScrapeGet(requestParameters: SetServiceApiSetsNameScrapeGetRequest, options?: RawAxiosRequestConfig): AxiosPromise<void> {
return localVarFp.apiSetsNameScrapeGet(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
*
* @summary Get a page of Card Sets with optional name query parameter
@@ -292,6 +282,16 @@ export const SetServiceFactory = function (configuration?: Configuration, basePa
getCardSetPage(requestParameters: SetServiceGetCardSetPageRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise<PageSetDto> {
return localVarFp.getCardSetPage(requestParameters.name, requestParameters.page, requestParameters.pageSize, options).then((request) => request(axios, basePath));
},
/**
*
* @summary Scrape a CardSet via name query parameter
* @param {SetServiceScrapeSetByNameRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
scrapeSetByName(requestParameters: SetServiceScrapeSetByNameRequest, options?: RawAxiosRequestConfig): AxiosPromise<void> {
return localVarFp.scrapeSetByName(requestParameters.name, options).then((request) => request(axios, basePath));
},
};
};
@@ -323,20 +323,6 @@ export interface SetServiceApiSetsNameNewGetRequest {
readonly name: string
}
/**
* Request parameters for apiSetsNameScrapeGet operation in SetService.
* @export
* @interface SetServiceApiSetsNameScrapeGetRequest
*/
export interface SetServiceApiSetsNameScrapeGetRequest {
/**
*
* @type {string}
* @memberof SetServiceApiSetsNameScrapeGet
*/
readonly name: string
}
/**
* Request parameters for getCardSetPage operation in SetService.
* @export
@@ -365,6 +351,20 @@ export interface SetServiceGetCardSetPageRequest {
readonly pageSize?: number
}
/**
* Request parameters for scrapeSetByName operation in SetService.
* @export
* @interface SetServiceScrapeSetByNameRequest
*/
export interface SetServiceScrapeSetByNameRequest {
/**
*
* @type {string}
* @memberof SetServiceScrapeSetByName
*/
readonly name: string
}
/**
* SetService - object-oriented interface
* @export
@@ -396,18 +396,6 @@ export class SetService extends BaseAPI {
return SetServiceFp(this.configuration).apiSetsNameNewGet(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary Scrape And Persist From Upstream
* @param {SetServiceApiSetsNameScrapeGetRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SetService
*/
public apiSetsNameScrapeGet(requestParameters: SetServiceApiSetsNameScrapeGetRequest, options?: RawAxiosRequestConfig) {
return SetServiceFp(this.configuration).apiSetsNameScrapeGet(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary Get a page of Card Sets with optional name query parameter
@@ -419,5 +407,17 @@ export class SetService extends BaseAPI {
public getCardSetPage(requestParameters: SetServiceGetCardSetPageRequest = {}, options?: RawAxiosRequestConfig) {
return SetServiceFp(this.configuration).getCardSetPage(requestParameters.name, requestParameters.page, requestParameters.pageSize, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary Scrape a CardSet via name query parameter
* @param {SetServiceScrapeSetByNameRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SetService
*/
public scrapeSetByName(requestParameters: SetServiceScrapeSetByNameRequest, options?: RawAxiosRequestConfig) {
return SetServiceFp(this.configuration).scrapeSetByName(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
}

View File

@@ -1,13 +1,16 @@
import type {UserManagerSettings} from "oidc-client-ts";
export const oidcConfig : UserManagerSettings = {
const redirectUri = import.meta.env.PROD
? "https://dex.smoothbrain.win"
: "http://localhost:5173";
export const oidcConfig: UserManagerSettings = {
authority: 'https://auth.smoothbrain.win/application/o/dex/',
client_id: 'K202NAqkgfjceLZr28gAVQgJDc6RjZfdrE1jNx0K',
redirect_uri: 'http://localhost:5173/callback',
redirect_uri: `${redirectUri}/callback`,
response_type: 'code',
scope: 'openid profile email',
post_logout_redirect_uri: 'http://localhost:5173', // Homepage URL
// automaticSilentRenew: true,
post_logout_redirect_uri: redirectUri,
loadUserInfo: true,
automaticSilentRenew: true,
extraQueryParams: {

2
src/components.d.ts vendored
View File

@@ -14,11 +14,13 @@ declare module 'vue' {
CardFilterPanel: typeof import('./components/CardFilterPanel.vue')['default']
CardListComponent: typeof import('./components/CardListComponent.vue')['default']
CardListExpansion: typeof import('./components/CardListExpansion.vue')['default']
CardSetImportModal: typeof import('./components/CardSetImportModal.vue')['default']
CardTable: typeof import('./components/CardTable.vue')['default']
Carousel: typeof import('primevue/carousel')['default']
Column: typeof import('primevue/column')['default']
CustomTag: typeof import('./components/CustomTag.vue')['default']
DataTable: typeof import('primevue/datatable')['default']
Dialog: typeof import('primevue/dialog')['default']
Divider: typeof import('primevue/divider')['default']
DynamicAsset: typeof import('./components/DynamicAsset.vue')['default']
Fieldset: typeof import('primevue/fieldset')['default']

View File

@@ -0,0 +1,77 @@
<template>
<Dialog
modal
:draggable="false"
:dismissable-mask="true"
:visible="visible"
@update:visible="emit('update:visible', $event)"
>
<template #header>
<div class="inline-flex items-center justify-center gap-2">
<span class="font-bold whitespace-nowrap">Import Set</span>
</div>
</template>
<span class="text-surface-500 dark:text-surface-400 block mb-8">Import a Set by its name</span>
<div class="flex items-center gap-4 mb-4">
<label for="setName" class="font-semibold w-24">Set Name</label>
<InputText id="setName" class="flex-auto" autocomplete="off" v-model="cardSetName"/>
</div>
<template #footer>
<Button label="Cancel" text severity="secondary" @click="visible = false"/>
<Button label="Import" outlined severity="secondary" @click="importSet(cardSetName)"/>
</template>
</Dialog>
</template>
<script setup lang="ts">
import {inject, ref, type Ref, watch} from "vue";
import {SetService} from "@/api/openapi";
import {SetServiceKey} from "@/main.ts";
import {useToast} from "primevue";
const toast = useToast();
const emit = defineEmits(['update:visible'])
const visible: Ref<boolean> = defineModel("visible", {
required: true
})
const setService: SetService = inject(SetServiceKey) as SetService;
const cardSetName: Ref<string | null> = ref(null);
const importSet = async(name: string | null) => {
if (!name) {
toast.add({
severity: "warn",
summary: `Name of Set is required to import`,
})
return;
}
try {
await setService.scrapeSetByName({
name: name,
});
toast.add({
severity: "info",
summary: `Import Job for Set '${cardSetName.value}' was started successfully`,
})
} catch (ex: unknown) {
toast.add({
severity: "error",
summary: `Error occurred trying to import Set '${cardSetName.value}'`,
})
} finally {
cardSetName.value = null;
visible.value = false
}
}
watch(visible, () => {
cardSetName.value = null;
})
</script>
<style scoped>
</style>

View File

@@ -10,7 +10,8 @@ import {
AccordionContent,
AccordionHeader,
AccordionPanel,
DatePicker, Fluid,
DatePicker,
Fluid,
ToastService
} from "primevue";
import {createPinia} from "pinia";
@@ -22,10 +23,14 @@ import DecksView from "./views/deck/DecksView.vue";
import DeckView from "./views/deck/DeckView.vue";
import Callback from "./views/Callback.vue";
import {useAuthStore} from "./stores/auth.ts";
import axiosInstance from "./api";
import SetsView from "./views/set/SetsView.vue";
import JobsView from "./views/JobsView.vue";
import {definePreset} from "@primeuix/themes";
import {getConfig, initConfig} from "@/util/config.ts";
import axios from "axios";
// Initialize configuration from window object
initConfig((window as any).__APP_CONFIG__ || {})
export const DeckServiceKey = Symbol("deckServiceKey")
export const CardServiceKey = Symbol("cardServiceKey")
@@ -134,11 +139,41 @@ router.beforeEach(async (to) => {
app.use(router);
app.use(ToastService)
const deckService: DeckService = new DeckService(undefined, "http://localhost:8080", axiosInstance)
const cardService: CardService = new CardService(undefined, "http://localhost:8080", axiosInstance)
const setService: SetService = new SetService(undefined, "http://localhost:8080", axiosInstance)
const cardPrintService: CardPrintService = new CardPrintService(undefined, "http://localhost:8080", axiosInstance)
const jobService: JobService = new JobService(undefined, "http://localhost:8080", axiosInstance)
const apiUrl = import.meta.env.PROD
? "/"
: `http://${getConfig().API_HOST}:${getConfig().API_PORT}`;
const axiosInstance = axios.create({
baseURL: apiUrl,
headers: {
'Content-Type': 'application/json'
}
})
axiosInstance.interceptors.request.use(async (config) => {
const user = await userManager.getUser()
if (user?.access_token) {
config.headers.Authorization = `Bearer ${user.access_token}`
}
return config
})
// Handle token expiration
axiosInstance.interceptors.response.use(
response => response,
async (error) => {
if (error.response?.status === 401) {
await userManager.signinRedirect()
}
return Promise.reject(error)
}
)
const deckService: DeckService = new DeckService(undefined, undefined, axiosInstance)
const cardService: CardService = new CardService(undefined, undefined, axiosInstance)
const setService: SetService = new SetService(undefined, undefined, axiosInstance)
const cardPrintService: CardPrintService = new CardPrintService(undefined, undefined, axiosInstance)
const jobService: JobService = new JobService(undefined, undefined, axiosInstance)
app.provide(DeckServiceKey, deckService)
app.provide(CardServiceKey, cardService)

View File

@@ -1,19 +0,0 @@
import darkAttribute from "/src/assets/DARK.svg"
import divineAttribute from "/src/assets/DIVINE.svg"
import earthAttribute from "/src/assets/EARTH.svg"
import fireAttribute from "/src/assets/FIRE.svg"
import laughAttribute from "/src/assets/LAUGH.svg"
import lightAttribute from "/src/assets/LIGHT.svg"
import waterAttribute from "/src/assets/WATER.svg"
import windAttribute from "/src/assets/WIND.svg"
export {
darkAttribute,
divineAttribute,
earthAttribute,
fireAttribute,
laughAttribute,
lightAttribute,
waterAttribute,
windAttribute
}

20
src/util/config.ts Normal file
View File

@@ -0,0 +1,20 @@
export interface AppConfig {
API_HOST: string;
API_PORT: number;
}
let runtimeConfig: AppConfig = {
API_HOST: import.meta.env.VITE_API_HOST || '',
API_PORT: import.meta.env.VITE_API_PORT || 8080
};
export function initConfig(config: Partial<AppConfig>) {
runtimeConfig = {
...runtimeConfig,
...config
};
}
export function getConfig(): AppConfig {
return runtimeConfig;
}

View File

@@ -1,4 +1,8 @@
<template>
<CardSetImportModal
:visible="importModalVisible"
@update:visible="args => importModalVisible = args"
/>
<DataTable
tableStyle="min-width: 50rem"
dataKey="id"
@@ -16,6 +20,11 @@
@page="handlePaging"
@sort="handleSorting"
>
<template #header>
<div class="flex justify-end">
<Button type="button" size="small" label="Import" icon="pi pi-download" @click="importModalVisible = true"/>
</div>
</template>
<Column header="Image">
<template #body>
<Image alt="Image" preview class="h-64">
@@ -24,7 +33,9 @@
</template>
<template #image>
<div class="overflow-hidden">
<img src="https://comicbook.com/wp-content/uploads/sites/4/2024/11/YuGiOh-Early-Days-Collection.png?resize=2000,1125" alt="image" width="650" height="650"/>
<img
src="https://comicbook.com/wp-content/uploads/sites/4/2024/11/YuGiOh-Early-Days-Collection.png?resize=2000,1125"
alt="image" width="650" height="650"/>
</div>
</template>
<template #preview="slotProps">
@@ -41,25 +52,26 @@
<Column field="name" header="Name">
<template #body="slotProps">
<p class="font-bold">
{{slotProps.data.name}}
{{ slotProps.data.name }}
</p>
</template>
</Column>
<Column header="No. of Regional Sets">
<template #body="slotProps">
{{ slotProps.data.regionalSets.length }}
<template #body>
N/A
</template>
</Column>
<template #footer> In total there are {{ sets ? sets.length : 0 }} Card Sets </template>
<template #footer> In total there are {{ sets ? sets.length : 0 }} Card Sets</template>
</DataTable>
</template>
<script setup lang="ts">
import {type SetDto, SetService} from "../../api/openapi";
import {type SetDto, SetService} from "@/api/openapi";
import {inject, onMounted, ref, type Ref} from "vue";
import {SetServiceKey} from "../../main.ts";
import {SetServiceKey} from "@/main.ts";
import type {DataTablePageEvent, DataTableSortEvent} from "primevue";
const importModalVisible: Ref<boolean> = ref(false);
const setService: SetService = inject(SetServiceKey) as SetService;
const loading: Ref<boolean> = ref(true);
const sets: Ref<SetDto[]> = ref([])
@@ -72,16 +84,16 @@ const first = ref(0);
const fetchCardSetPage = async (page: number, pageSize: number): Promise<void> => {
loading.value = true;
const cardPage = (await setService.getCardSetPage({
const setPage = (await setService.getCardSetPage({
name: null,
page: page,
pageSize: pageSize
}
)).data
sets.value = cardPage.content
pageCount.value = cardPage.totalPages!!
totalRecords.value = cardPage.totalRecords!!
sets.value = setPage.content
pageCount.value = setPage.totalPages!!
totalRecords.value = setPage.totalRecords!!
loading.value = false;
}