Detalji clanaka

This commit is contained in:
Senad Uka
2022-02-14 11:03:56 +01:00
parent f6e90deebd
commit 9f57520080
11 changed files with 207 additions and 62 deletions

View File

@@ -1,68 +1,23 @@
package main
import (
"fmt"
"gitlab.com/kbr4/svevijesti/internal/database"
"html/template"
"io/ioutil"
"gitlab.com/kbr4/svevijesti/internal/server"
"log"
"net/http"
"path/filepath"
"strings"
"time"
)
var tPath = "./web/tpl/"
var dPath = "./web/data/"
var templateDirs = []string{"./web/tpl", "./web/data"}
var templates *template.Template
func getTemplates() (templates *template.Template, err error) {
var allFiles []string
for _, dir := range templateDirs {
files2, _ := ioutil.ReadDir(dir)
for _, file := range files2 {
filename := file.Name()
if strings.HasSuffix(filename, ".html") {
filePath := filepath.Join(dir, filename)
fmt.Println("Template found: ", filePath)
allFiles = append(allFiles, filePath)
}
}
}
templates, err = template.New("").ParseFiles(allFiles...)
return
}
func init() {
templates, _ = getTemplates()
}
func rootHandler(wr http.ResponseWriter, req *http.Request) {
title := "Pocetna"
store, err := database.Connect()
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
}
articles, err := database.ArticlesForDay(store, time.Now())
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
}
data := map[string]interface{}{
"title": title,
"articles": articles,
}
err = templates.ExecuteTemplate(wr, "homeHTML", data)
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
}
}
func main() {
http.HandleFunc("/", rootHandler)
http.ListenAndServe(":8080", nil)
r := server.CreateRoutes()
http.Handle("/", r)
srv := &http.Server{
Handler: r,
Addr: "0.0.0.0:8080",
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Fatal(srv.ListenAndServe())
}

1
go.mod
View File

@@ -12,6 +12,7 @@ require (
github.com/gocolly/colly v1.2.0 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.3.1 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gosimple/slug v1.12.0 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect
github.com/kennygrant/sanitize v1.2.4 // indirect

2
go.sum
View File

@@ -19,6 +19,8 @@ github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18h
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gosimple/slug v1.12.0 h1:xzuhj7G7cGtd34NXnW/yF0l+AGNfWqwgh/IXgFy7dnc=
github.com/gosimple/slug v1.12.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ=
github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o=

View File

@@ -4,7 +4,9 @@ import (
"fmt"
_ "github.com/lib/pq"
"gitlab.com/kbr4/svevijesti/internal/model"
"html/template"
"math"
"strings"
"time"
)
@@ -86,3 +88,45 @@ func ArticlesForDay(store *Store, day time.Time) (articles []model.DisplayArticl
return result, nil
}
func ArticleByID(store *Store, ID int, slug string) (article model.DisplayArticle, err error) {
result := model.DisplayArticle{}
query, err := store.Prepare(`
select id,title, content, slug, original_url, source_id, created_at from articles where id = $1 and slug = $2;
`)
if err != nil {
return result, err
}
row := query.QueryRow(ID, slug)
if err != nil {
return result, err
}
r := model.DisplayArticle{}
content := ""
err = row.Scan(&r.ID, &r.Title, &content, &r.Slug, &r.OriginalUrl, &r.SourceId, &r.CreatedAt)
if err != nil {
return result, err
}
ago := time.Now().Sub(r.CreatedAt)
hours := ago.Hours()
r.Content = template.HTML(strings.Replace(content, "\n", "<br>\n", -1))
if hours < 1 {
r.FormatedCreatedAt = fmt.Sprintf("Prije %d minuta.", int(math.Floor(ago.Minutes())))
} else if hours > 24 {
r.FormatedCreatedAt = r.CreatedAt.Format("01.02.2006. 15:04:05")
} else {
r.FormatedCreatedAt = fmt.Sprintf("Prije %d sati.", int(math.Floor(hours)))
}
r.SourceName = model.SourceName(r.SourceId)
result = r
return result, nil
}

View File

@@ -1,6 +1,9 @@
package model
import "time"
import (
"html/template"
"time"
)
type ScrapedArticle struct {
Title string
@@ -13,7 +16,7 @@ type ScrapedArticle struct {
type DisplayArticle struct {
ID int
Title string
Content string
Content template.HTML
Slug string
OriginalUrl string
SourceId int

View File

@@ -0,0 +1,61 @@
package server
import (
"github.com/gorilla/mux"
"gitlab.com/kbr4/svevijesti/internal/database"
"net/http"
"strconv"
"time"
)
func rootHandler(wr http.ResponseWriter, req *http.Request) {
title := "Pocetna"
store, err := database.Connect()
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
}
articles, err := database.ArticlesForDay(store, time.Now())
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
}
data := map[string]interface{}{
"title": title,
"articles": articles,
}
err = templates.ExecuteTemplate(wr, "homeHTML", data)
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
}
}
func articleHandler(wr http.ResponseWriter, req *http.Request) {
title := "Pocetna"
store, err := database.Connect()
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
}
vars := mux.Vars(req)
articleID, err := strconv.Atoi(vars["id"])
if err != nil {
articleID = -1
}
articleSlug := vars["slug"]
article, err := database.ArticleByID(store, articleID, articleSlug)
if err != nil {
http.Error(wr, err.Error(), http.StatusNotFound)
}
data := map[string]interface{}{
"title": title,
"article": article,
}
err = templates.ExecuteTemplate(wr, "articleHTML", data)
if err != nil {
http.Error(wr, err.Error(), http.StatusInternalServerError)
}
}

View File

@@ -1 +1,45 @@
package server
import (
"fmt"
"github.com/gorilla/mux"
"html/template"
"io/ioutil"
"path/filepath"
"strings"
)
var tPath = "./web/tpl/"
var dPath = "./web/data/"
var templateDirs = []string{"./web/tpl", "./web/data"}
var templates *template.Template
func getTemplates() (templates *template.Template, err error) {
var allFiles []string
for _, dir := range templateDirs {
files2, _ := ioutil.ReadDir(dir)
for _, file := range files2 {
filename := file.Name()
if strings.HasSuffix(filename, ".html") {
filePath := filepath.Join(dir, filename)
fmt.Println("Template found: ", filePath)
allFiles = append(allFiles, filePath)
}
}
}
templates, err = template.New("").ParseFiles(allFiles...)
return
}
func init() {
templates, _ = getTemplates()
}
func CreateRoutes() *mux.Router {
r := mux.NewRouter()
r.HandleFunc("/", rootHandler)
r.HandleFunc("/{id:[0-9]+}/{slug}", articleHandler)
return r
}

View File

@@ -1,6 +1,6 @@
{{define "footerHTML"}}
<footer>
© StareNovine
SN
</footer>
{{end}}

View File

@@ -20,8 +20,20 @@
max-width: 98vw;
}
h1#title {
margin-block-end: 0;
font-size: 1.7em;
}
.timestamp {
font-size: 0.8em;
color: gray;
}
.single_timestamp {
font-size: 0.77em;
margin-bottom: 0.7em;
color: gray;
}
#logo {

View File

@@ -0,0 +1,11 @@
{{define "singleArticleHTML"}}
{{with .article }}
<div class="article_content">
<h1 id="title">{{.Title}}</h1>
<div class="single_timestamp">{{.SourceName}} - {{ .FormatedCreatedAt }}</div>
<div class="article_body">
{{.Content}}
</div>
<br><br>
{{end}}
{{end}}

12
web/tpl/article.html Normal file
View File

@@ -0,0 +1,12 @@
{{define "articleHTML"}}
{{template "headHTML" .}}
<body>
{{template "headerHTML" .}}
{{template "singleArticleHTML" .}}
{{template "footerHTML" .}}
</body>
</html>
{{end}}