! Published.
All checks were successful
Build docker image / build_docker_image (push) Successful in 3m50s

This commit is contained in:
2025-05-01 19:26:39 +02:00
commit 7393af96ac
290 changed files with 40752 additions and 0 deletions

21
src/public/.htaccess Normal file
View File

@@ -0,0 +1,21 @@
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

View File

@@ -0,0 +1 @@
/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[data-field-wrapper]{scroll-margin-top:8rem}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.ms-3{margin-inline-start:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.w-1\/3{width:33.333333%}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity))}@media (prefers-color-scheme:dark){.dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.fi-pagination-items,.fi-pagination-overview,.fi-pagination-records-per-page-select:not(.fi-compact){display:none}@supports (container-type:inline-size){.fi-pagination{container-type:inline-size}@container (min-width: 28rem){.fi-pagination-records-per-page-select.fi-compact{display:none}.fi-pagination-records-per-page-select:not(.fi-compact){display:inline}}@container (min-width: 56rem){.fi-pagination:not(.fi-simple)>.fi-pagination-previous-btn{display:none}.fi-pagination-overview{display:inline}.fi-pagination:not(.fi-simple)>.fi-pagination-next-btn{display:none}.fi-pagination-items{display:flex}}}@supports not (container-type:inline-size){@media (min-width:640px){.fi-pagination-records-per-page-select.fi-compact{display:none}.fi-pagination-records-per-page-select:not(.fi-compact){display:inline}}@media (min-width:768px){.fi-pagination:not(.fi-simple)>.fi-pagination-previous-btn{display:none}.fi-pagination-overview{display:inline}.fi-pagination:not(.fi-simple)>.fi-pagination-next-btn{display:none}.fi-pagination-items{display:flex}}}.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{background-color:#333;border-radius:4px;color:#fff;font-size:14px;line-height:1.4;outline:0;position:relative;transition-property:transform,visibility,opacity;white-space:normal}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{border-top-color:initial;border-width:8px 8px 0;bottom:-7px;left:0;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:initial;border-width:0 8px 8px;left:0;top:-7px;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-left-color:initial;border-width:8px 0 8px 8px;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{border-right-color:initial;border-width:8px 8px 8px 0;left:-7px;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{color:#333;height:16px;width:16px}.tippy-arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.tippy-content{padding:5px 9px;position:relative;z-index:1}.tippy-box[data-theme~=light]{background-color:#fff;box-shadow:0 0 20px 4px #9aa1b126,0 4px 80px -8px #24282f40,0 4px 4px -2px #5b5e6926;color:#26323d}.tippy-box[data-theme~=light][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=light][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=light][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=light][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}.tippy-box[data-theme~=light]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=light]>.tippy-svg-arrow{fill:#fff}.fi-sortable-ghost{opacity:.3}

View File

@@ -0,0 +1,612 @@
{
"variable": [
{
"id": "baseUrl",
"key": "baseUrl",
"type": "string",
"name": "string",
"value": "localhost:9000"
}
],
"info": {
"name": "API documentation",
"_postman_id": "7404156f-c8b1-4ba6-88d2-bfd277ad3788",
"description": "Documentation for the Backend API.",
"schema": "https:\/\/schema.getpostman.com\/json\/collection\/v2.1.0\/collection.json"
},
"item": [
{
"name": "Discord User By snowflake Managment",
"description": "\nAPIs to manage DiscordUser records.\n\nThese endpoints can be used to identify\/create DiscordUser records identified by the [snowflake](#snowflake) that already exists in the discord app.",
"item": [
{
"name": "Get the DiscordUser identified by the specified snowflake.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-user-by-snowflake\/:discord_user_snowflake",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-user-by-snowflake\/:discord_user_snowflake",
"variable": [
{
"id": "discord_user_snowflake",
"key": "discord_user_snowflake",
"value": "481398158916845568",
"description": "A valid [snowflake](#snowflake)."
}
]
},
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": null,
"description": "Returns the [DiscordUser](#discorduser) record for the specified [snowflake](#snowflake), given in the url __discord_user_snowflake__ parameter.\n\nIf it cannot be found, a [**404, Not Found**](#not-found-404) error is returned."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":{\"id\":42,\"snowflake\":\"481398158916845568\",\"user_name\":\"bigfootmcfly\",\"global_name\":\"BigFoot McFly\",\"locale\":\"hu_HU\",\"timezone\":\"Europe\\\/Budapest\"}}",
"name": "success"
},
{
"header": [],
"code": 404,
"body": "{\"message\":\"Not Found.\"}",
"name": "not found"
}
]
},
{
"name": "Get _OR_ Update\/Create the DiscordUser identified by the specified snowflake.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-user-by-snowflake\/:snowflake",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-user-by-snowflake\/:snowflake",
"variable": [
{
"id": "snowflake",
"key": "snowflake",
"value": "481398158916845568",
"description": "A valid [snowflake](#snowflake)."
}
]
},
"method": "PUT",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": {
"mode": "raw",
"raw": "{\"snowflake\":\"481398158916845568\",\"user_name\":\"bigfootmcfly\",\"global_name\":\"BigFoot McFly\",\"locale\":\"en_GB\",\"timezone\":\"Europe\\\/London\"}"
},
"description": "If the record specified by the url __discord_user_snowflake__ parameter exists, it will be updated with the data provided in the body of the request.\n\nIf it does not exists, it will be created using the given data.\n\nReturns the **updated\/created** [DiscordUser](#discorduser) record.\n\nIf anything goes wrong, a [**422, Unprocessable Content**](#unprocessable-content-422) error with more details will be returned."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":{\"id\":42,\"snowflake\":\"481398158916845568\",\"user_name\":\"bigfootmcfly\",\"global_name\":\"BigFoot McFly\",\"locale\":\"en_GB\",\"timezone\":\"Europe\\\/London\"},\"changes\":{\"locale\":{\"old\":\"hu_HU\",\"new\":\"en_GB\"},\"timezone\":{\"old\":\"Europe\\\/Budapest\",\"new\":\"Europe\\\/London\"}}}",
"name": "success"
},
{
"header": [],
"code": 422,
"body": "{\"errors\":{\"snowflake\":[\"The snowflake field is required.\"]}}",
"name": "Unprocessable Content"
}
]
}
]
},
{
"name": "Discord User Managment",
"description": "\nAPIs to manage [DiscordUser](#discorduser) records.\n\nThese endpoints can be used to Query\/Update\/Delete [DiscordUser](#discorduser) records.",
"item": [
{
"name": "List DiscorUsers.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users",
"query": [
{
"key": "page_size",
"value": "25",
"description": "Items per page. Defaults to 100.",
"disabled": false
},
{
"key": "page",
"value": "1",
"description": "Page to query. Defaults to 1.",
"disabled": false
}
],
"raw": "{{baseUrl}}\/api\/v1\/discord-users?page_size=25&page=1"
},
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": null,
"description": "Paginated list of [DiscordUser](#discorduser) records."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":[{\"id\":1,\"snowflake\":\"481398158916845568\",\"user_name\":\"bigfootmcfly\",\"global_name\":\"BigFoot McFly\",\"locale\":\"hu_HU\",\"timezone\":\"Europe\/Budapest\"},{\"id\":6,\"snowflake\":\"860046989130727450\",\"user_name\":\"Teszt Elek\",\"global_name\":\"holnap_is_teszt_elek\",\"locale\":\"hu\",\"timezone\":\"Europe\/Budapest\"},{\"id\":12,\"snowflake\":\"112233445566778899\",\"user_name\":\"Igaz \u00c1lmos\",\"global_name\":\"almos#1244\",\"locale\":null,\"timezone\":null}],\"meta\":{\"current_page\":1,\"from\":1,\"last_page\":1,\"per_page\":10,\"to\":3,\"total\":3}}",
"name": "success"
}
]
},
{
"name": "Create a new DiscordUser record.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-users"
},
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": {
"mode": "raw",
"raw": "{\"snowflake\":\"481398158916845568\",\"user_name\":\"bigfootmcfly\",\"global_name\":\"BigFoot McFly\",\"locale\":\"hu_HU\",\"timezone\":\"Europe\\\/Budapest\"}"
},
"description": "Creates a new [DiscordUser](#discorduser) record with the provided parameters."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":{\"id\":42,\"snowflake\":\"481398158916845568\",\"user_name\":\"bigfootmcfly\",\"global_name\":\"BigFoot McFly\",\"locale\":\"hu_HU\",\"timezone\":\"Europe\\\/Budapest\"}}",
"name": "success"
},
{
"header": [],
"code": 422,
"body": "{\"errors\":{\"snowflake\":[\"The snowflake has already been taken.\"]}}",
"name": "Unprocessable Content"
}
]
},
{
"name": "Get the specified DiscordUser record.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users\/:id",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-users\/:id",
"variable": [
{
"id": "id",
"key": "id",
"value": "42",
"description": "[DiscordUser](#discorduser) ID."
}
]
},
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": null,
"description": "Returns the specified [DiscordUser](#discorduser) record."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":{\"id\":42,\"snowflake\":\"481398158916845568\",\"user_name\":\"bigfootmcfly\",\"global_name\":\"BigFoot McFly\",\"locale\":\"hu_HU\",\"timezone\":\"Europe\\\/Budapest\"}}",
"name": "success"
}
]
},
{
"name": "Update the specified DiscordUser record.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users\/:id",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-users\/:id",
"variable": [
{
"id": "id",
"key": "id",
"value": "42",
"description": "[DiscordUser](#discorduser) ID."
}
]
},
"method": "PUT",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": {
"mode": "raw",
"raw": "{\"snowflake\":\"481398158916845568\",\"timezone\":\"Europe\\\/London\"}"
},
"description": "Updates the specified [DiscordUser](#discorduser) with the supplied values."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":{\"id\":42,\"snowflake\":\"481398158916845568\",\"user_name\":\"bigfootmcfly\",\"global_name\":\"BigFoot McFly\",\"locale\":\"hu_HU\",\"timezone\":\"Europe\\\/London\"}}",
"name": ""
},
{
"header": [],
"code": 422,
"body": "{\"errors\":{\"snowflake\":[\"Invalid snowflake\"]}}",
"name": "Unprocessable Content"
}
]
},
{
"name": "Remove the specified DiscordUser record.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users\/:id",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-users\/:id",
"variable": [
{
"id": "id",
"key": "id",
"value": "42",
"description": "[DiscordUser](#discorduser) ID."
}
]
},
"method": "DELETE",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": {
"mode": "raw",
"raw": "{\"snowflake\":\"481398158916845568\"}"
},
"description": "Removes the specified [DiscordUser](#discorduser) record **with** all the [Remainder](#remainder) records belonging to it."
},
"response": [
{
"header": [],
"code": 204,
"body": "{}",
"name": ""
}
]
}
]
},
{
"name": "Remainder Managment",
"description": "\nAPIs to manage Remainders records.\n\nThese endpoints can be used to Query\/Update\/Delete [Remainder](#remainder) records.",
"item": [
{
"name": "List of Remainder records.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users\/:discord_user_id\/remainders",
"query": [
{
"key": "page_size",
"value": "25",
"description": "Items per page. Defaults to 100.",
"disabled": false
},
{
"key": "page",
"value": "1",
"description": "Page to query. Defaults to 1.",
"disabled": false
}
],
"raw": "{{baseUrl}}\/api\/v1\/discord-users\/:discord_user_id\/remainders?page_size=25&page=1",
"variable": [
{
"id": "discord_user_id",
"key": "discord_user_id",
"value": "42",
"description": "[DiscordUser](#discorduser) ID."
}
]
},
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": null,
"description": "Paginated list of [Remainder](#remainder) records belonging to the specified [DiscordUser](#discorduser)."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":[{\"id\":38,\"discord_user_id\":42,\"channel_id\":null,\"due_at\":1736259300,\"message\":\"Update todo list\",\"status\":\"new\",\"error\":null},{\"id\":121,\"discord_user_id\":42,\"channel_id\":null,\"due_at\":1736259480,\"message\":\"Water plants\",\"status\":\"new\",\"error\":null}],\"meta\":{\"current_page\":1,\"from\":1,\"last_page\":1,\"per_page\":25,\"to\":2,\"total\":2}}",
"name": "success"
}
]
},
{
"name": "Create a new Remainder record.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users\/:discord_user_id\/remainders",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-users\/:discord_user_id\/remainders",
"variable": [
{
"id": "discord_user_id",
"key": "discord_user_id",
"value": "42",
"description": "[DiscordUser](#discorduser) ID."
}
]
},
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": {
"mode": "raw",
"raw": "{\"due_at\":\"1732550400\",\"message\":\"Check maintance results!\"}"
},
"description": "Creates a new [Remainder](#remainder) record with the provided parameters."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":{\"id\":18568,\"discord_user_id\":42,\"channel_id\":null,\"due_at\":1732550400,\"message\":\"Check maintance results!\",\"status\":\"new\",\"error\":null}}",
"name": ""
}
]
},
{
"name": "Update the specified Remainder record.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users\/:discord_user_id\/remainders\/:id",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-users\/:discord_user_id\/remainders\/:id",
"variable": [
{
"id": "discord_user_id",
"key": "discord_user_id",
"value": "42",
"description": "[DiscordUser](#discorduser) ID."
},
{
"id": "id",
"key": "id",
"value": "18568",
"description": "[Remainder](#remainder) ID."
}
]
},
"method": "PUT",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": {
"mode": "raw",
"raw": "{\"status\":\"failed\",\"error\":\"Unknow user\"}"
},
"description": "Updates the specified [Remainder](#remainder) record with the provided parameters."
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":{\"id\":18568,\"discord_user_id\":42,\"channel_id\":null,\"due_at\":1732550400,\"message\":\"Check maintance results!\",\"status\":\"failed\",\"error\":\"Unknow user\"},\"changes\":{\"status\":{\"old\":\"new\",\"new\":\"failed\"},\"error\":{\"old\":null,\"new\":\"Unknow user\"}}}",
"name": ""
}
]
},
{
"name": "Remove the specified Remainder record.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/discord-users\/:discord_user_id\/remainders\/:id",
"query": [],
"raw": "{{baseUrl}}\/api\/v1\/discord-users\/:discord_user_id\/remainders\/:id",
"variable": [
{
"id": "discord_user_id",
"key": "discord_user_id",
"value": "42",
"description": "[DiscordUser](#discorduser) ID."
},
{
"id": "id",
"key": "id",
"value": "18568",
"description": "[Remainder](#remainder) ID."
}
]
},
"method": "DELETE",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": {
"mode": "raw",
"raw": "{\"snowflake\":\"481398158916845568\"}"
},
"description": "Removes the specified [Remainder](#remainder) record with the provided parameters."
},
"response": [
{
"header": [],
"code": 204,
"body": "{}",
"name": ""
}
]
}
]
},
{
"name": "Remainder by DueAt Managment",
"description": "\nAPI to get Remainder records.\n\nThis endpoint can be used to Query the actual [Remainder](#remainder) records.",
"item": [
{
"name": "Returns all the \"actual\" reaminders for the given second.",
"request": {
"url": {
"host": "{{baseUrl}}",
"path": "api\/v1\/remainder-by-due-at\/:due_at",
"query": [
{
"key": "page_size",
"value": "25",
"description": "Items per page. Defaults to 100.",
"disabled": false
},
{
"key": "page",
"value": "1",
"description": "Page to query. Defaults to 1.",
"disabled": false
}
],
"raw": "{{baseUrl}}\/api\/v1\/remainder-by-due-at\/:due_at?page_size=25&page=1",
"variable": [
{
"id": "due_at",
"key": "due_at",
"value": "1735685999",
"description": "The time ([timestamp](#timestamp)) of the requested remainders."
}
]
},
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "application\/json"
},
{
"key": "Accept",
"value": "application\/json"
}
],
"body": null,
"description": ""
},
"response": [
{
"header": [],
"code": 200,
"body": "{\"data\":[{\"id\":56,\"discord_user_id\":42,\"channel_id\":null,\"due_at\":1735685999,\"message\":\"Update conatiner registry!\",\"status\":\"new\",\"error\":null},{\"id\":192,\"discord_user_id\":47,\"channel_id\":null,\"due_at\":1735685999,\"message\":\"Get some milk\",\"status\":\"new\",\"error\":null}],\"meta\":{\"current_page\":1,\"from\":1,\"last_page\":1,\"per_page\":100,\"to\":2,\"total\":2}}",
"name": "success"
}
]
}
]
}
],
"auth": {
"type": "bearer",
"bearer": [
{
"key": "Authorization",
"type": "string"
}
]
}
}

