Explorar o código

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 hai 11 meses
pai
achega
d5edffb43d

+ 5 - 1
cmd/keiji/keiji.go

@@ -94,7 +94,11 @@ func main() {
 	if err != nil {
 	if err != nil {
 		log.Fatal(err)
 		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)
 	err = webserverDb.Migrate(storage.RequiredTables)
 	if err != nil {
 	if err != nil {
 		log.Fatal(err)
 		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(),
 			"menu":    c.database.GetDropdownElements(),
 			"headers": c.database.GetNavBarLinks(),
 			"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])
 		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 {
 	if err != nil {
 		ctx.HTML(500, "upload_status", gin.H{"UpdateMessage": err, "Color": "red"})
 		ctx.HTML(500, "upload_status", gin.H{"UpdateMessage": err, "Color": "red"})
 		return
 		return

+ 1 - 1
pkg/controller/html_handlers.go

@@ -108,7 +108,7 @@ func (c *Controller) ServeCreative(ctx *gin.Context) {
 // @Tags webpages
 // @Tags webpages
 // @Router /digital [get]
 // @Router /digital [get]
 func (c *Controller) ServeDigitalArt(ctx *gin.Context) {
 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{
 	ctx.HTML(http.StatusOK, "digital_art", gin.H{
 		"navigation": gin.H{
 		"navigation": gin.H{
 			"headers": c.database.GetNavBarLinks(),
 			"headers": c.database.GetNavBarLinks(),

+ 2 - 1
pkg/storage/queries.go

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

+ 55 - 9
pkg/storage/storage.go

@@ -21,6 +21,7 @@ const CONFIGURATION = "configuration"
 const BLOG = "blog"
 const BLOG = "blog"
 const CREATIVE = "creative"
 const CREATIVE = "creative"
 const DIGITAL_ART = "digital_art"
 const DIGITAL_ART = "digital_art"
+const MISC_ASSET = "misc_asset"
 const HOMEPAGE = "homepage"
 const HOMEPAGE = "homepage"
 
 
 var Topics = []string{
 var Topics = []string{
@@ -30,6 +31,11 @@ var Topics = []string{
 	HOMEPAGE,
 	HOMEPAGE,
 }
 }
 
 
+var ImageCategories = []string{
+	MISC_ASSET,
+	DIGITAL_ART,
+}
+
 type DatabaseSchema struct {
 type DatabaseSchema struct {
 	// Gotta figure out what this looks like
 	// Gotta figure out what this looks like
 	// so that the ExtractAll() function gets
 	// so that the ExtractAll() function gets
@@ -104,7 +110,7 @@ type Image struct {
 	File     *multipart.FileHeader `form:"file"`
 	File     *multipart.FileHeader `form:"file"`
 	Desc     string                `json:"description" form:"description"`
 	Desc     string                `json:"description" form:"description"`
 	Created  string
 	Created  string
-	Category string
+	Category string `json:"category" form:"category"`
 	Data     []byte
 	Data     []byte
 }
 }
 
 
@@ -112,11 +118,12 @@ type DocumentIO interface {
 	GetDocument(id Identifier) (Document, error)
 	GetDocument(id Identifier) (Document, error)
 	GetImage(id Identifier) (Image, error)
 	GetImage(id Identifier) (Image, error)
 	GetAllImages() []Image
 	GetAllImages() []Image
+	GetImagesByCategory(category string) []Image
 	UpdateDocument(doc Document) error
 	UpdateDocument(doc Document) error
 	DeleteDocument(id Identifier) error
 	DeleteDocument(id Identifier) error
 	DeleteNavbarItem(id Identifier) error
 	DeleteNavbarItem(id Identifier) error
 	AddDocument(doc Document) (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
 	AddAsset(name string, data []byte) error
 	AddAdminTableEntry(TableData, string) error
 	AddAdminTableEntry(TableData, string) error
 	AddNavbarItem(NavBarItem) error
 	AddNavbarItem(NavBarItem) error
@@ -150,6 +157,19 @@ type FilesystemImageIO struct {
 	RootDir string
 	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
 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) {
 func (s *SQLiteRepo) GetImage(id Identifier) (Image, error) {
 	row := s.db.QueryRow("SELECT * FROM images WHERE id = ?", id)
 	row := s.db.QueryRow("SELECT * FROM images WHERE id = ?", id)
 	var rowNum int
 	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) {
 		if errors.Is(err, sql.ErrNoRows) {
 			return Image{}, ErrNotExists
 			return Image{}, ErrNotExists
 		}
 		}
@@ -419,7 +439,7 @@ func (s *SQLiteRepo) GetImage(id Identifier) (Image, error) {
 	if err != nil {
 	if err != nil {
 		return Image{}, err
 		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() {
 	for rows.Next() {
 		var img Image
 		var img Image
 		var rowNum int
 		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 {
 		if err != nil {
 			log.Fatal(err)
 			log.Fatal(err)
 		}
 		}
@@ -442,7 +488,7 @@ func (s *SQLiteRepo) GetAllImages() []Image {
 		if err != nil {
 		if err != nil {
 			log.Fatal(err)
 			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()
 	err = rows.Err()
 	if err != nil {
 	if err != nil {
@@ -459,13 +505,13 @@ Add an image to the database
 	:param desc: the description of the image, if any
 	:param desc: the description of the image, if any
 	:param data: the binary data for the image
 	: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()
 	id := newIdentifier()
 	err := s.imageIO.Put(data, id)
 	err := s.imageIO.Put(data, id)
 	if err != nil {
 	if err != nil {
 		return Identifier(""), err
 		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 {
 	if err != nil {
 		return Identifier(""), err
 		return Identifier(""), err
 	}
 	}

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

@@ -9,6 +9,17 @@
                     <div class="row container p-2 m-2">
                     <div class="row container p-2 m-2">
                         <input type='file' name='file'>
                         <input type='file' name='file'>
                     </div>
                     </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">
                     <div class="row container p-2 m-2">
                         <textarea name="title" wrap="soft" required="required" placeholder="Name of the piece?"></textarea>
                         <textarea name="title" wrap="soft" required="required" placeholder="Name of the piece?"></textarea>
                     </div>
                     </div>