First version of web UI

This commit is contained in:
Senad Uka
2022-02-13 05:12:49 +01:00
parent a040320827
commit f6e90deebd
9 changed files with 274 additions and 34 deletions

68
cmd/web/web.go Normal file
View File

@@ -0,0 +1,68 @@
package main
import (
"fmt"
"gitlab.com/kbr4/svevijesti/internal/database"
"html/template"
"io/ioutil"
"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)
}

View File

@@ -0,0 +1,88 @@
package database
import (
"fmt"
_ "github.com/lib/pq"
"gitlab.com/kbr4/svevijesti/internal/model"
"math"
"time"
)
func InsertArticle(store *Store, article model.ScrapedArticle) (err error) {
query := `
INSERT INTO articles
(title, content, slug, original_url, source_id)
VALUES
($1,$2,$3,$4,$5);`
_, err = store.Exec(query, article.Title, article.Content, article.Slug, article.OriginalUrl, article.SourceId)
if err != nil {
return err
}
return nil
}
func IsSaved(store *Store, url string) bool {
exists := false
query, err := store.Prepare(`
select exists(select 1 from articles where original_url = $1);
`)
if err != nil {
panic(err)
}
row := query.QueryRow(url)
err = row.Scan(&exists)
if err != nil {
panic(err)
}
return exists
}
func ArticlesForDay(store *Store, day time.Time) (articles []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 created_at > $1 and created_at < $2 and LENGTH(content) > 10 order by id desc;
`)
if err != nil {
return result, err
}
tomorrow := day.AddDate(0, 0, 1)
todayDate := day.Format("2006-01-02")
tomorrowDate := tomorrow.Format("2006-01-02")
rows, err := query.Query(todayDate, tomorrowDate)
if err != nil {
return result, err
}
defer rows.Close()
for rows.Next() {
r := model.DisplayArticle{}
err = rows.Scan(&r.ID, &r.Title, &r.Content, &r.Slug, &r.OriginalUrl, &r.SourceId, &r.CreatedAt)
if err != nil {
return result, err
}
ago := time.Now().Sub(r.CreatedAt)
hours := ago.Hours()
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 = append(result, r)
}
return result, nil
}

View File

@@ -4,7 +4,6 @@ import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
"gitlab.com/kbr4/svevijesti/internal/model"
)
const (
@@ -24,36 +23,3 @@ func Connect() (*Store, error) {
db, err := sql.Open("postgres", psqlInfo)
return db, err
}
func InsertArticle(store *Store, article model.ScrapedArticle) (err error) {
query := `
INSERT INTO articles
(title, content, slug, original_url, source_id)
VALUES
($1,$2,$3,$4,$5);`
_, err = store.Exec(query, article.Title, article.Content, article.Slug, article.OriginalUrl, article.SourceId)
if err != nil {
return err
}
return nil
}
func IsSaved(store *Store, url string) bool {
exists := false
query, err := store.Prepare(`
select exists(select 1 from articles where original_url = $1);
`)
if err != nil {
panic(err)
}
row := query.QueryRow(url)
err = row.Scan(&exists)
if err != nil {
panic(err)
}
return exists
}

View File

@@ -1,5 +1,7 @@
package model
import "time"
type ScrapedArticle struct {
Title string
Content string
@@ -8,6 +10,26 @@ type ScrapedArticle struct {
SourceId int
}
type DisplayArticle struct {
ID int
Title string
Content string
Slug string
OriginalUrl string
SourceId int
CreatedAt time.Time
FormatedCreatedAt string
SourceName string
}
const (
KlixSource = 1
)
func SourceName(sourceId int) string {
switch sourceId {
case KlixSource:
return "klix"
}
return "starenovine"
}

16
web/data/articles.html Normal file
View File

@@ -0,0 +1,16 @@
{{define "articlesHTML"}}
<ol reversed>
{{range .articles}}
<li>
<div class="article_content">
<a href="/{{.ID}}/{{.Slug}}">
{{.Title}}</a></div>
<div class="timestamp">{{.SourceName}} - {{ .FormatedCreatedAt }}</div>
</li>
<br><br>
{{else}}
Nema članaka za izabrani datum.
{{end}}
</ol>
{{end}}

6
web/data/footer.html Normal file
View File

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

44
web/data/head.html Normal file
View File

@@ -0,0 +1,44 @@
{{define "headHTML"}}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta property="og:site_name" content="svevijesti">
<meta name="twitter:card" content="preview">
<meta property="og:title" content="stare novine: bosna i hercegovina, klix, avaz, faktor, blijesak, srpskainfo">
<meta name="description" content="stare novine omogucavaju citanje svih vijesti iz bosne i hercegovine, hrvatske, srbije, crne gore, kosova na bosanskom, crnogorskom, hrvatskom, srpskom jeziku na svim uredjajima koliko god stari bili">
<meta property="og:url" content="https://www.starenovine.com">
<title>{{.title}} - stare novine</title>
<link rel="canonical" href="https://www.starenovine.com/">
<style type="text/css">
body {
font-family: monospace;
font-size: 1.5em;
width: 90%;
max-width: 98vw;
}
.timestamp {
font-size: 0.8em;
}
#logo {
font-size: 2vw;
background: white;
}
pre.article_content {
background: white;
}
html {
margin: 0 auto;
max-width: 98vw;
overflow-x: hidden;
}
</style>
</head>
{{end}}

18
web/data/header.html Normal file
View File

@@ -0,0 +1,18 @@
{{define "headerHTML"}}
<header>
<pre id="logo">
_____ ______ ____ ____ ___ ____ ___ __ __ ____ ____ ___
/ ___/| | / || \ / _]| \ / \ | | || || \ / _]
( \_ | || o || D ) / [_ | _ || || | | | | | _ | / [_
\__ ||_| |_|| || / | _]| | || O || | | | | | | || _]
/ \ | | | | _ || \ | [_ | | || || : | | | | | || [_
\ | | | | | || . \| || | || | \ / | | | | || |
\___| |__| |__|__||__|\_||_____||__|__| \___/ \_/ |____||__|__||_____|
</pre>
<br>
<nav>
<a href="/">Početna</a>
</nav>
</header>
{{end}}

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

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