Эх сурвалжийг харах

made image store creation and verification functions and added categories to image upload. Allows for adding assets that can be added to blog posts

aeth 11 сар өмнө
parent
commit
d5edffb43d

+ 5 - 1
cmd/keiji/keiji.go

@@ -94,7 +94,11 @@ func main() {
 	if err != nil {
 		log.Fatal(err)
 	}
-	webserverDb := storage.NewSQLiteRepo(db, storage.FilesystemImageIO{RootDir: os.Getenv(env.IMAGE_STORE)})
+	path := os.Getenv(env.IMAGE_STORE)
+	if path == "" {
+		log.Fatalf("Environment variable: '%s' resolved to a null value: '%s'", env.IMAGE_STORE, path)
+	}
+	webserverDb := storage.NewSQLiteRepo(db, storage.MustNewFilesystemImageIO(path))
 	err = webserverDb.Migrate(storage.RequiredTables)
 	if err != nil {
 		log.Fatal(err)

+ 3 - 1
pkg/controller/admin_handlers.go

@@ -398,6 +398,8 @@ func (c *Controller) ServeFileUpload(ctx *gin.Context) {
 			"menu":    c.database.GetDropdownElements(),
 			"headers": c.database.GetNavBarLinks(),
 		},
+		"Topics":       storage.ImageCategories,
+		"DefaultTopic": storage.DIGITAL_ART,
 	})
 }
 
@@ -433,7 +435,7 @@ func (c *Controller) SaveFile(ctx *gin.Context) {
 		}
 		output.Write(fb[:n])
 	}
