Compare commits

..

No commits in common. "main" and "0.7.4" have entirely different histories.
main ... 0.7.4

54 changed files with 820 additions and 4505 deletions

4
.gitignore vendored
View File

@ -23,7 +23,3 @@ yarn-error.log*
/supabase/volumes/db/data
/supabase/volumes/storage
supabase.zip
.idea/copilot/chatSessions/00000000000.xd
.idea/copilot/chatSessions/blobs/version
.idea/copilot/chatSessions/xd.lck
.idea/workspace.xml

5
.idea/.gitignore generated vendored
View File

@ -1,5 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# GitHub Copilot persisted chat sessions
/copilot/chatSessions

1
.idea/.name generated
View File

@ -1 +0,0 @@
page.tsx

17
.idea/aws.xml generated
View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="accountSettings">
<option name="activeProfile" value="profile:default" />
<option name="activeRegion" value="us-east-1" />
<option name="recentlyUsedProfiles">
<list>
<option value="profile:default" />
</list>
</option>
<option name="recentlyUsedRegions">
<list>
<option value="us-east-1" />
</list>
</option>
</component>
</project>

4
.idea/encodings.xml generated
View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

6
.idea/misc.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated
View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/neroshitron.iml" filepath="$PROJECT_DIR$/.idea/neroshitron.iml" />
</modules>
</component>
</project>

