feat: improved pools ui
This commit is contained in:
parent
11c51b057c
commit
dca949f636
7 changed files with 156 additions and 8 deletions
1
.tool-versions
Normal file
1
.tool-versions
Normal file
|
@ -0,0 +1 @@
|
||||||
|
nodejs 22.12.0
|
31
Makefile
31
Makefile
|
@ -1,16 +1,35 @@
|
||||||
dc-up:
|
SHELL := /bin/bash
|
||||||
|
|
||||||
|
.PHONY: dc-up
|
||||||
|
dc-up: ## Bring up the stack
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|
||||||
dc-down:
|
.PHONY: dc-up-dev
|
||||||
|
dc-up-dev: ## Bring up the stack
|
||||||
|
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||||||
|
|
||||||
|
.PHONY: dc-down
|
||||||
|
dc-down: ## Bring down the stack
|
||||||
docker compose down --volumes
|
docker compose down --volumes
|
||||||
|
|
||||||
dc-restart:
|
.PHONY: dc-restart
|
||||||
|
dc-restart: ## Restart the stack
|
||||||
make dc-down
|
make dc-down
|
||||||
make dc-up
|
make dc-up
|
||||||
|
|
||||||
dc-build:
|
.PHONY: dc-build
|
||||||
|
dc-build: ## Build Docker images
|
||||||
docker compose build
|
docker compose build
|
||||||
|
|
||||||
dc-rebuild:
|
.PHONY: dc-rebuild
|
||||||
|
dc-rebuild: ## Rebuild Docker images and restart stack
|
||||||
make dc-build
|
make dc-build
|
||||||
make dc-restart
|
make dc-restart
|
||||||
|
|
||||||
|
.PHONY: build-client
|
||||||
|
build-client: ## Builds the client locally
|
||||||
|
cd ./client && npm run build
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help:
|
||||||
|
@awk 'BEGIN {FS = ":.*##"; printf "Usage:\n make \033[36m<target>\033[0m\n\nTargets:\n"} /^[a-zA-Z_\-\\.\/0-9]+:.*?##/ { printf " \033[36m%s:\033[0m%s\n", $$1, $$2 | "column -c2 -t -s :" }' $(MAKEFILE_LIST)
|
|
@ -1,5 +1,64 @@
|
||||||
@import colors
|
@import colors
|
||||||
|
|
||||||
|
.pools-grid
|
||||||
|
display: grid
|
||||||
|
grid-template-columns: repeat(4, 1fr)
|
||||||
|
gap: 16px
|
||||||
|
width: 100%
|
||||||
|
padding: 16px
|
||||||
|
box-sizing: border-box
|
||||||
|
|
||||||
|
h1
|
||||||
|
font-size: 1.5em
|
||||||
|
|
||||||
|
.pool
|
||||||
|
width: 100%
|
||||||
|
aspect-ratio: 1
|
||||||
|
display: flex
|
||||||
|
justify-content: center
|
||||||
|
align-items: center
|
||||||
|
background-color: #f0f0f0
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
.pool-inner-grid
|
||||||
|
display: grid
|
||||||
|
grid-template-columns: repeat(2, 1fr)
|
||||||
|
grid-template-rows: repeat(2, 1fr)
|
||||||
|
gap: 4px
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
div
|
||||||
|
aspect-ratio: 1
|
||||||
|
position: relative
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
img
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
object-fit: cover
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
|
||||||
|
.pool-title
|
||||||
|
font-weight: 900
|
||||||
|
aspect-ratio: auto
|
||||||
|
position: absolute
|
||||||
|
top: 50%
|
||||||
|
left: 50%
|
||||||
|
transform: translate(-50%, -50%)
|
||||||
|
background: rgba(0, 0, 0, 0.8)
|
||||||
|
color: white
|
||||||
|
font-size: 1.2rem
|
||||||
|
padding: 8px 16px
|
||||||
|
border-radius: 4px
|
||||||
|
text-align: center
|
||||||
|
pointer-events: none
|
||||||
|
z-index: 1
|
||||||
|
|
||||||
|
|
||||||
.pool-list
|
.pool-list
|
||||||
table
|
table
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
|
@ -1,3 +1,34 @@
|
||||||
|
<%
|
||||||
|
function kebabToTitleCase(str) {
|
||||||
|
return str
|
||||||
|
.split('-') // Split the string into words using the hyphen as the delimiter
|
||||||
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Capitalize the first letter of each word
|
||||||
|
.join(' '); // Join the words back together with spaces
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
|
||||||
|
<div class='pools-grid'>
|
||||||
|
<% if (ctx.response.results.length) { %>
|
||||||
|
<% for (const pool of ctx.response.results) { %>
|
||||||
|
<a href='<%- ctx.formatClientLink('posts', {query: 'pool:' + pool.id}) %>'>
|
||||||
|
<div class='pool'>
|
||||||
|
<div class='pool-inner-grid'>
|
||||||
|
<% let counter = 0 %>
|
||||||
|
<% for (const post of pool.posts) { %>
|
||||||
|
<div><img src='<%- post.thumbnailUrl %>' /></div>
|
||||||
|
<% counter++ %>
|
||||||
|
<% if (counter === 4) break %>
|
||||||
|
<% } %>
|
||||||
|
<div class='pool-title'><%= kebabToTitleCase(pool.names[0]) %> (<%- pool.postCount %>)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<% } %>
|
||||||
|
<% } else { %>
|
||||||
|
<p>No pools to display.</p>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class='pool-list table-wrap'>
|
<div class='pool-list table-wrap'>
|
||||||
<% if (ctx.response.results.length) { %>
|
<% if (ctx.response.results.length) { %>
|
||||||
<table>
|
<table>
|
||||||
|
|
|
@ -211,6 +211,13 @@ function getPrettyName(tag) {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function kebabToTitleCase(str) {
|
||||||
|
return str
|
||||||
|
.split('-') // Split the string into words using the hyphen as the delimiter
|
||||||
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Capitalize the first letter of each word
|
||||||
|
.join(' '); // Join the words back together with spaces
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
range: range,
|
range: range,
|
||||||
formatRelativeTime: formatRelativeTime,
|
formatRelativeTime: formatRelativeTime,
|
||||||
|
@ -229,4 +236,5 @@ module.exports = {
|
||||||
escapeSearchTerm: escapeSearchTerm,
|
escapeSearchTerm: escapeSearchTerm,
|
||||||
dataURItoBlob: dataURItoBlob,
|
dataURItoBlob: dataURItoBlob,
|
||||||
getPrettyName: getPrettyName,
|
getPrettyName: getPrettyName,
|
||||||
|
kebabToTitleCase: kebabToTitleCase,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node build.js",
|
"build": "node build.js",
|
||||||
"watch": "node build.js --watch",
|
"watch": "node build.js --watch --no-live-reload",
|
||||||
"build-container": "docker build -t szurubooru/client:dev ."
|
"build-container": "docker build -t szurubooru/client:dev ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -34,4 +34,4 @@
|
||||||
"watchify": "^4.0.0",
|
"watchify": "^4.0.0",
|
||||||
"ws": "^7.4.6"
|
"ws": "^7.4.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
30
docker-compose.dev.yml
Normal file
30
docker-compose.dev.yml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
## Example Docker Compose configuration
|
||||||
|
##
|
||||||
|
## Use this as a template to set up docker-compose, or as guide to set up other
|
||||||
|
## orchestration services
|
||||||
|
services:
|
||||||
|
|
||||||
|
client:
|
||||||
|
image: szurubooru/client:latest
|
||||||
|
build: client
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
environment:
|
||||||
|
BACKEND_HOST: server
|
||||||
|
BASE_URL:
|
||||||
|
volumes:
|
||||||
|
- ./client/public:/var/www
|
||||||
|
- "${MOUNT_DATA}:/data:ro"
|
||||||
|
ports:
|
||||||
|
- "${PORT}:80"
|
||||||
|
|
||||||
|
sql:
|
||||||
|
image: postgres:11-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER:
|
||||||
|
POSTGRES_PASSWORD:
|
||||||
|
ports:
|
||||||
|
- 15432:5432
|
||||||
|
volumes:
|
||||||
|
- "${MOUNT_SQL}:/var/lib/postgresql/data"
|
Reference in a new issue