Jelajahi Sumber

updating html templates to allow for inserting images with a button

aeth 2 hari lalu
induk
melakukan
617df0997f

+ 5 - 1
Makefile

@@ -19,10 +19,14 @@ test:
 	go test -v ./...
 
 
-coverage:
+coverage-html:
+	mkdir -p coverage/
 	go test -v ./... -covermode=count -coverpkg=./... -coverprofile coverage/coverage.out
 	go tool cover -html coverage/coverage.out -o coverage/coverage.html
 
+coverage:
+	go test ./... -cover
+
 
 dev-run:
 	go build -o ./build/linux/$(WEBSERVER)/$(WEBSERVER) ./cmd/$(WEBSERVER)/$(WEBSERVER).go && \

+ 7 - 0
pkg/controller/admin_handlers.go

@@ -306,6 +306,12 @@ func (c *Controller) GetBlogPostEditor(ctx *gin.Context) {
 		})
 		return
 	}
+	images := c.database.GetAllImages()
+	imgIds := []storage.Identifier{}
+	for i := range images {
+		imgIds = append(imgIds, images[i].Ident)
+	}
+
 	ctx.HTML(200, "blogpost_editor", gin.H{
 		"navigation": gin.H{
 			"menu":    c.database.GetDropdownElements(),
@@ -317,6 +323,7 @@ func (c *Controller) GetBlogPostEditor(ctx *gin.Context) {
 		"DefaultTopic": doc.Category,
 		"Created":      doc.Created,
 		"Body":         doc.Body,
+		"ImageIds":     imgIds,
 	})
 }
 

+ 36 - 10
pkg/env/env_test.go

@@ -1,27 +1,53 @@
 package env
 
 import (
-	"bytes"
 	"io"
-	"log"
 	"os"
+	"path"
+	"strings"
 	"testing"
 )
 
 // Testing that the template writer creates the appropriate data
 func TestWriteTemplate(t *testing.T) {
-	b, err := os.ReadFile("../../test/.env.template")
+	tmp := t.TempDir()
+	envTmp := path.Join(tmp, ".env")
+	wr, err := os.Create(envTmp)
 	if err != nil {
-		log.Fatal(err)
+		t.Errorf("failed to created test file: %s\n", err.Error())
 	}
-	buf := bytes.NewBuffer([]byte{})
-	err = WriteTemplate(buf)
+	defer wr.Close()
+	err = WriteTemplate(wr)
 	if err != nil {
-		log.Fatal(err)
+		t.Errorf("failed to write to test file: %s\n", err.Error())
 	}
-	got, err := io.ReadAll(buf)
-	if string(got) != string(b) {
-		t.Errorf("test failed! Got: %s\nWanted: %s\n", string(got), string(b))
+	wr.Close()
+	r, err := os.Open(envTmp)
+	if err != nil {
+		t.Errorf("failed to open test file for reading: %s\n", err.Error())
+	}
+	got, err := io.ReadAll(r)
+	if err != nil {
+		t.Errorf("failed to read from open file: %s\n", err.Error())
+	}
+
+	want := []string{
+		KEIJI_USERNAME,
+		KEIJI_PASSWORD,
+		IMAGE_STORE,
+		WEB_ROOT,
+		DOMAIN_NAME,
+		HOST_PORT,
+		HOST_ADDR,
+		USE_SSL,
+		CHAIN,
+		KEY,
+	}
+	for i := range want {
+
+		if !strings.Contains(string(got), want[i]) {
+			t.Errorf("test failed! Template file with content: '%s'\n Did not contain: '%s'\n", string(got), want[i])
+		}
 	}
 
 }

+ 3 - 2
pkg/storage/storage.go

@@ -469,7 +469,8 @@ func (s *SQLiteRepo) GetAllImages() []Image {
 		}
 		b, err := s.imageIO.Get(img.Ident)
 		if err != nil {
-			log.Fatal(err)
+			fmt.Printf("Failed to get image: %+v\nError: %s\n", img, err.Error())
+			continue
 		}
 		imgs = append(imgs, Image{Ident: img.Ident, Title: img.Title, Desc: img.Desc, Data: b, Created: img.Created, Category: img.Category})
 	}
@@ -495,7 +496,7 @@ func (s *SQLiteRepo) GetImagesByCategory(category string) []Image {
 		}
 		b, err := s.imageIO.Get(img.Ident)
 		if err != nil {
-			log.Fatal(err)
+			fmt.Printf("Failed to get image: %+v\nError: %s\n", img, err.Error())
 		}
 		imgs = append(imgs, Image{Ident: img.Ident, Title: img.Title, Desc: img.Desc, Data: b, Created: img.Created, Category: img.Category})
 	}