11
.idea/neroshitron.iml generated
View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.idea/copilot/chatSessions" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -49,6 +49,51 @@ Configuration is done through the Owncast administration page located on your se
![image](https://github.com/D4M13N-D3V/neroshitron/assets/13697702/57379445-8bd5-4a7e-8a15-7fa0b3ae42dc)
# Database Diagram
![image](https://github.com/D4M13N-D3V/neroshitron/assets/13697702/b3387b77-d8c6-41c4-9fe8-d52dadb6bc5e)
![image](https://github.com/D4M13N-D3V/neroshitron/assets/13697702/3a22f05b-0de3-4f6c-9f95-06e035d03cb5)
# React Components
## Gallery Component
The `Gallery` component is a React component used to display a gallery of images. It fetches images from an API and displays them in a Masonry layout.
### Props
- `id` (number): The ID of the gallery to fetch images from.
- `closeMenu` (function): A function to close the menu.
### State
- `isSingle` (boolean): A state to check if only a single image is to be displayed.
- `loaded` (object): A state to keep track of loaded images.
- `selectedImage` (string | null): A state to keep track of the selected image.
- `images` (string[]): A state to store the fetched images.
- `galleryId` (number): A state to store the gallery ID.
### Functions
- `getData`: An async function to fetch images from the API.
- `generateRandomString`: A function to generate a random string of a given length.
- `handleDownload`: A function to handle the download of an image.
### Usage
The example below will load the images of the the gallery with an ID of `58201557-b392-471e-ac55-dcf6171cd18d` and will call the function for `setIsOpen(false)` when the back button is clicked.
```tsx
<Gallery id={"58201557-b392-471e-ac55-dcf6171cd18d"} closeMenu={() => setIsOpen(false)}></Gallery>
```
## GalleryThumbnail Component
The `GalleryThumbnail` component is a React component used to display a thumbnail of a gallery. It fetches the thumbnail image from an API and displays it. When clicked, it triggers a callback function with the gallery ID.
### Props
- `id` (string): The ID of the gallery to fetch the thumbnail for.
- `onSelect` (function): A function to be called when the thumbnail is clicked. The gallery ID is passed as an argument.
- `title` (string) : The name of the gallery.
- `subscription` (subscription) : The name of the subscription required for the gallery.
### State
- `galleryId` (string): A state to store the gallery ID.
- `thumbnailUrl` (string): A state to store the fetched thumbnail URL.
- `isLoading` (boolean): A state to keep track of the loading status.
### Functions
- `openGallery`: A function to call the `onSelect` prop with the gallery ID.
- `getData`: An async function to fetch the thumbnail from the API.
### Usage
This will render a thumbnail for the gallery with the ID of "1". When the thumbnail is clicked, it will log the gallery ID to the console.
```tsx
<GalleryThumbnail id="1" onSelect={(id) => //console.log(id)} />
```

View File

@ -1,4 +0,0 @@
import { middleware } from './middleware/path-header'
export default middleware

View File

@ -1,41 +0,0 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const supabase = createClient();
const getData = async () => {
}
useEffect(() => {
getData();
}, []);
const router = useRouter();
return (
<div className="w-full text-white flex justify-center items-center animate-in">
<div className="w-2/3 lg:w-1/3 rounded-md bg-primary p-8 mt-32 shadow-lg opacity-90 backdrop-blur-lg">
<div className="w-full flex justify-center">
<span className="text-2xl pb-4">System Settings</span>
</div>
<div className="flex justify-center ">
<button onClick={()=>{ router.push("/admin/tiers") }} className="bg-secondary hover:bg-secondary-dark rounded p-2 mr-1 w-full">Tiers Management</button>
<button onClick={()=>{ router.push("/gallery/admin") }} className="ml-1 bg-secondary hover:bg-secondary-dark rounded p-2 w-full">Gallery Management</button>
</div>
<div className="flex justify-center pt-2">
<button onClick={()=>{ router.push("/admin/theme") }} className="mr-1 bg-secondary hover:bg-secondary-dark rounded p-2 mr-1 w-full">Theme Settings</button>
<button className="bg-secondary hover:bg-secondary-dark rounded p-2 ml-1 w-full">User Management</button>
</div>
<div className="flex justify-center pt-2">
<button className="bg-secondary hover:bg-secondary-dark rounded p-2 w-full mr-1">Payment/Payout Settings</button>
<button className="bg-secondary hover:bg-secondary-dark rounded p-2 w-full ml-1">Comissions Settings</button>
</div>
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,474 +0,0 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const router = useRouter();
const supabase = createClient();
const [primary, setPrimary] = useState('#201240');
const [primaryLight, setPrimaryLight] = useState('#403260');
const [primaryDark, setPrimaryDark] = useState('#100120');
const [secondary, setSecondary] = useState('#4F3D70');
const [secondaryLight, setSecondaryLight] = useState('#6F5D90');
const [secondaryDark, setSecondaryDark] = useState('#2F1D50');
const [error, setError] = useState('#862117');
const [errorLight, setErrorLight] = useState('#C44C4C');
const [errorDark, setErrorDark] = useState('#5C0D0D');
const [changed, setChanged] = useState(false);
const [success, setSuccess] = useState('#00C9A6');
const [successLight, setSuccessLight] = useState('#20E9C6');
const [successDark, setSuccessDark] = useState('#00A986');
const [warning, setWarning] = useState('#E17558');
const [warningLight, setWarningLight] = useState('#E39578');
const [warningDark, setWarningDark] = useState('#C15538');
const [info, setInfo] = useState('#222140');
const [infoLight, setInfoLight] = useState('#424260');
const [infoDark, setInfoDark] = useState('#020120');
const [saving, setSaving] = useState(false);
const getData = async () => {
var primaryConfig = await getColorConfig('primary');
setPrimary(primaryConfig.value);
var primaryLightConfig = await getColorConfig('primary-light');
setPrimaryLight(primaryLightConfig.value);
var primaryDarkConfig = await getColorConfig('primary-dark');
setPrimaryDark(primaryDarkConfig.value);
var secondaryConfig = await getColorConfig('secondary');
setSecondary(secondaryConfig.value);
var secondaryLightConfig = await getColorConfig('secondary-light');
setSecondaryLight(secondaryLightConfig.value);
var secondaryDarkConfig = await getColorConfig('secondary-dark');
setSecondaryDark(secondaryDarkConfig.value);
var errorConfig = await getColorConfig('error');
setError(errorConfig.value);
var errorLightConfig = await getColorConfig('error-light');
setErrorLight(errorLightConfig.value);
var errorDarkConfig = await getColorConfig('error-dark');
setErrorDark(errorDarkConfig.value);
var successConfig = await getColorConfig('success');
setSuccess(successConfig.value);
var successLightConfig = await getColorConfig('success-light');
setSuccessLight(successLightConfig.value);
var successDarkConfig = await getColorConfig('success-dark');
setSuccessDark(successDarkConfig.value);
var warningConfig = await getColorConfig('warning');
setWarning(warningConfig.value);
var warningLightConfig = await getColorConfig('warning-light');
setWarningLight(warningLightConfig.value);
var warningDarkConfig = await getColorConfig('warning-dark');
setWarningDark(warningDarkConfig.value);
var infoConfig = await getColorConfig('info');
setInfo(infoConfig.value);
var infoLightConfig = await getColorConfig('info-light');
setInfoLight(infoLightConfig.value);
var infoDarkConfig = await getColorConfig('info-dark');
setInfoDark(infoDarkConfig.value);
}
const getColorConfig = async (name: string) => {
try {
const response = await fetch(`/api/admin/interface-configs?name=${name}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error('Failed to call GET request');
}
const data = await response.json();
return data;
} catch (error) {
console.error(error);
throw new Error('Failed to call GET request');
}
}
const setColorConfig = async (name: string, value:string) => {
try {
const response = await fetch(`/api/admin/interface-configs`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, value }),
});
if (!response.ok) {
throw new Error('Failed to call GET request');
}
const data = await response.json();
return data;
} catch (error) {
console.error(error);
throw new Error('Failed to call GET request');
}
}
const save = async () => {
setSaving(true);
await Promise.all([
setColorConfig('primary', primary),
setColorConfig('primary-light', primaryLight),
setColorConfig('primary-dark', primaryDark),
setColorConfig('secondary', secondary),
setColorConfig('secondary-light', secondaryLight),
setColorConfig('secondary-dark', secondaryDark),
setColorConfig('error', error),
setColorConfig('error-light', errorLight),
setColorConfig('error-dark', errorDark),
setColorConfig('success', success),
setColorConfig('success-light', successLight),
setColorConfig('success-dark', successDark),
setColorConfig('warning', warning),
setColorConfig('warning-light', warningLight),
setColorConfig('warning-dark', warningDark),
setColorConfig('info', info),
setColorConfig('info-light', infoLight),
setColorConfig('info-dark', infoDark)
]);
window.location.reload();
}
useEffect(() => {
getData();
}, []);
const colorChange = async ()=>{
setChanged(true)
document.documentElement.style.setProperty(`--color-primary`, primary);
document.documentElement.style.setProperty(`--color-primary-light`, primaryLight);
document.documentElement.style.setProperty(`--color-primary-dark`, primaryDark);
document.documentElement.style.setProperty(`--color-secondary`, secondary);
document.documentElement.style.setProperty(`--color-secondary-light`, secondaryLight);
document.documentElement.style.setProperty(`--color-secondary-dark`, secondaryDark);
document.documentElement.style.setProperty(`--color-error`, error);
document.documentElement.style.setProperty(`--color-error-light`, errorLight);
document.documentElement.style.setProperty(`--color-error-dark`, errorDark);
document.documentElement.style.setProperty(`--color-success`, success);
document.documentElement.style.setProperty(`--color-success-light`, successLight);
document.documentElement.style.setProperty(`--color-success-dark`, successDark);
document.documentElement.style.setProperty(`--color-warning`, warning);
document.documentElement.style.setProperty(`--color-warning-light`, warningLight);
document.documentElement.style.setProperty(`--color-warning-dark`, warningDark);
document.documentElement.style.setProperty(`--color-info`, info);
document.documentElement.style.setProperty(`--color-info-light`, infoLight);
document.documentElement.style.setProperty(`--color-info-dark`, infoDark);
}
return (
<div className="w-5/6 h-1/2 text-white lg:flex justify-center items-center animate-in overflow-y-hidden">
<div className=" w-5/6 md:w-4/6 lg:w-3/6 xl:w-2/6 rounded-md bg-primary opacity-90 p-12 m-1 mt-24 shadow-lg backdrop-blur">
<div className="w-full relative">
<span className="text-2xl pb-4">Color Settings</span>
<button onClick={()=>{router.push("/admin")}} className={`float-right bg-error hover:bg-error-light ml-2 rounded p-2`}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor"
className="md:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
</svg>
<span className="hidden md:block">Back</span>
</button>
<button onClick={save} disabled={!changed}
className={`float-right ${changed ? "bg-success hover:bg-success-light" : "bg-success-dark"} rounded p-2`}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor"
className="md:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m4.5 12.75 6 6 9-13.5" />
</svg>
<span className="hidden md:block">{saving?"Saving...":"Save"}</span>
</button>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Primary Color</label>
<div className="flex">
<input
value={primary}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setPrimary(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={primary}
onChange={(e) => { setPrimary(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Primary Light Color</label>
<div className="flex">
<input
value={primaryLight}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setPrimaryLight(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={primaryLight}
onChange={(e) => { setPrimaryLight(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Primary Dark Color</label>
<div className="flex">
<input
value={primaryDark}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setPrimaryDark(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={primaryDark}
onChange={(e) => { setPrimaryDark(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Secondary Color</label>
<div className="flex">
<input
value={secondary}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSecondary(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={secondary}
onChange={(e) => { setSecondary(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Secondary Dark Color</label>
<div className="flex">
<input
value={secondaryDark}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSecondaryDark(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={secondaryDark}
onChange={(e) => { setSecondaryDark(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Secondary Light Color</label>
<div className="flex">
<input
value={secondaryLight}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSecondaryLight(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={secondaryLight}
onChange={(e) => { setSecondaryLight(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Error Color</label>
<div className="flex">
<input
value={error}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setError(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={error}
onChange={(e) => { setError(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Error Dark Color</label>
<div className="flex">
<input
value={errorDark}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setErrorDark(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={errorDark}
onChange={(e) => { setErrorDark(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Error Light Color</label>
<div className="flex">
<input
value={errorLight}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setErrorLight(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={errorLight}
onChange={(e) => { setErrorLight(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Success Color</label>
<div className="flex">
<input
value={success}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSuccess(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={success}
onChange={(e) => { setSuccess(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Success Dark Color</label>
<div className="flex">
<input
value={successDark}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSuccessDark(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={successDark}
onChange={(e) => { setSuccessDark(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Success Light Color</label>
<div className="flex">
<input
value={successLight}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSuccessLight(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={successLight}
onChange={(e) => { setSuccessLight(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,124 +0,0 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const supabase = createClient();
const router = useRouter();
const [name, setName] = useState<string>('');
const [price, setPrice] = useState<number>(0);
const [description, setDescription] = useState<string>('');
const [color, setColor] = useState<string>('#000000');
const getData = async () => {
}
useEffect(() => {
getData();
}, []);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const data = {
name,
price,
color,
description
};
const response = await fetch('/api/tiers', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (response.ok) {
const responseData = await response.json();
window.location.href = "/admin/tiers";
} else {
console.log(response);
}
}
return (
<div className="w-full p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<form onSubmit={handleSubmit}>
<div className="w-full flex">
<span className="text-2xl pb-4">Creating New Tier</span>
</div>
<div className="w-full flex">
<input
value={name}
required
type="text"
onChange={(e) => { setName(e.target.value) }}
className="mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
placeholder="Tag Name"
/>
<div className="flex border border-gray-300 w-1/2 rounded-md">
<span className="flex items-center bg-gray-100 rounded-l-md border-r px-3 text-gray-500">
$
</span>
<input
value={price}
onChange={(e) => { setPrice(Number(e.target.value)) }}
required
placeholder="Price in USD per month"
type="number"
className="flex-1 min-w-0 bg-info-bright rounded-r-md px-3 py-2 text-black focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
</div>
</div>
<div className="w-full pt-2 justify-center flex">
<textarea
value={description}
onChange={(e) => { setDescription(e.target.value) }}
required
placeholder="Description of the tier and what the user gets from subscribing."
rows={3}
className="w-full rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
></textarea>
</div>
<div className="w-full pt-2 justify-center flex">
<div className="w-1/2 relative">
<input
value={color}
required
type="text"
className="w-full rounded-md bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setColor(e.target.value) }}
placeholder="Choose the tiers color"
/>
<input
value={color}
onChange={(e) => { setColor(e.target.value) }}
required
id="colorInput"
type="color"
className="absolute right-0 top-0 w-10 h-full rounded-r p-1"
/>
</div>
<button
type="submit"
className="hover:scale-95 ml-2 shadow-lg w-1/2 h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded flex items-center justify-center"
>
Create
</button>
<button
type="button"
onClick={() => { router.push("/admin/tiers") }}
className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error-dark hover:bg-error text-white font-bold rounded flex items-center justify-center"
>
Back
</button>
</div>
</form>
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,55 +0,0 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const router = useRouter();
const supabase = createClient();
const [tiers, setTiers] = useState<any[]>([]);
const getData = async () => {
try {
const response = await fetch('/api/tiers');
if (response.ok) {
const data = await response.json();
setTiers(data);
} else {
console.error('failed to fetch tiers');
}
} catch (error) {
console.error('Error fetching users:', error);
}
}
useEffect(() => {
getData();
}, []);
return (
<div className="w-2/3 p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-8 m-1 mt-32 shadow-lg backdrop-blur">
<div className="w-full flex justify-center">
<span className="text-2xl pb-4">Tiers Management</span>
</div>
<div className="w-full flex justify-center">
<button onClick={() => { router.push("/admin/tiers/create") }} className="bg-success hover:bg-success-light rounded p-2 w-full">New Tier</button>
<button onClick={() => { router.push("/admin") }} className="bg-error hover:bg-error-light rounded p-2 w-full ml-2">Back</button>
</div>
<div className="w-full justify-center pt-8">
{tiers.map((item, index) => (
<div className="w-full flex justify-center">
<div key={index} className="text-white w-full text-stroke mt-2">
<button onClick={() => { router.push("/admin/tiers/view?name=" + item.name) }} className="py-2 w-full rounded hover:scale-105" style={{ backgroundColor: item.color }}>{item.name} - ${item.price}/month</button>
</div>
</div>
))}
</div>
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,141 +0,0 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const router = useRouter();
const supabase = createClient();
const [tier, setTier] = useState<any[]>([]);
const [users, setUsers] = useState<any[]>([]);
const [name, setName] = useState<string>('');
const [price, setPrice] = useState<number>(0);
const [description, setDescription] = useState<string>('');
const [color, setColor] = useState<string>('#000000');
const getData = async () => {
try {
const searchParams = new URLSearchParams(window.location.search);
const name = searchParams.get('name');
const response = await fetch('/api/tiers/'+name);
if (response.ok) {
const data = await response.json();
setTier(data);
setName(data.name);
setPrice(data.price);
setDescription(data.description);
setColor(data.color);
} else {
console.error('failed to fetch tiers');
}
} catch (error) {
console.error('Error fetching users:', error);
}
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const data = {
newName:name,
price,
color,
description
};
const response = await fetch('/api/tiers/'+name, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (response.ok) {
const responseData = await response.json();
window.location.href = "/admin/tiers";
} else {
console.log(response);
}
}
useEffect(() => {
getData();
}, []);
return (
<div className="w-full p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<form onSubmit={handleSubmit}>
<div className="w-full flex">
<span className="text-2xl pb-4">Editing Existing Tier</span>
</div>
<div className="w-full flex">
<input
value={name}
required
type="text"
onChange={(e) => { setName(e.target.value) }}
className="mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
placeholder="Tag Name"
/>
<div className="flex border border-gray-300 w-1/2 rounded-md">
<span className="flex items-center bg-gray-100 rounded-l-md border-r px-3 text-gray-500">
$
</span>
<input
value={price}
onChange={(e) => { setPrice(Number(e.target.value)) }}
required
placeholder="Price in USD per month"
type="number"
className="flex-1 min-w-0 bg-info-bright rounded-r-md px-3 py-2 text-black focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
</div>
</div>
<div className="w-full pt-2 justify-center flex">
<textarea
value={description}
onChange={(e) => { setDescription(e.target.value) }}
required
placeholder="Description of the tier and what the user gets from subscribing."
rows={3}
className="w-full rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
></textarea>
</div>
<div className="w-full pt-2 justify-center flex">
<div className="w-1/2 relative">
<input
value={color}
required
type="text"
className="w-full rounded-md bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setColor(e.target.value) }}
placeholder="Choose the tiers color"
/>
<input
value={color}
onChange={(e) => { setColor(e.target.value) }}
required
id="colorInput"
type="color"
className="absolute right-0 top-0 w-10 h-full rounded-r p-1"
/>
</div>
<button onClick={() => { }} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-warning hover:bg-warning-light text-white font-bold rounded flex items-center justify-center">
Update
</button>
<button type="button" onClick={() => { }} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error hover:bg-error-light text-white font-bold rounded flex items-center justify-center">
Delete
</button>
<button type="button" onClick={() => { router.push("/admin/tiers") }} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error-dark hover:bg-error text-white font-bold rounded flex items-center justify-center">
Back
</button>
</div>
</form>
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,26 +0,0 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { createClient } from "@/utils/supabase/server";
import { NextResponse } from "next/server";
export async function PUT(request: Request) {
const body = await request.json();
console.log(body)
const supabase = createClient();
var value = body.value;
const { error } = await supabase.from('interface_configurations').update({ value }).eq('name', body.name);
console.log(error)
if (error) {
return NextResponse.error();
}
return NextResponse.json({});
}
export async function GET(request: Request) {
const url = new URL(request.url as string, 'http://localhost');
const name = url.searchParams.get('name') || '';
const supabase = createClient();
const { data, error } = await supabase.from('interface_configurations').select('*').eq('name', name).single();
return NextResponse.json(data);
}

View File

@ -1,17 +0,0 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { createClient } from "@/utils/supabase/server";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
try {
const supabase = createClient();
const { data, error } = await supabase.auth.admin.listUsers();
console.log(error)
if (error) {
throw error;
}
return NextResponse.json(data);
} catch (error) {
return NextResponse.error();
}
}

View File

@ -1,34 +0,0 @@
import { NextResponse } from "next/server";
import { createClient } from "@/utils/supabase/server";
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const galleryId = params.id;
const supabase = createClient();
const { data: gallery, error: galleryError } = await supabase
.from('galleries')
.select('*')
.eq('name', galleryId)
.single();
// List all files in the galleryId path
let { data: files, error } = await supabase.storage
.from('galleries')
.list(params.id.toLowerCase().replace(/\s+/g, '_'));
if (files == null || error) {
//console.error('Error listing files:', error);
return NextResponse.error();
}
// Extract file names from the list of files
const fileNames = files.map((file) => file.name);
// Return a JSON response with the array of file names
return new Response(JSON.stringify(fileNames), {
headers: { 'content-type': 'application/json' },
});
}

View File

@ -18,7 +18,7 @@ export async function GET(
{ params }: { params: { id: string } }
) {
const galleryId = params.id; const supabase = createClient();
const galleryId = params.id.toLowerCase().replace(/\s+/g, '_'); const supabase = createClient();
const user = await supabase.auth.getUser();
@ -54,6 +54,8 @@ export async function GET(
.select('*')
.eq('user_id', userId)
.single();
console.log(subscription)
console.log(gallery.tier)
switch(gallery.tier){
case "Tier 3":
if(subscription?.tier!="Tier 3"){

View File

@ -17,6 +17,7 @@ export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const galleryId = params.id.toLowerCase().replace(/\s+/g, '_');
const supabase = createClient();
const user = await supabase.auth.getUser();
const url = new URL(request.url);
@ -29,17 +30,15 @@ export async function GET(
.eq('name', params.id)
.single();
var thumbnailFile = gallery.thumbnail_file;
if(thumbnailFile==null || thumbnailFile==""){
let { data: files, error } = await supabase.storage.from('galleries').list(params.id);
if (files == null || files?.length == 0) {
return NextResponse.error();
}
thumbnailFile = files[0].name;
let { data: files, error } = await supabase.storage.from('galleries').list(galleryId);
if (files == null || files?.length == 0) {
return NextResponse.error();
}
// Loop through each file, download it, convert it to base64, and add the data URL to the array
let { data: blobdata, error: fileError } = await supabase.storage.from('galleries').download(params.id + "/" + thumbnailFile);
let { data: blobdata, error: fileError } = await supabase.storage.from('galleries').download(galleryId + "/" + files[0].name);
if (fileError || blobdata == null) {
//console.error('Error downloading file:', error);
return NextResponse.error();
@ -55,7 +54,7 @@ export async function GET(
if(nsfw && gallery.nsfw){
blobBuffer = await blurImage(blobBuffer);
}
const contentType = thumbnailFile.endsWith('.png') ? 'image/png' : 'image/jpeg';
const contentType = files[0].name.endsWith('.png') ? 'image/png' : 'image/jpeg';
const dataUrl = `data:${contentType};base64,${blobBuffer.toString('base64')}`;

View File

@ -1,110 +0,0 @@
import { NextResponse } from "next/server";
import { createClient } from "@/utils/supabase/server";
import path from 'path';
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const id = params.id;
const supabase = createClient();
const { data: gallery, error } = await supabase.from('galleries').select("*").eq('name', id).single();
return NextResponse.json({ gallery });
}
export async function PUT(
request: Request,
{ params }: { params: { id: string } }){
const supabase = createClient();
const formData = await request.formData();
const tags = JSON.parse(formData.getAll('tags').toString()) as string[];
const originalName = formData.get('originalName');
const name = formData.get('name')?.toString();
const nsfw = formData.get('nsfw')?.toString();
const tier = formData.get('tier')?.toString();
const thumbnail = formData.get('thumbnail');
const { error } = await supabase.from('galleries').update({name, tags, nsfw, tier, thumbnail_file:thumbnail}).eq('name', originalName ?? '');
async function renameFolder(oldFolderName: any, newFolderName: string) {
// Get a list of all files in the old folder
let { data: oldFiles, error } = await supabase.storage.from('galleries').list(oldFolderName);
if (error) {
console.error('Error fetching files:', error);
return;
}
// Move each file to the new folder
if (oldFiles) {
for (let file of oldFiles) {
let oldPath = file.name;
let newPath = newFolderName + '/' + oldPath.split('/').pop();
let { error: moveError } = await supabase.storage.from('galleries').move(oldPath, newPath);
if (moveError) {
console.error(`Error moving file ${oldPath} to ${newPath}:`, moveError);
}
}
}
// Delete the old folder
let { error: deleteError } = await supabase.storage.from('galleries').remove([oldFolderName]);
if (deleteError) {
console.error('Error deleting old folder:', deleteError);
}
}
renameFolder(originalName, name ?? '');
if(error){
return NextResponse.error();
}
let { data: galleries, error:galleriesError } = await supabase
.from('galleries')
.select('*');
return NextResponse.json({ success: true, galleries });
}
export async function DELETE(
request: Request,
{ params }: { params: { id: string } }
) {
const id =params.id;
const supabase = createClient();
const { data: gallery, error } = await supabase.from('galleries').delete().eq('name', id).single();
let { data: galleries, error:galleriesError } = await supabase
.from('galleries')
.select('*');
return NextResponse.json({ success: true, galleries });
}
// const tagsResponse = await fetch(`/api/galleries/tags?search=${search}`);
// const tagsData = await tagsResponse.json();
// const galleriesWithTagData = galleriesData.map((gallery: any) => {
// const tags = tagsData.filter((tag: any) => gallery.tags.includes(tag.name));
// return { ...gallery, tags };
// });
// const formData = new FormData();
// formData.append('name', name);
// formData.append('tags', JSON.stringify(tags));
// files.forEach((file: File) => {
// formData.append('files', file);
// });
// const response = await fetch('/api/galleries', {
// method: 'POST',
// body: formData,
// });
// if (response.ok) {
// const data = await response.json();
// // Handle success
// } else {
// // Handle error
// }

View File

@ -1,37 +0,0 @@
import { NextResponse } from "next/server";
import { createClient } from "@/utils/supabase/server";
import path from 'path';
export async function GET(request: Request) {
const supabase = createClient();
let { data: galleries, error } = await supabase
.from('galleries')
.select('*');
return NextResponse.json(galleries);
}
export async function POST(request: Request) {
const supabase = createClient();
const formData = await request.formData();
const files = formData.getAll('files');
const tags = JSON.parse(formData.getAll('tags').toString()) as string[];
const name = formData.get('name');
const nsfw = formData.get('nsfw');
const tier = formData.get('tier');
const thumbnail = formData.get('thumbnail');
for (let i = 0; i < files.length; i++) {
const file = files[i] as File; // Cast 'file' to 'File' type
supabase.storage.from('galleries').upload(`${name}/${file.name}`, file);
}
const { data: gallery, error } = await supabase.from('galleries').insert({ name, tags, nsfw, thumbnail_file:thumbnail, tier, column_number: 3 }).single();
let { data: galleries, error: galleriesError } = await supabase
.from('galleries')
.select('*');
return NextResponse.json({ success: true, galleries });
}

View File

@ -13,17 +13,20 @@ export async function POST(request: Request) {
.from('galleries')
.select('*')
.ilike('name', `%${search}%`)
//console.log(error)
return NextResponse.json(galleries);
}
else{
// Rest of the code...
let { data: galleries, error } = await supabase
.from('galleries')
.select('*')
.contains('tags', tags) // Fix: Use contains instead of overlaps
.ilike('name', `%${search}%`)
console.log(tags)
let { data: galleries, error } = await supabase
.from('galleries')
.select('*')
.contains('tags', tags) // Fix: Use contains instead of overlaps
.ilike('name', `%${search}%`)
//console.log(error)
return NextResponse.json(galleries);
return NextResponse.json(galleries);
}
}

View File

@ -5,28 +5,8 @@ import { createClient } from "@/utils/supabase/server";
export async function GET(request: Request) {
const supabase = createClient();
let { data: tags, error } = await supabase
.from('tags')
.select('*')
.order('name', { ascending: true });
.from('tags')
.select('*')
return NextResponse.json(tags)
}
export async function POST(request: Request) {
const supabase = createClient();
const data = await request.json();
const { data: tag, error } = await supabase.from('tags').insert({ name: data.tag }).single();
if (error) {
return NextResponse.error();
}
return NextResponse.json(tag);
}
export async function PUT(request: Request) {
const supabase = createClient();
const data = await request.json();
const { data: tag, error } = await supabase.from('tags').delete().eq('name', data.tag).single();
if (error) {
return NextResponse.error();
}
return NextResponse.json(tag);
}

View File

@ -1,36 +0,0 @@
import { NextResponse } from "next/server";
import { createClient } from "@/utils/supabase/server";
export async function GET(
request: Request,
{ params }: { params: { name: string } }
) {
const supabase = createClient();
const { data: tier, error: galleryError } = await supabase
.from('tiers')
.select('*')
.eq('name', params.name)
.single();
if(galleryError) {
return NextResponse.error();
}
return NextResponse.json(tier);
}
export async function PUT(
request: Request,
{ params }: { params: { name: string } }
) {
const supabase = createClient();
const { newName, price, color, description } = await request.json();
console.log(newName)
const { error } = await supabase.from('tiers')
.update({ name:newName, price, color, description }).eq('name', params.name);
if (error) {
console.error('Error updating tier:', error);
return NextResponse.error();
}
return NextResponse.json({});
}

View File

@ -1,26 +0,0 @@
import { NextResponse } from "next/server";
import { createClient } from "@/utils/supabase/server";
export async function GET(request: Request) {
const supabase = createClient();
const { data, error } = await supabase.from('tiers').select('*');
if (error) {
console.error('Error fetching tiers:', error);
return NextResponse.error();
}
const tiers = data ?? [];
return NextResponse.json(tiers);
}
export async function POST(request: Request) {
const supabase = createClient();
const { name, price, color, description } = await request.json();
const { data, error } = await supabase.from('tiers').insert([{ name, price, color, description }]);
if (error) {
console.error('Error inserting tier:', error);
return NextResponse.error();
}
return NextResponse.json(data);
}

View File

@ -1,168 +0,0 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import Masonry from "react-masonry-css";
import SearchInput from "@/components/neroshitron/search_input";
function PageComponent() {
const router = useRouter();
const [selectedGallery, setSelectedGallery] = useState<string | null>(null);
const [filePreviews, setFilePreviews] = useState<string[]>([]);
const [name, setName] = useState<string>('');
const [nsfw, setNsfw] = useState<boolean>(false);
const [tags, setTags] = useState<string[]>([]);
const [tier, setTier] = useState<string>('Free');
const [thumbnail, setThumbnail] = useState<string>("");
const [files, setFiles] = useState<FileList>();
const [tiers, setTiers] = useState<any[]>([]);
const supabase = createClient();
const user = supabase.auth.getUser();
const getData = async () => {
try {
const response = await fetch('/api/tiers');
if (response.ok) {
const data = await response.json();
setTiers(data);
} else {
console.error('failed to fetch tiers');
}
} catch (error) {
console.error('Error fetching users:', error);
}
}
useEffect(() => {
getData();
}, [selectedGallery]);
const closeGallery = () => {
setSelectedGallery(null);
}
const createGallery = async () => {
const formData = new FormData();
formData.append('name', name);
if (files) {
Array.from(files).forEach((file: File) => {
formData.append('files', file);
});
}
formData.append('tags', JSON.stringify(tags));
formData.append('nsfw', nsfw.toString());
formData.append('thumbnail', thumbnail);
formData.append('tier', tier);
const response = await fetch('/api/galleries/admin', {
method: 'POST',
body: formData,
});
if (response.ok) {
const data = await response.json();
window.location.href = "/gallery/admin/view?id="+name;
} else {
console.log(response)
}
}
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = event.target.files;
if (files) {
const previews: string[] = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
const reader = new FileReader();
reader.onload = (e) => {
if (e.target && e.target.result) {
previews.push(e.target.result.toString());
if (previews.length === files.length) {
setFiles(files);
setFilePreviews(previews);
}
}
};
reader.readAsDataURL(file);
}
}
};
return (
<div className="w-full p-8 text-white flex justify-center items-center animate-in">
<div className="w-full lg:w-1/2 rounded-md bg-primary opacity-90 backdrop-blur-lg p-12 mt-32 shadow-lg">
<div className="w-full flex pb-4">
<span className="text-2xl">Creating New Gallery</span>
</div>
<div className="w-full flex">
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className="mb-8 mr-2 rounded-md bg-secondary p-2 w-1/2 text-white shadow-lg"
placeholder="Gallery Name"
/>
<div className="w-1/4">
<button onClick={() => router.push("/gallery/admin")} className="w-full bg-error hover:bg-error-light text-white rounded-md p-2 shadow-lg">
Back
</button>
</div>
<div className="w-1/4">
<button onClick={()=>{createGallery()}} className="w-full bg-success hover:bg-success-light text-white rounded-md p-2 ml-2 shadow-lg ">
<span></span>Create
</button>
</div>
</div>
<div className="w-full lg:flex">
<div className="w-full lg:w-1/2">
<div className="w-1/2 absolute pr-14">
<SearchInput
placeholderTags={[
{ value: "tags", label: "❗️ click here to add tags" },
]}
startingTags={tags}
nsfwButtonEnabled={true}
searchChanged={(search) => { }}
nsfwChanged={(nsfw) => { }}
tagsChanged={(tags) => { setTags(tags) }}
/>
</div>
</div>
<div className="w-full lg:w-1/2 lg:pt-0 pt-4">
<select value={nsfw ? "NSFW" : "SFW"} className="mb-2 shadow-lg rounded-md bg-secondary p-2 w-full text-white" onChange={e=>{
setNsfw(e.target.value === "NSFW");
}}>
<option value="NSFW" selected={nsfw}>NSFW</option>
<option value="SFW" selected={nsfw}>SFW</option>
</select>
<select onChange={e=>{
setTier(e.target.value);
}} className="mb-2 shadow-lg mr-2 rounded-md bg-secondary p-2 w-full text-white">
<option value="" disabled >Select New Tier</option>
{tiers.map((tier, index) => (
<option key={index} value={tier.name}>{tier.name}</option>
))}
</select>
<select onChange={e=>{setThumbnail(e.target.value)}} className="mb-2 shadow-lg mr-2 rounded-md bg-secondary p-2 w-full text-white">
<option value="" disabled selected>Select Thumbnail</option>
{files && Array.from(files).map((file: File, index: number) => (
<option key={index} value={file.name}>{file.name}</option>
))}
</select>
<input
className="relative m-0 block w-full min-w-0 flex-auto cursor-pointer rounded border border-solid border-secondary-lighter bg-transparent bg-clip-padding px-3 py-[0.32rem] text-base font-normal text-surface transition duration-300 ease-in-out file:-mx-3 file:-my-[0.32rem] file:me-3 file:cursor-pointer file:overflow-hidden file:rounded-none file:border-0 file:border-e file:border-solid file:border-inherit file:bg-transparent file:px-3 file:py-[0.32rem] file:text-surface focus:border-primary focus:text-gray-700 focus:shadow-inset focus:outline-none dark:border-white/70 dark:text-white file:dark:text-white"
type="file"
id="formFileMultiple"
multiple
onChange={handleFileChange}
/>
<Masonry breakpointCols={3} className="my-masonry-grid pl-6 col-span-2">
{filePreviews.map((preview, index) => (
<img key={index} src={preview} alt={`Preview ${index}`} />
))}
</Masonry>
</div>
</div>
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,161 +0,0 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import SearchInput from "@/components/neroshitron/search_input";
import { useRouter } from 'next/navigation';
function PageComponent() {
const router = useRouter();
const supabase = createClient();
const user = supabase.auth.getUser();
const [tags, setTags] = useState<any[]>([]);
const [nsfwState, setNsfwState] = useState<boolean>(false);
const [tagsState, setTagsState] = useState<string[]>([]);
const [searchState, setSearchState] = useState<string>("");
const [galleries, setGalleries] = useState([]);
const [tagSearch, setTagSearch] = useState<string>('');
const [newTagName, setNewTagName] = useState<string>('');
const getData = async () => {
const tagsResponse = await fetch(`/api/galleries/tags`);
const tagsData = await tagsResponse.json();
setTags(tagsData);
const galleriesResponse = await fetch(`/api/galleries?search=` + searchState + '&nsfw=' + nsfwState, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ tags: tagsState })
});
const galleriesData = await galleriesResponse.json();
setGalleries(galleriesData);
}
const createTag = async () => {
let formattedTag = newTagName.toLowerCase().replace(" ", "_");
const tagsResponse = await fetch(`/api/galleries/tags`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ tag: formattedTag })
});
const tagsData = await tagsResponse.json();
setNewTagName('');
getData();
}
const deleteTag = async (tagParam: string) => {
const tagsResponse = await fetch(`/api/galleries/tags`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ tag:tagParam })
});
const tagsData = await tagsResponse.json();
getData();
}
useEffect(() => {
getData();
}, [tagsState, newTagName]);
return (
<div className="w-full p-8 h-max text-white lg:flex justify-center items-start animate-in mt-32">
<div className="w-full h-max lg:w-1/3 rounded-md bg-primary opacity-90 p-8 m-1 shadow-lg backdrop-blur">
<span className="text-2xl">Tags Management</span>
<div className="w-full flex pt-4">
<form onSubmit={createTag} className="flex w-full">
<input value={newTagName} required type="text" onChange={(e)=>{setNewTagName(e.target.value)}} className=" mb-8 mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg" placeholder="Tag Name" />
<button className=" ml-2 shadow-lg w-1/2 h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="lg:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
<span className="lg:hidden block">Tag</span>
<span className="lg:block hidden">New Tag</span>
</button>
</form>
</div>
<div className="w-full flex">
<input type="text" value={tagSearch} onChange={(e)=>{setTagSearch(e.target.value)}} className=" mb-8 shadow-lg mr-2 rounded-md bg-info-bright p-2 w-full text-black" placeholder="Search all tags by name" />
</div>
<div className="w-full h-96 overflow-y-scroll no-scrollbar">
<table className="w-full bg-primary-light rounded">
<tbody>
{tags.filter((value,index,array)=>{
return value.name.toLowerCase().includes(tagSearch.toLowerCase());
}).map((item:any) => (
<tr key={item.name} className="hover:bg-secondary-dark animate-in shadow">
<td className="px-4 py-2">{item.name}</td>
<td className="px-4 py-2">
<button onClick={()=>{deleteTag(item.name)}} className=" bg-error shadow-lg hover:bg-error-light text-white font-bold py-2 px-4 rounded float-right">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div className="w-full h-max lg:w-1/2 rounded-md bg-primary opacity-90 backdrop-blur-lg p-8 m-1 shadow-lg">
<div className="w-full pb-2 flex justify-between">
<span className="text-2xl">Galleries Management</span>
<div>
<button onClick={()=>{router.push("/admin/")}} className="ml-2 p-2 shadow-lg h-10 text-center bg-error hover:bg-error-light text-white font-bold rounded">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="xl:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
<span className="xl:block hidden">Back</span>
</button>
<button onClick={()=>{router.push("/gallery/admin/create")}} className="ml-2 p-2 shadow-lg h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="xl:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
<span className="xl:block hidden">New Gallery</span>
</button>
</div>
</div>
<div className="w-full pb-2 flex">
<div className="absolute w-full z-20 pr-16">
<SearchInput
startingTags={[]}
placeholderTags={[
{ value: "tags", label: "❗️ click here to add tags to search" }
]} nsfwButtonEnabled={false} searchChanged={(search) => { setSearchState(search) }} nsfwChanged={(nsfw) => { setNsfwState(nsfw) }} tagsChanged={(tags) => { setTagsState(tags) }} />
</div>
</div>
<div className="w-full h-96 overflow-y-scroll no-scrollbar">
<table className="w-full mt-20 bg-primary-light rounded">
<tbody>
{/* Replace this with your data mapping logic */}
{galleries.map((item: { name: string, imageCount: number, tier: string }) => (
<tr key={item.name} className="hover:bg-secondary-dark shadow animate-in">
<td className="px-4 py-2" style={{ width: '65%' }}>{item.name}</td>
<td className="px-4 py-2">{item.imageCount}</td>
<td className="px-4 py-2">{item.tier}</td>
<td className="px-4 py-2">
<button onClick={()=>{ router.push(`/gallery/admin/view?id=${encodeURIComponent(item.name)}`)}} className="bg-secondary shadow-lg hover:bg-secondary-light text-white font-bold py-2 px-4 rounded float-right">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m5.231 13.481L15 17.25m-4.5-15H5.625c-.621 0-1.125.504-1.125 1.125v16.5c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Zm3.75 11.625a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" />
</svg>
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,271 +0,0 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import Gallery from "@/components/neroshitron/gallery";
import SearchInput from "@/components/neroshitron/search_input";
import GalleryThumbnail from "@/components/neroshitron/gallery_thumbnail";
function PageComponent() {
const [filePreviews, setFilePreviews] = useState<string[]>([]);
const supabase = createClient();
const user = supabase.auth.getUser();
const [gallery , setGallery] = useState<any>(null);
const [originalName, setOriginalGalleryName] = useState<string>('');
const [galleryName, setGalleryName] = useState<string>('');
const [nsfw, setNsfw] = useState<boolean>(false);
const [tags, setTags] = useState<string[]>([]);
const [tier, setTier] = useState<string>('Free');
const [thumbnail, setThumbnail] = useState<string>();
const [fileNames, setFileNames] = useState<string[]>([]);
const [selectedTags, setSelectedTags] = useState<string[]>([]);
const router = useRouter();
const [tiers, setTiers] = useState<any[]>([]);
const [open, setOpen] = useState<boolean>(false);
const [images, setImages] = useState<string[]>([]);
const getData = async () => {
try {
const response = await fetch('/api/tiers');
if (response.ok) {
const data = await response.json();
setTiers(data);
} else {
console.error('failed to fetch tiers');
}
} catch (error) {
console.error('Error fetching users:', error);
}
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get('id');
const galleryResponse = await fetch(`/api/galleries/admin/${id}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const galleryData = await galleryResponse.json();
setGallery(galleryData.gallery);
const filesResponse = await fetch(`/api/galleries/${id}/images/names`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const filesData = await filesResponse.json();
setFileNames(filesData);
setNsfw(galleryData.gallery.nsfw);
setTags(galleryData.gallery.tags);
setTier(galleryData.gallery.tier);
setGalleryName(galleryData.gallery.name);
if(originalName === ''){
setOriginalGalleryName(galleryData.gallery.name);
}
const imagesResponse = await fetch('/api/galleries/' + galleryData.gallery.name+ '/images');
const imagesUrls = await imagesResponse.json() as string[];
setImages(imagesUrls);
}
useEffect(() => {
getData();
}, []);
useEffect(() => {
}, [gallery]);
useEffect(() => {
}, [gallery, ]);
useEffect(() => {
}, [ nsfw ]);
useEffect(() => {
}, [tags ]);
useEffect(() => {
}, [galleryName]);
useEffect(() => {
}, [ tier]);
const updateGallery = async () => {
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get('id');
const formData = new FormData();
formData.append('id', gallery.name);
formData.append('name', galleryName);
formData.append('thumbnail', thumbnail ?? '');
formData.append('originalName', originalName);
formData.append('tags', JSON.stringify(selectedTags));
formData.append('nsfw', nsfw.toString());
formData.append('tier', tier);
const response = await fetch(`/api/galleries/admin/${originalName}`, {
method: 'PUT',
body: formData
});
if (response.ok) {
console.log(response)
const data = await response.json();
} else {
console.log(response)
}
if(originalName != galleryName){
router.push(`/gallery/admin/view?id=${galleryName}`)
}
else{
window.location.reload();
}
}
const deleteGallery = async () => {
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get('id');
const response = await fetch(`/api/gallery/admin/${gallery.name}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
router.push("/gallery/admin");
} else {
console.log(response)
}
}
const tierObj = tiers.find((tier) => tier.name == gallery.tier);
const subscriptionColor = tier ? tierObj.color : null;
return (
<div className="w-full p-8 h-screen text-white flex justify-center items-center animate-in">
<div className="w-full lg:w-1/2 rounded-md p-12 mt-14 ">
<div className="w-full lg:pt-0 pt-32 flex pb-60 justify-center"> {/* Center the gallery thumbnail */}
{gallery != null && (
<GalleryThumbnail
key={"galleryThumbnail"+galleryName+"-"+tags.join("")}
id={originalName}
columns={3}
onSelect={function (id: string, columns: number): void { setOpen(true) }}
title={galleryName}
subscription={tier}
tags={tags}
subscriptionColor={subscriptionColor}
showNsfw={false}
nsfw={nsfw}
></GalleryThumbnail>
)}
</div>
<div className="w-full opacity-90 backdrop-blur-lg bg-primary shadow-lg p-8 pb-0 rounded">
<span className="text-2xl">Editing Gallery</span>
<div className="w-full flex justify-end">
<div className="w-1/2 flex">
<input
type="text"
className="mb-8 mr-2 rounded-md bg-secondary p-2 w-full text-white"
placeholder="Gallery Name"
value={galleryName}
onChange={(e) => setGalleryName(e.target.value)}
/>
</div>
<div className="w-1/2 flex">
<button
onClick={() => deleteGallery()}
className="h-10 text-center w-full bg-error hover:bg-error-light text-white rounded-md p-2 flex items-center justify-center"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5}
stroke="currentColor" className="md:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
<span className="md:block hidden">Delete</span>
</button>
<button
onClick={() => (router.push("/gallery/admin"))}
className="h-10 w-full bg-error-dark hover:bg-error text-white rounded-md p-2 ml-2 flex items-center justify-center"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5}
stroke="currentColor" className="md:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
</svg>
<span className="md:block hidden">Back</span>
</button>
<button onClick={()=>{updateGallery()}} className="h-10 w-full bg-warning hover:bg-warning-light text-white rounded-md p-2 ml-2">
<span>Update</span>
</button>
</div>
</div>
</div>
<div className="w-full lg:flex opacity-90 backdrop-blur-lg bg-primary shadow-lg p-8 pt-0 rounded">
<div className="w-full lg:w-1/2 mr-44">
<div className="w-1/2 fixed mr-8">
{gallery &&(
<SearchInput
placeholderTags={[
{ value: "tags", label: "❗️ click here to add tags" },
]}
startingTags={gallery.tags}
nsfwButtonEnabled={true}
searchChanged={(search) => {}}
nsfwChanged={(nsfw) => {}}
tagsChanged={(tags) => { setSelectedTags(tags) }}
/>
)}
</div>
</div>
<div className="w-full lg:w-1/2 pt-4">
{gallery != null && (<>
<select value={nsfw ? "NSFW" : "SFW"} className="mb-2 shadow-lg rounded-md bg-secondary p-2 w-full text-white" onChange={e=>{
setNsfw(e.target.value == "NSFW");
}}>
<option value="" disabled >Set NSFW</option>
<option value="NSFW" selected={nsfw}>NSFW</option>
<option value="SFW" selected={!nsfw}>SFW</option>
</select>
<select onChange={e=>{
setTier(e.target.value);
}} className="mb-2 shadow-lg mr-2 rounded-md bg-secondary p-2 w-full text-white">
<option value="" disabled >Select New Tier</option>
{tiers.map((tier, index) => (
<option selected={tier.name==gallery.tier} key={index} value={tier.name}>{tier.name}</option>
))}
</select>
<select onChange={e=>{setThumbnail(e.target.value)}} className="mb-2 shadow-lg mr-2 rounded-md bg-secondary p-2 w-full text-white">
<option value="" disabled selected>Select New Thumbnail</option>
{fileNames.map((name, index) => (
<option selected={name==gallery.thumbnail_file} key={index} value={name}>{name}</option>
))}
</select>
</>
)}
</div>
</div>
{(open) && (
<>
{/*
This is the modal for holding the gallery
*/}
<div
className={`fixed inset-0 transition-opacity z-30 animate-in`}
aria-hidden="true"
>
<div
className="absolute w-full h-full inset-0 bg-secondary-dark opacity-70 z-30"
onClick={() => setOpen(true)}
></div>
<div className="absolute inset-0 overflow-y-auto overflow-x-hidden no-scrollbar pt-2 w-full p-20 h-full z-30">
<Gallery
id={gallery.name}
columns={3}
closeMenu={() => setOpen(false)}
></Gallery>
</div>
</div>
</>
)}
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,56 +1,200 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import { redirect } from "next/navigation";
import GalleryThumbnail from "@/components/ui/gallery_thumbnail";
import React, { useState, useEffect } from 'react';
import Search from "@/components/neroshitron/search";
import Gallery from "@/components/neroshitron/gallery";
import Link from "next/link";
import { User } from "@supabase/supabase-js";
import Gallery from "@/components/ui/gallery";
function PageComponent() {
const [selectedGallery, setSelectedGallery] = useState<string | null>(null);
const supabase = createClient();
const getData = async () => {
const [showNSFW, setShowNSFW] = useState<boolean>(true);
const [randomIds, setRandomIds] = useState<string[]>([]); // replace any with your gallery type
const [isOpen, setIsOpen] = useState<boolean>(false);
const [galleries, setGalleries] = useState<any[]>([]); // replace any with your gallery type
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [selectedGallery, setSelectedGallery] = useState<string | null>(null);
const [tags, setTags] = useState<any[]>([]);
const [search, setSearch] = useState<string>('');
const [galleryColumns, setColumns] = useState<number>(0);
const [selectedTags, setSelectedTags] = useState<number[]>([]);
const generateRandomString = function (length: number) {
let result = '';
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
const selectGallery = (gallery: string, columns: number) => {
setRandomIds([generateRandomString(3), generateRandomString(3), generateRandomString(3), generateRandomString(3)]);
setSelectedGallery(gallery);
setColumns(columns);
setIsOpen(true);
};
const closeGallery = () => {
setSelectedGallery(null);
setColumns(0);
setIsOpen(false);
}
const getData = async () => {
let { data: { user } } = await supabase.auth.getUser();
const galleriesResponse = await fetch(`/api/galleries?search=` + search + '&nsfw=' + showNSFW, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ tags: selectedTags })
});
//console.log(galleriesResponse)
const galleriesData = await galleriesResponse.json();
const tagsResponse = await fetch(`/api/galleries/tags`);
const tagsData = await tagsResponse.json();
setGalleries(galleriesData);
setTags(tagsData);
setUser(user);
setLoading(false);
}
useEffect(() => {
getData();
}, [selectedGallery]);
const closeGallery = () => {
setSelectedGallery(null);
}
}, [selectedTags, search, showNSFW]);
const handleTagClick = (tag: number) => {
if (selectedTags.includes(tag)) {
setSelectedTags(selectedTags.filter((selectedTag) => selectedTag !== tag));
} else {
setSelectedTags([...selectedTags, tag]);
}
//console.log(selectedTags)
};
return (
<div className="w-full">
<div className="w-2/4">
<Search gallerySelected={(gallery:string)=>{setSelectedGallery(gallery)}}/>
<div>
<div className="fixed w-full h-full overflow-hidden z-0 animate-fade-left animate-fade-left animate-once animate-duration-[2000ms] animate-normal animate-fill-forwards">
<img
src="gallery_girl.png"
className="float-right object-cover h-screen w-6/6 md:w-5/6 lg:w-3/6 opacity-50 overflow-hidden"
alt="Background"
/>
</div>
{selectedGallery!=null ? (
<>
{/*
This is the modal for holding the gallery
*/}
<div
className={`fixed inset-0 transition-opacity z-30 animate-in`}
aria-hidden="true"
>
<div
className="absolute inset-0 bg-secondary-dark opacity-70 z-30"
onClick={() => closeGallery()}
></div>
<div className="absolute inset-0 overflow-y-auto overflow-x-hidden no-scrollbar pt-2 w-full p-20 z-30">
<Gallery
id={selectedGallery as string}
columns={3}
closeMenu={() => closeGallery()}
></Gallery>
</div>
</div>
</>
) : null}
{/*
THIS IS THE SEARCH BAR AND TAGS SECTION
THIS IS THE SEARCH BAR AND TAGS SECTION
THIS IS THE SEARCH BAR AND TAGS SECTION
THIS IS THE SEARCH BAR AND TAGS SECTION
THIS IS THE SEARCH BAR AND TAGS SECTION
THIS IS THE SEARCH BAR AND TAGS SECTION
*/}
<section className="flex items-center w-full p-8 pt-20 opacity-90 animate-jump-in animate-once animate-duration-500">
{(tags.length > 0) ? (
<div className="container mx-auto py-8">
<div className="relative w-full mx-auto">
<input
className="w-full text-neroshi-blue-950 h-16 px-3 rounded mb-8 focus:outline-none focus:shadow-outline text-xl px-8 shadow-lg"
type="search"
placeholder="Search by title..."
onChange={(e) => setSearch(e.target.value)}
style={{
animation: 'expandFromLeft 2s ease-out forwards',
paddingRight: '2rem', // make room for the checkbox
}}
/>
<label htmlFor="toggleNSFW" className="absolute right-0 top-0 h-full mr-2 flex items-center text-neroshi-blue-950 animate-fade animate-once animate-duration-500 animate-delay-[2000ms] animate-ease-out">
Censor NSFW
<input
id="toggleNSFW"
type="checkbox"
checked={showNSFW}
onChange={() => setShowNSFW(!showNSFW)}
className="form-checkbox h-5 w-5 text-neroshi-blue-950 ml-2 "
/>
</label>
</div>
{(tags.length > 0) ? (
<nav className="grid grid-cols-4 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10 gap-4 justify-items-center">
{tags.map((tag, index) => (
<a
key={index}
className={`w-full rounded-lg no-underline text-white py-3 px-4 font-medium text-center animate-jump-in animate-once animate-duration-500 animate-ease-out ${selectedTags.includes(tag.name) ? 'bg-neroshi-blue-950 hover:bg-neroshi-blue-900' : 'bg-neroshi-blue-800 hover:bg-neroshi-blue-700'
}`}
href="#"
onClick={() => handleTagClick(tag.name)}
>
{tag.name}
</a>
))}
</nav>
) : (
<div className="flex justify-center">
<p className="text-white">Loading Tags...</p>
</div>
)}
</div>
) : (
<div className="animate-pulse bg-neroshi-blue-950 rounded-3xl w-full p-8 mt-10 h-48" ></div>
)}
</section>
{/*
These are the thumbnails for the gallery below the search bar
*/}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-60 gap-x-5 h-full mb-96 animate-in">
{galleries && galleries.map((gallery, index) => (
<div className="mx-auto">
<GalleryThumbnail
key={gallery.name + " " + showNSFW}
id={gallery.name}
title={gallery.name}
tags={gallery.tags}
columns={gallery.columns}
showNsfw={showNSFW}
subscription={gallery.tier as string}
onSelect={selectGallery}
nsfw={gallery.nsfw}
></GalleryThumbnail>
</div>
))}
</div>
{isOpen ? (
<>
{/*
This is the modal for holding the gallery
*/}
<div
className={`fixed inset-0 transition-opacity z-30 ${isOpen ? 'animate-in' : 'fade-out'
}`}
aria-hidden="true"
>
<div
className="absolute inset-0 bg-neroshi-blue-900 opacity-70 z-30"
onClick={() => setIsOpen(false)}
></div>
<div className="absolute inset-0 overflow-y-auto overflow-x-hidden no-scrollbar pt-2 w-full p-20 z-30">
<Gallery
id={selectedGallery as string}
columns={galleryColumns}
closeMenu={() => closeGallery()}
></Gallery>
</div>
</div>
</>
) : null}
</div>
);
}

View File

@ -16,7 +16,23 @@
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.my-masonry-grid {
display: -webkit-box; /* Not needed if autoprefixing */
display: -ms-flexbox; /* Not needed if autoprefixing */
display: flex;
margin-left: -30px; /* gutter size offset */
width: auto;
}
.my-masonry-grid_column {
padding-left: 30px; /* gutter size */
background-clip: padding-box;
}
/* Style your items */
.my-masonry-grid_column > div { /* change div to reference your elements you put in <Masonry> */
background: grey;
margin-bottom: 30px;
}
/* Hide scrollbar for IE, Edge and Firefox */
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
@ -47,22 +63,10 @@
}
}
.my-masonry-grid {
display: -webkit-box; /* Not needed if autoprefixing */
display: -ms-flexbox; /* Not needed if autoprefixing */
display: flex;
margin-left: -30px; /* gutter size offset */
width: auto;
}
.my-masonry-grid_column {
padding-left: 30px; /* gutter size */
background-clip: padding-box;
}
/* Style your items */
.my-masonry-grid_column > div { /* change div to reference your elements you put in <Masonry> */
background: grey;
margin-bottom: 30px;
@layer base {
* {
@apply border-foreground/20;
}
}
.animate-in {
@ -79,33 +83,3 @@
transform: translateY(0);
}
}
button:disabled {
filter: grayscale(50%);
}
:root {
--color-primary: #201240;
--color-primary-light: #403260;
--color-primary-dark: #100120;
--color-secondary: #4F3D70;
--color-secondary-light: #6F5D90;
--color-secondary-dark: #2F1D50;
--color-error: #862117;
--color-error-light: #C44C4C;
--color-error-dark: #5C0D0D;
--color-success: #00C9A6;
--color-success-light: #20E9C6;
--color-success-dark: #00A986;
--color-warning: #E17558;
--color-warning-light: #E39578;
--color-warning-dark: #C15538;
--color-info: #222140;
--color-info-light: #424260;
--color-info-dark: #020120;
}

View File

@ -1,11 +1,7 @@
import { GeistSans } from "geist/font/sans";
import "./globals.css";
import { createClient } from "@/utils/supabase/client";
import NavigationBar from "@/components/neroshitron/navigation_bar";
import { SpeedInsights } from "@vercel/speed-insights/next"
import { Analytics } from "@vercel/analytics/react"
import RightHandLayoutImage from "@/components/neroshitron/right_hand_layout_image";
import Theme from "@/components/theme";
import NavigationBar from "@/components/NavigationBar";
const defaultUrl = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "http://localhost:3000";
@ -16,10 +12,6 @@ export const metadata = {
description: "The fastest way to build apps with Next.js and Supabase",
};
const supabase = createClient();
export default function RootLayout({
children,
}: {
@ -28,14 +20,10 @@ export default function RootLayout({
return (
<html lang="en" className={GeistSans.className}>
<body className="bg-background text-foreground">
<Theme/>
<RightHandLayoutImage/>
<div className="w-full fixed z-30 text-white white">
<NavigationBar/>
<SpeedInsights/>
<Analytics/>
</div>
<main className="min-h-screen flex flex-col items-center bg-gradient-to-r from-primary to-secondary overflow-hidden">
<main className="min-h-screen flex flex-col items-center bg-gradient-to-r from-neroshi-blue-900 to-neroshi-blue-950 overflow-hidden">
{children}
</main>
</body>

View File

@ -30,6 +30,7 @@ export default async function Login({
password,
});
//console.log(error);
if (error) {
return redirect("/login?message=Could not authenticate user");
}
@ -53,6 +54,7 @@ export default async function Login({
},
});
//console.log(error);
if (error) {
return redirect("/login?message=Could not authenticate user");
}
@ -64,11 +66,11 @@ export default async function Login({
<div className="flex-1 w-full flex flex-col gap-20 items-center animate-in"> <div className="flex-1 flex flex-col w-full px-8 sm:max-w-md justify-center gap-2">
<form className="animate-in flex-1 flex flex-col w-full my-32 gap-2 text-white">
<form className="animate-in flex-1 flex flex-col w-full my-32 gap-2 text-foreground">
<Link
href="/"
className="absolute left-1 top-44 py-2 px-4 rounded-md no-underline text-white flex items-center group text-sm"
className="absolute left-1 top-44 py-2 px-4 rounded-md no-underline text-foreground flex items-center group text-sm"
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -87,36 +89,36 @@ export default async function Login({
Back
</Link>
<input
className="rounded-md px-4 py-2 bg-inherit border mb-2 mx-1 w-full sm:w-auto"
className="rounded-md px-4 py-2 bg-inherit border mb-2 mx-1"
name="email"
placeholder="Email Address"
required
/>
<input
className="rounded-md px-4 py-2 bg-inherit border mb-2 mx-1 w-full sm:w-auto"
className="rounded-md px-4 py-2 bg-inherit border mb-2 mx-1"
type="password"
name="password"
placeholder="Password "
required
/>
<div className="flex text-white white">
<div className="flex">
<SubmitButton
formAction={signIn}
className="bg-success hover:bg-success-light rounded-md px-4 py-2 text-white mb-2 mx-1 w-1/2"
className="bg-neroshi-blue-500 hover:bg-neroshi-blue-400 rounded-md px-4 py-2 text-foreground mb-2 mx-1 w-1/2"
pendingText="Signing In..."
>
Sign In
</SubmitButton>
<SubmitButton
formAction={signUp}
className="bg-info hover:bg-info-light border border-foreground/20 rounded-md px-4 py-2 text-white mb-2 mx-1 w-1/2"
className="bg-neroshi-blue-300 hover:bg-neroshi-blue-200 border border-foreground/20 rounded-md px-4 py-2 text-foreground mb-2 mx-1 w-1/2"
pendingText="Signing Up..."
>
Sign Up
</SubmitButton>
</div>
{searchParams?.message && (
<p className="mt-4 bg-foreground/10 mt-14 p-2 text-white text-center">
<p className="mt-4 bg-foreground/10 mt-14 p-2 text-foreground text-center">
{searchParams.message}
</p>
)}

View File

@ -1,12 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
export function middleware(req:NextRequest, res:NextResponse) {
const requestHeaders = new Headers(req.headers)
requestHeaders.set('x-path', req.nextUrl.pathname)
return NextResponse.next({
request: {
headers: requestHeaders
}
})
}

View File

@ -0,0 +1,154 @@
import { createClient } from "@/utils/supabase/server";
import Link from "next/link";
import { redirect } from "next/navigation";
import crypto from 'crypto';
export default async function AuthButton() {
const supabase = createClient();
const {
data: { user },
} = await supabase.auth.getUser();
const signOut = async () => {
"use server";
const supabase = createClient();
await supabase.auth.signOut();
return redirect("/login");
};
if(user){
let email = user.email;
if(email != null){
const emailHash = crypto.createHash('md5').update(email.trim().toLowerCase()).digest('hex');
const gravatarUrl = `https://www.gravatar.com/avatar/${emailHash}`;
return(
<div className="flex justify-center items-center pt-2 ">
<nav className="w-auto bg-neroshi-blue-300 bg-opacity-10 flex justify-center z-10 h-16 animate-in rounded-3xl" style={{ backdropFilter: 'blur(10px)' }}>
<div className="w-full max-w-2xl flex justify-between items-center p-3 text-sm">
<div className="flex items-center gap-2 z-10">
<Link
href="/gallery"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
</svg>
<span className="hidden lg:block">Gallery</span>
</Link>
<Link
href="/livestream"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" />
</svg>
<span className="hidden lg:block">Livestream</span>
</Link>
<Link
href="/commissions"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 10.5V6a3.75 3.75 0 1 0-7.5 0v4.5m11.356-1.993 1.263 12c.07.665-.45 1.243-1.119 1.243H4.25a1.125 1.125 0 0 1-1.12-1.243l1.264-12A1.125 1.125 0 0 1 5.513 7.5h12.974c.576 0 1.059.435 1.119 1.007ZM8.625 10.5a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm7.5 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
</svg>
<span className="hidden lg:block">Commissions</span>
</Link>
<Link
href="/subscriptions"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
<span className="hidden lg:block">Subscription</span>
</Link>
</div>
<div className="flex items-center gap-2">
<form action={signOut}>
<button className="py-2 px-4 ml-2 rounded-3xl no-underline bg-pink-950 hover:bg-pink-900">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="lg:hidden block size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15M12 9l-3 3m0 0 3 3m-3-3h12.75" />
</svg>
<span className="hidden lg:block">Logout</span>
</button>
</form>
<img src={gravatarUrl} alt="Profile" className="w-10 h-10 object-cover rounded-full cursor-pointer" />
</div>
</div>
</nav>
</div>)
}
}
else{
return( <div className="flex justify-center items-center pt-2 ">
<nav className="w-auto bg-neroshi-blue-300 bg-opacity-10 flex justify-center h-16 animate-in rounded-3xl" style={{ backdropFilter: 'blur(10px)' }}>
<div className="w-full max-w-2xl flex justify-between items-center p-3 text-sm">
<div className="flex items-center gap-2 ">
<Link
href="/gallery"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
</svg>
<span className="hidden lg:block">Gallery</span>
</Link>
<Link
href="/livestream"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" />
</svg>
<span className="hidden lg:block">Livestream</span>
</Link>
<Link
href="/commissions"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 10.5V6a3.75 3.75 0 1 0-7.5 0v4.5m11.356-1.993 1.263 12c.07.665-.45 1.243-1.119 1.243H4.25a1.125 1.125 0 0 1-1.12-1.243l1.264-12A1.125 1.125 0 0 1 5.513 7.5h12.974c.576 0 1.059.435 1.119 1.007ZM8.625 10.5a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm7.5 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
</svg>
<span className="hidden lg:block">Commissions</span>
</Link>
<Link
href="/subscriptions"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
<span className="hidden lg:block">Subscription</span>
</Link>
</div>
<div className="flex items-center gap-2">
<Link
href="/login"
className="py-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 md:hidden">
<path strokeLinecap="round" strokeLinejoin="round" d="M13.5 10.5V6.75a4.5 4.5 0 1 1 9 0v3.75M3.75 21.75h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H3.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" />
</svg>
<span className="hidden lg:block">Login</span>
</Link>
<Link
href="/login"
className="hidden lg:blockpy-2 px-3 flex rounded-3xl no-underline bg-neroshi-blue-900 hover:bg-neroshi-blue-800"
>
<span className="">Signup</span>
</Link>
</div>
</div>
</nav>
</div>)
}
}

View File

@ -1,81 +0,0 @@
"use client;"
import React, { useState, useEffect } from 'react';
import GalleryThumbnail from './gallery_thumbnail';
interface TagProps {
nsfw: boolean;
tags: string[];
search: string;
gallerySelected: (gallery: string) => void;
}
const Galleries = ({ nsfw, tags, search, gallerySelected }: TagProps) => {
const [galleries, setGalleries] = useState([]);
const [nsfwState, setNsfwState] = useState<boolean>(nsfw);
const [tagsState, setTagsState] = useState<string[]>(tags);
const [searchState, setSearchState] = useState<string>(search);
const [selectedGallery, setSelectedGallery] = useState<string | null>(null);
const [tiers, setTiers] = useState<any[]>([]);
const selectGallery = (gallery: string) => {
setSelectedGallery(gallery);
gallerySelected(gallery);
};
const getData = async () => {
try {
const response = await fetch('/api/tiers');
if (response.ok) {
const data = await response.json();
setTiers(data);
} else {
console.error('failed to fetch tiers');
}
} catch (error) {
console.error('Error fetching users:', error);
}
const galleriesResponse = await fetch(`/api/galleries?search=` + searchState + '&nsfw=' + nsfwState, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ tags: tagsState })
});
const galleriesData = await galleriesResponse.json();
setGalleries(galleriesData);
}
useEffect(() => {
getData();
}, [tagsState]);
return (
<div className="absolute inset-0 mx-auto ml-16 md:ml-0 pt-48 p-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-y-48 gap-x-4 animate-in overflow-y-scroll no-scrollbar z-0">
{galleries && galleries.map((gallery: any, index) => {
const tier = tiers.find((tier) => tier.name == gallery.tier);
const subscriptionColor = tier ? tier.color : null;
return (
<GalleryThumbnail
key={gallery.name + " " + nsfw}
id={gallery.name}
title={gallery.name}
tags={gallery.tags}
columns={gallery.columns}
showNsfw={nsfw}
subscription={gallery.tier as string}
subscriptionColor={subscriptionColor}
onSelect={selectGallery}
nsfw={gallery.nsfw}
></GalleryThumbnail>
);
})}
</div>
);
};
export default Galleries;

View File

@ -1,149 +0,0 @@
import { createClient } from "@/utils/supabase/server";
import Link from "next/link";
import { redirect, useRouter } from "next/navigation";
import crypto from 'crypto';
import { headers } from "next/headers";
export default async function AuthButton() {
const supabase = createClient();
const {
data: { user },
} = await supabase.auth.getUser();
const signOut = async () => {
"use server";
const supabase = createClient();
await supabase.auth.signOut();
return redirect("/login");
};
const heads = headers()
const currentPage = heads.get('x-path')
const getGravatarUrl = () => {
if (user == null) {
return;
}
let email = user.email;
if (email != null) {
const emailHash = crypto.createHash('md5').update(email.trim().toLowerCase()).digest('hex');
return `https://www.gravatar.com/avatar/${emailHash}`;
}
return "";
}
const url = getGravatarUrl();
const admins = await supabase.from('admins').select('user_id');
let isAdmin = false;
if(!admins.error) {
for (const admin of admins.data) {
if (admin.user_id == user?.id) {
isAdmin = true;
break;
}
}
}
return (
<div className="flex justify-center items-center pt-2 ">
<nav className="w-auto bg-primary bg-opacity-40 flex justify-center z-10 h-16 animate-in rounded-md shadow-lg" style={{ backdropFilter: 'blur(10px)' }}>
<div className="w-auto flex justify-between items-center p-3 text-sm">
<div className="flex items-center gap-2 z-10">
{/* This is admin stuff */}
{(isAdmin) && (
<>
<Link
href="/gallery/admin/"
className={`py-2 px-3 w-38 text-center flex rounded-md no-underline bg-secondary hover:bg-secondary-light`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="lg:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M11.42 15.17 17.25 21A2.652 2.652 0 0 0 21 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 1 1-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 0 0 4.486-6.336l-3.276 3.277a3.004 3.004 0 0 1-2.25-2.25l3.276-3.276a4.5 4.5 0 0 0-6.336 4.486c.091 1.076-.071 2.264-.904 2.95l-.102.085m-1.745 1.437L5.909 7.5H4.5L2.25 3.75l1.5-1.5L7.5 4.5v1.409l4.26 4.26m-1.745 1.437 1.745-1.437m6.615 8.206L15.75 15.75M4.867 19.125h.008v.008h-.008v-.008Z" />
</svg>
<span className="hidden lg:block">Gallery Admin</span>
</Link>
<Link
href="/admin/"
className={`py-2 px-3 w-38 text-center flex rounded-md no-underline bg-secondary hover:bg-secondary-light`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="lg:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
<path strokeLinecap="round" strokeLinejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
<span className="hidden lg:block">System Settings</span>
</Link>
</>
)}
<Link
href="/gallery"
className={`py-2 px-3 flex rounded-md no-underline ${currentPage!="gallery" ? 'bg-primary hover:bg-primary-light' : 'bg-secondary hover:bg-secondary-light'}`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
</svg>
<span className="hidden lg:block">Gallery</span>
</Link>
<Link
href="/livestream"
className={`py-2 px-3 flex rounded-md no-underline ${currentPage!="livestream" ? 'bg-primary hover:bg-primary-light' : 'bg-secondary hover:bg-secondary-light'}`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" />
</svg>
<span className="hidden lg:block">Livestream</span>
</Link>
<Link
href="/commissions"
className={`py-2 px-3 flex rounded-md no-underline ${currentPage!="commissions" ? 'bg-primary hover:bg-primary-light' : 'bg-secondary hover:bg-secondary-light'}`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 10.5V6a3.75 3.75 0 1 0-7.5 0v4.5m11.356-1.993 1.263 12c.07.665-.45 1.243-1.119 1.243H4.25a1.125 1.125 0 0 1-1.12-1.243l1.264-12A1.125 1.125 0 0 1 5.513 7.5h12.974c.576 0 1.059.435 1.119 1.007ZM8.625 10.5a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm7.5 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
</svg>
<span className="hidden lg:block">Commissions</span>
</Link>
<Link
href="/subscriptions"
className={`py-2 px-3 flex rounded-md no-underline ${currentPage!="subscriptions" ? 'bg-primary hover:bg-primary-light' : 'bg-secondary hover:bg-secondary-light'}`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
<span className="hidden lg:block">Subscription</span>
</Link>
</div>
<div className="flex items-center gap-2">
{(user != null) ? (
<>
<form action={signOut}>
<button className="py-2 px-4 ml-2 rounded-md no-underline bg-error hover:bg-error-light">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden ">
<path strokeLinecap="round" strokeLinejoin="round" d="M13.5 10.5V6.75a4.5 4.5 0 1 1 9 0v3.75M3.75 21.75h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H3.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" />
</svg>
<span className="hidden lg:block">Logout</span>
</button>
</form>
<a href="https://gravatar.com/" target="_blank">
<img src={url} alt="Profile" className="w-10 h-10 object-cover rounded-full cursor-pointer" />
</a>
</>
) : (
<Link
href="/subscriptions"
className={`ml-2 py-2 px-3 flex rounded-md no-underline bg-success hover:bg-success-light`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6 lg:hidden block">
<path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
<span className="hidden lg:block">Login</span>
</Link>
)}
</div>
</div>
</nav>
</div>)
}

View File

@ -1,16 +0,0 @@
"use client;"
import React from 'react';
const RightHandLayoutImage: React.FC = () => {
return (
<div className="fixed w-full h-full overflow-hidden z-0 animate-fade-left animate-once animate-duration-[2000ms] animate-normal animate-fill-forwards">
<img
src="/gallery_girl.png"
className="float-right object-cover h-screen w-full lg:w-5/6 xl:w-3/6 opacity-50 overflow-hidden"
alt="Background"
/>
</div>
);
};
export default RightHandLayoutImage;

View File

@ -1,60 +0,0 @@
"use client;"
import React, { useState, useEffect } from 'react';
import SearchInput from '@/components/neroshitron/search_input';
import Galleries from './galleries';
interface SearchProps {
gallerySelected: (gallery: string) => void;
}
const Search = ({ gallerySelected }: SearchProps) => {
const [tags, setTags] = useState<string[]>([]);
const [search, setSearch] = useState<string>('');
const [nsfw, setNsfw] = useState<boolean>(false);
const [gallery, setGallery] = useState<string | null>(null);
const getData = async () => {
}
useEffect(() => {
getData();
}, [search]);
useEffect(() => {
getData();
}, [nsfw]);
useEffect(() => {
getData();
}, [tags]);
useEffect(() => {
getData();
if (gallery != null)
gallerySelected(gallery);
}, [gallery]);
//TRY TESTING WITH THIS REMOVED!
useEffect(() => {
getData();
}, []);
return (
<>
<Galleries gallerySelected={(gallery: string) => { setGallery(gallery) }} key={search + "-" + tags.length + "-" + nsfw} search={search} nsfw={nsfw} tags={tags} />
<section className="fixed flex items-center w-full p-8 pt-20 opacity-90 animate-in animate-once animate-duration-500">
<div className="container mx-auto py-8">
<SearchInput
startingTags={[]}
placeholderTags={[
{ value: "neroshi", label: "🧑‍🎨 neroshi" },
{ value: "neroshi", label: "❗️ click here for tags to search!" },
]} nsfwButtonEnabled={true} searchChanged={(search) => { setSearch(search) }} nsfwChanged={(nsfw) => { setNsfw(nsfw) }} tagsChanged={(tags) => { setTags(tags); }} />
</div>
</section>
</>
);
};
export default Search;

View File

@ -1,190 +0,0 @@
"use client;"
import React, { useState, useEffect, useRef, forwardRef } from 'react';
import TagSelector from '../neroshitron/tag_selector';
import Select from "react-tailwindcss-select";
import { SelectValue } from 'react-tailwindcss-select/dist/components/type';
import { Option } from 'react-tailwindcss-select/dist/components/type';
interface SearchInputProps {
tagsChanged: (tags: string[]) => void;
searchChanged: (search: string) => void;
nsfwChanged: (nsfw: boolean) => void;
nsfwButtonEnabled: boolean | null;
placeholderTags: Option[];
startingTags: string[] | null;
}
const SearchInput = ({ tagsChanged, searchChanged, nsfwChanged, nsfwButtonEnabled, placeholderTags, startingTags }: SearchInputProps) => {
const [tagSearch, setTagSearch] = useState<string>('');
const [nsfw, setNsfw] = useState<boolean>(false);
const [selectedTags, setSelectedTags] = useState<string[]>(startingTags ?? []);
const [selectedTagsInput, setSelectedTagsInput] = useState<Option[]>([...placeholderTags, ...(startingTags ?? []).map((tag) => ({ value: tag, label: tag }))]);
const [selectingTags, setSelectingTags] = useState<boolean>(false);
const tagSelectorRef = React.useRef(null);
const [tags, setTags] = useState<any[]>([]);
const getData = async () => {
const tagsResponse = await fetch(`/api/galleries/tags`);
const tagsData = await tagsResponse.json();
setTags(tagsData);
}
const updateTags = (newTags: string[]) => {
setSelectedTags(newTags)
}
const onTagsClosed = (tags: string[]) => {
setSelectingTags(false);
}
const openTags = () => {
setSelectingTags(true);
if (selectingTags) {
onTagsClosed(selectedTags);
}
}
useEffect(() => {
tagsChanged(selectedTags.filter(tag => tag != "neroshi"));
}, [selectedTags]);
useEffect(() => {
nsfwChanged(nsfw);
}, [nsfw]);
useEffect(() => {
getData();
}, []);
const [color, setColor] = useState('black');
const selectRef = useRef(null);
const [currentTag, setCurrentTag] = useState<string>('');
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'ArrowUp') {
const currentIndex = tags.findIndex(tag => tag.name === currentTag);
const newIndex = currentIndex === 0 ? tags.length - 1 : currentIndex - 1;
setCurrentTag(tags[newIndex].name);
} else if (event.key === 'ArrowDown') {
const currentIndex = tags.findIndex(tag => tag.name === currentTag);
const newIndex = currentIndex === tags.length - 1 ? 0 : currentIndex + 1;
setCurrentTag(tags[newIndex].name);
} else if (event.key === 'Enter') {
const currentIndex = tags.findIndex(tag => tag.name === currentTag);
if (currentIndex !== -1 && !selectedTags.includes(tags[currentIndex].name)) {
setSelectedTags([...selectedTags, tags[currentIndex].name]);
const tagsInput = selectedTagsInput;
tagsInput.push({ value: tags[currentIndex].name, label: tags[currentIndex].name });
setSelectedTagsInput(tagsInput);
setCurrentTag('');
}
}
};
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [currentTag, tags]);
const tagOptions = tags.map((tag: { name: string; }) => ({ value: tag.name, label: tag.name }));
return (
<>
<div className={` opacity 0 relative w-full flex flex-col items-center justify-center z-10`}>
<div className="search-box mx-auto my-auto w-full">
<div className={`flex flex-row`}>
{(selectingTags) ? (
<>
<input autoFocus value={tagSearch} onChange={(e) => setTagSearch(e.target.value)} className="rounded-l-md h-16 bg-gray-100 text-grey-darker py-2 font-normal text-grey-darkest border border-gray-100 font-bold w-full py-1 px-2 outline-none text-lg text-gray-600" type="text" placeholder="Looking for specific tag?" />
<span className="flex items-center bg-gray-100 rounded rounded-l-none border-0 px-3 font-bold text-grey-100">
<button key="back" onClick={() => { openTags() }} type="button" className={`animate-in bg-pink-900 hover:bg-pink-800 text-lg text-white font-bold py-3 px-6 rounded`}>
Back
</button>
</span>
</>
)
: (
<>
<div className="w-full top-0">
<Select isMultiple isSearchable isClearable searchInputPlaceholder='Start typing to search tags...'
options={tagOptions}
placeholder="Select tags for your search"
onChange={(value: Option | Option[] | null) => {
if (value === null) {
setSelectedTags([]);
setSelectedTagsInput([]);
}
if (Array.isArray(value)) {
setSelectedTags(value.map((option) => option.value));
setSelectedTagsInput(value as Option[])
} else if (value) {
setSelectedTags([value.value]);
setSelectedTagsInput([value])
}
if (Array.isArray(value)) {
setSelectedTags(value.map((option) => option.value));
setSelectedTagsInput(value.filter((option) => option.value !== 'placeholder'));
} else if (value) {
setSelectedTags([value.value]);
setSelectedTagsInput([value]);
}
}}
onSearchInputChange={(value) => {
}}
classNames={{
menu: "bg-secondary-dark text-white pb-4 rounded",
searchBox: "rounded-md bg-secondary w-1/2 text-white w-full mt-2 p-2 mb-2 animate-in",
searchIcon: "hidden",
tagItem: (value) => "hover:scale-95 bg-primary-light rounded-md pl-2 p-1 m-1 flex",
tagItemText: "text-white animate-in",
closeIcon: "text-white",
tagItemIconContainer:"animate-in"
}}
formatOptionLabel={data => (
<li key={"tag-" + data.value}
className={`animate-in block transition rounded duration-200 px-2 py-2 cursor-pointer select-none truncate pt-2 bg-primary text-white ${currentTag==data.value ? "bg-primary-light" : ""} hover:bg-primary-light
}`}
>
{data.label}
</li>
)}
value={selectedTagsInput}
primaryColor={"indigo"} />
</div>
{(nsfwButtonEnabled) && (
<span className="w-1/6 border-0 font-bold text-grey-100">
<button
onClick={() => { setNsfw(!nsfw) }}
type="button"
className={`animate-in text-sm text-white font-bold h-full w-16 px-2 rounded rounded-l-none ${nsfw ? "bg-error hover:bg-error-light" : "bg-success hover:bg-success-light"}`}
>
{nsfw ? "NSFW" : "SFW"}
</button>
</span>
)}
</>
)}
</div>
</div>
</div>
{(selectingTags) &&
<TagSelector key={tagSearch} tagSearch={tagSearch} tagsChanged={(newTags: string[]) => { updateTags(newTags) }} selectedTagsInput={selectedTags} ref={tagSelectorRef} />}
</>
);
};
export default SearchInput;

View File

@ -1,20 +0,0 @@
"use client;"
import React, { useState, useEffect } from 'react';
interface TagProps { onTagClicked: (tag: string) => void, selected: boolean, tag: string }
const Tag = ({ onTagClicked, selected, tag, }: TagProps) => {
return (
<button
key={tag}
type="button"
className={`animate-in w-full h-8 rounded-md no-underline text-sm text-white py-1 font-medium text-center ${selected ? 'hover:bg-pink-800 bg-pink-900' : 'hover:bg-pink-600 bg-neroshi-blue-800 border-neroshi-blue-900 border-2'}`}
onClick={() => onTagClicked(tag)}
>
{tag}
</button>
);
};
export default Tag;

View File

@ -1,61 +0,0 @@
"use client;"
import React, { forwardRef, useState, useEffect } from 'react';
import Tag from './tag_pill';
interface TagSelectorProps {
tagSearch: string,
selectedTagsInput: string[],
tagsChanged: (tags: string[]) => void
}
const TagSelector = forwardRef<TagSelectorProps, { tagSearch: string, selectedTagsInput: string[], tagsChanged: (tags: string[]) => void }>((props, ref) => {
const [tags, setTags] = useState<any[]>([]);
const [tagSearch, setTagSearch] = useState<string>(props.tagSearch);
const [selectedTags, setSelectedTags] = useState<string[]>(props.selectedTagsInput);
const handleTag = (tag: string) => {
if (selectedTags.includes(tag)) {
setSelectedTags(selectedTags.filter(t => t !== tag));
} else {
setSelectedTags([...selectedTags, tag]);
}
setTags(selectedTags);
};
const getData = async () => {
const tagsResponse = await fetch(`/api/galleries/tags`);
const tagsData = await tagsResponse.json();
setTags(tagsData);
}
useEffect(() => {
props.tagsChanged(selectedTags);
getData();
}, [selectedTags, tagSearch]);
useEffect(() => {
props.tagsChanged(selectedTags);
getData();
}, [selectedTags, tagSearch]);
useEffect(() => {
getData();
}, []);
return (
<div className="flex md:w-full pt-4 justify-center items-center">
{(tags.length > 0) && (
<div className="z-10 grid p-4 grid-cols-2 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-1 w-full max-h-96 overflow-y-scroll no-scrollbar pt-4 bg-neroshi-blue-900 rounded-md opacity-90 backdrop-filter backdrop-blur-md mx-auto">
{tags.map((tag: any) => (
(tagSearch === '' || tag.name.toLowerCase().includes(tagSearch.toLowerCase())) && // Updated condition
<Tag tag={tag.name} selected={selectedTags.includes(tag.name)} onTagClicked={(tag) => handleTag(tag)} />
))}
</div>
)}
</div>
);
});
export default TagSelector;

View File

@ -1,37 +0,0 @@
"use client";
import { useEffect, useState } from 'react';
import { createClient } from '@/utils/supabase/client';
interface GalleryThumbnailProps {}
const ThemeProvider = ({}: GalleryThumbnailProps) => {
const [data, setData] = useState<any[]>([]); // State to store the fetched data
const getData = async () => {
const supabase = createClient();
const { data, error } = await supabase.from('interface_configurations').select('*');
if (error) {
console.error('Error fetching data:', error);
} else {
setData(data || []);
}
};
useEffect(() => {
getData();
}, []);
useEffect(() => {
// Update variables when data changes
for (const config of data) {
if (config.type === 'color') {
document.documentElement.style.setProperty(`--color-${config.name}`, config.value);
}
}
}, [data]);
return <></>;
};
export default ThemeProvider;

View File

@ -12,11 +12,18 @@ interface GalleryProps {
const Gallery = ({ id, columns, closeMenu }: GalleryProps) => {
const [isSingle, setIsSingle] = useState<boolean>(false);
const [loaded, setLoaded] = useState({})
const [selectedImage, setSelectedImage] = useState<string | null>(null);
const [images, setImages] = useState<string[]>([]);
const [galleryId, setGalleryId] = useState(id as string);
const [currentIndex, setCurrentIndex] = useState(0);
const panZoomRef = useRef<any>(null);
const getData = async () => {
const thumbnailResponse = await fetch('/api/galleries/' + String(galleryId) + '/images');
const thumbnailUrl = await thumbnailResponse.json() as string[];
setImages(thumbnailUrl);
}
const next = () => {
if (currentIndex < images.length - 1) {
@ -34,6 +41,50 @@ const Gallery = ({ id, columns, closeMenu }: GalleryProps) => {
}
}
const renderButtons = () => {
return (
<div className="z-20 bottom-10 fixed pt-4 bg-purple-900 bg-opacity-40 animate-in rounded-2xl" style={{ backdropFilter: 'blur(10px)' }}>
<div className='grid grid-cols-4 pl-4 gap-4 pr-4'>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 bg-neroshi-blue-900 hover:bg-neroshi-blue-800`}
onClick={() => close()}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</button>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 ${!selectedImage ? 'opacity-50 cursor-not-allowed bg-gray-800' : 'bg-pink-700 hover:bg-pink-600'}`}
onClick={() => previous()}
disabled={!selectedImage}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5" />
</svg>
</button>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 ${!selectedImage ? 'opacity-50 cursor-not-allowed bg-gray-800' : 'bg-pink-700 hover:bg-pink-600'}`}
onClick={() => next()}
disabled={!selectedImage}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5" />
</svg>
</button>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 ${!selectedImage ? 'opacity-50 cursor-not-allowed bg-gray-800' : 'bg-purple-700 hover:bg-purple-600'}`}
onClick={() => selectedImage && handleDownload(selectedImage)}
disabled={!selectedImage}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m9 13.5 3 3m0 0 3-3m-3 3v-6m1.06-4.19-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z" />
</svg>
</button>
</div>
</div>
);
};
const handleDownload = (image: string) => {
const link = document.createElement('a');
link.href = image;
@ -44,13 +95,6 @@ const Gallery = ({ id, columns, closeMenu }: GalleryProps) => {
link.click();
document.body.removeChild(link);
};
const getData = async () => {
const thumbnailResponse = await fetch('/api/galleries/' + String(galleryId) + '/images');
const thumbnailUrl = await thumbnailResponse.json() as string[];
setImages(thumbnailUrl);
}
useEffect(() => {
getData();
const handleKeyDown = (event: KeyboardEvent) => {
@ -81,16 +125,30 @@ const Gallery = ({ id, columns, closeMenu }: GalleryProps) => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [selectedImage, currentIndex]);
}, [selectedImage,currentIndex]);
const handleClick = (image: string) => {
setSelectedImage(image);
setCurrentIndex(images.indexOf(image));
};
const resetPanZoom = () => {
panZoomRef.current.autoCenter();
};
const open = () => {
if (selectedImage === null) return;
//console.log(selectedImage)
let base64Image = selectedImage.split(';base64,').pop();
if (!base64Image) return;
let blob = new Blob([Uint8Array.from(atob(base64Image), c => c.charCodeAt(0))], { type: 'image/jpeg' }); // adjust the type as needed
let url = URL.createObjectURL(blob);
window.open(url, '_blank');
}
const panZoomRef = useRef<any>(null);
const resetPanZoom = (event: any) => {
if (panZoomRef.current && event.target.id != "image-container") {
panZoomRef.current.autoCenter();
}
};
const close = () => {
if (selectedImage != null) {
@ -100,121 +158,69 @@ const Gallery = ({ id, columns, closeMenu }: GalleryProps) => {
else {
closeMenu();
}
}
const breakpointColumnsObj = {
default: 3
};
const back_page = () => {
if (selectedImage != null) {
setSelectedImage(null);
setImages([]);
}
};
const renderButtons = () => {
return (
<div className="z-20 bottom-10 fixed text-white pt-4 bg-primary bg-opacity-90 animate-in rounded-md" style={{ backdropFilter: 'blur(10px)' }}>
<div className='grid grid-cols-5 pl-4 gap-4 pr-4'>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 bg-error hover:bg-error-light`}
onClick={() => close()}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</button>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 ${!selectedImage ? 'opacity-50 cursor-not-allowed bg-gray-800' : 'bg-secondary hover:bg-secondary-light'}`}
onClick={() => resetPanZoom()}
disabled={!selectedImage}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 9V4.5M9 9H4.5M9 9 3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5 5.25 5.25" />
</svg>
</button>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 ${!selectedImage ? 'opacity-50 cursor-not-allowed bg-gray-800' : 'bg-secondary hover:bg-secondary-light'}`}
onClick={() => previous()}
disabled={!selectedImage}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5" />
</svg>
</button>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 ${!selectedImage ? 'opacity-50 cursor-not-allowed bg-gray-800' : 'bg-secondary hover:bg-secondary-light'}`}
onClick={() => next()}
disabled={!selectedImage}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5" />
</svg>
</button>
<button
className={`justify-center text-center w-full animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse mb-4 py-2 px-4 rounded-lg no-underline flex items-center z-50 ${!selectedImage ? 'opacity-50 cursor-not-allowed bg-gray-800' : 'bg-success hover:bg-success-light'}`}
onClick={() => selectedImage && handleDownload(selectedImage)}
disabled={!selectedImage}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m9 13.5 3 3m0 0 3-3m-3 3v-6m1.06-4.19-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z" />
</svg>
</button>
</div>
</div>
);
};
return (
<div >
<div className="z-20" style={{ width: selectedImage ? "100%" : "auto", height: selectedImage ? "100%" : "auto" }}>
<div className='flex justify-center items-center pt-2 pb-20'>
{renderButtons()}
<div className="z-20"
onClick={resetPanZoom} style={{ width: selectedImage ? "100%" : "auto", height: selectedImage ? "100%" : "auto" }}>
<div className='flex justify-center items-center pt-2 pb-20'>
{renderButtons()}
</div>
{selectedImage ? (
<>
<PanZoom
key={selectedImage}
autoCenter={true}
ref={panZoomRef}
>
<div id="image-container" >
<img
src={images[currentIndex]}
style={{ objectFit: "contain", maxWidth: "100%", maxHeight: "calc(100vh - 20px)", pointerEvents: "none" }}
className="cursor-pointer animate-in w-full h-auto"
>
</img>
</div>
</PanZoom>
</>
) : (
<div
className="z-30"
style={{
display: selectedImage ? "flex" : "block",
alignItems: "flex-start",
}}
> <div className='flex justify-center items-center pt-2 '>
{selectedImage ? (
<>
<PanZoom
key={selectedImage}
autoCenter={true}
ref={panZoomRef}
>
{/*
<div
onClick={() => resetPanZoom()} className='w-full h-full z-10'>
</div> */}
<div id="image-container" >
<img
src={images[currentIndex]}
style={{ objectFit: "contain", maxWidth: "100%", maxHeight: "calc(100vh - 20px)", pointerEvents:"none" }}
className="cursor-pointer animate-in w-full h-auto"
>
</img>
</div>
</PanZoom>
</>
) : (
<div
className="z-30"
style={{
display: selectedImage ? "flex" : "block",
alignItems: "flex-start",
}}
> <div className='flex justify-center items-center pt-2 '>
<Masonry
breakpointCols={3}
className="my-masonry-grid pl-6 "
style={{ width: selectedImage ? "50%" : "100%" }}
>
{images
.filter((img) => img !== selectedImage)
.map((image, index) => (
<img
key={index}
src={image}
onClick={() => handleClick(image)}
className={`animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse hover:scale-105 p-2 cursor-pointer my-2 transition-all opacity-100 duration-500 ease-in-out transform`}
/>
))}
</Masonry>
</div>
<Masonry
breakpointCols={columns}
className="my-masonry-grid pl-6 "
style={{ width: selectedImage ? "50%" : "100%" }}
>
{images
.filter((img) => img !== selectedImage)
.map((image, index) => (
<img
src={image}
onClick={() => handleClick(image)}
className={`animate-in animate-once animate-duration-1000 animate-ease-out animate-reverse hover:scale-105 p-2 cursor-pointer my-2 transition-all opacity-100 duration-500 ease-in-out transform`}
/>
))}
</Masonry>
</div>
)}
</div>
<>
</>
</div>
)}
</div>
</div>
);
}

View File

@ -6,13 +6,12 @@ interface GalleryThumbnailProps {
onSelect: (id: string, columns: number) => void;
title: string;
subscription: string;
subscriptionColor: string;
tags: string[];
showNsfw: boolean;
nsfw: boolean;
}
const GalleryThumbnail = ({ id, columns, onSelect, title, showNsfw, nsfw, subscription, subscriptionColor, tags }: GalleryThumbnailProps) => {
const GalleryThumbnail = ({ id, columns, onSelect, title,showNsfw, nsfw, subscription, tags }: GalleryThumbnailProps) => {
const [galleryId, setGalleryId] = useState<string>(id);
const [thumbnailUrl, setThumbnailUrl] = useState<string>('');
const [isLoading, setIsLoading] = useState<boolean>(true);
@ -22,16 +21,15 @@ const GalleryThumbnail = ({ id, columns, onSelect, title, showNsfw, nsfw, subscr
const [showNsfwState, setShowNsfw] = useState<boolean>(showNsfw);
const [subscriptionState, setSubscription] = useState<string>(subscription);
const [tagsState, setTags] = useState<string[]>(tags);
console.log(subscriptionColor)
const openGallery = () => {
onSelect(galleryId, galleryCollumns);
};
const getData = async () => {
setIsLoading(true);
const thumbnailResponse = await fetch('/api/galleries/' + id + '/thumbnail?nsfw=' + showNsfwState);
const thumbnailResponse = await fetch('/api/galleries/' + title + '/thumbnail?nsfw=' + showNsfwState);
const thumbnailUrl = await thumbnailResponse.text();
const imagesCountResponse = await fetch('/api/galleries/' + id + '/images/count');
const imagesCountResponse = await fetch('/api/galleries/' + title + '/images/count');
const imageCount = await imagesCountResponse.json() as number;
setImageCount(imageCount);
setThumbnailUrl(thumbnailUrl);
@ -43,12 +41,12 @@ const GalleryThumbnail = ({ id, columns, onSelect, title, showNsfw, nsfw, subscr
}, [galleryId]);
return (
<div className=" py-3 sm:max-w-xl sm:mx-auto flex-3 animate-fade-up animate-once animate-duration-1000 animate-ease-out animate-normal animate-fill-forwards">
<div className="h-48 overflow-visible w-full relative hover:scale-95 rounded-3xl" style={{ cursor: 'pointer'}}>
<div className="py-3 sm:max-w-xl sm:mx-auto flex-3 animate-fade-up animate-once animate-duration-1000 animate-ease-out animate-normal animate-fill-forwards">
<div className="h-48 overflow-visible w-full relative hover:scale-95 rounded-3xl">
{!isLoading ? (
<>
<img
className={`aspect-content rounded-3xl shadow-lg`}
className={`aspect-content rounded-3xl`}
src={thumbnailUrl}
alt=""
onClick={openGallery}
@ -65,20 +63,30 @@ const GalleryThumbnail = ({ id, columns, onSelect, title, showNsfw, nsfw, subscr
</div>
<div className="text-white flex justify-between">
<div className="flex items-center">
<span className="bg-secondary text-white mr-2 px-2 py-1 rounded-md text-sm flex items-center h-full">
<span className="bg-neroshi-blue-900 text-white mr-2 px-2 py-1 rounded-md text-sm flex items-center h-full">
<span className="text-center">{imageCount}</span>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="pl-2 size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
</svg>
</span>
{nsfwState && (
<span className=" bg-error text-white px-2 py-1 mr-2 rounded-md text-sm h-full flex items-center">NSFW</span>
<span className=" bg-red-900 text-white px-2 py-1 mr-2 rounded-md text-sm h-full flex items-center">NSFW</span>
)}
{subscription === "Free" && (
<span className=" bg-gray-900 text-white px-2 py-1 rounded-md text-sm h-full flex items-center">Free</span>
)}
{subscription === "Tier 1" && (
<span className=" bg-purple-600 text-white px-2 py-1 rounded-md text-sm h-full flex items-center">Tier 1</span>
)}
{subscription === "Tier 2" && (
<span className=" bg-pink-700 text-white px-2 py-1 rounded-md text-sm h-full flex items-center">Tier 2</span>
)}
{subscription === "Tier 3" && (
<span className=" bg-fuchsia-500 text-white px-2 py-1 rounded-md text-sm h-full flex items-center">Tier 3</span>
)}
<span className="text-white px-2 py-1 rounded-md text-sm h-full flex items-center" style={{ cursor: 'pointer', backgroundColor: subscriptionColor }}>Free</span>
</div>
</div>
{/* <div className="text-white flex justify-between">
<div className="text-white flex justify-between">
<div>
<div className="flex">
{tagsState.map((tag, index) => (
@ -92,11 +100,11 @@ const GalleryThumbnail = ({ id, columns, onSelect, title, showNsfw, nsfw, subscr
))}
</div>
</div>
</div> */}
</div>
</div>
</>
) : (
<div className="animate-pulse bg-secondary-light rounded-3xl" style={{ width: '20rem', height: '20rem' }}></div>
<div className="animate-pulse bg-neroshi-blue-950 rounded-3xl" style={{ width: '20rem', height: '20rem' }}></div>
)}
</div>
</div>

View File

@ -1,503 +0,0 @@
<mxfile host="Electron" modified="2024-06-04T04:27:05.636Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.2.5 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="x7V6P6bjO-UHE86F-Cl3" version="24.2.5" type="device">
<diagram name="Page-1" id="F3YAVjulPUqdYhbqfjdd">
<mxGraphModel dx="1877" dy="2420" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-28" value="&lt;h1&gt;Database Design&lt;/h1&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="332.5" y="-70" width="390" height="10" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-29" value="&lt;h1&gt;UX Flow&lt;/h1&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="30" y="620" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-33" target="9zziB1Dtd-V9IfowJO3V-36" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-33" value="Actor" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxGeometry x="35" y="690" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-39" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-36" target="9zziB1Dtd-V9IfowJO3V-38" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-36" value="Open Site" style="whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1">
<mxGeometry x="105" y="705" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-42" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-41" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-43" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-42" vertex="1" connectable="0">
<mxGeometry x="0.2533" y="2" relative="1" as="geometry">
<mxPoint x="2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-48" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-47" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-72" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-48" vertex="1" connectable="0">
<mxGeometry x="-0.2273" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-73" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-71" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="265" y="740" />
<mxPoint x="265" y="795" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-74" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-73" vertex="1" connectable="0">
<mxGeometry x="0.0411" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-81" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="305" y="890" />
<mxPoint x="93" y="890" />
<mxPoint x="93" y="940" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-83" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-82" vertex="1" connectable="0">
<mxGeometry x="-0.8649" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-92" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-91" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-93" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-92" vertex="1" connectable="0">
<mxGeometry x="-0.6335" y="-2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-38" value="&lt;br&gt;Logged&lt;br&gt;In" style="rhombus;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1">
<mxGeometry x="265" y="680" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-41" target="9zziB1Dtd-V9IfowJO3V-45" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-41" value="Login/Signup Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#a20025;strokeColor=#6F0000;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="245" y="620" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-45" target="9zziB1Dtd-V9IfowJO3V-47" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-50" value="Click Activation&lt;br&gt;Email Link" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-49" vertex="1" connectable="0">
<mxGeometry x="0.1683" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-45" value="Send Confirmation Email" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#a20025;strokeColor=#6F0000;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="235" y="560" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-52" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-47" target="9zziB1Dtd-V9IfowJO3V-51" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="540" y="716.31" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-47" value="Gallery Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="440" y="705" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-54" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-51" target="9zziB1Dtd-V9IfowJO3V-53" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-51" value="Search By Title &amp;amp;&lt;br&gt;Filter By Tag" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="642" y="698.02" width="120" height="45" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-55" value="Refine Search" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-53" target="9zziB1Dtd-V9IfowJO3V-51" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-57" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-53" target="9zziB1Dtd-V9IfowJO3V-56" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-53" value="Browse Galleries" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="802" y="704.27" width="120" height="32.5" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-56" target="9zziB1Dtd-V9IfowJO3V-58" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-56" value="Open Gallery" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="802" y="780.52" width="120" height="32.5" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-61" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-60" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-63" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-62" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-65" value="Directional&lt;br&gt;Buttons" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-63" vertex="1" connectable="0">
<mxGeometry x="0.1714" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-69" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-68" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="742" y="850.52" />
<mxPoint x="742" y="840.52" />
<mxPoint x="732" y="840.52" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-58" value="Enlarge Image &amp;amp;&amp;nbsp;&lt;br&gt;Pan/Zoom" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="802" y="840.52" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-60" value="Download Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="802" y="900.52" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-62" target="9zziB1Dtd-V9IfowJO3V-58" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="672" y="960.52" />
<mxPoint x="782" y="960.52" />
<mxPoint x="782" y="870.52" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-62" value="Next/Previous&lt;br&gt;Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="612" y="890.52" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-68" target="9zziB1Dtd-V9IfowJO3V-56" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="762" y="797.39" as="sourcePoint" />
<mxPoint x="792" y="796.14" as="targetPoint" />
<Array as="points">
<mxPoint x="762" y="796.52" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-68" value="Close Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="642" y="787.52" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-76" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-71" target="9zziB1Dtd-V9IfowJO3V-75" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-78" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-71" target="9zziB1Dtd-V9IfowJO3V-77" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-71" value="Livestream Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="125" y="780" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-75" value="Watch Stream" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="125" y="840" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-77" value="Chat" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="12.5" y="780" width="75" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-85" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-81" target="9zziB1Dtd-V9IfowJO3V-84" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-87" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-81" target="9zziB1Dtd-V9IfowJO3V-86" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-81" value="Subscriptions Page" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="32.5" y="940" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-84" value="View Current Tier" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="32.5" y="990" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-89" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-86" target="9zziB1Dtd-V9IfowJO3V-88" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-86" value="View Available Tiers" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="187.5" y="940" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-90" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-88" target="9zziB1Dtd-V9IfowJO3V-84" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-88" value="Upgrade Tier" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="187.5" y="990" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-95" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-91" target="9zziB1Dtd-V9IfowJO3V-94" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="410" y="810" />
<mxPoint x="360" y="810" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-100" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-91" target="9zziB1Dtd-V9IfowJO3V-99" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-91" value="Commissions Page" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="350" y="770" width="120" height="27.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-97" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-94" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-98" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-97" vertex="1" connectable="0">
<mxGeometry x="-0.6109" relative="1" as="geometry">
<mxPoint x="20" y="2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-105" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-94" target="9zziB1Dtd-V9IfowJO3V-110" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-106" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-105" vertex="1" connectable="0">
<mxGeometry x="-0.1779" y="-2" relative="1" as="geometry">
<mxPoint y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-94" value="Has Existing&lt;br&gt;Commission" style="rhombus;whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="310" y="830.52" width="100" height="100" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-101" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-96" target="9zziB1Dtd-V9IfowJO3V-99" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-96" value="View Existing&lt;br&gt;Commission Status" style="whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="350" y="970" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-99" value="View All Commissions" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="500" y="770" width="130" height="27.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-109" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-104" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="560" y="985" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-104" value="Request New&lt;br&gt;Commission" style="whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;rounded=0;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="470" y="817.52" width="120" height="39.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-111" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-110" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="440" y="930" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-112" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-111" vertex="1" connectable="0">
<mxGeometry x="0.0044" relative="1" as="geometry">
<mxPoint y="5" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-113" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-110" target="9zziB1Dtd-V9IfowJO3V-104" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-114" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-113" vertex="1" connectable="0">
<mxGeometry x="-0.5043" y="1" relative="1" as="geometry">
<mxPoint x="3" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-110" value="Requests&lt;br&gt;Open" style="rhombus;whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="440" y="860.52" width="79.48" height="79.48" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-5" value="public.tags" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="207.5" y="440" width="140" height="60" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-6" value="name" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-5">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-9" value="public.admins" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="243" y="60" width="175" height="120" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-10" value="PK FK Unique uuid user_id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="30" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-11" value="assigned_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="60" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-12" value="assigner_id:uuid?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="90" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-17" value="auth.users" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;" vertex="1" parent="1">
<mxGeometry x="10" y="120" width="140" height="60" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-18" value="id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-17">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-23" value="public.tier" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#a20025;fontColor=#ffffff;strokeColor=#6F0000;" vertex="1" parent="1">
<mxGeometry x="32.5" y="290" width="140" height="120" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-24" value="PK name:text" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-25" value="price:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-26" value="stripe_product_id:string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#a20025;strokeColor=#6F0000;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-24" target="1AZqCnQGpeGdDfHHl4o8-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-34" value="public.galleries" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="497.5" y="320" width="140" height="180" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-35" value="PK string name" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-37" value="FK tier string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-38" value="string thumbnail_file" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-41" value="bool nsfw" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="120" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-39" value="text[] tags" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="150" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#a20025;strokeColor=#6F0000;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-24" target="1AZqCnQGpeGdDfHHl4o8-37">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="207.5" y="335" />
<mxPoint x="207.5" y="395" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-43" value="public.skibs" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="499.5" width="140" height="300" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-44" value="PK AI id:&amp;nbsp;int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-46" value="amount:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-49" value="user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-50" value="request_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="120" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-51" value="accepted:bool?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="150" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-58" value="processed_date:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="180" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-52" value="payment_url:string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="210" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-57" value="paidDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="240" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-59" value="completedDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="270" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-48" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;startArrow=classic;startFill=1;fillColor=#1ba1e2;strokeColor=#006EAF;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-6" target="1AZqCnQGpeGdDfHHl4o8-39">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-56" value="No FK Relationship" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#FFFFFF;labelBackgroundColor=none;" vertex="1" connectable="0" parent="1AZqCnQGpeGdDfHHl4o8-48">
<mxGeometry x="-0.0082" y="2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-13" value="public.user_subscriptions" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="243" y="203" width="175" height="180" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-14" value="PK FK Unique user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="30" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-15" value="FK tier:text" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="60" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-54" value="active:bool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="90" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-53" value="last_paid_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="120" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-47" value="start_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="150" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-49">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="105" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-60" value="public.commissions" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="697.5" y="30" width="170" height="330" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-61" value="PK AI id:&amp;nbsp;int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="30" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-62" value="amount:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="60" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-63" value="user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="90" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-64" value="request_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="120" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-65" value="accepted:bool?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="150" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-66" value="processed_date:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="180" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-67" value="hours:number" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="210" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-70" value="pending_approval:bool false" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="240" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-68" value="paidDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="270" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-69" value="completedDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="300" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-71" value="public.comission_messages" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="957.5" y="180" width="210" height="120" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-72" value="PK AI id:int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="30" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-73" value="FK comission_id:int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="60" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-74" value="FK sender_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="90" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-63">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="-30" />
<mxPoint x="667.5" y="-30" />
<mxPoint x="667.5" y="135" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#1ba1e2;strokeColor=#006EAF;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-61" target="1AZqCnQGpeGdDfHHl4o8-73">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-74">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="-30" />
<mxPoint x="667.5" y="-30" />
<mxPoint x="667.5" y="400" />
<mxPoint x="897.5" y="400" />
<mxPoint x="897.5" y="285" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -1,44 +1,107 @@
<mxfile host="Electron" modified="2024-06-04T04:27:06.049Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.2.5 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="nuI_NnP1br-4Uuhgp7xU" version="24.2.5" type="device">
<mxfile host="app.diagrams.net" modified="2024-05-28T00:00:21.084Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" etag="8DUvRLFdr2zWCX9JS4oW" version="24.2.5" type="device">
<diagram name="Page-1" id="F3YAVjulPUqdYhbqfjdd">
<mxGraphModel dx="1877" dy="2420" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<mxGraphModel dx="1314" dy="865" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-28" value="&lt;h1&gt;Database Design&lt;/h1&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="332.5" y="-70" width="390" height="10" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-1" target="9zziB1Dtd-V9IfowJO3V-20">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-29" value="&lt;h1&gt;UX Flow&lt;/h1&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-1" value="auth.users.id" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="50" y="210" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-2" value="public.galleries" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="280" y="320" width="140" height="180" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-3" value="PK string name" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-2">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-4" value="int8 columns" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-2">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-5" value="tier tier" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-2">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-6" value="bool nsfw" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-2">
<mxGeometry y="120" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-7" value="text[] tags" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-2">
<mxGeometry y="150" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-8" value="public.tags" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="50" y="440" width="140" height="60" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-9" value="name" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-8">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-9" target="9zziB1Dtd-V9IfowJO3V-7">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-13" value="Custom Type : Tier" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="50" y="260" width="140" height="150" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-14" value="Free" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-13">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-15" value="Tier 1" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-13">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-16" value="Tier 2" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-13">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-17" value="Tier 3" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-13">
<mxGeometry y="120" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1.008;entryY=0.09;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endArrow=none;endFill=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-5" target="9zziB1Dtd-V9IfowJO3V-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-19" value="public.user_subscriptions" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="280" y="180" width="160" height="90" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-20" value="FK PK user_id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-19">
<mxGeometry y="30" width="160" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-21" value="tier tier" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-19">
<mxGeometry y="60" width="160" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.989;entryY=0.09;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endArrow=none;endFill=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-21" target="9zziB1Dtd-V9IfowJO3V-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-28" value="&lt;h1&gt;Database Design&lt;/h1&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="235" y="120" width="390" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-29" value="&lt;h1&gt;UX Flow&lt;/h1&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="30" y="620" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-33" target="9zziB1Dtd-V9IfowJO3V-36" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-33" target="9zziB1Dtd-V9IfowJO3V-36">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-33" value="Actor" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-33" value="Actor" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="35" y="690" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-39" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-36" target="9zziB1Dtd-V9IfowJO3V-38" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-39" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-36" target="9zziB1Dtd-V9IfowJO3V-38">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-36" value="Open Site" style="whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-36" value="Open Site" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
<mxGeometry x="105" y="705" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-42" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-41" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-42" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-41">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-43" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-42" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-43" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-42">
<mxGeometry x="0.2533" y="2" relative="1" as="geometry">
<mxPoint x="2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-48" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-47" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-48" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-47">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-72" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-48" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-72" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-48">
<mxGeometry x="-0.2273" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-73" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-71" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-73" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-71">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="265" y="740" />
@ -46,12 +109,12 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-74" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-73" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-74" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-73">
<mxGeometry x="0.0411" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-81" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-81">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="305" y="890" />
@ -60,80 +123,80 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-83" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-82" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-83" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-82">
<mxGeometry x="-0.8649" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-92" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-91" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-92" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-91">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-93" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-92" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-93" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-92">
<mxGeometry x="-0.6335" y="-2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-38" value="&lt;br&gt;Logged&lt;br&gt;In" style="rhombus;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-38" value="&lt;br&gt;Logged&lt;br&gt;In" style="rhombus;whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
<mxGeometry x="265" y="680" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-41" target="9zziB1Dtd-V9IfowJO3V-45" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-41" target="9zziB1Dtd-V9IfowJO3V-45">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-41" value="Login/Signup Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#a20025;strokeColor=#6F0000;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-41" value="Login/Signup Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
<mxGeometry x="245" y="620" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-45" target="9zziB1Dtd-V9IfowJO3V-47" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-45" target="9zziB1Dtd-V9IfowJO3V-47">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-50" value="Click Activation&lt;br&gt;Email Link" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-49" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-50" value="Click Activation&lt;br&gt;Email Link" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-49">
<mxGeometry x="0.1683" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-45" value="Send Confirmation Email" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#a20025;strokeColor=#6F0000;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-45" value="Send Confirmation Email" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
<mxGeometry x="235" y="560" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-52" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-47" target="9zziB1Dtd-V9IfowJO3V-51" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-52" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-47" target="9zziB1Dtd-V9IfowJO3V-51">
<mxGeometry relative="1" as="geometry">
<mxPoint x="540" y="716.31" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-47" value="Gallery Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-47" value="Gallery Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="440" y="705" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-54" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-51" target="9zziB1Dtd-V9IfowJO3V-53" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-54" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-51" target="9zziB1Dtd-V9IfowJO3V-53">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-51" value="Search By Title &amp;amp;&lt;br&gt;Filter By Tag" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-51" value="Search By Title &amp;amp;&lt;br&gt;Filter By Tag" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="642" y="698.02" width="120" height="45" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-55" value="Refine Search" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-53" target="9zziB1Dtd-V9IfowJO3V-51" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-55" value="Refine Search" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-53" target="9zziB1Dtd-V9IfowJO3V-51">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-57" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-53" target="9zziB1Dtd-V9IfowJO3V-56" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-57" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-53" target="9zziB1Dtd-V9IfowJO3V-56">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-53" value="Browse Galleries" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-53" value="Browse Galleries" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="802" y="704.27" width="120" height="32.5" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-56" target="9zziB1Dtd-V9IfowJO3V-58" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-56" target="9zziB1Dtd-V9IfowJO3V-58">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-56" value="Open Gallery" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-56" value="Open Gallery" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="802" y="780.52" width="120" height="32.5" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-61" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-60" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-61" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-60">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-63" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-62" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-63" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-62">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-65" value="Directional&lt;br&gt;Buttons" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-63" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-65" value="Directional&lt;br&gt;Buttons" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-63">
<mxGeometry x="0.1714" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-69" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-68" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-69" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-68">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="742" y="850.52" />
@ -142,13 +205,13 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-58" value="Enlarge Image &amp;amp;&amp;nbsp;&lt;br&gt;Pan/Zoom" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-58" value="Enlarge Image &amp;amp;&amp;nbsp;&lt;br&gt;Pan/Zoom" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="802" y="840.52" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-60" value="Download Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-60" value="Download Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="802" y="900.52" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-62" target="9zziB1Dtd-V9IfowJO3V-58" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-62" target="9zziB1Dtd-V9IfowJO3V-58">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="672" y="960.52" />
@ -157,10 +220,10 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-62" value="Next/Previous&lt;br&gt;Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-62" value="Next/Previous&lt;br&gt;Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="612" y="890.52" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-68" target="9zziB1Dtd-V9IfowJO3V-56" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-68" target="9zziB1Dtd-V9IfowJO3V-56">
<mxGeometry relative="1" as="geometry">
<mxPoint x="762" y="797.39" as="sourcePoint" />
<mxPoint x="792" y="796.14" as="targetPoint" />
@ -169,49 +232,49 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-68" value="Close Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-68" value="Close Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="642" y="787.52" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-76" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-71" target="9zziB1Dtd-V9IfowJO3V-75" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-76" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-71" target="9zziB1Dtd-V9IfowJO3V-75">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-78" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-71" target="9zziB1Dtd-V9IfowJO3V-77" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-78" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-71" target="9zziB1Dtd-V9IfowJO3V-77">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-71" value="Livestream Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-71" value="Livestream Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="125" y="780" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-75" value="Watch Stream" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-75" value="Watch Stream" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="125" y="840" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-77" value="Chat" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-77" value="Chat" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
<mxGeometry x="12.5" y="780" width="75" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-85" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-81" target="9zziB1Dtd-V9IfowJO3V-84" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-85" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-81" target="9zziB1Dtd-V9IfowJO3V-84">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-87" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-81" target="9zziB1Dtd-V9IfowJO3V-86" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-87" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-81" target="9zziB1Dtd-V9IfowJO3V-86">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-81" value="Subscriptions Page" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-81" value="Subscriptions Page" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="32.5" y="940" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-84" value="View Current Tier" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-84" value="View Current Tier" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="32.5" y="990" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-89" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-86" target="9zziB1Dtd-V9IfowJO3V-88" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-89" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-86" target="9zziB1Dtd-V9IfowJO3V-88">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-86" value="View Available Tiers" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-86" value="View Available Tiers" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="187.5" y="940" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-90" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-88" target="9zziB1Dtd-V9IfowJO3V-84" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-90" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-88" target="9zziB1Dtd-V9IfowJO3V-84">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-88" value="Upgrade Tier" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-88" value="Upgrade Tier" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="187.5" y="990" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-95" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-91" target="9zziB1Dtd-V9IfowJO3V-94" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-95" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-91" target="9zziB1Dtd-V9IfowJO3V-94">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="410" y="810" />
@ -219,282 +282,100 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-100" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-91" target="9zziB1Dtd-V9IfowJO3V-99" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-100" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-91" target="9zziB1Dtd-V9IfowJO3V-99">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-91" value="Commissions Page" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-91" value="Commissions Page" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="350" y="770" width="120" height="27.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-97" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-94" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-97" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-94" target="9zziB1Dtd-V9IfowJO3V-96">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-98" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-97" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-98" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-97">
<mxGeometry x="-0.6109" relative="1" as="geometry">
<mxPoint x="20" y="2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-105" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-94" target="9zziB1Dtd-V9IfowJO3V-110" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-105" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-94" target="9zziB1Dtd-V9IfowJO3V-110">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-106" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-105" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-106" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-105">
<mxGeometry x="-0.1779" y="-2" relative="1" as="geometry">
<mxPoint y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-94" value="Has Existing&lt;br&gt;Commission" style="rhombus;whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-94" value="Has Existing&lt;br&gt;Commission" style="rhombus;whiteSpace=wrap;html=1;rounded=0;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="310" y="830.52" width="100" height="100" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-101" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-96" target="9zziB1Dtd-V9IfowJO3V-99" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-101" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-96" target="9zziB1Dtd-V9IfowJO3V-99">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-96" value="View Existing&lt;br&gt;Commission Status" style="whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-96" value="View Existing&lt;br&gt;Commission Status" style="whiteSpace=wrap;html=1;rounded=0;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="350" y="970" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-99" value="View All Commissions" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-99" value="View All Commissions" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="500" y="770" width="130" height="27.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-109" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-104" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-109" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-104" target="9zziB1Dtd-V9IfowJO3V-96">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="560" y="985" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-104" value="Request New&lt;br&gt;Commission" style="whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;rounded=0;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-104" value="Request New&lt;br&gt;Commission" style="whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;rounded=0;" vertex="1" parent="1">
<mxGeometry x="470" y="817.52" width="120" height="39.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-111" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-110" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-111" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-110" target="9zziB1Dtd-V9IfowJO3V-96">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="440" y="930" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-112" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-111" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-112" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-111">
<mxGeometry x="0.0044" relative="1" as="geometry">
<mxPoint y="5" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-113" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-110" target="9zziB1Dtd-V9IfowJO3V-104" edge="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-113" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-110" target="9zziB1Dtd-V9IfowJO3V-104">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-114" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-113" vertex="1" connectable="0">
<mxCell id="9zziB1Dtd-V9IfowJO3V-114" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="9zziB1Dtd-V9IfowJO3V-113">
<mxGeometry x="-0.5043" y="1" relative="1" as="geometry">
<mxPoint x="3" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-110" value="Requests&lt;br&gt;Open" style="rhombus;whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxCell id="9zziB1Dtd-V9IfowJO3V-110" value="Requests&lt;br&gt;Open" style="rhombus;whiteSpace=wrap;html=1;rounded=0;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
<mxGeometry x="440" y="860.52" width="79.48" height="79.48" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-5" value="public.tags" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="207.5" y="440" width="140" height="60" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-115" value="galleries Supabase Bucket" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="519.48" y="180" width="291" height="230" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-6" value="name" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-5">
<mxGeometry y="30" width="140" height="30" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-116" value="image" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-115">
<mxGeometry x="160.52" y="40" width="40" height="50" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-9" value="public.admins" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="243" y="60" width="175" height="120" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-117" value="public.galleries.name" style="sketch=0;outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#232F3D;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.folder;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-115">
<mxGeometry x="40.519999999999996" y="60" width="78" height="71" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-10" value="PK FK Unique uuid user_id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="30" width="175" height="30" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-120" value="image" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-115">
<mxGeometry x="220.51999999999998" y="40" width="40" height="50" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-11" value="assigned_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="60" width="175" height="30" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-121" value="image" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-115">
<mxGeometry x="160.51999999999998" y="100" width="40" height="50" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-12" value="assigner_id:uuid?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="90" width="175" height="30" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-122" value="image" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-115">
<mxGeometry x="220.51999999999998" y="100" width="40" height="50" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-17" value="auth.users" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;" vertex="1" parent="1">
<mxGeometry x="10" y="120" width="140" height="60" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-123" value="image" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-115">
<mxGeometry x="220.51999999999998" y="160" width="40" height="50" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-18" value="id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-17">
<mxGeometry y="30" width="140" height="30" as="geometry" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-124" value="image" style="shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;" vertex="1" parent="9zziB1Dtd-V9IfowJO3V-115">
<mxGeometry x="160.51999999999998" y="160" width="40" height="50" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-23" value="public.tier" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#a20025;fontColor=#ffffff;strokeColor=#6F0000;" vertex="1" parent="1">
<mxGeometry x="32.5" y="290" width="140" height="120" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-24" value="PK name:text" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-25" value="price:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-26" value="stripe_product_id:string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#a20025;strokeColor=#6F0000;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-24" target="1AZqCnQGpeGdDfHHl4o8-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-34" value="public.galleries" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="497.5" y="320" width="140" height="180" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-35" value="PK string name" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-37" value="FK tier string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-38" value="string thumbnail_file" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-41" value="bool nsfw" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="120" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-39" value="text[] tags" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="150" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#a20025;strokeColor=#6F0000;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-24" target="1AZqCnQGpeGdDfHHl4o8-37">
<mxCell id="9zziB1Dtd-V9IfowJO3V-118" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="9zziB1Dtd-V9IfowJO3V-3" target="9zziB1Dtd-V9IfowJO3V-117">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="207.5" y="335" />
<mxPoint x="207.5" y="395" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-43" value="public.skibs" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="499.5" width="140" height="300" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-44" value="PK AI id:&amp;nbsp;int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-46" value="amount:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-49" value="user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-50" value="request_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="120" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-51" value="accepted:bool?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="150" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-58" value="processed_date:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="180" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-52" value="payment_url:string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="210" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-57" value="paidDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="240" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-59" value="completedDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="270" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-48" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;startArrow=classic;startFill=1;fillColor=#1ba1e2;strokeColor=#006EAF;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-6" target="1AZqCnQGpeGdDfHHl4o8-39">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-56" value="No FK Relationship" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#FFFFFF;labelBackgroundColor=none;" vertex="1" connectable="0" parent="1AZqCnQGpeGdDfHHl4o8-48">
<mxGeometry x="-0.0082" y="2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-13" value="public.user_subscriptions" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="243" y="203" width="175" height="180" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-14" value="PK FK Unique user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="30" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-15" value="FK tier:text" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="60" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-54" value="active:bool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="90" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-53" value="last_paid_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="120" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-47" value="start_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="150" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-49">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="105" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-60" value="public.commissions" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="697.5" y="30" width="170" height="330" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-61" value="PK AI id:&amp;nbsp;int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="30" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-62" value="amount:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="60" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-63" value="user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="90" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-64" value="request_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="120" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-65" value="accepted:bool?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="150" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-66" value="processed_date:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="180" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-67" value="hours:number" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="210" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-70" value="pending_approval:bool false" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="240" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-68" value="paidDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="270" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-69" value="completedDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="300" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-71" value="public.comission_messages" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="957.5" y="180" width="210" height="120" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-72" value="PK AI id:int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="30" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-73" value="FK comission_id:int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="60" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-74" value="FK sender_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="90" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-63">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="-30" />
<mxPoint x="667.5" y="-30" />
<mxPoint x="667.5" y="135" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#1ba1e2;strokeColor=#006EAF;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-61" target="1AZqCnQGpeGdDfHHl4o8-73">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-74">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="-30" />
<mxPoint x="667.5" y="-30" />
<mxPoint x="667.5" y="400" />
<mxPoint x="897.5" y="400" />
<mxPoint x="897.5" y="285" />
</Array>
<mxPoint x="620" y="320" as="targetPoint" />
</mxGeometry>
</mxCell>
</root>

562
package-lock.json generated
View File

@ -8,8 +8,6 @@
"@supabase/ssr": "latest",
"@supabase/supabase-js": "latest",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.11",
"autoprefixer": "10.4.17",
"clsx": "^2.1.1",
"framer-motion": "^11.2.6",
@ -23,8 +21,6 @@
"react-easy-panzoom": "^0.4.4",
"react-masonry-css": "^1.0.16",
"react-responsive-masonry": "^2.2.0",
"react-select": "^5.8.0",
"react-tailwindcss-select": "^1.8.5",
"sharp": "^0.33.4",
"simplex-noise": "^4.0.1",
"tailwind-merge": "^2.3.0",
@ -52,102 +48,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@babel/code-frame": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz",
"integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==",
"dependencies": {
"@babel/highlight": "^7.24.6",
"picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz",
"integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==",
"dependencies": {
"@babel/types": "^7.24.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz",
"integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz",
"integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/highlight": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz",
"integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==",
"dependencies": {
"@babel/helper-validator-identifier": "^7.24.6",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/highlight/node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dependencies": {
"color-convert": "^1.9.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/highlight/node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/highlight/node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/highlight/node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/runtime": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz",
@ -159,19 +59,6 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz",
"integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==",
"dependencies": {
"@babel/helper-string-parser": "^7.24.6",
"@babel/helper-validator-identifier": "^7.24.6",
"to-fast-properties": "^2.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz",
@ -181,150 +68,6 @@
"tslib": "^2.4.0"
}
},
"node_modules/@emotion/babel-plugin": {
"version": "11.11.0",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
"integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
"dependencies": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/runtime": "^7.18.3",
"@emotion/hash": "^0.9.1",
"@emotion/memoize": "^0.8.1",
"@emotion/serialize": "^1.1.2",
"babel-plugin-macros": "^3.1.0",
"convert-source-map": "^1.5.0",
"escape-string-regexp": "^4.0.0",
"find-root": "^1.1.0",
"source-map": "^0.5.7",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@emotion/babel-plugin/node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@emotion/cache": {
"version": "11.11.0",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
"integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==",
"dependencies": {
"@emotion/memoize": "^0.8.1",
"@emotion/sheet": "^1.2.2",
"@emotion/utils": "^1.2.1",
"@emotion/weak-memoize": "^0.3.1",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/hash": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
"integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
},
"node_modules/@emotion/memoize": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
},
"node_modules/@emotion/react": {
"version": "11.11.4",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
"integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.11.0",
"@emotion/cache": "^11.11.0",
"@emotion/serialize": "^1.1.3",
"@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
"@emotion/utils": "^1.2.1",
"@emotion/weak-memoize": "^0.3.1",
"hoist-non-react-statics": "^3.3.1"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/serialize": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz",
"integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==",
"dependencies": {
"@emotion/hash": "^0.9.1",
"@emotion/memoize": "^0.8.1",
"@emotion/unitless": "^0.8.1",
"@emotion/utils": "^1.2.1",
"csstype": "^3.0.2"
}
},
"node_modules/@emotion/sheet": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
"integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA=="
},
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
"integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
},
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
"integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@emotion/utils": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
"integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg=="
},
"node_modules/@emotion/weak-memoize": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
"integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
},
"node_modules/@floating-ui/core": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz",
"integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==",
"dependencies": {
"@floating-ui/utils": "^0.2.0"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz",
"integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==",
"dependencies": {
"@floating-ui/core": "^1.0.0",
"@floating-ui/utils": "^0.2.0"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz",
"integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw=="
},
"node_modules/@fullhuman/postcss-purgecss": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.3.0.tgz",
@ -1185,11 +928,6 @@
"undici-types": "~5.26.4"
}
},
"node_modules/@types/parse-json": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
"integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
},
"node_modules/@types/phoenix": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.4.tgz",
@ -1198,12 +936,14 @@
"node_modules/@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
"dev": true
},
"node_modules/@types/react": {
"version": "18.2.48",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz",
"integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@ -1219,18 +959,11 @@
"@types/react": "*"
}
},
"node_modules/@types/react-transition-group": {
"version": "4.4.10",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
"integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw=="
"integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==",
"dev": true
},
"node_modules/@types/ws": {
"version": "8.5.10",
@ -1240,60 +973,6 @@
"@types/node": "*"
}
},
"node_modules/@vercel/analytics": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.3.1.tgz",
"integrity": "sha512-xhSlYgAuJ6Q4WQGkzYTLmXwhYl39sWjoMA3nHxfkvG+WdBT25c563a7QhwwKivEOZtPJXifYHR1m2ihoisbWyA==",
"dependencies": {
"server-only": "^0.0.1"
},
"peerDependencies": {
"next": ">= 13",
"react": "^18 || ^19"
},
"peerDependenciesMeta": {
"next": {
"optional": true
},
"react": {
"optional": true
}
}
},
"node_modules/@vercel/speed-insights": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@vercel/speed-insights/-/speed-insights-1.0.11.tgz",
"integrity": "sha512-l9hzSNmJvb2Yqpgd/BzpiT0J0aQDdtqxOf3Xm+iW4PICxVvhY1ef7Otdx4GXI+88dVkws57qMzXiShz19gXzSQ==",
"hasInstallScript": true,
"peerDependencies": {
"@sveltejs/kit": "^1 || ^2",
"next": ">= 13",
"react": "^18 || ^19",
"svelte": "^4",
"vue": "^3",
"vue-router": "^4"
},
"peerDependenciesMeta": {
"@sveltejs/kit": {
"optional": true
},
"next": {
"optional": true
},
"react": {
"optional": true
},
"svelte": {
"optional": true
},
"vue": {
"optional": true
},
"vue-router": {
"optional": true
}
}
},
"node_modules/acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
@ -1403,20 +1082,6 @@
"postcss": "^8.1.0"
}
},
"node_modules/babel-plugin-macros": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"cosmiconfig": "^7.0.0",
"resolve": "^1.19.0"
},
"engines": {
"node": ">=10",
"npm": ">=6"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -1502,14 +1167,6 @@
"node": ">= 0.8"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"engines": {
"node": ">=6"
}
},
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
@ -1681,11 +1338,6 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
},
"node_modules/cookie": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
@ -1694,29 +1346,6 @@
"node": ">= 0.6"
}
},
"node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
"integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
"yaml": "^1.10.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/cosmiconfig/node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"engines": {
"node": ">= 6"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -1757,7 +1386,8 @@
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
},
"node_modules/defined": {
"version": "1.0.1",
@ -1801,15 +1431,6 @@
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
},
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@ -1834,19 +1455,6 @@
"iconv-lite": "^0.6.2"
}
},
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dependencies": {
"is-arrayish": "^0.2.1"
}
},
"node_modules/error-ex/node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
@ -1908,11 +1516,6 @@
"node": ">=8"
}
},
"node_modules/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
},
"node_modules/foreground-child": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
@ -2067,14 +1670,6 @@
"node": ">= 0.4"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/html-tags": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
@ -2098,21 +1693,6 @@
"node": ">=0.10.0"
}
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@ -2230,11 +1810,6 @@
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
},
"node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@ -2290,11 +1865,6 @@
"is-buffer": "~1.1.6"
}
},
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -2511,34 +2081,6 @@
"wrappy": "1"
}
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dependencies": {
"callsites": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"dependencies": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
"json-parse-even-better-errors": "^2.3.0",
"lines-and-columns": "^1.1.6"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -2575,14 +2117,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"engines": {
"node": ">=8"
}
},
"node_modules/picocolors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
@ -3099,49 +2633,6 @@
"resolved": "https://registry.npmjs.org/react-responsive-masonry/-/react-responsive-masonry-2.2.0.tgz",
"integrity": "sha512-IYbnfe2tWCZ3pvyTLyBWPj7uv5ZmNOULYMcAZi5a47ZLhSotOck1vkkISq6gP2qiyWdMvPfeMhjvYzUYGw9BOQ=="
},
"node_modules/react-select": {
"version": "5.8.0",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.0.tgz",
"integrity": "sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==",
"dependencies": {
"@babel/runtime": "^7.12.0",
"@emotion/cache": "^11.4.0",
"@emotion/react": "^11.8.1",
"@floating-ui/dom": "^1.0.1",
"@types/react-transition-group": "^4.4.0",
"memoize-one": "^6.0.0",
"prop-types": "^15.6.0",
"react-transition-group": "^4.3.0",
"use-isomorphic-layout-effect": "^1.1.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-tailwindcss-select": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/react-tailwindcss-select/-/react-tailwindcss-select-1.8.5.tgz",
"integrity": "sha512-x29IrLiqBT5FnkC9oFQReOr05tEOZHtDtZdha84nlSWcj3qD67yonKFHXIf69yc8ElFlKUxCEv0zCllN8jHBFA==",
"peerDependencies": {
"react": "^18.2.0"
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
"dependencies": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": ">=16.6.0",
"react-dom": ">=16.6.0"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@ -3196,14 +2687,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"engines": {
"node": ">=4"
}
},
"node_modules/reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@ -3260,11 +2743,6 @@
"node": ">=10"
}
},
"node_modules/server-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz",
"integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="
},
"node_modules/sharp": {
"version": "0.33.4",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.4.tgz",
@ -3509,11 +2987,6 @@
}
}
},
"node_modules/stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
},
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
@ -3744,14 +3217,6 @@
"node": ">=0.8"
}
},
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
"engines": {
"node": ">=4"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -3832,19 +3297,6 @@
"browserslist": ">= 4.21.0"
}
},
"node_modules/use-isomorphic-layout-effect": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
"integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