View File

@@ -0,0 +1,393 @@
/* Copied from https://github.com/slatedocs/slate/blob/c4b4c0b8f83e891ca9fab6bbe9a1a88d5fe41292/stylesheets/print.css and unminified */
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
html {
font-family: sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%
}
body {
margin: 0
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block
}
audio,
canvas,
progress,
video {
display: inline-block;
vertical-align: baseline
}
audio:not([controls]) {
display: none;
height: 0
}
[hidden],
template {
display: none
}
a {
background-color: transparent
}
a:active,
a:hover {
outline: 0
}
abbr[title] {
border-bottom: 1px dotted
}
b,
strong {
font-weight: bold
}
dfn {
font-style: italic
}
h1 {
font-size: 2em;
margin: 0.67em 0
}
mark {
background: #ff0;
color: #000
}
small {
font-size: 80%
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline
}
sup {
top: -0.5em
}
sub {
bottom: -0.25em
}
img {
border: 0
}
svg:not(:root) {
overflow: hidden
}
figure {
margin: 1em 40px
}
hr {
box-sizing: content-box;
height: 0
}
pre {
overflow: auto
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em
}
button,
input,
optgroup,
select,
textarea {
color: inherit;
font: inherit;
margin: 0
}
button {
overflow: visible
}
button,
select {
text-transform: none
}
button,
html input[type="button"],
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button;
cursor: pointer
}
button[disabled],
html input[disabled] {
cursor: default
}
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0
}
input {
line-height: normal
}
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box;
padding: 0
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto
}
input[type="search"] {
-webkit-appearance: textfield;
box-sizing: content-box
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em
}
legend {
border: 0;
padding: 0
}
textarea {
overflow: auto
}
optgroup {
font-weight: bold
}
table {
border-collapse: collapse;
border-spacing: 0
}
td,
th {
padding: 0
}
.content h1,
.content h2,
.content h3,
.content h4,
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 14px
}
.content h1,
.content h2,
.content h3,
.content h4 {
font-weight: bold
}
.content pre,
.content code {
font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif;
font-size: 12px;
line-height: 1.5
}
.content pre,
.content code {
word-break: break-all;
-webkit-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto
}
@font-face {
font-family: 'slate';
src: url(../fonts/slate.eot?-syv14m);
src: url(../fonts/slate.eot?#iefix-syv14m) format("embedded-opentype"), url(../fonts/slate.woff2?-syv14m) format("woff2"), url(../fonts/slate.woff?-syv14m) format("woff"), url(../fonts/slate.ttf?-syv14m) format("truetype"), url(../fonts/slate.svg?-syv14m#slate) format("svg");
font-weight: normal;
font-style: normal
}
.content aside.warning:before,
.content aside.notice:before,
.content aside.success:before {
font-family: 'slate';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1
}
.content aside.warning:before {
content: "\e600"
}
.content aside.notice:before {
content: "\e602"
}
.content aside.success:before {
content: "\e606"
}
.tocify,
.toc-footer,
.lang-selector,
.search,
#nav-button {
display: none
}
.tocify-wrapper>img {
margin: 0 auto;
display: block
}
.content {
font-size: 12px
}
.content pre,
.content code {
border: 1px solid #999;
border-radius: 5px;
font-size: 0.8em
}
.content pre code {
border: 0
}
.content pre {
padding: 1.3em
}
.content code {
padding: 0.2em
}
.content table {
border: 1px solid #999
}
.content table tr {
border-bottom: 1px solid #999
}
.content table td,
.content table th {
padding: 0.7em
}
.content p {
line-height: 1.5
}
.content a {
text-decoration: none;
color: #000
}
.content h1 {
font-size: 2.5em;
padding-top: 0.5em;
padding-bottom: 0.5em;
margin-top: 1em;
margin-bottom: 21px;
border: 2px solid #ccc;
border-width: 2px 0;
text-align: center
}
.content h2 {
font-size: 1.8em;
margin-top: 2em;
border-top: 2px solid #ccc;
padding-top: 0.8em
}
.content h1+h2,
.content h1+div+h2 {
border-top: none;
padding-top: 0;
margin-top: 0
}
.content h3,
.content h4 {
font-size: 0.8em;
margin-top: 1.5em;
margin-bottom: 0.8em;
text-transform: uppercase
}
.content h5,
.content h6 {
text-transform: uppercase
}
.content aside {
padding: 1em;
border: 1px solid #ccc;
border-radius: 5px;
margin-top: 1.5em;
margin-bottom: 1.5em;
line-height: 1.6
}
.content aside:before {
vertical-align: middle;
padding-right: 0.5em;
font-size: 14px
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

3251
src/public/docs/index.html Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,149 @@
document.addEventListener('DOMContentLoaded', function() {
const updateHash = function (id) {
window.location.hash = `#${id}`;
};
const navButton = document.getElementById('nav-button');
const menuWrapper = document.querySelector('.tocify-wrapper');
function toggleSidebar(event) {
event.preventDefault();
if (menuWrapper) {
menuWrapper.classList.toggle('open');
navButton.classList.toggle('open');
}
}
function closeSidebar() {
if (menuWrapper) {
menuWrapper.classList.remove('open');
navButton.classList.remove('open');
}
}
navButton.addEventListener('click', toggleSidebar);
window.hljs.highlightAll();
const wrapper = document.getElementById('toc');
// https://jets.js.org/
window.jets = new window.Jets({
// *OR - Selects elements whose values contains at least one part of search substring
searchSelector: '*OR',
searchTag: '#input-search',
contentTag: '#toc li',
didSearch: function(term) {
wrapper.classList.toggle('jets-searching', String(term).length > 0)
},
// map these accent keys to plain values
diacriticsMap: {
a: 'ÀÁÂÃÄÅàáâãäåĀāąĄ',
c: 'ÇçćĆčČ',
d: 'đĐďĎ',
e: 'ÈÉÊËèéêëěĚĒēęĘ',
i: 'ÌÍÎÏìíîïĪī',
l: 'łŁ',
n: 'ÑñňŇńŃ',
o: 'ÒÓÔÕÕÖØòóôõöøŌō',
r: 'řŘ',
s: 'ŠšśŚ',
t: 'ťŤ',
u: 'ÙÚÛÜùúûüůŮŪū',
y: 'ŸÿýÝ',
z: 'ŽžżŻźŹ'
}
});
function hashChange() {
const currentItems = document.querySelectorAll('.tocify-subheader.visible, .tocify-item.tocify-focus');
Array.from(currentItems).forEach((elem) => {
elem.classList.remove('visible', 'tocify-focus');
});
const currentTag = document.querySelector(`a[href="${window.location.hash}"]`);
if (currentTag) {
const parent = currentTag.closest('.tocify-subheader');
if (parent) {
parent.classList.add('visible');
}
const siblings = currentTag.closest('.tocify-header');
if (siblings) {
Array.from(siblings.querySelectorAll('.tocify-subheader')).forEach((elem) => {
elem.classList.add('visible');
});
}
currentTag.parentElement.classList.add('tocify-focus');
// wait for dom changes to be done
setTimeout(() => {
currentTag.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' });
// only close the sidebar on level-2 events
if (currentTag.parentElement.classList.contains('level-2')) {
closeSidebar();
}
}, 1500);
}
}
let languages = JSON.parse(document.body.getAttribute('data-languages'));
// Support a key => value object where the key is the name, or an array of strings where the value is the name
if (!Array.isArray(languages)) {
languages = Object.values(languages);
}
// if there is no language use the first one
const currentLanguage = window.localStorage.getItem('language') || languages[0];
const languageStyle = document.getElementById('language-style');
const langSelector = document.querySelectorAll('.lang-selector button.lang-button');
function setActiveLanguage(newLanguage) {
window.localStorage.setItem('language', newLanguage);
if (!languageStyle) {
return;
}
const newStyle = languages.map((language) => {
return language === newLanguage
// the current one should be visible
? `body .content .${language}-example pre { display: block; }`
// the inactive one should be hidden
: `body .content .${language}-example pre { display: none; }`;
}).join(`\n`);
Array.from(langSelector).forEach((elem) => {
elem.classList.toggle('active', elem.getAttribute('data-language-name') === newLanguage);
});
const activeHash = window.location.hash.slice(1);
languageStyle.innerHTML = newStyle;
setTimeout(() => {
updateHash(activeHash);
}, 200);
}
setActiveLanguage(currentLanguage);
Array.from(langSelector).forEach((elem) => {
elem.addEventListener('click', () => {
const newLanguage = elem.getAttribute('data-language-name');
setActiveLanguage(newLanguage);
});
});
window.addEventListener('hashchange', hashChange, false);
const divs = document.querySelectorAll('.content h1[id], .content h2[id]');
document.addEventListener('scroll', () => {
divs.forEach(item => {
const rect = item.getBoundingClientRect();
if (rect.top > 0 && rect.top < 150) {
const location = window.location.toString().split('#')[0];
history.replaceState(null, null, location + '#' + item.id);
hashChange();
}
});
});
hashChange();
});

View File

@@ -0,0 +1,289 @@
window.abortControllers = {};
function cacheAuthValue() {
// Whenever the auth header is set for one endpoint, cache it for the others
window.lastAuthValue = '';
let authInputs = document.querySelectorAll(`.auth-value`)
authInputs.forEach(el => {
el.addEventListener('input', (event) => {
window.lastAuthValue = event.target.value;
authInputs.forEach(otherInput => {
if (otherInput === el) return;
// Don't block the main thread
setTimeout(() => {
otherInput.value = window.lastAuthValue;
}, 0);
});
});
});
}
window.addEventListener('DOMContentLoaded', cacheAuthValue);
function getCookie(name) {
if (!document.cookie) {
return null;
}
const cookies = document.cookie.split(';')
.map(c => c.trim())
.filter(c => c.startsWith(name + '='));
if (cookies.length === 0) {
return null;
}
return decodeURIComponent(cookies[0].split('=')[1]);
}
function tryItOut(endpointId) {
document.querySelector(`#btn-tryout-${endpointId}`).hidden = true;
document.querySelector(`#btn-canceltryout-${endpointId}`).hidden = false;
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`).hidden = false;
executeBtn.disabled = false;
// Show all input fields
document.querySelectorAll(`input[data-endpoint=${endpointId}],label[data-endpoint=${endpointId}]`)
.forEach(el => el.style.display = 'block');
if (document.querySelector(`#form-${endpointId}`).dataset.authed === "1") {
const authElement = document.querySelector(`#auth-${endpointId}`);
authElement && (authElement.hidden = false);
}
// Expand all nested fields
document.querySelectorAll(`#form-${endpointId} details`)
.forEach(el => el.open = true);
}
function cancelTryOut(endpointId) {
if (window.abortControllers[endpointId]) {
window.abortControllers[endpointId].abort();
delete window.abortControllers[endpointId];
}
document.querySelector(`#btn-tryout-${endpointId}`).hidden = false;
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`);
executeBtn.hidden = true;
executeBtn.textContent = executeBtn.dataset.initialText;
document.querySelector(`#btn-canceltryout-${endpointId}`).hidden = true;
// Hide inputs
document.querySelectorAll(`input[data-endpoint=${endpointId}],label[data-endpoint=${endpointId}]`)
.forEach(el => el.style.display = 'none');
document.querySelectorAll(`#form-${endpointId} details`)
.forEach(el => el.open = false);
const authElement = document.querySelector(`#auth-${endpointId}`);
authElement && (authElement.hidden = true);
document.querySelector('#execution-results-' + endpointId).hidden = true;
document.querySelector('#execution-error-' + endpointId).hidden = true;
// Revert to sample code blocks
document.querySelector('#example-requests-' + endpointId).hidden = false;
document.querySelector('#example-responses-' + endpointId).hidden = false;
}
function makeAPICall(method, path, body = {}, query = {}, headers = {}, endpointId = null) {
console.log({endpointId, path, body, query, headers});
if (!(body instanceof FormData) && typeof body !== "string") {
body = JSON.stringify(body)
}
const url = new URL(window.tryItOutBaseUrl + '/' + path.replace(/^\//, ''));
// We need this function because if you try to set an array or object directly to a URLSearchParams object,
// you'll get [object Object] or the array.toString()
function addItemToSearchParamsObject(key, value, searchParams) {
if (Array.isArray(value)) {
value.forEach((v, i) => {
// Append {filters: [first, second]} as filters[0]=first&filters[1]second
addItemToSearchParamsObject(key + '[' + i + ']', v, searchParams);
})
} else if (typeof value === 'object' && value !== null) {
Object.keys(value).forEach((i) => {
// Append {filters: {name: first}} as filters[name]=first
addItemToSearchParamsObject(key + '[' + i + ']', value[i], searchParams);
});
} else {
searchParams.append(key, value);
}
}
Object.keys(query)
.forEach(key => addItemToSearchParamsObject(key, query[key], url.searchParams));
window.abortControllers[endpointId] = new AbortController();
return fetch(url, {
method,
headers,
body: method === 'GET' ? undefined : body,
signal: window.abortControllers[endpointId].signal,
referrer: window.tryItOutBaseUrl,
mode: 'cors',
credentials: 'same-origin',
})
.then(response => Promise.all([response.status, response.statusText, response.text(), response.headers]));
}
function hideCodeSamples(endpointId) {
document.querySelector('#example-requests-' + endpointId).hidden = true;
document.querySelector('#example-responses-' + endpointId).hidden = true;
}
function handleResponse(endpointId, response, status, headers) {
hideCodeSamples(endpointId);
// Hide error views
document.querySelector('#execution-error-' + endpointId).hidden = true;
const responseContentEl = document.querySelector('#execution-response-content-' + endpointId);
// Check if the response contains Laravel's dd() default dump output
const isLaravelDump = response.includes('Sfdump');
// If it's a Laravel dd() dump, use innerHTML to render it safely
if (isLaravelDump) {
responseContentEl.innerHTML = response === '' ? responseContentEl.dataset.emptyResponseText : response;
} else {
// Otherwise, stick to textContent for regular responses
responseContentEl.textContent = response === '' ? responseContentEl.dataset.emptyResponseText : response;
}
// Prettify it if it's JSON
let isJson = false;
try {
const jsonParsed = JSON.parse(response);
if (jsonParsed !== null) {
isJson = true;
response = JSON.stringify(jsonParsed, null, 4);
responseContentEl.textContent = response;
}
} catch (e) {
}
isJson && window.hljs.highlightElement(responseContentEl);
const statusEl = document.querySelector('#execution-response-status-' + endpointId);
statusEl.textContent = ` (${status})`;
document.querySelector('#execution-results-' + endpointId).hidden = false;
statusEl.scrollIntoView({behavior: "smooth", block: "center"});
}
function handleError(endpointId, err) {
hideCodeSamples(endpointId);
// Hide response views
document.querySelector('#execution-results-' + endpointId).hidden = true;
// Show error views
let errorMessage = err.message || err;
const $errorMessageEl = document.querySelector('#execution-error-message-' + endpointId);
$errorMessageEl.textContent = errorMessage + $errorMessageEl.textContent;
const errorEl = document.querySelector('#execution-error-' + endpointId);
errorEl.hidden = false;
errorEl.scrollIntoView({behavior: "smooth", block: "center"});
}
async function executeTryOut(endpointId, form) {
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`);
executeBtn.textContent = executeBtn.dataset.loadingText;
executeBtn.disabled = true;
executeBtn.scrollIntoView({behavior: "smooth", block: "center"});
let body;
let setter;
if (form.dataset.hasfiles === "1") {
body = new FormData();
setter = (name, value) => body.append(name, value);
} else if (form.dataset.isarraybody === "1") {
body = [];
setter = (name, value) => _.set(body, name, value);
} else {
body = {};
setter = (name, value) => _.set(body, name, value);
}
const bodyParameters = form.querySelectorAll('input[data-component=body]');
bodyParameters.forEach(el => {
let value = el.value;
if (el.type === 'number' && typeof value === 'string') {
value = parseFloat(value);
}
if (el.type === 'file' && el.files[0]) {
setter(el.name, el.files[0]);
return;
}
if (el.type !== 'radio') {
if (value === "" && el.required === false) {
// Don't include empty optional values in the request
return;
}
setter(el.name, value);
return;
}
if (el.checked) {
value = (value === 'false') ? false : true;
setter(el.name, value);
}
});
const query = {};
const queryParameters = form.querySelectorAll('input[data-component=query]');
queryParameters.forEach(el => {
if (el.type !== 'radio' || (el.type === 'radio' && el.checked)) {
if (el.value === '') {
// Don't include empty values in the request
return;
}
_.set(query, el.name, el.value);
}
});
let path = form.dataset.path;
const urlParameters = form.querySelectorAll('input[data-component=url]');
urlParameters.forEach(el => (path = path.replace(new RegExp(`\\{${el.name}\\??}`), el.value)));
const headers = Object.fromEntries(Array.from(form.querySelectorAll('input[data-component=header]'))
.map(el => [el.name, el.value]));
// When using FormData, the browser sets the correct content-type + boundary
let method = form.dataset.method;
if (body instanceof FormData) {
delete headers['Content-Type'];
// When using FormData with PUT or PATCH, use method spoofing so PHP can access the post body
if (['PUT', 'PATCH'].includes(form.dataset.method)) {
method = 'POST';
setter('_method', form.dataset.method);
}
}
let preflightPromise = Promise.resolve();
if (window.useCsrf && window.csrfUrl) {
preflightPromise = makeAPICall('GET', window.csrfUrl).then(() => {
headers['X-XSRF-TOKEN'] = getCookie('XSRF-TOKEN');
});
}
return preflightPromise.then(() => makeAPICall(method, path, body, query, headers, endpointId))
.then(([responseStatus, statusText, responseContent, responseHeaders]) => {
handleResponse(endpointId, responseContent, responseStatus, responseHeaders)
})
.catch(err => {
if (err.name === "AbortError") {
console.log("Request cancelled");
return;
}
console.log("Error while making request: ", err);
handleError(endpointId, err);
})
.finally(() => {
executeBtn.disabled = false;
executeBtn.textContent = executeBtn.dataset.initialText;
});
}

1151
src/public/docs/openapi.yaml Normal file

File diff suppressed because it is too large Load Diff

0
src/public/favicon.ico Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

17
src/public/index.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
// Determine if the application is in maintenance mode...
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
require $maintenance;
}
// Register the Composer autoloader...
require __DIR__.'/../vendor/autoload.php';
// Bootstrap Laravel and handle the request...
(require_once __DIR__.'/../bootstrap/app.php')
->handleRequest(Request::capture());

View File

@@ -0,0 +1,31 @@
// resources/js/observer.js
function observer() {
return {
observer: null,
init: function() {
const nodeSelector = ".fi-global-search-field";
const node = document.querySelector(nodeSelector);
if (node) {
this.checkForTargetClass(node);
}
},
checkForTargetClass: function(node) {
const inputElement = node.querySelector("input[type=search]");
if (inputElement) {
["click", "focus", "keydown", "input"].forEach((event) => {
inputElement.addEventListener(event, () => {
this.handleNodeActions(inputElement);
});
});
}
},
handleNodeActions: function(node) {
Alpine.store("globalSearchModalStore").showModal();
node.disabled = true;
}
};
}
export {
observer as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vcmVzb3VyY2VzL2pzL29ic2VydmVyLmpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBvYnNlcnZlcigpIHtcbiAgcmV0dXJuIHtcbiAgICBvYnNlcnZlcjogbnVsbCxcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBub2RlU2VsZWN0b3IgPSBcIi5maS1nbG9iYWwtc2VhcmNoLWZpZWxkXCI7XG4gICAgICBjb25zdCBub2RlID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihub2RlU2VsZWN0b3IpOyAgICAgIFxuICAgICAgaWYgKG5vZGUpIHtcbiAgICAgICAgdGhpcy5jaGVja0ZvclRhcmdldENsYXNzKG5vZGUpO1xuICAgICAgfVxuICAgIH0sXG4gICAgY2hlY2tGb3JUYXJnZXRDbGFzczogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgIGNvbnN0IGlucHV0RWxlbWVudCA9IG5vZGUucXVlcnlTZWxlY3RvcihcImlucHV0W3R5cGU9c2VhcmNoXVwiKTtcbiAgICAgIGlmIChpbnB1dEVsZW1lbnQpIHtcbiAgICAgICAgW1wiY2xpY2tcIiwgXCJmb2N1c1wiLCBcImtleWRvd25cIiwgXCJpbnB1dFwiXS5mb3JFYWNoKChldmVudCkgPT4ge1xuICAgICAgICAgIGlucHV0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZU5vZGVBY3Rpb25zKGlucHV0RWxlbWVudCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sXG4gICAgaGFuZGxlTm9kZUFjdGlvbnM6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICBBbHBpbmUuc3RvcmUoXCJnbG9iYWxTZWFyY2hNb2RhbFN0b3JlXCIpLnNob3dNb2RhbCgpO1xuICAgICAgbm9kZS5kaXNhYmxlZCA9IHRydWU7XG4gICAgfSxcbiAgfTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBZSxTQUFSLFdBQTRCO0FBQ2pDLFNBQU87QUFBQSxJQUNMLFVBQVU7QUFBQSxJQUNWLE1BQU0sV0FBWTtBQUNoQixZQUFNLGVBQWU7QUFDckIsWUFBTSxPQUFPLFNBQVMsY0FBYyxZQUFZO0FBQ2hELFVBQUksTUFBTTtBQUNSLGFBQUssb0JBQW9CLElBQUk7QUFBQSxNQUMvQjtBQUFBLElBQ0Y7QUFBQSxJQUNBLHFCQUFxQixTQUFVLE1BQU07QUFDbkMsWUFBTSxlQUFlLEtBQUssY0FBYyxvQkFBb0I7QUFDNUQsVUFBSSxjQUFjO0FBQ2hCLFNBQUMsU0FBUyxTQUFTLFdBQVcsT0FBTyxFQUFFLFFBQVEsQ0FBQyxVQUFVO0FBQ3hELHVCQUFhLGlCQUFpQixPQUFPLE1BQU07QUFDekMsaUJBQUssa0JBQWtCLFlBQVk7QUFBQSxVQUNyQyxDQUFDO0FBQUEsUUFDSCxDQUFDO0FBQUEsTUFDSDtBQUFBLElBQ0Y7QUFBQSxJQUNBLG1CQUFtQixTQUFVLE1BQU07QUFDakMsYUFBTyxNQUFNLHdCQUF3QixFQUFFLFVBQVU7QUFDakQsV0FBSyxXQUFXO0FBQUEsSUFDbEI7QUFBQSxFQUNGO0FBQ0Y7IiwKICAibmFtZXMiOiBbXQp9Cg==

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
// resources/js/swappable.js
function swappable() {
return {
startY: 0,
currentY: 0,
moving: false,
init() {
Alpine.effect(() => {
this.$el.parentElement.parentElement.style.transform = `translateY(${this.distance}px)`;
});
},
get distance() {
return this.moving ? Math.max(0, this.currentY - this.startY) : 0;
},
handleMovingStart(event) {
this.moving = true;
this.startY = this.currentY = event.touches[0].clientY;
},
handleWhileMoving(event) {
this.currentY = event.touches[0].clientY;
},
handleMovingEnd() {
if (this.distance > 100) {
Alpine.store("globalSearchModalStore").hideModal();
}
this.moving = false;
}
};
}
export {
swappable as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vcmVzb3VyY2VzL2pzL3N3YXBwYWJsZS5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLy8gdGhpcyBjb2RlIHdhcyB3cml0dGVuIGJlZm9yZSBtYWtpbmcgdGhlIHNlZWFyY2ggY29tcG9uZW50IG5vdCBsYXp5IGxvYWRlZCBjb21wb25lbnRcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIHN3YXBwYWJsZSgpIHtcclxuICByZXR1cm4ge1xyXG4gICAgc3RhcnRZOiAwLFxyXG4gICAgY3VycmVudFk6IDAsXHJcbiAgICBtb3Zpbmc6IGZhbHNlLFxyXG4gICAgaW5pdCgpIHtcclxuICAgICAgQWxwaW5lLmVmZmVjdCgoKSA9PiB7XHJcbiAgICAgICAgdGhpcy4kZWwucGFyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50LnN0eWxlLnRyYW5zZm9ybSA9IGB0cmFuc2xhdGVZKCR7dGhpcy5kaXN0YW5jZX1weClgO1xyXG4gICAgICB9KTtcclxuICAgIH0sXHJcbiAgICBnZXQgZGlzdGFuY2UoKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLm1vdmluZyA/IE1hdGgubWF4KDAsIHRoaXMuY3VycmVudFkgLSB0aGlzLnN0YXJ0WSkgOiAwO1xyXG4gICAgfSxcclxuXHJcbiAgICBoYW5kbGVNb3ZpbmdTdGFydChldmVudCkge1xyXG4gICAgICB0aGlzLm1vdmluZyA9IHRydWU7XHJcbiAgICAgIHRoaXMuc3RhcnRZID0gdGhpcy5jdXJyZW50WSA9IGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WTtcclxuICAgIH0sXHJcbiAgICBoYW5kbGVXaGlsZU1vdmluZyhldmVudCkge1xyXG4gICAgICB0aGlzLmN1cnJlbnRZID0gZXZlbnQudG91Y2hlc1swXS5jbGllbnRZO1xyXG4gICAgfSxcclxuICAgIGhhbmRsZU1vdmluZ0VuZCgpIHtcclxuICAgICAgaWYgKHRoaXMuZGlzdGFuY2UgPiAxMDApIHtcclxuICAgICAgICBBbHBpbmUuc3RvcmUoXCJnbG9iYWxTZWFyY2hNb2RhbFN0b3JlXCIpLmhpZGVNb2RhbCgpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMubW92aW5nID0gZmFsc2U7XHJcbiAgICB9LFxyXG4gIH07XHJcbn1cclxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUVlLFNBQVIsWUFBNkI7QUFDbEMsU0FBTztBQUFBLElBQ0wsUUFBUTtBQUFBLElBQ1IsVUFBVTtBQUFBLElBQ1YsUUFBUTtBQUFBLElBQ1IsT0FBTztBQUNMLGFBQU8sT0FBTyxNQUFNO0FBQ2xCLGFBQUssSUFBSSxjQUFjLGNBQWMsTUFBTSxZQUFZLGNBQWMsS0FBSyxRQUFRO0FBQUEsTUFDcEYsQ0FBQztBQUFBLElBQ0g7QUFBQSxJQUNBLElBQUksV0FBVztBQUNiLGFBQU8sS0FBSyxTQUFTLEtBQUssSUFBSSxHQUFHLEtBQUssV0FBVyxLQUFLLE1BQU0sSUFBSTtBQUFBLElBQ2xFO0FBQUEsSUFFQSxrQkFBa0IsT0FBTztBQUN2QixXQUFLLFNBQVM7QUFDZCxXQUFLLFNBQVMsS0FBSyxXQUFXLE1BQU0sUUFBUSxDQUFDLEVBQUU7QUFBQSxJQUNqRDtBQUFBLElBQ0Esa0JBQWtCLE9BQU87QUFDdkIsV0FBSyxXQUFXLE1BQU0sUUFBUSxDQUFDLEVBQUU7QUFBQSxJQUNuQztBQUFBLElBQ0Esa0JBQWtCO0FBQ2hCLFVBQUksS0FBSyxXQUFXLEtBQUs7QUFDdkIsZUFBTyxNQUFNLHdCQUF3QixFQUFFLFVBQVU7QUFBQSxNQUNuRDtBQUNBLFdBQUssU0FBUztBQUFBLElBQ2hCO0FBQUEsRUFDRjtBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo=

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
function r({state:o}){return{state:o,rows:[],shouldUpdateRows:!0,init:function(){this.updateRows(),this.rows.length<=0?this.rows.push({key:"",value:""}):this.updateState(),this.$watch("state",(t,e)=>{let s=i=>i===null?0:Array.isArray(i)?i.length:typeof i!="object"?0:Object.keys(i).length;s(t)===0&&s(e)===0||this.updateRows()})},addRow:function(){this.rows.push({key:"",value:""}),this.updateState()},deleteRow:function(t){this.rows.splice(t,1),this.rows.length<=0&&this.addRow(),this.updateState()},reorderRows:function(t){let e=Alpine.raw(this.rows);this.rows=[];let s=e.splice(t.oldIndex,1)[0];e.splice(t.newIndex,0,s),this.$nextTick(()=>{this.rows=e,this.updateState()})},updateRows:function(){if(!this.shouldUpdateRows){this.shouldUpdateRows=!0;return}let t=[];for(let[e,s]of Object.entries(this.state??{}))t.push({key:e,value:s});this.rows=t},updateState:function(){let t={};this.rows.forEach(e=>{e.key===""||e.key===null||(t[e.key]=e.value)}),this.shouldUpdateRows=!1,this.state=t}}}export{r as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
function i({state:a,splitKeys:n}){return{newTag:"",state:a,createTag:function(){if(this.newTag=this.newTag.trim(),this.newTag!==""){if(this.state.includes(this.newTag)){this.newTag="";return}this.state.push(this.newTag),this.newTag=""}},deleteTag:function(t){this.state=this.state.filter(e=>e!==t)},reorderTags:function(t){let e=this.state.splice(t.oldIndex,1)[0];this.state.splice(t.newIndex,0,e),this.state=[...this.state]},input:{"x-on:blur":"createTag()","x-model":"newTag","x-on:keydown"(t){["Enter",...n].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),this.createTag())},"x-on:paste"(){this.$nextTick(()=>{if(n.length===0){this.createTag();return}let t=n.map(e=>e.replace(/[/\-\\^$*+?.()|[\]{}]/g,"\\$&")).join("|");this.newTag.split(new RegExp(t,"g")).forEach(e=>{this.newTag=e,this.createTag()})})}}}}export{i as default};

View File

@@ -0,0 +1 @@
function r({initialHeight:t,shouldAutosize:i,state:s}){return{state:s,wrapperEl:null,init:function(){this.wrapperEl=this.$el.parentNode,this.setInitialHeight(),i?this.$watch("state",()=>{this.resize()}):this.setUpResizeObserver()},setInitialHeight:function(){this.$el.scrollHeight<=0||(this.wrapperEl.style.height=t+"rem")},resize:function(){if(this.setInitialHeight(),this.$el.scrollHeight<=0)return;let e=this.$el.scrollHeight+"px";this.wrapperEl.style.height!==e&&(this.wrapperEl.style.height=e)},setUpResizeObserver:function(){new ResizeObserver(()=>{this.wrapperEl.style.height=this.$el.style.height}).observe(this.$el)}}}export{r as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
function n(){return{checkboxClickController:null,collapsedGroups:[],isLoading:!1,selectedRecords:[],shouldCheckUniqueSelection:!0,lastCheckedRecord:null,livewireId:null,init:function(){this.livewireId=this.$root.closest("[wire\\:id]").attributes["wire:id"].value,this.$wire.$on("deselectAllTableRecords",()=>this.deselectAllRecords()),this.$watch("selectedRecords",()=>{if(!this.shouldCheckUniqueSelection){this.shouldCheckUniqueSelection=!0;return}this.selectedRecords=[...new Set(this.selectedRecords)],this.shouldCheckUniqueSelection=!1}),this.$nextTick(()=>this.watchForCheckboxClicks()),Livewire.hook("element.init",({component:e})=>{e.id===this.livewireId&&this.watchForCheckboxClicks()})},mountAction:function(e,t=null){this.$wire.set("selectedTableRecords",this.selectedRecords,!1),this.$wire.mountTableAction(e,t)},mountBulkAction:function(e){this.$wire.set("selectedTableRecords",this.selectedRecords,!1),this.$wire.mountTableBulkAction(e)},toggleSelectRecordsOnPage:function(){let e=this.getRecordsOnPage();if(this.areRecordsSelected(e)){this.deselectRecords(e);return}this.selectRecords(e)},toggleSelectRecordsInGroup:async function(e){if(this.isLoading=!0,this.areRecordsSelected(this.getRecordsInGroupOnPage(e))){this.deselectRecords(await this.$wire.getGroupedSelectableTableRecordKeys(e));return}this.selectRecords(await this.$wire.getGroupedSelectableTableRecordKeys(e)),this.isLoading=!1},getRecordsInGroupOnPage:function(e){let t=[];for(let s of this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[])s.dataset.group===e&&t.push(s.value);return t},getRecordsOnPage:function(){let e=[];for(let t of this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[])e.push(t.value);return e},selectRecords:function(e){for(let t of e)this.isRecordSelected(t)||this.selectedRecords.push(t)},deselectRecords:function(e){for(let t of e){let s=this.selectedRecords.indexOf(t);s!==-1&&this.selectedRecords.splice(s,1)}},selectAllRecords:async function(){this.isLoading=!0,this.selectedRecords=await this.$wire.getAllSelectableTableRecordKeys(),this.isLoading=!1},deselectAllRecords:function(){this.selectedRecords=[]},isRecordSelected:function(e){return this.selectedRecords.includes(e)},areRecordsSelected:function(e){return e.every(t=>this.isRecordSelected(t))},toggleCollapseGroup:function(e){if(this.isGroupCollapsed(e)){this.collapsedGroups.splice(this.collapsedGroups.indexOf(e),1);return}this.collapsedGroups.push(e)},isGroupCollapsed:function(e){return this.collapsedGroups.includes(e)},resetCollapsedGroups:function(){this.collapsedGroups=[]},watchForCheckboxClicks:function(){this.checkboxClickController&&this.checkboxClickController.abort(),this.checkboxClickController=new AbortController;let{signal:e}=this.checkboxClickController;this.$root?.addEventListener("click",t=>t.target?.matches(".fi-ta-record-checkbox")&&this.handleCheckboxClick(t,t.target),{signal:e})},handleCheckboxClick:function(e,t){if(!this.lastChecked){this.lastChecked=t;return}if(e.shiftKey){let s=Array.from(this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[]);if(!s.includes(this.lastChecked)){this.lastChecked=t;return}let o=s.indexOf(this.lastChecked),r=s.indexOf(t),l=[o,r].sort((i,d)=>i-d),c=[];for(let i=l[0];i<=l[1];i++)s[i].checked=t.checked,c.push(s[i].value);t.checked?this.selectRecords(c):this.deselectRecords(c)}this.lastChecked=t}}}export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
src/public/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow:

File diff suppressed because one or more lines are too long

7
src/public/vendor/telescope/app.css vendored Normal file

File diff suppressed because one or more lines are too long

2
src/public/vendor/telescope/app.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
src/public/vendor/telescope/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,5 @@
{
"/app.js": "/app.js?id=99f84d421ae083196e0a45c3c310168b",
"/app-dark.css": "/app-dark.css?id=1ea407db56c5163ae29311f1f38eb7b9",
"/app.css": "/app.css?id=de4c978567bfd90b38d186937dee5ccf"
}