wip(frontend): adding more information

This commit is contained in:
2025-03-21 14:36:03 +00:00
parent ea5802b61b
commit 3541a4755c
9 changed files with 63 additions and 26 deletions

View File

@ -15,5 +15,5 @@ type Events struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
Name string Name string
Description *string Description *string
Location *uuid.UUID LocationID *uuid.UUID
} }

View File

@ -20,7 +20,7 @@ type eventsTable struct {
ID postgres.ColumnString ID postgres.ColumnString
Name postgres.ColumnString Name postgres.ColumnString
Description postgres.ColumnString Description postgres.ColumnString
Location postgres.ColumnString LocationID postgres.ColumnString
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -64,9 +64,9 @@ func newEventsTableImpl(schemaName, tableName, alias string) eventsTable {
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
NameColumn = postgres.StringColumn("name") NameColumn = postgres.StringColumn("name")
DescriptionColumn = postgres.StringColumn("description") DescriptionColumn = postgres.StringColumn("description")
LocationColumn = postgres.StringColumn("location") LocationIDColumn = postgres.StringColumn("location_id")
allColumns = postgres.ColumnList{IDColumn, NameColumn, DescriptionColumn, LocationColumn} allColumns = postgres.ColumnList{IDColumn, NameColumn, DescriptionColumn, LocationIDColumn}
mutableColumns = postgres.ColumnList{NameColumn, DescriptionColumn, LocationColumn} mutableColumns = postgres.ColumnList{NameColumn, DescriptionColumn, LocationIDColumn}
) )
return eventsTable{ return eventsTable{
@ -76,7 +76,7 @@ func newEventsTableImpl(schemaName, tableName, alias string) eventsTable {
ID: IDColumn, ID: IDColumn,
Name: NameColumn, Name: NameColumn,
Description: DescriptionColumn, Description: DescriptionColumn,
Location: LocationColumn, LocationID: LocationIDColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -24,6 +24,12 @@ func getEventValues(event model.Events) []any {
arr = append(arr, nil) arr = append(arr, nil)
} }
if event.LocationID != nil {
arr = append(arr, *event.LocationID)
} else {
arr = append(arr, nil)
}
return arr return arr
} }

View File

@ -79,7 +79,7 @@ func (m UserModel) ListWithProperties(ctx context.Context, userId uuid.UUID) ([]
LEFT_JOIN(ImageLocations, ImageLocations.ImageID.EQ(UserImages.ImageID)). LEFT_JOIN(ImageLocations, ImageLocations.ImageID.EQ(UserImages.ImageID)).
LEFT_JOIN(Locations, Locations.ID.EQ(ImageLocations.LocationID)). LEFT_JOIN(Locations, Locations.ID.EQ(ImageLocations.LocationID)).
LEFT_JOIN(ImageEvents, ImageEvents.ImageID.EQ(UserImages.ImageID)). LEFT_JOIN(ImageEvents, ImageEvents.ImageID.EQ(UserImages.ImageID)).
LEFT_JOIN(Events, Events.ID.EQ(ImageEvents.ID))). LEFT_JOIN(Events, Events.ID.EQ(ImageEvents.EventID))).
WHERE(UserImages.UserID.EQ(UUID(userId))) WHERE(UserImages.UserID.EQ(UUID(userId)))
fmt.Println(listWithPropertiesStmt.DebugSql()) fmt.Println(listWithPropertiesStmt.DebugSql())

View File