View File

@ -9,8 +9,6 @@
"@supabase/ssr": "latest",
"@supabase/supabase-js": "latest",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.11",
"autoprefixer": "10.4.17",
"clsx": "^2.1.1",
"framer-motion": "^11.2.6",
@ -24,8 +22,6 @@
"react-easy-panzoom": "^0.4.4",
"react-masonry-css": "^1.0.16",
"react-responsive-masonry": "^2.2.0",
"react-select": "^5.8.0",
"react-tailwindcss-select": "^1.8.5",
"sharp": "^0.33.4",
"simplex-noise": "^4.0.1",
"tailwind-merge": "^2.3.0",

View File

@ -0,0 +1,21 @@
CREATE TYPE tier AS ENUM ('Free', 'Tier 1', 'Tier 2', 'Tier 3');
CREATE TABLE tags (
name text primary key,
gallery_name text
);
CREATE TABLE user_subscriptions (
user_id uuid primary key references auth.users(id),
tier tier
);
CREATE TABLE galleries (
name text primary key,
column_number int8,
tier tier,
nsfw boolean,
tags text[]
);
ALTER TABLE tags ADD FOREIGN KEY (gallery_name) REFERENCES galleries(name);

View File

@ -1,237 +0,0 @@
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
CREATE EXTENSION IF NOT EXISTS "pg_net" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pgsodium" WITH SCHEMA "pgsodium";
COMMENT ON SCHEMA "public" IS 'standard public schema';
CREATE EXTENSION IF NOT EXISTS "pg_graphql" WITH SCHEMA "graphql";
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pgcrypto" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pgjwt" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "supabase_vault" WITH SCHEMA "vault";
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA "extensions";
CREATE TYPE "public"."interface_config_option" AS ENUM (
'color',
'image'
);
ALTER TYPE "public"."interface_config_option" OWNER TO "postgres";
CREATE TYPE "public"."tier" AS ENUM (
'Free',
'Tier 1',
'Tier 2',
'Tier 3'
);
ALTER TYPE "public"."tier" OWNER TO "postgres";
SET default_tablespace = '';
SET default_table_access_method = "heap";
CREATE TABLE IF NOT EXISTS "public"."admins" (
"user_id" "uuid" NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
"assigner" "uuid"
);
ALTER TABLE "public"."admins" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."galleries" (
"name" "text" NOT NULL,
"column_number" bigint,
"tier" "text" DEFAULT 'Free'::"text",
"nsfw" boolean,
"tags" "text"[],
"thumbnail_file" "text" DEFAULT ''::"text"
);
ALTER TABLE "public"."galleries" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."interface_configurations" (
"name" "text" NOT NULL,
"value" "text" NOT NULL,
"type" "public"."interface_config_option" DEFAULT 'color'::"public"."interface_config_option" NOT NULL
);
ALTER TABLE "public"."interface_configurations" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."tags" (
"name" "text" NOT NULL,
"gallery_name" "text"
);
ALTER TABLE "public"."tags" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."tiers" (
"name" "text" NOT NULL,
"price" double precision NOT NULL,
"color" "text" NOT NULL,
"description" "text" NOT NULL
);
ALTER TABLE "public"."tiers" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."user_subscriptions" (
"user_id" "uuid" NOT NULL,
"tier" "public"."tier"
);
ALTER TABLE "public"."user_subscriptions" OWNER TO "postgres";
ALTER TABLE ONLY "public"."admins"
ADD CONSTRAINT "admins_pkey" PRIMARY KEY ("user_id");
ALTER TABLE ONLY "public"."galleries"
ADD CONSTRAINT "galleries_pkey" PRIMARY KEY ("name");
ALTER TABLE ONLY "public"."interface_configurations"
ADD CONSTRAINT "interface_configurations_pkey" PRIMARY KEY ("name");
ALTER TABLE ONLY "public"."tags"
ADD CONSTRAINT "tags_pkey" PRIMARY KEY ("name");
ALTER TABLE ONLY "public"."tiers"
ADD CONSTRAINT "tiers_pkey" PRIMARY KEY ("name");
ALTER TABLE ONLY "public"."user_subscriptions"
ADD CONSTRAINT "user_subscriptions_pkey" PRIMARY KEY ("user_id");
ALTER TABLE ONLY "public"."admins"
ADD CONSTRAINT "admins_assigner_fkey" FOREIGN KEY ("assigner") REFERENCES "auth"."users"("id");
ALTER TABLE ONLY "public"."admins"
ADD CONSTRAINT "admins_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id");
ALTER TABLE ONLY "public"."tags"
ADD CONSTRAINT "tags_gallery_name_fkey" FOREIGN KEY ("gallery_name") REFERENCES "public"."galleries"("name");
ALTER TABLE ONLY "public"."user_subscriptions"
ADD CONSTRAINT "user_subscriptions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id");
CREATE POLICY "Enable delete for admins" ON "public"."tags" FOR DELETE TO "authenticated" USING ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
CREATE POLICY "Enable delete for users based on admins" ON "public"."galleries" FOR DELETE TO "authenticated" USING ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
CREATE POLICY "Enable insert for admins" ON "public"."tags" FOR INSERT TO "authenticated" WITH CHECK ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
CREATE POLICY "Enable insert for users based admins" ON "public"."galleries" FOR INSERT WITH CHECK ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
CREATE POLICY "Enable read access for all users" ON "public"."admins" FOR SELECT USING (true);
CREATE POLICY "Enable read access for all users" ON "public"."galleries" FOR SELECT USING (true);
CREATE POLICY "Enable read access for all users" ON "public"."interface_configurations" FOR SELECT USING (true);
CREATE POLICY "Enable read access for all users" ON "public"."tags" FOR SELECT USING (true);
CREATE POLICY "Enable read access for all users" ON "public"."tiers" FOR SELECT USING (true);
CREATE POLICY "Enable read for users based on user_id" ON "public"."user_subscriptions" FOR SELECT USING (true);
CREATE POLICY "admin insert" ON "public"."tiers" FOR INSERT WITH CHECK ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
CREATE POLICY "admin update" ON "public"."tiers" FOR UPDATE USING ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
ALTER TABLE "public"."admins" ENABLE ROW LEVEL SECURITY;
CREATE POLICY "delete for admin" ON "public"."tiers" FOR DELETE USING ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
ALTER TABLE "public"."galleries" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."interface_configurations" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."tags" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."tiers" ENABLE ROW LEVEL SECURITY;
CREATE POLICY "update for admin" ON "public"."galleries" FOR UPDATE USING ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
CREATE POLICY "update theme admin" ON "public"."interface_configurations" FOR UPDATE USING ((EXISTS ( SELECT 1
FROM "public"."admins"
WHERE ("admins"."user_id" = "auth"."uid"()))));
ALTER TABLE "public"."user_subscriptions" ENABLE ROW LEVEL SECURITY;
ALTER PUBLICATION "supabase_realtime" OWNER TO "postgres";
GRANT USAGE ON SCHEMA "public" TO "postgres";
GRANT USAGE ON SCHEMA "public" TO "anon";
GRANT USAGE ON SCHEMA "public" TO "authenticated";
GRANT USAGE ON SCHEMA "public" TO "service_role";
GRANT ALL ON TABLE "public"."admins" TO "anon";
GRANT ALL ON TABLE "public"."admins" TO "authenticated";
GRANT ALL ON TABLE "public"."admins" TO "service_role";
GRANT ALL ON TABLE "public"."galleries" TO "anon";
GRANT ALL ON TABLE "public"."galleries" TO "authenticated";
GRANT ALL ON TABLE "public"."galleries" TO "service_role";
GRANT ALL ON TABLE "public"."interface_configurations" TO "anon";
GRANT ALL ON TABLE "public"."interface_configurations" TO "authenticated";
GRANT ALL ON TABLE "public"."interface_configurations" TO "service_role";
GRANT ALL ON TABLE "public"."tags" TO "anon";
GRANT ALL ON TABLE "public"."tags" TO "authenticated";
GRANT ALL ON TABLE "public"."tags" TO "service_role";
GRANT ALL ON TABLE "public"."tiers" TO "anon";
GRANT ALL ON TABLE "public"."tiers" TO "authenticated";
GRANT ALL ON TABLE "public"."tiers" TO "service_role";
GRANT ALL ON TABLE "public"."user_subscriptions" TO "anon";
GRANT ALL ON TABLE "public"."user_subscriptions" TO "authenticated";
GRANT ALL ON TABLE "public"."user_subscriptions" TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "service_role";
RESET ALL;

