Compare commits

...

21 Commits

Author SHA1 Message Date
brian 27ae08690e fixed the breadcrumbs 2026-05-22 17:07:58 -06:00
brian cb4879b109 change tasks to issues 2026-05-22 16:46:58 -06:00
brian 77f2032faf activity feed is more important that recent projects 2026-05-22 16:46:27 -06:00
brian f7bb39b266 making open issues more prominent on the page instead of projects 2026-05-22 16:45:15 -06:00
brian ab5337dc91 getting rid of dead html 2026-05-22 16:43:11 -06:00
brian 095b35f410 i'm getting...something...in the cookie now 2026-05-22 16:38:44 -06:00
brian 50546ae4d4 adding dummy avatars 2026-05-22 16:38:29 -06:00
brian 2d34202c9e adding scs for auth layer 2026-05-22 16:17:08 -06:00
brian a7d42f515d fixed double quote problem with users insert statements 2026-05-22 15:58:32 -06:00
brian 67f8143b1d bash script to migrate stuff 2026-05-22 15:57:49 -06:00
brian 2a45779278 adding packages for migrator 2026-05-22 15:28:46 -06:00
brian 116438cd0f adding migrator 2026-05-22 15:28:28 -06:00
brian c06582e084 adding down migration files 2026-05-22 15:16:52 -06:00
brian 15b77364eb fixing filename in top comment of up migration file 2026-05-22 15:16:33 -06:00
brian 43d6e98916 adding a - to the end of a line, because i like it pretty 2026-05-22 15:09:15 -06:00
brian 13f102755f renaming to denote these are 'up' files 2026-05-21 17:07:49 -06:00
brian 2928ff47a1 cosmetic formatting changes 2026-05-21 17:02:17 -06:00
brian d31382970a updated node package 2026-05-21 14:09:30 -06:00
brian 95e93bcf41 adding foreign key references 2026-05-21 13:55:17 -06:00
brian 688a1f90d2 bunch of migration files, iteration 1 2026-05-21 13:47:43 -06:00
brian 80b488008d fixing font awesome stuff 2026-05-21 10:24:25 -06:00
48 changed files with 552 additions and 84 deletions
+26 -15
View File
@@ -7,15 +7,13 @@ import (
"net/http"
"os"
"path/filepath"
"time"
"github.com/alexedwards/scs/v2"
"github.com/joho/godotenv"
)
func handler(writer http.ResponseWriter, request *http.Request) {
templ := template.Must(template.ParseFiles("./web/dist/index.html"))
templ.Execute(writer, nil)
}
var sessionManager *scs.SessionManager
func main() {
err := godotenv.Load()
@@ -23,20 +21,27 @@ func main() {
log.Fatal("Error loading .env file")
}
// handle authentication
sessionManager = scs.New()
sessionManager.Lifetime = 24 * time.Hour
// handle frontend views
webDir := "./web/dist"
fs := http.FileServer(http.Dir(webDir))
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/" {
path := filepath.Join(webDir, filepath.Clean(request.URL.Path))
_, err := os.Stat(path)
if err == nil {
fs.ServeHTTP(writer, request)
return
http.Handle("/", sessionManager.LoadAndSave(
http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/" {
path := filepath.Join(webDir, filepath.Clean(request.URL.Path))
_, err := os.Stat(path)
if err == nil {
fs.ServeHTTP(writer, request)
return
}
}
}
handler(writer, request)
})
handler(writer, request)
}),
))
port := os.Getenv("HTTP_PORT")
if port == "" {
@@ -48,3 +53,9 @@ func main() {
log.Fatalf("server error: %v", err)
}
}
func handler(writer http.ResponseWriter, request *http.Request) {
templ := template.Must(template.ParseFiles("./web/dist/index.html"))
templ.Execute(writer, nil)
}
+5 -1
View File
@@ -2,4 +2,8 @@ module solopm.com/solopm-server
go 1.26.3
require github.com/joho/godotenv v1.5.1 // indirect
require (
github.com/alexedwards/scs/v2 v2.9.0 // indirect
github.com/golang-migrate/migrate/v4 v4.19.1 // indirect
github.com/joho/godotenv v1.5.1 // indirect
)
+4
View File
@@ -1,2 +1,6 @@
github.com/alexedwards/scs/v2 v2.9.0 h1:xa05mVpwTBm1iLeTMNFfAWpKUm4fXAW7CeAViqBVS90=
github.com/alexedwards/scs/v2 v2.9.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8=
github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA=
github.com/golang-migrate/migrate/v4 v4.19.1/go.mod h1:CTcgfjxhaUtsLipnLoQRWCrjYXycRz/g5+RWDuYgPrE=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+35
View File
@@ -0,0 +1,35 @@
package db
import (
"database/sql",
"log"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/sqlite3"
_ "github.com/golang-migrate/migrate/v4/source/file"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, err := sql.Open("sqlite3", "database.sqlite")
if err != nil {
log.Fatal(err)
}
defer db.Close()
driver, err := sqlite3.WithInstance(db, &sqlite3.Config{})
if err != nil {
log.Fatal(err)
}
migrator, err := migrate.NewWithDatabaseInstance(
"file://migrations/", "sqlite3", driver
)
if err != nil {
log.Fatal(err)
}
if err := migrator.Up(); err != nill && err != migrate.ErrNoChange {
log.Fatal(err)
}
}
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_00_00_000000_create_audit_log_table.sql.down.sql
-- DROP TABLE "audit_log" --------------------------------------
DROP TABLE IF EXISTS "audit_log";
-- -------------------------------------------------------------
@@ -0,0 +1,34 @@
-- internal/db/migrations/2026_00_00_000000_create_audit_log_table.sql.up.sql
-- CREATE TABLE "audit_log" ------------------------------------
CREATE TABLE IF NOT EXISTS "audit_log" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"initiated_by" Integer NOT NULL REFERENCES "users"("id"),
"webhook_action" Boolean NOT NULL DEFAULT FALSE,
"resource_type" Text NOT NULL,
"resource_id" Integer NOT NULL,
"action_type" Text NOT NULL,
"summary" Text,
"previous_values" Text,
"new_values" Text
);
-- -------------------------------------------------------------
-- CREATE INDEX "idx_audit_resource" ---------------------------
CREATE INDEX IF NOT EXISTS "idx_audit_resource"
ON "audit_log" ( "resource_type", "resource_id" )
;
-- -------------------------------------------------------------
-- CREATE INDEX "idx_audit_initiator" --------------------------
CREATE INDEX IF NOT EXISTS "idx_audit_initiator"
ON "audit_log" ( "initiated_by", "created_at" )
;
-- -------------------------------------------------------------
-- CREATE INDEX "idx_audit_created" ----------------------------
CREATE INDEX IF NOT EXISTS "idx_audit_created"
ON "audit_log" ( "created_at" )
;
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000000_create_users_table.sql.down.sql
-- DROP TABLE "users" ------------------------------------------
DROP TABLE IF EXISTS "users";
-- -------------------------------------------------------------
@@ -0,0 +1,43 @@
-- internal/db/migrations/2026_01_01_000000_create_users_table.sql.up.sql
-- CREATE TABLE "users" ----------------------------------------
CREATE TABLE IF NOT EXISTS "users" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"username" Text NOT NULL,
"is_admin" Boolean DEFAULT FALSE,
"name" Text NOT NULL,
"email" Text NOT NULL,
"password" Text,
"avatar_url" Text,
"provider" Text NOT NULL DEFAULT 'local',
"provider_id" Text,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DateTime,
"deleted_at" DateTime,
CONSTRAINT "unique_username" UNIQUE ( username ),
CONSTRAINT "unique_email" UNIQUE ( email )
);
-- -------------------------------------------------------------
-- CREATE INDEX "idx_users_provider" ---------------------------
CREATE UNIQUE INDEX IF NOT EXISTS "idx_users_provider"
ON "users"( "provider", "provider_id" )
WHERE "provider_id" IS NOT NULL
;
-- -------------------------------------------------------------
-- INSERT "SYSTEM" USER ----------------------------------------
INSERT INTO users
(username,is_admin,name,email,avatar_url)
VALUES
('system', true, 'System User', 'system@localhost', '/uploads/avatars/system.png')
;
-- -------------------------------------------------------------
-- INSERT "ZOMBIE" USER ----------------------------------------
INSERT INTO users
(username,is_admin,name,email,avatar_url)
VALUES
('zombie', false, 'Zombie', 'zombie@localhost', '/uploads/avatars/zombie.png')
;
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000010_create_projects_table.sql.down.sql
-- DROP TABLE "projects" ---------------------------------------
DROP TABLE IF EXISTS "projects";
-- -------------------------------------------------------------
@@ -0,0 +1,20 @@
-- internal/db/migrations/2026_01_01_000010_create_projects_table.sql.up.sql
-- CREATE TABLE "projects" -------------------------------------
CREATE TABLE IF NOT EXISTS "projects"(
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"creator_id" Integer NOT NULL REFERENCES "users"("id"),
"owner_id" Integer NOT NULL REFERENCES "users"("id"),
"git_repository_url" Text,
"title" Text NOT NULL,
"description" Text,
"status" Text,
"priority" Text,
"start_date" DateTime,
"target_date" DateTime,
"completed_at" DateTime,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DateTime,
"deleted_at" DateTime
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000011_create_project_user_table.sql.down.sql
-- DROP TABLE "project_user" -----------------------------------
DROP TABLE IF EXISTS "project_user";
-- -------------------------------------------------------------
@@ -0,0 +1,13 @@
-- internal/db/migrations/2026_01_01_000011_create_project_user_table.sql.up.sql
-- CREATE TABLE "project_user" ---------------------------------
CREATE TABLE IF NOT EXISTS "project_user" (
"project_id" Integer NOT NULL REFERENCES "projects"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"invited_by_user_id" Integer REFERENCES "users"("id"),
"role" Text NOT NULL DEFAULT 'member',
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime,
CONSTRAINT "idx_project_user" UNIQUE ( project_id, user_id )
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000011_create_project_labels_table.sql.down.sql
-- DROP TABLE "project_labels" ---------------------------------
DROP TABLE IF EXISTS "project_labels";
-- -------------------------------------------------------------
@@ -0,0 +1,14 @@
-- internal/db/migrations/2026_01_01_000011_create_project_labels_table.sql.up.sql
-- CREATE TABLE "project_labels" -------------------------------
CREATE TABLE IF NOT EXISTS "project_labels" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"project_id" Integer NOT NULL REFERENCES "projects"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"label" Text NOT NULL,
"color" Text NOT NULL DEFAULT '#42f5ce',
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime,
CONSTRAINT "idx_project_labels" UNIQUE ( project_id, label )
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000013_create_project_links_table.sql.down.sql
-- DROP TABLE "project_links" ----------------------------------
DROP TABLE IF EXISTS "project_links";
-- -------------------------------------------------------------
@@ -0,0 +1,12 @@
-- internal/db/migrations/2026_01_01_000013_create_project_links_table.sql.up.sql
-- CREATE TABLE "project_links" --------------------------------
CREATE TABLE IF NOT EXISTS "project_links" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"project_id" Integer NOT NULL REFERENCES "projects"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"remote_url" Text NOT NULL,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000014_create_project_attachments_table.sql.down.sql
-- DROP TABLE "project_attachments" ----------------------------
DROP TABLE IF EXISTS "project_attachments";
-- -------------------------------------------------------------
@@ -0,0 +1,15 @@
-- internal/db/migrations/2026_01_01_000014_create_project_attachments_table.sql.up.sql
-- CREATE TABLE "project_attachments" --------------------------
CREATE TABLE IF NOT EXISTS "project_attachments" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"project_id" Integer NOT NULL REFERENCES "projects"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"path" TEXT NOT NULL,
"preview_path" TEXT NOT NULL,
"filesize" Integer NOT NULL DEFAULT 0,
"mimetype" TEXT NOT NULL,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000015_create_project_favorites_table.sql.down.sql
-- DROP TABLE "project_favorites" ------------------------------
DROP TABLE IF EXISTS "project_favorites";
@@ -0,0 +1,13 @@
-- internal/db/migrations/2026_01_01_000015_create_project_favorites_table.sql.up.sql
-- CREATE TABLE "project_favorites" ----------------------------
CREATE TABLE IF NOT EXISTS "project_favorites" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"project_id" Integer NOT NULL REFERENCES "projects"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"favorited_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime,
CONSTRAINT "idx_project_user" UNIQUE ( project_id, user_id )
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_00_000007_create_project_dependencies_table.sql.down.sql
-- DROP TABLE "project_dependencies" -----------------------------
DROP TABLE IF EXISTS "project_dependencies";
@@ -0,0 +1,11 @@
-- internal/db/migrations/2026_01_00_000007_create_project_dependencies_table.sql.up.sql
-- CREATE TABLE "project_dependencies" -----------------------------
CREATE TABLE IF NOT EXISTS "project_dependencies" (
"source_project_id" Integer NOT NULL REFERENCES "projects"("id"),
"blocking_project_id" Integer NOT NULL REFERENCES "projects"("id"),
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "idx_dependant_project" UNIQUE ( source_project_id, blocking_project_id )
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000020_create_issues_table.sql.down.sql
-- DROP TABLE "issues" -----------------------------------------
DROP TABLE IF EXISTS "issues";
-- -------------------------------------------------------------
@@ -0,0 +1,35 @@
-- internal/db/migrations/2026_01_01_000020_create_issues_table.sql.up.sql
-- CREATE TABLE "issues" ---------------------------------------
CREATE TABLE IF NOT EXISTS "issues" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"creator_id" Integer NOT NULL REFERENCES "users"("id"),
"assignee_id" Integer REFERENCES "users"("id"),
"project_id" Integer NOT NULL REFERENCES "projects"("id"),
"project_issue_id" Integer NOT NULL,
"title" Text,
"description" Text,
"status" Text,
"priority" Text,
"start_date" DateTime,
"target_date" DateTime,
"completed_at" DateTime,
"parent_issue_id" Integer REFERENCES "issues"("id"),
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DateTime,
"deleted_at" DateTime,
CONSTRAINT "uni_project_issue_id" UNIQUE ( project_id, project_issue_id )
);
-- -------------------------------------------------------------
-- CREATE INDEX "index_creator_id" -----------------------------
CREATE INDEX IF NOT EXISTS "index_creator_id" ON "issues"( "creator_id" );
-- -------------------------------------------------------------
-- CREATE INDEX "index_project_id" -----------------------------
CREATE INDEX IF NOT EXISTS "index_project_id" ON "issues"( "project_id" );
-- -------------------------------------------------------------
-- CREATE INDEX "index_assignee_id" ----------------------------
CREATE INDEX IF NOT EXISTS "index_assignee_id" ON "issues"( "assignee_id" );
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000021_create_issue_labels_table.sql.down.sql
-- DROP TABLE "issue_labels" -----------------------------------
DROP TABLE IF EXISTS "issue_labels";
-- -------------------------------------------------------------
@@ -0,0 +1,13 @@
-- internal/db/migrations/2026_01_01_000021_create_issue_labels_table.sql.up.sql
-- CREATE TABLE "issue_labels" ---------------------------------
CREATE TABLE IF NOT EXISTS "issue_labels" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"issue_id" Integer NOT NULL REFERENCES "issues"("id"),
"project_label_id" Integer NOT NULL REFERENCES "project_labels"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime,
CONSTRAINT "idx_issue_labels" UNIQUE ( issue_id, project_label_id )
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000022_create_issue_links_table.sql.down.sql
-- DROP TABLE "issue_links" ------------------------------------
DROP TABLE IF EXISTS "issue_links";
-- -------------------------------------------------------------
@@ -0,0 +1,12 @@
-- internal/db/migrations/2026_01_01_000022_create_issue_links_table.sql.up.sql
-- CREATE TABLE "issue_links" ----------------------------------
CREATE TABLE IF NOT EXISTS "issue_links" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"issue_id" Integer NOT NULL REFERENCES "issues"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"remote_url" Text NOT NULL,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000023_create_issue_attachments_table.sql.down.sql
-- DROP TABLE "issue_attachments" ------------------------------
DROP TABLE IF EXISTS "issue_attachments";
-- -------------------------------------------------------------
@@ -0,0 +1,15 @@
-- internal/db/migrations/2026_01_01_000023_create_issue_attachments_table.sql.up.sql
-- CREATE TABLE "issue_attachments" ----------------------------
CREATE TABLE IF NOT EXISTS "issue_attachments" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"issue_id" Integer NOT NULL REFERENCES "issues"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"path" TEXT NOT NULL,
"preview_path" TEXT NOT NULL,
"filesize" Integer NOT NULL DEFAULT 0,
"mimetype" TEXT NOT NULL,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000005_create_issue_blockers_table.sql.down.sql
-- DROP TABLE "issue_blockers" ---------------------------------
DROP TABLE IF EXISTS "issue_blockers";
-- -------------------------------------------------------------
@@ -0,0 +1,10 @@
-- internal/db/migrations/2026_01_01_000005_create_issue_blockers_table.sql.up.sql
-- CREATE TABLE "issue_blockers" -------------------------------
CREATE TABLE IF NOT EXISTS "issue_blockers" (
"source_issue_id" Integer NOT NULL REFERENCES "issues"("id"),
"blocking_issue_id" Integer NOT NULL REFERENCES "issues"("id"),
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "idx_blocking_issue" UNIQUE ( source_issue_id, blocking_issue_id )
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000024_create_issue_comments_table.sql.down.sql
-- DROP TABLE "issue_comments" ---------------------------------
DROP TABLE IF EXISTS "issue_comments";
-- -------------------------------------------------------------
@@ -0,0 +1,14 @@
-- internal/db/migrations/2026_01_01_000024_create_issue_comments_table.sql.up.sql
-- CREATE TABLE "issue_comments" -------------------------------
CREATE TABLE IF NOT EXISTS "issue_comments" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"issue_id" Integer NOT NULL REFERENCES "issues"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"body" TEXT NOT NULL,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DateTime,
"resolved_at" DateTime,
"deleted_at" DateTime
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000106_create_issue_comment_links_table.sql.down.sql
-- DROP TABLE "issue_comment_links" ----------------------------
DROP TABLE IF EXISTS "issue_comment_links";
-- -------------------------------------------------------------
@@ -0,0 +1,12 @@
-- internal/db/migrations/2026_01_01_000106_create_issue_comment_links_table.sql.up.sql
-- CREATE TABLE "issue_comment_links" --------------------------
CREATE TABLE IF NOT EXISTS "issue_comment_links" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"issue_comment_id" Integer NOT NULL REFERENCES "issue_comments"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"remote_url" Text NOT NULL,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_01_000107_create_issue_comment_attachments_table.sql.down.sql
-- DROP TABLE "issue_comment_attachments" --------------------------
DROP TABLE IF EXISTS "issue_comment_attachments";
-- -------------------------------------------------------------
@@ -0,0 +1,15 @@
-- internal/db/migrations/2026_01_01_000107_create_issue_comment_attachments_table.sql.up.sql
-- CREATE TABLE "issue_comment_attachments" --------------------------
CREATE TABLE IF NOT EXISTS "issue_comment_attachments" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"issue_comment_id" Integer NOT NULL REFERENCES "issue_comments"("id"),
"user_id" Integer NOT NULL REFERENCES "users"("id"),
"path" TEXT NOT NULL,
"preview_path" TEXT NOT NULL,
"filesize" Integer NOT NULL DEFAULT 0,
"mimetype" TEXT NOT NULL,
"created_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" DateTime
);
-- -------------------------------------------------------------
@@ -0,0 +1,5 @@
-- internal/db/migrations/2026_01_02_000001_create_webhook_receipts_table.sql.down.sql
-- DROP TABLE "webhook_receipts" -------------------------------
DROP TABLE IF EXISTS "webhook_receipts";
-- -------------------------------------------------------------
@@ -0,0 +1,15 @@
-- internal/db/migrations/2026_01_02_000001_create_webhook_receipts_table.sql.up.sql
-- CREATE TABLE "webhook_receipts" -------------------------------
CREATE TABLE IF NOT EXISTS "webhook_receipts" (
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"raw_payload" Text NOT NULL,
"source" Text NOT NULL,
"event_type" Text NOT NULL,
"delivery_id" Text NOT NULL,
"received_at" DateTime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"processing_status" Text NOT NULL DEFAULT 'pending',
"failure_reason" Text,
CONSTRAINT "unique_delivery_id" UNIQUE ( delivery_id )
);
-- -------------------------------------------------------------
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
DB_NAME="database.sqlite"
if [ -z "$1" ]; then
echo "You need to tell me up or down"
exit 1
fi
if [[ "$1" == "up" ]]; then
rm -f "$DB_NAME"
touch "$DB_NAME"
for file in migrations/*.up.sql; do
echo "Executing $file..."
sqlite3 "$DB_NAME" < "$file"
done
fi
if [[ "$1" == "down" ]]; then
for file in migrations/*.down.sql; do
echo "Executing $file..."
sqlite3 "$DB_NAME" < "$file"
done
fi
+4 -4
View File
@@ -546,8 +546,8 @@ packages:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
electron-to-chromium@1.5.359:
resolution: {integrity: sha512-8lPELWuYZIWk7NDvCNthtmMw/7Q5Wu25NpM4djFMHBmk8DubPAtL4YTOp7ou0e7HyJtwkVlWv8XMLURnrtgJQw==}
electron-to-chromium@1.5.360:
resolution: {integrity: sha512-GkcBt6YYAw9SxFWn+xVar4cLVGlXVuswwtRLBozi2zp0GjXs4ZnOrqV4zbXzg35n7w81hCkyJNYicgXlVHAmBA==}
entities@7.0.1:
resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
@@ -1316,7 +1316,7 @@ snapshots:
dependencies:
baseline-browser-mapping: 2.10.31
caniuse-lite: 1.0.30001793
electron-to-chromium: 1.5.359
electron-to-chromium: 1.5.360
node-releases: 2.0.44
update-browserslist-db: 1.2.3(browserslist@4.28.2)
@@ -1369,7 +1369,7 @@ snapshots:
es-errors: 1.3.0
gopd: 1.2.0
electron-to-chromium@1.5.359: {}
electron-to-chromium@1.5.360: {}
entities@7.0.1: {}
+10 -10
View File
@@ -6379,7 +6379,7 @@ readers do not read off random characters that represent icons */
font-style: normal;
font-weight: 400;
font-display: block;
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
src: url("webfonts/fa-brands-400.woff2") format("woff2"), url("webfonts/fa-brands-400.ttf") format("truetype"); }
.fab,
.fa-brands {
@@ -7896,7 +7896,7 @@ readers do not read off random characters that represent icons */
font-style: normal;
font-weight: 400;
font-display: block;
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }
src: url("webfonts/fa-regular-400.woff2") format("woff2"), url("webfonts/fa-regular-400.ttf") format("truetype"); }
.far,
.fa-regular {
@@ -7910,7 +7910,7 @@ readers do not read off random characters that represent icons */
font-style: normal;
font-weight: 900;
font-display: block;
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
src: url("webfonts/fa-solid-900.woff2") format("woff2"), url("webfonts/fa-solid-900.ttf") format("truetype"); }
.fas,
.fa-solid {
@@ -7919,37 +7919,37 @@ readers do not read off random characters that represent icons */
font-family: 'Font Awesome 5 Brands';
font-display: block;
font-weight: 400;
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
src: url("webfonts/fa-brands-400.woff2") format("woff2"), url("webfonts/fa-brands-400.ttf") format("truetype"); }
@font-face {
font-family: 'Font Awesome 5 Free';
font-display: block;
font-weight: 900;
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
src: url("webfonts/fa-solid-900.woff2") format("woff2"), url("webfonts/fa-solid-900.ttf") format("truetype"); }
@font-face {
font-family: 'Font Awesome 5 Free';
font-display: block;
font-weight: 400;
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }
src: url("webfonts/fa-regular-400.woff2") format("woff2"), url("webfonts/fa-regular-400.ttf") format("truetype"); }
@font-face {
font-family: 'FontAwesome';
font-display: block;
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
src: url("webfonts/fa-solid-900.woff2") format("woff2"), url("webfonts/fa-solid-900.ttf") format("truetype"); }
@font-face {
font-family: 'FontAwesome';
font-display: block;
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
src: url("webfonts/fa-brands-400.woff2") format("woff2"), url("webfonts/fa-brands-400.ttf") format("truetype"); }
@font-face {
font-family: 'FontAwesome';
font-display: block;
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype");
src: url("webfonts/fa-regular-400.woff2") format("woff2"), url("webfonts/fa-regular-400.ttf") format("truetype");
unicode-range: U+F003,U+F006,U+F014,U+F016-F017,U+F01A-F01B,U+F01D,U+F022,U+F03E,U+F044,U+F046,U+F05C-F05D,U+F06E,U+F070,U+F087-F088,U+F08A,U+F094,U+F096-F097,U+F09D,U+F0A0,U+F0A2,U+F0A4-F0A7,U+F0C5,U+F0C7,U+F0E5-F0E6,U+F0EB,U+F0F6-F0F8,U+F10C,U+F114-F115,U+F118-F11A,U+F11C-F11D,U+F133,U+F147,U+F14E,U+F150-F152,U+F185-F186,U+F18E,U+F190-F192,U+F196,U+F1C1-F1C9,U+F1D9,U+F1DB,U+F1E3,U+F1EA,U+F1F7,U+F1F9,U+F20A,U+F247-F248,U+F24A,U+F24D,U+F255-F25B,U+F25D,U+F271-F274,U+F278,U+F27B,U+F28C,U+F28E,U+F29C,U+F2B5,U+F2B7,U+F2BA,U+F2BC,U+F2BE,U+F2C0-F2C1,U+F2C3,U+F2D0,U+F2D2,U+F2D4,U+F2DC; }
@font-face {
font-family: 'FontAwesome';
font-display: block;
src: url("../webfonts/fa-v4compatibility.woff2") format("woff2"), url("../webfonts/fa-v4compatibility.ttf") format("truetype");
src: url("webfonts/fa-v4compatibility.woff2") format("woff2"), url("webfonts/fa-v4compatibility.ttf") format("truetype");
unicode-range: U+F041,U+F047,U+F065-F066,U+F07D-F07E,U+F080,U+F08B,U+F08E,U+F090,U+F09A,U+F0AC,U+F0AE,U+F0B2,U+F0D0,U+F0D6,U+F0E4,U+F0EC,U+F10A-F10B,U+F123,U+F13E,U+F148-F149,U+F14C,U+F156,U+F15E,U+F160-F161,U+F163,U+F175-F178,U+F195,U+F1F8,U+F219,U+F27A; }
File diff suppressed because one or more lines are too long
+4 -3
View File
@@ -4,11 +4,12 @@
<nav aria-label="breadcrumb">
<ol class="flex flex-wrap pt-1 mr-12 bg-transparent rounded-lg sm:mr-16">
<li class="text-sm leading-normal">
<RouterLink class="opacity-50 text-slate-700" to="/">Pages</RouterLink>
<li v-if="title !== 'Dashboard'" class="text-sm leading-normal">
<RouterLink class="opacity-50 text-slate-700" to="/dashboard">Dashboard</RouterLink>
</li>
<li
class="text-sm pl-2 capitalize leading-normal text-slate-700 before:float-left before:pr-2 before:content-['/']"
class="text-sm capitalize leading-normal text-slate-700"
:class="title !== 'Dashboard' ? 'pl-2 before:float-left before:pr-2 before:content-[\'/\']' : ''"
aria-current="page"
>
{{ title }}
-17
View File
@@ -66,23 +66,6 @@
</ul>
</div>
<div class="mx-4 mt-4">
<div class="relative flex min-w-0 flex-col items-center break-words rounded-2xl border-0 bg-white bg-clip-border shadow-none">
<div class="mb-7.5 h-28 w-full overflow-hidden rounded-xl">
<div class="bg-gradient-to-tl from-slate-600 to-slate-300 h-full w-full"></div>
</div>
<div class="-mt-14 w-3/4 text-center">
<p class="mt-0 mb-4 font-semibold leading-tight text-xs">Need help?</p>
<a
href="#"
class="inline-block w-full px-8 py-2 mb-4 font-bold text-center text-black uppercase transition-all ease-in bg-white border-0 rounded-lg shadow-soft-md bg-150 leading-pro text-xs hover:shadow-soft-2xl hover:scale-102"
>
Documentation
</a>
</div>
</div>
</div>
</aside>
</template>
+1 -1
View File
@@ -66,7 +66,7 @@
href="/api/auth/gitea"
class="inline-flex items-center justify-center w-full px-6 py-2.5 font-bold text-center text-slate-700 uppercase transition-all ease-in bg-white border border-solid border-gray-300 rounded-lg shadow-soft-sm text-xs hover:shadow-soft-md hover:scale-102"
>
<i class="fas fa-code-branch mr-2 text-base"></i>
<i class="fab fa-git-alt mr-2 text-base"></i>
Sign in with Gitea
</a>
</div>
+32 -32
View File
@@ -8,25 +8,7 @@
<div class="flex-auto p-4">
<div class="flex flex-row -mx-3">
<div class="flex-none w-2/3 max-w-full px-3">
<p class="mb-0 font-sans font-semibold leading-normal text-sm">Projects</p>
<h5 class="mb-0 font-bold"></h5>
</div>
<div class="px-3 text-right basis-1/3">
<div class="inline-flex w-12 h-12 text-center rounded-lg items-center justify-center bg-gradient-to-tl from-purple-700 to-pink-500 shadow-soft-2xl">
<i class="fas fa-layer-group text-white text-lg relative"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="w-full max-w-full px-3 mb-6 sm:w-1/2 sm:flex-none xl:mb-0 xl:w-1/4">
<div class="relative flex flex-col min-w-0 break-words bg-white shadow-soft-xl rounded-2xl bg-clip-border">
<div class="flex-auto p-4">
<div class="flex flex-row -mx-3">
<div class="flex-none w-2/3 max-w-full px-3">
<p class="mb-0 font-sans font-semibold leading-normal text-sm">Open Tasks</p>
<p class="mb-0 font-sans font-semibold leading-normal text-sm">Open Issues</p>
<h5 class="mb-0 font-bold"></h5>
</div>
<div class="px-3 text-right basis-1/3">
@@ -75,23 +57,29 @@
</div>
</div>
</div>
<div class="flex flex-wrap mt-6 -mx-3">
<div class="w-full max-w-full px-3 mt-0 lg:w-7/12 lg:flex-none">
<div class="relative flex flex-col min-w-0 break-words bg-white border-0 shadow-soft-xl rounded-2xl bg-clip-border">
<div class="border-black/12.5 rounded-t-2xl border-b-0 border-solid p-6 pb-0">
<h6 class="capitalize">Recent Projects</h6>
<p class="text-sm leading-normal">Your active projects</p>
</div>
<div class="flex-auto p-6 pt-4">
<p class="text-sm text-slate-500 text-center py-8">No projects yet.</p>
<div class="w-full max-w-full px-3 mb-6 sm:w-1/2 sm:flex-none xl:mb-0 xl:w-1/4">
<div class="relative flex flex-col min-w-0 break-words bg-white shadow-soft-xl rounded-2xl bg-clip-border">
<div class="flex-auto p-4">
<div class="flex flex-row -mx-3">
<div class="flex-none w-2/3 max-w-full px-3">
<p class="mb-0 font-sans font-semibold leading-normal text-sm">Projects</p>
<h5 class="mb-0 font-bold"></h5>
</div>
<div class="px-3 text-right basis-1/3">
<div class="inline-flex w-12 h-12 text-center rounded-lg items-center justify-center bg-gradient-to-tl from-purple-700 to-pink-500 shadow-soft-2xl">
<i class="fas fa-layer-group text-white text-lg relative"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="w-full max-w-full px-3 mt-4 lg:w-5/12 lg:flex-none lg:mt-0">
</div>
<div class="flex flex-wrap mt-6 -mx-3">
<div class="w-full max-w-full px-3 mt-4 lg:w-7/12 lg:flex-none lg:mt-0">
<div class="relative flex flex-col min-w-0 break-words bg-white border-0 shadow-soft-xl rounded-2xl bg-clip-border">
<div class="border-black/12.5 rounded-t-2xl border-b-0 border-solid p-6 pb-0">
<h6 class="capitalize">Activity</h6>
@@ -103,6 +91,18 @@
</div>
</div>
<div class="w-full max-w-full px-3 mt-0 lg:w-5/12 lg:flex-none">
<div class="relative flex flex-col min-w-0 break-words bg-white border-0 shadow-soft-xl rounded-2xl bg-clip-border">
<div class="border-black/12.5 rounded-t-2xl border-b-0 border-solid p-6 pb-0">
<h6 class="capitalize">Recent Projects</h6>
<p class="text-sm leading-normal">Your active projects</p>
</div>
<div class="flex-auto p-6 pt-4">
<p class="text-sm text-slate-500 text-center py-8">No projects yet.</p>
</div>
</div>
</div>
</div>
</AppLayout>