@ -74,7 +74,7 @@ CREATE TABLE haystack.events (
name TEXT NOT NULL, name TEXT NOT NULL,
description TEXT, description TEXT,
location UUID REFERENCES haystack.locations (id) location_id UUID REFERENCES haystack.locations (id)
); );
CREATE TABLE haystack.image_events ( CREATE TABLE haystack.image_events (

View File

@ -7,7 +7,7 @@ use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use tauri::AppHandle; use tauri::AppHandle;
use tauri::Emitter; use tauri::Emitter;
use tauri::{TitleBarStyle, WebviewUrl, WebviewWindowBuilder}; use tauri::{WebviewUrl, WebviewWindowBuilder};
struct WatcherState { struct WatcherState {
watcher: Option<RecommendedWatcher>, watcher: Option<RecommendedWatcher>,
@ -114,7 +114,6 @@ pub fn run() {
.invoke_handler(tauri::generate_handler![handle_selected_folder]) .invoke_handler(tauri::generate_handler![handle_selected_folder])
.setup(|app| { .setup(|app| {
let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default()) let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
.hidden_title(true)
.inner_size(480.0, 360.0) .inner_size(480.0, 360.0)
.resizable(true); .resizable(true);
// set transparent title bar only when building for macOS // set transparent title bar only when building for macOS

View File

@ -5,6 +5,7 @@ import clsx from "clsx";
import Fuse from "fuse.js"; import Fuse from "fuse.js";
import { createEffect, createResource, createSignal, For } from "solid-js"; import { createEffect, createResource, createSignal, For } from "solid-js";
import { getUserImages } from "./network"; import { getUserImages } from "./network";
import { ImageViewer } from "./components/ImageViewer";
type UserImages = Awaited<ReturnType<typeof getUserImages>>; type UserImages = Awaited<ReturnType<typeof getUserImages>>;
@ -18,7 +19,6 @@ function App() {
const nav = useNavigate(); const nav = useNavigate();
let fuze = new Fuse<NonNullable<UserImages[number]["Text"]>[number]>([], { let fuze = new Fuse<NonNullable<UserImages[number]["Text"]>[number]>([], {
keys: ["Text.ImageText"],
keys: ["ImageText"], keys: ["ImageText"],
}); });
@ -26,7 +26,6 @@ function App() {
createEffect(() => { createEffect(() => {
const userImages = images(); const userImages = images();
console.log(userImages);
if (userImages == null) { if (userImages == null) {
return; return;
} }
@ -98,23 +97,24 @@ function App() {
</Search.Indicator> </Search.Indicator>
<Search.Input class="appearance-none inline-flex w-full min-h-[40px] text-base bg-transparent rounded-l-md outline-none placeholder:text-gray-600" /> <Search.Input class="appearance-none inline-flex w-full min-h-[40px] text-base bg-transparent rounded-l-md outline-none placeholder:text-gray-600" />
</Search.Control> </Search.Control>
<Search.Portal>
<Search.Content
class="h-[254px] overflow-scroll scrollbar-hide"
onCloseAutoFocus={(e) => e.preventDefault()}
>
<Search.Listbox class="w-full grid grid-cols-9 grid-rows-9 gap-2 h-[480px] grid-flow-row-dense py-4" />
<Search.NoResult class="text-center p-2 pb-6 m-auto text-gray-600">
No results found
</Search.NoResult>
</Search.Content>
</Search.Portal>
</Search> </Search>
</div> </div>
{/* <div class="mt-4 text-base leading-none"> {/* <div class="mt-4 text-base leading-none">
Emoji selected: {emoji()?.emoji} {emoji()?.name} Emoji selected: {emoji()?.emoji} {emoji()?.name}
</div> */} </div> */}
{/* <ImageViewer /> */} <ImageViewer />
<div class="px-4 mt-4 bg-white rounded-t-2xl"> <div class="px-4 mt-4 bg-white rounded-t-2xl">
<Search.Content
class="h-[254px] overflow-scroll scrollbar-hide"
onCloseAutoFocus={(e) => e.preventDefault()}
>
<Search.Listbox class="w-full grid grid-cols-9 grid-rows-9 gap-2 h-[480px] grid-flow-row-dense py-4" />
<Search.NoResult class="text-center p-2 pb-6 m-auto text-gray-600">
No results found
</Search.NoResult>
</Search.Content>
<div class="col-span-3 row-span-3 bg-red-200 rounded-xl" /> <div class="col-span-3 row-span-3 bg-red-200 rounded-xl" />
<div class="col-span-3 row-span-3 bg-green-200 rounded-xl" /> <div class="col-span-3 row-span-3 bg-green-200 rounded-xl" />
<div class="col-span-6 row-span-3 bg-yellow-200 rounded-xl" /> <div class="col-span-6 row-span-3 bg-yellow-200 rounded-xl" />

View File

@ -25,10 +25,41 @@ export function ImagePage() {
<Suspense fallback={<>Loading...</>}> <Suspense fallback={<>Loading...</>}>
<A href="/">Back</A> <A href="/">Back</A>
<h1 class="text-2xl font-bold">{image()?.Image.ImageName}</h1> <h1 class="text-2xl font-bold">{image()?.Image.ImageName}</h1>
<img src={`http://localhost:3040/image/${image()?.ID}`} /> <img
src={`http://localhost:3040/image/${image()?.ID}`}
alt="link"
/>
<div class="flex flex-col"> <div class="flex flex-col">
<h2 class="text-xl font-bold">Tags</h2>
<For each={image()?.Tags ?? []}> <For each={image()?.Tags ?? []}>
{(tag) => <div>{tag.Tag}</div>} {(tag) => <div>{tag.Tag.Tag}</div>}
</For>
<h2 class="text-xl font-bold">Locations</h2>
<For each={image()?.Locations ?? []}>
{(location) => (
<ul>
<li>{location.Name}</li>
{location.Address && <li>{location.Address}</li>}
{location.Coordinates && (
<li>{location.Coordinates}</li>
)}
{location.Description && (
<li>{location.Description}</li>
)}
</ul>
)}
</For>
<h2 class="text-xl font-bold">Events</h2>
<For each={image()?.Events ?? []}>
{(event) => (
<ul>
<li>{event.Name}</li>
{event.Location && <li>{event.Location.Name}</li>}
{event.Description && <li>{event.Description}</li>}
</ul>
)}
</For> </For>
</div> </div>
</Suspense> </Suspense>

View File

@ -7,6 +7,7 @@ import {
parse, parse,
pipe, pipe,
string, string,
undefinedable,
uuid, uuid,
} from "valibot"; } from "valibot";
@ -82,7 +83,7 @@ const getUserImagesResponseValidator = array(
array( array(
object({ object({
ID: pipe(string(), uuid()), ID: pipe(string(), uuid()),
Links: string(), Link: string(),
ImageID: pipe(string(), uuid()), ImageID: pipe(string(), uuid()),
}), }),
), ),