+ 30 - 25
pkg/storage/storage_test.go

@@ -298,11 +298,12 @@ func TestGetImage(t *testing.T) {
 	for _, tc := range []testcase{
 		{
 			seed: Image{
-				Ident:   Identifier("abc123"),
-				Title:   "xyz098",
-				Desc:    "description",
-				Created: "2024-12-31",
-				Data:    []byte("abc123xyz098"),
+				Ident:    Identifier("abc123"),
+				Title:    "xyz098",
+				Desc:     "description",
+				Created:  "2024-12-31",
+				Category: "homepage",
+				Data:     []byte("abc123xyz098"),
 			},
 			shouldSeed: true,
 			err:        nil,
@@ -316,7 +317,7 @@ func TestGetImage(t *testing.T) {
 		},
 	} {
 		if tc.shouldSeed {
-			_, err := db.Exec("INSERT INTO images (id, title, desc, created) VALUES (?,?,?,?)", string(tc.seed.Ident), tc.seed.Title, tc.seed.Desc, "2024-12-31")
+			_, err := db.Exec("INSERT INTO images (id, title, desc, created, category) VALUES (?,?,?,?,?)", string(tc.seed.Ident), tc.seed.Title, tc.seed.Desc, "2024-12-31", tc.seed.Category)
 			if err != nil {
 				t.Error(err)
 			}
@@ -340,24 +341,26 @@ func TestGetAllImages(t *testing.T) {
 		{
 			seed: []Image{
 				{
-					Ident:   Identifier("abc123"),
-					Title:   "xyz098",
-					Data:    []byte("abc123xyz098"),
-					Created: "2024-12-31",
-					Desc:    "description",
+					Ident:    Identifier("abc123"),
+					Title:    "xyz098",
+					Data:     []byte("abc123xyz098"),
+					Created:  "2024-12-31",
+					Desc:     "description",
+					Category: "homepage",
 				},
 				{
-					Ident:   Identifier("xyz098"),
-					Title:   "abc123",
-					Data:    []byte("abc123xyz098"),
-					Created: "2024-12-31",
-					Desc:    "description",
+					Ident:    Identifier("xyz098"),
+					Title:    "abc123",
+					Data:     []byte("abc123xyz098"),
+					Created:  "2024-12-31",
+					Desc:     "description",
+					Category: "homepage",
 				},
 			},
 		},
 	} {
 		for i := range tc.seed {
-			_, err := db.Exec("INSERT INTO images (id, title, desc, created) VALUES (?,?,?,?)", string(tc.seed[i].Ident), tc.seed[i].Title, tc.seed[i].Desc, tc.seed[i].Created)
+			_, err := db.Exec("INSERT INTO images (id, title, desc, created, category) VALUES (?,?,?,?,?)", string(tc.seed[i].Ident), tc.seed[i].Title, tc.seed[i].Desc, tc.seed[i].Created, tc.seed[i].Category)
 			if err != nil {
 				t.Error(err)
 			}
@@ -515,20 +518,22 @@ func TestUpdateDocument(t *testing.T) {
 func TestAddImage(t *testing.T) {
 
 	type testcase struct {
-		data  []byte
-		title string
-		desc  string
-		err   error
+		data     []byte
+		title    string
+		desc     string
+		category string
+		err      error
 	}
 	testDb, _ := newTestDb(t.TempDir(), true)
 	for _, tc := range []testcase{
 		{
-			data:  []byte("abc123xyz098"),
-			title: "dont matter",
-			desc:  "also dont matter",
+			data:     []byte("abc123xyz098"),
+			title:    "dont matter",
+			desc:     "also dont matter",
+			category: "homepage",
 		},
 	} {
-		id, err := testDb.AddImage(tc.data, tc.title, tc.desc)
+		id, err := testDb.AddImage(tc.data, tc.title, tc.desc, tc.category)
 		if err != nil {
 			assert.Equal(t, tc.err, err)
 		} else {

+ 29 - 0
pkg/webpages/cdn/image-insert.js

@@ -0,0 +1,29 @@
+function insertHtmlAtCursor(textarea, html) {
+    const start = textarea.selectionStart;
+    const end = textarea.selectionEnd;
+    const before = textarea.value.substring(0, start);
+    const after = textarea.value.substring(end);
+
+    textarea.value = before + html + after;
+
+    // move cursor after inserted block
+    textarea.selectionStart = textarea.selectionEnd = start + html.length;
+}
+
+function insertSelectedImage() {
+    const select = document.getElementById("imageSelect");
+    const imageId = select.value;
+
+    if (!imageId) {
+        alert("Please select an image first.");
+        return;
+    }
+
+    const html = `<div class="text-center">
+<img src="/api/v1/images/${imageId}" class="rounded img-fluid">
+</div>`;
+
+    const textarea = document.getElementById("myTextarea");
+
+    insertHtmlAtCursor(textarea, html);
+}

+ 24 - 2
pkg/webpages/html/blogpost_editor.html

@@ -55,10 +55,32 @@
                             <div class="row"
                                 style="background-color: rgb(22, 22, 22); color: white; height: fit-content; font-size: larger; font-family: monospace;">
                                 <a>Post Body:</a>
-                                <textarea name="body" rows="30" wrap="soft"
+                                <textarea name="body" rows="30" wrap="soft" id="myTextarea"
                                     style="background-color: rgb(73, 73, 73); color: white;">{{ .Body }}</textarea>
                             </div>
-                            <button type="submit">Send</button><div id="response"></div>
+                            <div class="row"
+                                style="background-color: rgb(22, 22, 22); color: white; height: fit-content; font-size: larger; font-family: monospace;">
+                                
+                                <a>Insert an image:</a>
+
+                                <select id="imageSelect" class="form-select"
+                                    style="background-color: rgb(73, 73, 73); color: white; height: fit-content; font-size: larger; font-family: monospace;">
+                                    <option selected value="">select an image to insert</option>
+                                    {{ range .ImageIds }}
+                                    <option value="{{ . }}">{{ . }}</option>
+                                    {{ end }}
+                                </select>
+
+                                <button 
+                                    type="button"
+                                    hx-on:click="insertSelectedImage()">
+                                    Insert Image
+                                </button>
+                            </div>
+                            <div class="row"
+                                style="background-color: rgb(22, 22, 22); color: white; height: fit-content; font-size: larger; font-family: monospace;">
+                                <button type="submit">Send</button><div id="response"></div>
+                            </div>
                         </form>
                     </div>
                 </div>

+ 1 - 0
pkg/webpages/html/home.html

@@ -84,6 +84,7 @@
     </div>
         <script type="text/javascript" src="/api/v1/cdn/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
         <script src="/api/v1/cdn/slide.js"></script>
+        <script src="/api/v1/cdn/image-insert.js"></script>
         <script src="/api/v1/cdn/htmx.min.js"></script>
         <script src="/api/v1/cdn/json-enc.js"></script>
     </body>

+ 3 - 3
pkg/webpages/html/upload.html

@@ -6,9 +6,6 @@
         <div class="col" style="min-width: 80vw; background-color: rgb(22, 22, 22); font-family: monospace;">
             <form hx-encoding='multipart/form-data' hx-post='/admin/images/upload'
                  _='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
-                    <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>
@@ -26,6 +23,9 @@
                     <div class="row container p-2 m-2">
                         <textarea name="description" wrap="soft" required="required" placeholder="What would you like to say about it?"></textarea>
                     </div>
+                    <div class="row container p-2 m-2">
+                        <input type='file' name='file'>
+                    </div>
                     <div class="row container p-2 m-2">
                         <button>
                            Upload

+ 1 - 1
pkg/webpages/pages.go

@@ -56,7 +56,7 @@ func (f FilesystemWebpages) Open(file string) (fs.File, error) {
 	filePath := path.Join(f.Webroot, file)
 	fh, err := os.Open(filePath)
 	if err != nil {
-		fmt.Printf("Error opening the file: %s because %s", filePath, err)
+		fmt.Printf("Error opening the file: %s because %s\n", filePath, err)
 		return nil, os.ErrNotExist
 	}
 	return fh, nil