-	_, err = c.database.AddImage(fb, img.Title, img.Desc)
+	_, err = c.database.AddImage(fb, img.Title, img.Desc, img.Category)
 	if err != nil {
 		ctx.HTML(500, "upload_status", gin.H{"UpdateMessage": err, "Color": "red"})
 		return

+ 1 - 1
pkg/controller/html_handlers.go

@@ -108,7 +108,7 @@ func (c *Controller) ServeCreative(ctx *gin.Context) {
 // @Tags webpages
 // @Router /digital [get]
 func (c *Controller) ServeDigitalArt(ctx *gin.Context) {
-	images := c.database.GetAllImages()
+	images := c.database.GetImagesByCategory(storage.DIGITAL_ART)
 	ctx.HTML(http.StatusOK, "digital_art", gin.H{
 		"navigation": gin.H{
 			"headers": c.database.GetNavBarLinks(),

+ 2 - 1
pkg/storage/queries.go

@@ -17,7 +17,8 @@ const imagesTable = `
 		id TEXT NOT NULL,
 		title TEXT NOT NULL,
 		desc TEXT NOT NULL,
-		created TEXT NOT NULL
+		created TEXT NOT NULL,
+		category TEXT NOT NULL
 	);
 	`
 const menuItemsTable = `

+ 55 - 9
pkg/storage/storage.go

@@ -21,6 +21,7 @@ const CONFIGURATION = "configuration"
 const BLOG = "blog"
 const CREATIVE = "creative"
 const DIGITAL_ART = "digital_art"
+const MISC_ASSET = "misc_asset"
 const HOMEPAGE = "homepage"
 
 var Topics = []string{
@@ -30,6 +31,11 @@ var Topics = []string{
 	HOMEPAGE,
 }
 
+var ImageCategories = []string{
+	MISC_ASSET,
+	DIGITAL_ART,
+}
+
 type DatabaseSchema struct {
 	// Gotta figure out what this looks like
 	// so that the ExtractAll() function gets
@@ -104,7 +110,7 @@ type Image struct {
 	File     *multipart.FileHeader `form:"file"`
 	Desc     string                `json:"description" form:"description"`
 	Created  string
-	Category string
+	Category string `json:"category" form:"category"`
 	Data     []byte
 }
 
@@ -112,11 +118,12 @@ type DocumentIO interface {
 	GetDocument(id Identifier) (Document, error)
 	GetImage(id Identifier) (Image, error)
 	GetAllImages() []Image
+	GetImagesByCategory(category string) []Image
 	UpdateDocument(doc Document) error
 	DeleteDocument(id Identifier) error
 	DeleteNavbarItem(id Identifier) error
 	AddDocument(doc Document) (Identifier, error)
-	AddImage(data []byte, title, desc string) (Identifier, error)
+	AddImage(data []byte, title, desc, category string) (Identifier, error)
 	AddAsset(name string, data []byte) error
 	AddAdminTableEntry(TableData, string) error
 	AddNavbarItem(NavBarItem) error
@@ -150,6 +157,19 @@ type FilesystemImageIO struct {
 	RootDir string
 }
 
+/*
+create a new FilesystemImageIO struct
+*/
+func MustNewFilesystemImageIO(path string) FilesystemImageIO {
+	var filemode os.FileMode
+	filemode = 0775
+	err := os.MkdirAll(path, filemode)
+	if err != nil {
+		log.Fatalf("Error creating path: '%s' with permissions: '%d'. Error: %s\n", path, filemode, err.Error())
+	}
+	return FilesystemImageIO{RootDir: path}
+}
+
 /*
 Put a data blob on the filesystem
 
@@ -408,8 +428,8 @@ get image data from the images table
 func (s *SQLiteRepo) GetImage(id Identifier) (Image, error) {
 	row := s.db.QueryRow("SELECT * FROM images WHERE id = ?", id)
 	var rowNum int
-	var title, desc, created string
-	if err := row.Scan(&rowNum, &id, &title, &desc, &created); err != nil {
+	var title, desc, created, category string
+	if err := row.Scan(&rowNum, &id, &title, &desc, &created, &category); err != nil {
 		if errors.Is(err, sql.ErrNoRows) {
 			return Image{}, ErrNotExists
 		}
@@ -419,7 +439,7 @@ func (s *SQLiteRepo) GetImage(id Identifier) (Image, error) {
 	if err != nil {
 		return Image{}, err
 	}
-	return Image{Ident: id, Title: title, Desc: desc, Data: data, Created: created}, nil
+	return Image{Ident: id, Title: title, Desc: desc, Data: data, Created: created, Category: category}, nil
 }
 
 /*
@@ -434,7 +454,33 @@ func (s *SQLiteRepo) GetAllImages() []Image {
 	for rows.Next() {
 		var img Image
 		var rowNum int
-		err := rows.Scan(&rowNum, &img.Ident, &img.Title, &img.Desc, &img.Created)
+		err := rows.Scan(&rowNum, &img.Ident, &img.Title, &img.Desc, &img.Created, &img.Category)
+		if err != nil {
+			log.Fatal(err)
+		}
+		b, err := s.imageIO.Get(img.Ident)
+		if err != nil {
+			log.Fatal(err)
+		}
+		imgs = append(imgs, Image{Ident: img.Ident, Title: img.Title, Desc: img.Desc, Data: b, Created: img.Created, Category: img.Category})
+	}
+	err = rows.Err()
+	if err != nil {
+		log.Fatal(err)
+	}
+	return imgs
+}
+
+func (s *SQLiteRepo) GetImagesByCategory(category string) []Image {
+	rows, err := s.db.Query("SELECT * FROM images WHERE category = ?", category)
+	if err != nil {
+		log.Fatal(err)
+	}
+	imgs := []Image{}
+	for rows.Next() {
+		var img Image
+		var rowNum int
+		err := rows.Scan(&rowNum, &img.Ident, &img.Title, &img.Desc, &img.Created, &img.Category)
 		if err != nil {
 			log.Fatal(err)
 		}
@@ -442,7 +488,7 @@ func (s *SQLiteRepo) GetAllImages() []Image {
 		if err != nil {
 			log.Fatal(err)
 		}
-		imgs = append(imgs, Image{Ident: img.Ident, Title: img.Title, Desc: img.Desc, Data: b, Created: img.Created})
+		imgs = append(imgs, Image{Ident: img.Ident, Title: img.Title, Desc: img.Desc, Data: b, Created: img.Created, Category: img.Category})
 	}
 	err = rows.Err()
 	if err != nil {
@@ -459,13 +505,13 @@ Add an image to the database
 	:param desc: the description of the image, if any
 	:param data: the binary data for the image
 */
-func (s *SQLiteRepo) AddImage(data []byte, title string, desc string) (Identifier, error) {
+func (s *SQLiteRepo) AddImage(data []byte, title string, desc string, category string) (Identifier, error) {
 	id := newIdentifier()
 	err := s.imageIO.Put(data, id)
 	if err != nil {
 		return Identifier(""), err
 	}
-	_, err = s.db.Exec("INSERT INTO images (id, title, desc, created) VALUES (?,?,?,?)", string(id), title, desc, time.Now().String())
+	_, err = s.db.Exec("INSERT INTO images (id, title, desc, created, category) VALUES (?,?,?,?,?)", string(id), title, desc, time.Now().String(), category)
 	if err != nil {
 		return Identifier(""), err
 	}

+ 11 - 0
pkg/webpages/html/upload.html

@@ -9,6 +9,17 @@
                     <div class="row container p-2 m-2">
                         <input type='file' name='file'>
                     </div>
+                    <div class="row"
+                        style="background-color: rgb(22, 22, 22); color: white; height: fit-content; font-size: larger; font-family: monospace;">
+                        <a>Category:</a>
+                        <select name="category" class="form-select"
+                            style="background-color: rgb(73, 73, 73); color: white; height: fit-content; font-size: larger; font-family: monospace;">
+                            <option selected>{{ .DefaultTopic }}</option>
+                            {{ range .Topics }}
+                            <option value="{{ . }}">{{ . }}</option>
+                            {{ end }}
+                        </select>
+                    </div>
                     <div class="row container p-2 m-2">
                         <textarea name="title" wrap="soft" required="required" placeholder="Name of the piece?"></textarea>
                     </div>