View File

@ -43,106 +43,7 @@ INSERT INTO "auth"."audit_log_entries" ("instance_id", "id", "payload", "created
('00000000-0000-0000-0000-000000000000', 'e878d51d-2524-4796-9288-88bcf8d1982b', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-05-27 21:11:27.314657+00', ''),
('00000000-0000-0000-0000-000000000000', '0d3f4871-8215-4ae7-920b-c261ba7eaf11', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-05-27 21:11:27.315598+00', ''),
('00000000-0000-0000-0000-000000000000', 'f70081c9-673b-4e8e-84c6-574d4a6fc095', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-05-28 00:06:54.425581+00', ''),
('00000000-0000-0000-0000-000000000000', 'ff4e9892-902a-4e6f-9493-976acd87e5ad', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-05-28 00:06:54.426626+00', ''),
('00000000-0000-0000-0000-000000000000', '13891f74-fb79-45bd-a202-3c3846723eb3', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-05-28 01:11:09.34946+00', ''),
('00000000-0000-0000-0000-000000000000', '6125acd2-6bd2-4ae1-8b41-4b54b8097a64', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-05-28 01:11:09.350568+00', ''),
('00000000-0000-0000-0000-000000000000', '904b1ae0-83cb-4bce-a1b9-65f4215e0095', '{"action":"logout","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account"}', '2024-05-28 01:45:53.937368+00', ''),
('00000000-0000-0000-0000-000000000000', '16bba433-9af2-4328-b0d2-d59a9d072edb', '{"action":"user_signedup","actor_id":"e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd","actor_username":"damienostler1@gmail.com","actor_via_sso":false,"log_type":"team","traits":{"provider":"email"}}', '2024-05-28 02:01:35.369669+00', ''),
('00000000-0000-0000-0000-000000000000', 'a80de210-524f-41a2-b437-a0a68a5b0dc5', '{"action":"login","actor_id":"e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd","actor_username":"damienostler1@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-05-28 02:01:35.372417+00', ''),
('00000000-0000-0000-0000-000000000000', '56e9bcfc-28ea-4fbf-aae2-a6c611da2536', '{"action":"token_refreshed","actor_id":"e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd","actor_username":"damienostler1@gmail.com","actor_via_sso":false,"log_type":"token"}', '2024-05-28 03:03:11.47339+00', ''),
('00000000-0000-0000-0000-000000000000', 'f661df3e-4600-4254-a606-dab87b0bf241', '{"action":"token_revoked","actor_id":"e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd","actor_username":"damienostler1@gmail.com","actor_via_sso":false,"log_type":"token"}', '2024-05-28 03:03:11.474173+00', ''),
('00000000-0000-0000-0000-000000000000', 'eccb045f-3fa3-4cc4-92b5-2181ae4c684e', '{"action":"token_refreshed","actor_id":"e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd","actor_username":"damienostler1@gmail.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 01:54:12.341648+00', ''),
('00000000-0000-0000-0000-000000000000', 'bdca3f89-401a-40b5-b1bd-7b053f72f15a', '{"action":"token_revoked","actor_id":"e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd","actor_username":"damienostler1@gmail.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 01:54:12.342909+00', ''),
('00000000-0000-0000-0000-000000000000', 'a76ea115-0732-45e4-a05f-cbf9aec04dab', '{"action":"logout","actor_id":"e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd","actor_username":"damienostler1@gmail.com","actor_via_sso":false,"log_type":"account"}', '2024-06-01 01:54:44.965028+00', ''),
('00000000-0000-0000-0000-000000000000', '73e58d43-80dc-4c40-93b8-66debb2d79f2', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-01 01:54:50.928035+00', ''),
('00000000-0000-0000-0000-000000000000', 'a7b0b5b0-42d0-4970-a799-f918e320a460', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 02:52:51.499031+00', ''),
('00000000-0000-0000-0000-000000000000', 'dd70c686-fc1b-42da-8aa1-91a6d7fbcc14', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 02:52:51.50256+00', ''),
('00000000-0000-0000-0000-000000000000', '09161c6c-3f38-4405-b26e-67fe90bc0005', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 03:51:46.507091+00', ''),
('00000000-0000-0000-0000-000000000000', '7fd17052-1b4a-4178-98b8-3b16b9de930a', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 03:51:46.5081+00', ''),
('00000000-0000-0000-0000-000000000000', '727021f7-1385-43eb-9139-5c8d0984fb07', '{"action":"logout","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account"}', '2024-06-01 04:28:20.313782+00', ''),
('00000000-0000-0000-0000-000000000000', '7df2cdbc-1c84-4847-8142-90477524ee7a', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-01 04:32:18.045015+00', ''),
('00000000-0000-0000-0000-000000000000', 'abb0a2d8-d525-4612-a364-9ba3ea22eabf', '{"action":"logout","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account"}', '2024-06-01 04:32:21.789565+00', ''),
('00000000-0000-0000-0000-000000000000', '21e30d5b-7f03-459f-814d-43757cf3f8bf', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-01 04:33:07.034577+00', ''),
('00000000-0000-0000-0000-000000000000', '1d8fca22-6ef6-42eb-a1e9-659e702e0568', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 05:31:30.614051+00', ''),
('00000000-0000-0000-0000-000000000000', '3a9c811c-fad9-4739-9e2f-807a65f92ebc', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 05:31:30.614956+00', ''),
('00000000-0000-0000-0000-000000000000', '7620c8d4-9662-4c6b-b04f-8bcf5fc37cd2', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 07:21:44.28552+00', ''),
('00000000-0000-0000-0000-000000000000', '4cfcd7b6-8a95-4713-9409-317734ae7b38', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 07:21:44.286437+00', ''),
('00000000-0000-0000-0000-000000000000', '41cd74f2-8882-4e30-ae82-b743901cae3a', '{"action":"logout","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account"}', '2024-06-01 07:37:28.737433+00', ''),
('00000000-0000-0000-0000-000000000000', 'a490a17d-b47e-4820-923d-e7c8bc88efb5', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-01 07:37:35.302764+00', ''),
('00000000-0000-0000-0000-000000000000', '3c44829d-3ec7-4698-95c3-b53597422759', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 08:36:15.774+00', ''),
('00000000-0000-0000-0000-000000000000', '5b2c215f-bfd1-4b59-a782-eaac62d1c458', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 08:36:15.775505+00', ''),
('00000000-0000-0000-0000-000000000000', '0a5a278a-9fd1-4bcc-a041-66f1302ac7e6', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 09:34:29.572756+00', ''),
('00000000-0000-0000-0000-000000000000', '89b87acd-362b-4c51-8c3a-5a5e356ed8e2', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 09:34:29.573904+00', ''),
('00000000-0000-0000-0000-000000000000', '8c413fec-a827-4ede-a533-2409f855d2e0', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 10:35:29.39825+00', ''),
('00000000-0000-0000-0000-000000000000', '786f5ba3-670c-4799-8b5d-9e2536b75ca0', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 10:35:29.399482+00', ''),
('00000000-0000-0000-0000-000000000000', 'da188f51-e5c3-467c-b9c4-7e2ba8430981', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 20:10:45.655684+00', ''),
('00000000-0000-0000-0000-000000000000', 'c415ee23-3497-4445-9b18-b3698dd35e16', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 20:10:45.656475+00', ''),
('00000000-0000-0000-0000-000000000000', '4c5c4c36-a506-4c80-b467-68618dbf10db', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 22:05:34.985137+00', ''),
('00000000-0000-0000-0000-000000000000', '52eb3774-6624-4987-b357-fb07ff22e368', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-01 22:05:34.986175+00', ''),
('00000000-0000-0000-0000-000000000000', '4c493923-b97a-4ca7-ad59-801212c59692', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 03:42:48.403833+00', ''),
('00000000-0000-0000-0000-000000000000', '04114bf3-53c5-447b-bb9d-0cf0e97411ce', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 03:42:48.405516+00', ''),
('00000000-0000-0000-0000-000000000000', '59785eb8-3a22-4596-b534-c76d0aaadf9b', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 04:41:14.398806+00', ''),
('00000000-0000-0000-0000-000000000000', '1da856fa-1582-447b-a033-6dfd6e91ee5b', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 04:41:14.399986+00', ''),
('00000000-0000-0000-0000-000000000000', '3790f005-05d8-439d-a828-fb8e6a22356f', '{"action":"logout","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account"}', '2024-06-02 05:20:51.896435+00', ''),
('00000000-0000-0000-0000-000000000000', '903ece4b-635c-4fd0-9a6d-c60103328e11', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-02 05:21:03.760977+00', ''),
('00000000-0000-0000-0000-000000000000', 'ab8d42bd-c9df-4782-8cbd-14279592fe94', '{"action":"logout","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account"}', '2024-06-02 06:18:43.051255+00', ''),
('00000000-0000-0000-0000-000000000000', '008ae3d1-61c4-4456-8e70-8a2030acbbc4', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-02 07:19:23.344522+00', ''),
('00000000-0000-0000-0000-000000000000', 'bf042910-d447-4f27-bb63-fbd6b80c266f', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 08:17:36.070061+00', ''),
('00000000-0000-0000-0000-000000000000', '55f64c6a-d6bd-4dd4-8627-3c35caa6dc7e', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 08:17:36.071183+00', ''),
('00000000-0000-0000-0000-000000000000', '578dc04e-5665-410c-8c0e-bbf40b397b18', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 09:23:17.276185+00', ''),
('00000000-0000-0000-0000-000000000000', '4ccf2be5-8ecd-48ee-9400-7fef1004dc56', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 09:23:17.277357+00', ''),
('00000000-0000-0000-0000-000000000000', '824ccdf1-4dc0-4cee-8c01-ac66cdea101f', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 10:21:37.85499+00', ''),
('00000000-0000-0000-0000-000000000000', '98aa3855-f2ff-4118-9618-041c82318963', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 10:21:37.856028+00', ''),
('00000000-0000-0000-0000-000000000000', 'f1599f7e-e1c1-4861-87e5-9b8e5e9fa8f7', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 11:20:00.113655+00', ''),
('00000000-0000-0000-0000-000000000000', '84f7562d-151d-4e30-b810-70891f3a8a2b', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 11:20:00.115274+00', ''),
('00000000-0000-0000-0000-000000000000', '7451f114-d011-4552-9b21-bcf6d6df6243', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 20:49:23.877784+00', ''),
('00000000-0000-0000-0000-000000000000', '24b82857-e2fd-4732-a2e8-ac99f67fffa9', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 20:49:23.878598+00', ''),
('00000000-0000-0000-0000-000000000000', 'bf2935a0-244a-449d-925c-ca7ad6bf91d6', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 21:49:06.535623+00', ''),
('00000000-0000-0000-0000-000000000000', '88b130fb-5418-49ec-9e54-7db1df9b9353', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 21:49:06.536554+00', ''),
('00000000-0000-0000-0000-000000000000', '2aafc337-642d-4f4c-b550-b1c88b0f698a', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 22:47:33.949246+00', ''),
('00000000-0000-0000-0000-000000000000', '7b7bc3c1-3751-4e00-a08c-14b5bb3cf892', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-02 22:47:33.950537+00', ''),
('00000000-0000-0000-0000-000000000000', '7b3b5a37-ed60-4b75-84ae-0caba9254581', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-03 00:10:51.713229+00', ''),
('00000000-0000-0000-0000-000000000000', 'd984ff2d-6d96-43d9-9a39-703de7400fd1', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 01:10:47.663131+00', ''),
('00000000-0000-0000-0000-000000000000', 'e996a172-f818-489a-84b3-8dc8b8a1068b', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 01:10:47.663668+00', ''),
('00000000-0000-0000-0000-000000000000', '0f07359e-4c78-40a7-8711-4127dc74c0fb', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 02:08:53.524332+00', ''),
('00000000-0000-0000-0000-000000000000', 'b8f1d6e8-4e3f-473c-b0be-98f4540da6f3', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 02:08:53.525533+00', ''),
('00000000-0000-0000-0000-000000000000', '1043d8ee-0301-46e0-a451-2bb043fe6634', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 03:07:09.462821+00', ''),
('00000000-0000-0000-0000-000000000000', '6924eb3a-0588-46ff-94dc-b45f29a06e74', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 03:07:09.463674+00', ''),
('00000000-0000-0000-0000-000000000000', '3995cc04-3976-47bd-aafb-04fcf8a533db', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 04:05:10.557103+00', ''),
('00000000-0000-0000-0000-000000000000', 'd5cb3c9b-aa2d-4ca6-9067-4c31ecbb7827', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 04:05:10.558474+00', ''),
('00000000-0000-0000-0000-000000000000', '8c7ca4b6-0b87-4704-9508-8cdfaac13c65', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 05:04:07.678559+00', ''),
('00000000-0000-0000-0000-000000000000', '7a1eb770-9f3c-4ac2-a13a-fafe80704bef', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 05:04:07.679535+00', ''),
('00000000-0000-0000-0000-000000000000', 'c4c2ae8b-62eb-4dde-8023-bb4a52fd8402', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 06:02:18.158106+00', ''),
('00000000-0000-0000-0000-000000000000', 'f3deb712-a27b-4652-b3dc-bb782188943c', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-03 06:02:18.159666+00', ''),
('00000000-0000-0000-0000-000000000000', 'db502a30-3a84-4151-8c02-7be7eba0f8d1', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-04 00:29:24.732764+00', ''),
('00000000-0000-0000-0000-000000000000', 'a24f4f60-00aa-48eb-8318-ed131fd44b2e', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-04 00:29:24.734165+00', ''),
('00000000-0000-0000-0000-000000000000', 'f1d4e360-3355-4850-9f9e-64961bb1cadf', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-04 01:27:58.415574+00', ''),
('00000000-0000-0000-0000-000000000000', '45e4135f-e65c-4011-bd07-c6a5bcb33860', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-04 01:27:58.416715+00', ''),
('00000000-0000-0000-0000-000000000000', '95c4b03d-1f15-4ad9-83c1-79f079407908', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-04 02:26:28.440011+00', ''),
('00000000-0000-0000-0000-000000000000', '9b5db737-976a-459f-8f12-eed61184218d', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-04 02:26:28.441438+00', ''),
('00000000-0000-0000-0000-000000000000', '2bbe5699-d14f-4c3f-9c87-52b7f01ed087', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-05 00:52:31.052995+00', ''),
('00000000-0000-0000-0000-000000000000', 'b54ff1b9-6254-43d2-a210-b5d9d2701974', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-05 00:52:31.055077+00', ''),
('00000000-0000-0000-0000-000000000000', 'b0611a51-8bb8-4fab-937e-68a413e02b5e', '{"action":"logout","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account"}', '2024-06-05 01:03:30.844197+00', ''),
('00000000-0000-0000-0000-000000000000', '57f72aa6-2609-4efe-bf06-950681c975f9', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-05 01:03:39.551264+00', ''),
('00000000-0000-0000-0000-000000000000', '3e6b6d3e-c8bd-4cd6-a7ac-b55c59269df1', '{"action":"login","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}', '2024-06-05 01:06:08.194567+00', ''),
('00000000-0000-0000-0000-000000000000', '59805a05-bfba-4dbe-8021-8db6d6b71a4e', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-05 02:02:22.65237+00', ''),
('00000000-0000-0000-0000-000000000000', 'eaf050ba-9bdc-4771-8dcb-1534c38d68b9', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-05 02:02:22.653268+00', ''),
('00000000-0000-0000-0000-000000000000', 'a326a1f9-92f7-472c-bbb7-f10c6f3c1dff', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-05 03:00:26.781265+00', ''),
('00000000-0000-0000-0000-000000000000', '473362fc-dc06-43d5-99df-065c9e671347', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-05 03:00:26.782565+00', ''),
('00000000-0000-0000-0000-000000000000', '3a82cdde-76bf-4cc4-a5e2-b818601100a1', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-07 23:35:28.284863+00', ''),
('00000000-0000-0000-0000-000000000000', 'c3ecf585-5984-4b7e-8115-f57523a31e23', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-07 23:35:28.285858+00', ''),
('00000000-0000-0000-0000-000000000000', 'cc3425df-b1e8-4e7b-8729-80e66eae2b27', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 00:33:56.442635+00', ''),
('00000000-0000-0000-0000-000000000000', 'd991bd91-d600-457c-a887-67a3be188c83', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 00:33:56.44418+00', ''),
('00000000-0000-0000-0000-000000000000', 'a8bd8737-8115-4643-b9a7-f288be170b28', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 02:07:59.069381+00', ''),
('00000000-0000-0000-0000-000000000000', '495056f7-149e-43b3-bc58-1712e3787215', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 02:07:59.070256+00', ''),
('00000000-0000-0000-0000-000000000000', '27ca0341-280d-474a-a3da-39fa4c69748e', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 03:06:06.149018+00', ''),
('00000000-0000-0000-0000-000000000000', 'aa06c3b0-cd66-440a-a184-d44795552f11', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 03:06:06.15067+00', ''),
('00000000-0000-0000-0000-000000000000', '398046e7-2dc1-49e0-92ad-4823c0001271', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 04:04:06.664163+00', ''),
('00000000-0000-0000-0000-000000000000', 'eb481c2d-2f96-4efa-84cb-e715ee547913', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 04:04:06.665465+00', ''),
('00000000-0000-0000-0000-000000000000', '088f4537-0025-44e9-a499-dc85d7034ed3', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 22:08:31.582227+00', ''),
('00000000-0000-0000-0000-000000000000', '7f476998-602e-4d2e-9129-92ea021b1d50', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 22:08:31.583859+00', ''),
('00000000-0000-0000-0000-000000000000', '1c9bf13b-7ecf-4432-a83e-8dcd95eeb6c9', '{"action":"token_refreshed","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 23:06:38.987497+00', ''),
('00000000-0000-0000-0000-000000000000', '07c85a08-4a4b-4238-ac4c-047350db4b7f', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-06-08 23:06:38.988275+00', '');
('00000000-0000-0000-0000-000000000000', 'ff4e9892-902a-4e6f-9493-976acd87e5ad', '{"action":"token_revoked","actor_id":"893c7701-d5df-4415-80bd-1ec089764400","actor_username":"damienostler1@outlook.com","actor_via_sso":false,"log_type":"token"}', '2024-05-28 00:06:54.426626+00', '');
--
@ -156,8 +57,8 @@ INSERT INTO "auth"."audit_log_entries" ("instance_id", "id", "payload", "created
--
INSERT INTO "auth"."users" ("instance_id", "id", "aud", "role", "email", "encrypted_password", "email_confirmed_at", "invited_at", "confirmation_token", "confirmation_sent_at", "recovery_token", "recovery_sent_at", "email_change_token_new", "email_change", "email_change_sent_at", "last_sign_in_at", "raw_app_meta_data", "raw_user_meta_data", "is_super_admin", "created_at", "updated_at", "phone", "phone_confirmed_at", "phone_change", "phone_change_token", "phone_change_sent_at", "email_change_token_current", "email_change_confirm_status", "banned_until", "reauthentication_token", "reauthentication_sent_at", "is_sso_user", "deleted_at", "is_anonymous") VALUES
('00000000-0000-0000-0000-000000000000', 'e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd', 'authenticated', 'authenticated', 'damienostler1@gmail.com', '', '2024-05-28 02:01:35.370491+00', '2024-05-27 15:44:27.171961+00', '', '2024-05-27 15:44:27.171961+00', '', NULL, '', '', NULL, '2024-05-28 02:01:35.372861+00', '{"provider": "email", "providers": ["email"]}', '{}', NULL, '2024-05-27 15:44:27.167772+00', '2024-06-01 01:54:12.344577+00', NULL, NULL, '', '', NULL, '', 0, NULL, '', NULL, false, NULL, false),
('00000000-0000-0000-0000-000000000000', '893c7701-d5df-4415-80bd-1ec089764400', 'authenticated', 'authenticated', 'damienostler1@outlook.com', '$2a$10$ISYdoWsKL7gxfRz7c5IKDOTsmcjNpGgg9OOApYLMOvtOoNTo4HGM6', '2024-05-27 14:10:29.639017+00', NULL, '', NULL, '', NULL, '', '', NULL, '2024-06-05 01:06:08.194961+00', '{"provider": "email", "providers": ["email"]}', '{"sub": "893c7701-d5df-4415-80bd-1ec089764400", "email": "damienostler1@outlook.com", "email_verified": false, "phone_verified": false}', NULL, '2024-05-27 14:10:29.634157+00', '2024-06-08 23:06:38.990134+00', NULL, NULL, '', '', NULL, '', 0, NULL, '', NULL, false, NULL, false);
('00000000-0000-0000-0000-000000000000', 'e11e6fda-d1fc-4b0a-bd61-80233fcb5cdd', 'authenticated', 'authenticated', 'damienostler1@gmail.com', '', NULL, '2024-05-27 15:44:27.171961+00', 'dd81fbfd6a7ad5d261d7f98fb37620afb3f954f350dacd2cac9f4b56', '2024-05-27 15:44:27.171961+00', '', NULL, '', '', NULL, NULL, '{"provider": "email", "providers": ["email"]}', '{}', NULL, '2024-05-27 15:44:27.167772+00', '2024-05-27 15:44:27.174941+00', NULL, NULL, '', '', NULL, '', 0, NULL, '', NULL, false, NULL, false),
('00000000-0000-0000-0000-000000000000', '893c7701-d5df-4415-80bd-1ec089764400', 'authenticated', 'authenticated', 'damienostler1@outlook.com', '$2a$10$ISYdoWsKL7gxfRz7c5IKDOTsmcjNpGgg9OOApYLMOvtOoNTo4HGM6', '2024-05-27 14:10:29.639017+00', NULL, '', NULL, '', NULL, '', '', NULL, '2024-05-27 17:18:49.039562+00', '{"provider": "email", "providers": ["email"]}', '{"sub": "893c7701-d5df-4415-80bd-1ec089764400", "email": "damienostler1@outlook.com", "email_verified": false, "phone_verified": false}', NULL, '2024-05-27 14:10:29.634157+00', '2024-05-28 00:06:54.428256+00', NULL, NULL, '', '', NULL, '', 0, NULL, '', NULL, false, NULL, false);
--
@ -180,8 +81,7 @@ INSERT INTO "auth"."identities" ("provider_id", "user_id", "identity_data", "pro
--
INSERT INTO "auth"."sessions" ("id", "user_id", "created_at", "updated_at", "factor_id", "aal", "not_after", "refreshed_at", "user_agent", "ip", "tag") VALUES
('88176780-1709-4810-92de-36f909e3fafb', '893c7701-d5df-4415-80bd-1ec089764400', '2024-06-05 01:06:08.19499+00', '2024-06-05 01:06:08.19499+00', NULL, 'aal1', NULL, NULL, 'node', '192.168.65.1', NULL),
('8de4dae9-a9f9-44ad-bf2a-c42356feb0e2', '893c7701-d5df-4415-80bd-1ec089764400', '2024-06-05 01:03:39.551694+00', '2024-06-08 23:06:38.991049+00', NULL, 'aal1', NULL, '2024-06-08 23:06:38.990997', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36', '192.168.65.1', NULL);
('ab123eaa-eab2-4fac-a018-82ee972401fd', '893c7701-d5df-4415-80bd-1ec089764400', '2024-05-27 17:18:49.039625+00', '2024-05-28 00:06:54.429202+00', NULL, 'aal1', NULL, '2024-05-28 00:06:54.429127', 'Next.js Middleware', '192.168.65.1', NULL);
--
@ -189,8 +89,7 @@ INSERT INTO "auth"."sessions" ("id", "user_id", "created_at", "updated_at", "fac
--
INSERT INTO "auth"."mfa_amr_claims" ("session_id", "created_at", "updated_at", "authentication_method", "id") VALUES
('8de4dae9-a9f9-44ad-bf2a-c42356feb0e2', '2024-06-05 01:03:39.553156+00', '2024-06-05 01:03:39.553156+00', 'password', '70b28b1d-9c1c-42ed-b9b6-4629b4dc6610'),
('88176780-1709-4810-92de-36f909e3fafb', '2024-06-05 01:06:08.195749+00', '2024-06-05 01:06:08.195749+00', 'password', '2d748036-15f9-49a1-ba18-a9636803f795');
('ab123eaa-eab2-4fac-a018-82ee972401fd', '2024-05-27 17:18:49.041915+00', '2024-05-27 17:18:49.041915+00', 'password', 'be546f0f-4e91-4f94-97e1-cc15c25191be');
--
@ -205,28 +104,17 @@ INSERT INTO "auth"."mfa_amr_claims" ("session_id", "created_at", "updated_at", "
--
-- Data for Name: one_time_tokens; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin
--
--
-- Data for Name: refresh_tokens; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin
--
INSERT INTO "auth"."refresh_tokens" ("instance_id", "id", "token", "user_id", "revoked", "created_at", "updated_at", "parent", "session_id") VALUES
('00000000-0000-0000-0000-000000000000', 83, 'c6bYIcVnSBosWtn4QX8F6w', '893c7701-d5df-4415-80bd-1ec089764400', false, '2024-06-05 01:06:08.195296+00', '2024-06-05 01:06:08.195296+00', NULL, '88176780-1709-4810-92de-36f909e3fafb'),
('00000000-0000-0000-0000-000000000000', 82, 'vgibpWzclaC1SiIWnkWFTw', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-05 01:03:39.55241+00', '2024-06-05 02:02:22.653721+00', NULL, '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 84, 'kcsINvcmhD18guzedNei0Q', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-05 02:02:22.654159+00', '2024-06-05 03:00:26.783216+00', 'vgibpWzclaC1SiIWnkWFTw', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 85, '4eJVeDMlvmAUk20ZqwdGQA', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-05 03:00:26.784329+00', '2024-06-07 23:35:28.286039+00', 'kcsINvcmhD18guzedNei0Q', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 86, 'Nb0zuvJjDL8keK1lF1xX9Q', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-07 23:35:28.28691+00', '2024-06-08 00:33:56.445064+00', '4eJVeDMlvmAUk20ZqwdGQA', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 119, 'y9oA8pEThLtPyEJW2IK3eA', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-08 00:33:56.446127+00', '2024-06-08 02:07:59.070607+00', 'Nb0zuvJjDL8keK1lF1xX9Q', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 120, 'TwWGx47OPQs1BNtkLs9JSA', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-08 02:07:59.07107+00', '2024-06-08 03:06:06.151386+00', 'y9oA8pEThLtPyEJW2IK3eA', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 121, 'mL_eZQCxVdYq7SR-UjEJgQ', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-08 03:06:06.154686+00', '2024-06-08 04:04:06.666124+00', 'TwWGx47OPQs1BNtkLs9JSA', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 122, 'cFLCDOB1QfKd_ydDNLRmoQ', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-08 04:04:06.667264+00', '2024-06-08 22:08:31.584256+00', 'mL_eZQCxVdYq7SR-UjEJgQ', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 123, 'G5KZsQQhC6kFqd0Xht2ypg', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-06-08 22:08:31.584969+00', '2024-06-08 23:06:38.988706+00', 'cFLCDOB1QfKd_ydDNLRmoQ', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2'),
('00000000-0000-0000-0000-000000000000', 124, '4p4Q-c4t1ZH2PUvl_mcYtQ', '893c7701-d5df-4415-80bd-1ec089764400', false, '2024-06-08 23:06:38.989251+00', '2024-06-08 23:06:38.989251+00', 'G5KZsQQhC6kFqd0Xht2ypg', '8de4dae9-a9f9-44ad-bf2a-c42356feb0e2');
('00000000-0000-0000-0000-000000000000', 5, 'vG2zuPl4y7OvEwgeItgotw', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-05-27 17:18:49.040453+00', '2024-05-27 18:17:16.201027+00', NULL, 'ab123eaa-eab2-4fac-a018-82ee972401fd'),
('00000000-0000-0000-0000-000000000000', 6, 'd1l7CJUy3osp97yqDTyibw', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-05-27 18:17:16.201648+00', '2024-05-27 19:15:16.232194+00', 'vG2zuPl4y7OvEwgeItgotw', 'ab123eaa-eab2-4fac-a018-82ee972401fd'),
('00000000-0000-0000-0000-000000000000', 7, 'jrCD6NCqj5WFyjkiWG6BTw', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-05-27 19:15:16.232976+00', '2024-05-27 20:13:20.141029+00', 'd1l7CJUy3osp97yqDTyibw', 'ab123eaa-eab2-4fac-a018-82ee972401fd'),
('00000000-0000-0000-0000-000000000000', 8, 'zFVkt2ATfYlYT0nzRKmX0A', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-05-27 20:13:20.141361+00', '2024-05-27 21:11:27.316138+00', 'jrCD6NCqj5WFyjkiWG6BTw', 'ab123eaa-eab2-4fac-a018-82ee972401fd'),
('00000000-0000-0000-0000-000000000000', 9, 'OWwpxx1Pg11r5r4c2ZUhaw', '893c7701-d5df-4415-80bd-1ec089764400', true, '2024-05-27 21:11:27.316818+00', '2024-05-28 00:06:54.426908+00', 'zFVkt2ATfYlYT0nzRKmX0A', 'ab123eaa-eab2-4fac-a018-82ee972401fd'),
('00000000-0000-0000-0000-000000000000', 10, 'a7ykvMnMcqG4qFeQK6WX5g', '893c7701-d5df-4415-80bd-1ec089764400', false, '2024-05-28 00:06:54.427389+00', '2024-05-28 00:06:54.427389+00', 'OWwpxx1Pg11r5r4c2ZUhaw', 'ab123eaa-eab2-4fac-a018-82ee972401fd');
--
@ -259,63 +147,29 @@ INSERT INTO "auth"."refresh_tokens" ("instance_id", "id", "token", "user_id", "r
--
-- Data for Name: admins; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO "public"."admins" ("user_id", "created_at", "assigner") VALUES
('893c7701-d5df-4415-80bd-1ec089764400', '2024-06-02 21:12:58.507093+00', NULL);
--
-- Data for Name: galleries; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO "public"."galleries" ("name", "column_number", "tier", "nsfw", "tags", "thumbnail_file") VALUES
('Test', 3, 'Free', false, '{twatwat}', ''),
('Testsdadas', 3, 'Free', false, '{}', '');
--
-- Data for Name: interface_configurations; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO "public"."interface_configurations" ("name", "value", "type") VALUES
('primary-dark', '#100120', 'color'),
('secondary-light', '#6F5D90', 'color'),
('secondary-dark', '#2F1D50', 'color'),
('primary', '#18161d', 'color'),
('secondary', '#4F3D70', 'color'),
('primary-light', '#403260', 'color'),
('error-dark', '#5C0D0D', 'color'),
('error', '#862117', 'color'),
('success-dark', '#00A986', 'color'),
('error-light', '#C44C4C', 'color'),
('success-light', '#20E9C6', 'color'),
('success', '#00C9A6', 'color'),
('warning', '#E17558', 'color'),
('warning-light', '#E39578', 'color'),
('info-light', '#424260', 'color'),
('warning-dark', '#C15538', 'color'),
('info-dark', '#020120', 'color'),
('info', '#222140', 'color');
INSERT INTO "public"."galleries" ("name", "column_number", "tier", "tags", "nsfw") VALUES
('Another Test Gallery', 3, 'Free', '{Hentai}', true),
('Test Gallery', 3, 'Tier 1', '{Dojin}', true),
('More Test Gallery', 3, 'Tier 3', '{Hentai,VTuber}', true),
('Some More Testing', 3, 'Tier 2', '{Hentai,Dojin}', false),
('Even More Testing', 3, 'Free', '{VTuber}', false),
('Killa Testing Here', 3, 'Tier 1', '{VTuber,Dojin}', false),
('Popcorn Tester', 3, 'Free', '{Hentai}', true);
--
-- Data for Name: tags; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO "public"."tags" ("name", "gallery_name") VALUES
('twatwat', NULL),
('', NULL);
--
-- Data for Name: tiers; Type: TABLE DATA; Schema: public; Owner: postgres
--
INSERT INTO "public"."tiers" ("name", "price", "color", "description") VALUES
('Free', 0, '#8f6eaa', 'This is a test tier.dasdasd');
INSERT INTO "public"."tags" ("name") VALUES
('Hentai'),
('Dojin
'),
('VTuber');
--
@ -326,54 +180,11 @@ INSERT INTO "public"."user_subscriptions" ("user_id", "tier") VALUES
('893c7701-d5df-4415-80bd-1ec089764400', 'Tier 2');
--
-- Data for Name: objects; Type: TABLE DATA; Schema: storage; Owner: supabase_storage_admin
-- Data for Name: buckets; Type: TABLE DATA; Schema: storage; Owner: supabase_storage_admin
--
--
-- Data for Name: s3_multipart_uploads; Type: TABLE DATA; Schema: storage; Owner: supabase_storage_admin
--
INSERT INTO "storage"."buckets" ("id", "name", "owner", "created_at", "updated_at", "public", "avif_autodetection", "file_size_limit", "allowed_mime_types", "owner_id") VALUES
('galleries', 'galleries', NULL, '2024-05-27 13:06:16.360824+00', '2024-05-27 13:06:16.360824+00', false, false, NULL, NULL, NULL);
--
-- Data for Name: s3_multipart_uploads_parts; Type: TABLE DATA; Schema: storage; Owner: supabase_storage_admin
--
--
-- Data for Name: hooks; Type: TABLE DATA; Schema: supabase_functions; Owner: supabase_functions_admin
--
--
-- Data for Name: secrets; Type: TABLE DATA; Schema: vault; Owner: supabase_admin
--
--
-- Name: refresh_tokens_id_seq; Type: SEQUENCE SET; Schema: auth; Owner: supabase_auth_admin
--
SELECT pg_catalog.setval('"auth"."refresh_tokens_id_seq"', 124, true);
--
-- Name: key_key_id_seq; Type: SEQUENCE SET; Schema: pgsodium; Owner: supabase_admin
--
SELECT pg_catalog.setval('"pgsodium"."key_key_id_seq"', 1, false);
--
-- PostgreSQL database dump complete
--
RESET ALL;

View File

@ -3,8 +3,6 @@ module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/**/*.{js,jsx,ts,tsx}",
"./node_modules/react-tailwindcss-select/dist/index.esm.js"
],
theme: {
extend: {
@ -16,27 +14,31 @@ module.exports = {
},
aspectRatio: {}, // enable aspect-ratio plugin
textShadow: {
// 'pink-glow': '0 0 4px #524FFD, 0 0 4px #524FFD, 0 0 4px #524FFD, 0 0 4px #524FFD',
'pink-glow': '0 0 4px #524FFD, 0 0 4px #524FFD, 0 0 4px #524FFD, 0 0 4px #524FFD',
'purple-grey-glow': '0 0 4px #9f7aea, 0 0 15px #9f7aea, 0 0 20px #9f7aea, 0 0 25px #9f7aea',
'green-grey-glow': '0 0 4px #32CD32, 0 0 15px #32CD32, 0 0 20px #32CD32, 0 0 25px #32CD32',
},
colors: {
'primary': 'var(--color-primary)',
'primary-light': 'var(--color-primary-light)',
'primary-dark': 'var(--color-primary-dark)',
'secondary': 'var(--color-secondary)',
'secondary-light': 'var(--color-secondary-light)',
'secondary-dark': 'var(--color-secondary-dark)',
'error': 'var(--color-error)',
'error-light': 'var(--color-error-light)',
'error-dark': 'var(--color-error-dark)',
'success': 'var(--color-success)',
'success-light': 'var(--color-success-light)',
'success-dark': 'var(--color-success-dark)',
'warning': 'var(--color-warning)',
'warning-light': 'var(--color-warning-light)',
'warning-dark': 'var(--color-warning-dark)',
'info': 'var(--color-info)',
'info-light': 'var(--color-info-light)',
'info-dark': 'var(--color-info-dark)',
"neroshi-blue": {
50: "#EBEBFF",
100: "#D2D2FE",
200: "#A6A4FE",
300: "#7E7CFD",
400: "#524FFD",
500: "#2522FC",
600: "#0703E2",
700: "#0502AB",
800: "#03026F",
900: "#020137",
950: "#01001E"
},
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
btn: {
background: "hsl(var(--btn-background))",
"background-hover": "hsl(var(--btn-background-hover))",
},
},
},
},
@ -45,4 +47,4 @@ module.exports = {
require('tailwindcss-textshadow'),
require('@tailwindcss/aspect-ratio')
],
};
};