gofmt, delete works

This commit is contained in:
Dan Ballard 2015-09-13 14:57:22 -07:00
parent 8f9969b4cc
commit bc7fcdde54
6 changed files with 392 additions and 393 deletions

View File

@ -1,18 +1,18 @@
package categories package categories
import ( import (
"database/sql" "database/sql"
_ "github.com/lib/pq"
"fmt"
"strings"
"errors" "errors"
"fmt"
_ "github.com/lib/pq"
"strings"
) )
type Category struct { type Category struct {
Id int Id int
Name string Name string
Parent sql.NullInt64 Parent sql.NullInt64
Children []*Category Children []*Category
} }
var CategoriesTree []*Category var CategoriesTree []*Category
@ -20,15 +20,15 @@ var CategoriesFlat map[int]*Category
// Cavet: slight cheat. All parents must have Category_id < their children. // Cavet: slight cheat. All parents must have Category_id < their children.
func LoadCategories(db *sql.DB) { func LoadCategories(db *sql.DB) {
CategoriesTree = []*Category{} CategoriesTree = []*Category{}
CategoriesFlat = make(map[int]*Category) CategoriesFlat = make(map[int]*Category)
rows, err := db.Query("select categories.id, categories.name, categories.parent_id from categories order by coalesce(parent_id, id), parent_id is not null") rows, err := db.Query("select categories.id, categories.name, categories.parent_id from categories order by coalesce(parent_id, id), parent_id is not null")
if err != nil { if err != nil {
fmt.Println("DB Error loading Categories:", err) fmt.Println("DB Error loading Categories:", err)
return return
} }
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
category := &Category{Children: []*Category{}} category := &Category{Children: []*Category{}}
@ -41,10 +41,10 @@ func LoadCategories(db *sql.DB) {
CategoriesFlat[category.Id] = category CategoriesFlat[category.Id] = category
if category.Parent.Valid { if category.Parent.Valid {
pid := int(category.Parent.Int64) pid := int(category.Parent.Int64)
CategoriesFlat[pid].Children = append(CategoriesFlat[pid].Children, category) CategoriesFlat[pid].Children = append(CategoriesFlat[pid].Children, category)
} else { } else {
CategoriesTree = append(CategoriesTree, category) CategoriesTree = append(CategoriesTree, category)
} }
} }
} }
@ -57,7 +57,7 @@ func Add(db *sql.DB, name string, parent int) error {
_, err = db.Exec("INSERT INTO categories (name, parent_id) VALUES ($1, $2)", name, parent) _, err = db.Exec("INSERT INTO categories (name, parent_id) VALUES ($1, $2)", name, parent)
} }
if err != nil { if err != nil {
fmt.Println("Categories DB Error Add(): " , err) fmt.Println("Categories DB Error Add(): ", err)
} }
return err return err
} }
@ -67,65 +67,64 @@ func Add(db *sql.DB, name string, parent int) error {
// set category of news to parent // set category of news to parent
// finallly delete // finallly delete
func Delete(db *sql.DB, id int) error { func Delete(db *sql.DB, id int) error {
rows, err := db.Query("SELECT parent_id FROM categories WHERE id=$1", id) rows, err := db.Query("SELECT parent_id FROM categories WHERE id=$1", id)
if err != nil { if err != nil {
fmt.Println("Categories DB Error loading category parent id: ", err) fmt.Println("Categories DB Error loading category parent id: ", err)
return err return err
} }
if !rows.Next() { if !rows.Next() {
fmt.Println("Categories DB Error loading category parent id: no category") fmt.Println("Categories DB Error loading category parent id: no category")
return errors.New("No category") return errors.New("No category")
} }
var parent_id sql.NullInt64 var parent_id sql.NullInt64
err = rows.Scan(&parent_id) err = rows.Scan(&parent_id)
_, err = db.Exec("UPDATE categories SET parent_id =$2 WHERE parent_id=$1", id, parent_id) _, err = db.Exec("UPDATE categories SET parent_id =$2 WHERE parent_id=$1", id, parent_id)
if err != nil { if err != nil {
fmt.Println("Categories DB error changing child parent: ", err) fmt.Println("Categories DB error changing child parent: ", err)
return err return err
} }
_, err = db.Exec("UPDATE news SET category_id =$2 WHERE category_id=$1", id, parent_id)
if err != nil {
fmt.Println("Categories DB error changing category of news: ", err)
return err
}
_, err = db.Exec("UPDATE news SET category_id =$2 WHERE category_id=$1", id, parent_id) _, err = db.Exec("DELETE FROM categories WHERE id=$1", id)
if err != nil { if err != nil {
fmt.Println("Categories DB error changing category of news: ", err) fmt.Println("Categories DB Error Delete(): ", err)
return err }
} return err
_, err = db.Exec("DELETE FROM categories WHERE id=$1", id)
if err != nil {
fmt.Println("Categories DB Error Delete(): ", err)
}
return err
} }
func (category *Category) ChangeParent(db *sql.DB, parent *Category) error { func (category *Category) ChangeParent(db *sql.DB, parent *Category) error {
var err error var err error
if parent == nil { if parent == nil {
_, err = db.Exec("UPDATE categories SET parent_id = NULL WHERE id = $1", category.Id) _, err = db.Exec("UPDATE categories SET parent_id = NULL WHERE id = $1", category.Id)
} else { } else {
_, err = db.Exec("UPDATE categories SET parent_id = $2 WHERE id = $1", category.Id, parent.Id) _, err = db.Exec("UPDATE categories SET parent_id = $2 WHERE id = $1", category.Id, parent.Id)
} }
if err != nil { if err != nil {
fmt.Println("Categories DB Error: ", err) fmt.Println("Categories DB Error: ", err)
} }
return err return err
} }
// get the number of parents a category has // get the number of parents a category has
func (category *Category) Depth() int { func (category *Category) Depth() int {
depth := 0 depth := 0
current := category current := category
for current.Parent.Valid { for current.Parent.Valid {
current = CategoriesFlat[int(current.Parent.Int64)] current = CategoriesFlat[int(current.Parent.Int64)]
depth ++ depth++
} }
return depth return depth
} }
// Helper function for templates (add form select list) // Helper function for templates (add form select list)
func (category *Category) ToString() string { func (category *Category) ToString() string {
return strings.Repeat("- ", category.Depth()) + category.Name return strings.Repeat("- ", category.Depth()) + category.Name
} }

13
main.go
View File

@ -3,16 +3,16 @@ package main
import ( import (
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"flag"
"fmt" "fmt"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
_ "github.com/lib/pq" _ "github.com/lib/pq"
"net/http" "net/http"
"os" "os"
"flag"
) )
const ( const (
VERSION = "0.1" VERSION = "0.1"
MAX_DB_CONNS = 10 // already excessive for personal app MAX_DB_CONNS = 10 // already excessive for personal app
) )
@ -24,7 +24,7 @@ type Config struct {
Password string Password string
} }
Port string Port string
Url string Url string
} }
const ( const (
@ -33,9 +33,9 @@ const (
) )
var ( var (
config Config config Config
db *sql.DB db *sql.DB
store = sessions.NewCookieStore([]byte("key-store-auth-secret")) store = sessions.NewCookieStore([]byte("key-store-auth-secret"))
) )
func loadConfig(env string) { func loadConfig(env string) {
@ -73,7 +73,6 @@ func main() {
envFlag := flag.String("env", "local", "load config/{env}.json") envFlag := flag.String("env", "local", "load config/{env}.json")
flag.Parse() flag.Parse()
fmt.Println("Loading...") fmt.Println("Loading...")
loadConfig(*envFlag) loadConfig(*envFlag)

View File

@ -1,22 +1,21 @@
package news package news
import ( import (
"time" "database/sql"
"database/sql"
_ "github.com/lib/pq"
"fmt" "fmt"
"github.com/dballard/transmet/categories" "github.com/dballard/transmet/categories"
_ "github.com/lib/pq"
"time"
) )
type News struct { type News struct {
id int id int
Url string Url string
Title string Title string
Category_id int Category_id int
Date time.Time Date time.Time
Notes string Notes string
Expoerted bool Expoerted bool
} }
/* Storage Node containing: /* Storage Node containing:
@ -26,53 +25,58 @@ type News struct {
* Children - sub containers: mapped to sub categories * Children - sub containers: mapped to sub categories
*/ */
type NewsContainer struct { type NewsContainer struct {
Name string Name string
News []News News []News
Category *categories.Category Category *categories.Category
Children map[int]*NewsContainer Children map[int]*NewsContainer
} }
// Insert News item into DB // Insert News item into DB
func (news *News) Insert(db *sql.DB) error { func (news *News) Insert(db *sql.DB) error {
_, err := db.Exec("INSERT INTO news (url, title, category_id, notes) VALUES($1, $2, $3, $4)", news.Url, news.Title, news.Category_id, news.Notes ); _, err := db.Exec("INSERT INTO news (url, title, category_id, notes) VALUES($1, $2, $3, $4)", news.Url, news.Title, news.Category_id, news.Notes)
if err != nil { if err != nil {
fmt.Println("Error inserting news: ", err) fmt.Println("Error inserting news: ", err)
return err return err
} }
return nil return nil
} }
func Delete(db *sql.DB, id int) error { func Delete(db *sql.DB, id int) error {
_, err := db.Exec("DELETE FROM news WHERE id = $1", id)
if err != nil {
fmt.Println("Error deleting news: ", err)
return err
}
return nil return nil
} }
func nullStringToString(str *sql.NullString) string { func nullStringToString(str *sql.NullString) string {
if str.Valid { if str.Valid {
return str.String return str.String
} else { } else {
return "" return ""
} }
} }
// Init and add a news container to the Data Structs // Init and add a news container to the Data Structs
func addContainer(category_id int, flat, tree map[int]*NewsContainer) { func addContainer(category_id int, flat, tree map[int]*NewsContainer) {
container := &NewsContainer{ Category: categories.CategoriesFlat[category_id], Name: categories.CategoriesFlat[category_id].Name, News: []News{}, Children: map[int]*NewsContainer{} } container := &NewsContainer{Category: categories.CategoriesFlat[category_id], Name: categories.CategoriesFlat[category_id].Name, News: []News{}, Children: map[int]*NewsContainer{}}
flat[category_id] = container flat[category_id] = container
parent := categories.CategoriesFlat[category_id].Parent parent := categories.CategoriesFlat[category_id].Parent
if parent.Valid { if parent.Valid {
if _, ok := flat[int(parent.Int64)]; !ok { if _, ok := flat[int(parent.Int64)]; !ok {
addContainer(int(parent.Int64), flat, tree) addContainer(int(parent.Int64), flat, tree)
} }
flat[int(parent.Int64)].Children[category_id] = container flat[int(parent.Int64)].Children[category_id] = container
} else { } else {
tree[category_id] = container tree[category_id] = container
} }
} }
// Load and return in NewsContainer format all the unexported news items // Load and return in NewsContainer format all the unexported news items
func LoadPage(db *sql.DB, offset, amount int) ([]*News, int, error) { func LoadPage(db *sql.DB, offset, amount int) ([]*News, int, error) {
categories.LoadCategories(db) // required by addContainer categories.LoadCategories(db) // required by addContainer
rows, err := db.Query("SELECT id, url, title, category_id, timestamp, notes FROM news WHERE exported is null order by timestamp DESC") rows, err := db.Query("SELECT id, url, title, category_id, timestamp, notes FROM news WHERE exported is null order by timestamp DESC")
if err != nil { if err != nil {
@ -86,7 +90,7 @@ func LoadPage(db *sql.DB, offset, amount int) ([]*News, int, error) {
// Load and return in NewsContainer format all the unexported news items // Load and return in NewsContainer format all the unexported news items
func Unexported(db *sql.DB) (map[int]*NewsContainer, int, error) { func Unexported(db *sql.DB) (map[int]*NewsContainer, int, error) {
categories.LoadCategories(db) // required by addContainer categories.LoadCategories(db) // required by addContainer
rows, err := db.Query("SELECT id, url, title, category_id, timestamp, notes FROM news WHERE exported is null order by category_id ASC") rows, err := db.Query("SELECT id, url, title, category_id, timestamp, notes FROM news WHERE exported is null order by category_id ASC")
if err != nil { if err != nil {
@ -102,28 +106,27 @@ func convertSqlToNews(rows *sql.Rows) ([]*News, int, error) {
news := []*News{} news := []*News{}
count := 0 count := 0
for rows.Next() { for rows.Next() {
newsItem := &News{} newsItem := &News{}
var url, title, notes sql.NullString var url, title, notes sql.NullString
var category_id sql.NullInt64 var category_id sql.NullInt64
err := rows.Scan(&newsItem.id, &url, &title, &category_id, &newsItem.Date, &notes) err := rows.Scan(&newsItem.id, &url, &title, &category_id, &newsItem.Date, &notes)
if err != nil { if err != nil {
fmt.Println("Error reading news from DB: " + err.Error()) fmt.Println("Error reading news from DB: " + err.Error())
return nil, 0, err return nil, 0, err
} }
newsItem.Url = nullStringToString(&url) newsItem.Url = nullStringToString(&url)
newsItem.Title = nullStringToString(&title) newsItem.Title = nullStringToString(&title)
newsItem.Notes = nullStringToString(&notes) newsItem.Notes = nullStringToString(&notes)
if category_id.Valid { if category_id.Valid {
newsItem.Category_id = int(category_id.Int64) newsItem.Category_id = int(category_id.Int64)
} else { } else {
continue // needs a category id continue // needs a category id
} }
news = append(news, newsItem)
news = append(news, newsItem) count++
count++
} }
return news, count, nil return news, count, nil
@ -134,31 +137,31 @@ func convertSqlToNewsContainer(rows *sql.Rows) (map[int]*NewsContainer, int, err
newsFlat := map[int]*NewsContainer{} newsFlat := map[int]*NewsContainer{}
count := 0 count := 0
for rows.Next() { for rows.Next() {
news := News{} news := News{}
var url, title, notes sql.NullString var url, title, notes sql.NullString
var category_id sql.NullInt64 var category_id sql.NullInt64
err := rows.Scan(&news.id, &url, &title, &category_id, &news.Date, &notes) err := rows.Scan(&news.id, &url, &title, &category_id, &news.Date, &notes)
if err != nil { if err != nil {
fmt.Println("Error reading news from DB: " + err.Error()) fmt.Println("Error reading news from DB: " + err.Error())
return nil, 0, err return nil, 0, err
} }
news.Url = nullStringToString(&url) news.Url = nullStringToString(&url)
news.Title = nullStringToString(&title) news.Title = nullStringToString(&title)
news.Notes = nullStringToString(&notes) news.Notes = nullStringToString(&notes)
if category_id.Valid { if category_id.Valid {
news.Category_id = int(category_id.Int64) news.Category_id = int(category_id.Int64)
} else { } else {
continue // needs a category id continue // needs a category id
} }
if _, ok := newsFlat[news.Category_id]; !ok { if _, ok := newsFlat[news.Category_id]; !ok {
addContainer(news.Category_id, newsFlat, newsTree) addContainer(news.Category_id, newsFlat, newsTree)
} }
container := newsFlat[news.Category_id] container := newsFlat[news.Category_id]
container.News = append(container.News, news) container.News = append(container.News, news)
count++ count++
} }
return newsTree, count, nil return newsTree, count, nil
@ -166,20 +169,20 @@ func convertSqlToNewsContainer(rows *sql.Rows) (map[int]*NewsContainer, int, err
// Helper fn - formating - math // Helper fn - formating - math
func (this *NewsContainer) HeaderDepth(start int) int { func (this *NewsContainer) HeaderDepth(start int) int {
return start + this.Category.Depth() return start + this.Category.Depth()
} }
// Mark the current batch (news.exported is null) as exported in this batch (exported = now()) // Mark the current batch (news.exported is null) as exported in this batch (exported = now())
func MarkExported(db *sql.DB) error { func MarkExported(db *sql.DB) error {
now := time.Now() now := time.Now()
_, err := db.Exec("UPDATE news SET exported=$1 WHERE exported is null", now) _, err := db.Exec("UPDATE news SET exported=$1 WHERE exported is null", now)
if err != nil { if err != nil {
fmt.Println("DB errror: news.MarkExported():", err) fmt.Println("DB errror: news.MarkExported():", err)
} }
return err return err
} }
func (news *News) Id() int { func (news *News) Id() int {
return news.id return news.id
} }

View File

@ -1,21 +1,21 @@
package main package main
import ( import (
"github.com/gorilla/mux" "bytes"
"github.com/gorilla/sessions"
"net/http"
"github.com/dballard/transmet/user"
"fmt" "fmt"
"time"
"io/ioutil"
"regexp"
"strings"
"strconv"
"github.com/dballard/transmet/categories" "github.com/dballard/transmet/categories"
"github.com/dballard/transmet/news" "github.com/dballard/transmet/news"
"bytes" "github.com/dballard/transmet/user"
txtTemplate "text/template" "github.com/gorilla/mux"
"github.com/gorilla/sessions"
"io/ioutil"
"net/http"
"path" "path"
"regexp"
"strconv"
"strings"
txtTemplate "text/template"
"time"
) )
func GetFlashes(session *sessions.Session) map[string]interface{} { func GetFlashes(session *sessions.Session) map[string]interface{} {
@ -86,7 +86,7 @@ func LoginPostHandler(w http.ResponseWriter, r *http.Request) {
session.Values["username"] = user.Username session.Values["username"] = user.Username
session.Save(r, w) session.Save(r, w)
if r.URL.Query().Get("url") != "" { if r.URL.Query().Get("url") != "" {
http.Redirect(w, r, "/add?" + r.URL.RawQuery, http.StatusFound) http.Redirect(w, r, "/add?"+r.URL.RawQuery, http.StatusFound)
} }
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
} else { } else {
@ -107,31 +107,31 @@ func LogoutHandler(w http.ResponseWriter, r *http.Request, user *user.User, sess
} }
func getUrlTitle(url string) string { func getUrlTitle(url string) string {
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
fmt.Println("Error looking up link", url, ":", err) fmt.Println("Error looking up link", url, ":", err)
} else { } else {
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
fmt.Println("Error reading link", url, ":", err) fmt.Println("Error reading link", url, ":", err)
} else { } else {
re := regexp.MustCompile("< *[Tt][Ii][Tt][Ll][Ee] *>(.*)</ *[Tt][Ii][Tt][Ll][Ee] *>") re := regexp.MustCompile("< *[Tt][Ii][Tt][Ll][Ee] *>(.*)</ *[Tt][Ii][Tt][Ll][Ee] *>")
title := re.FindStringSubmatch(string(body)) title := re.FindStringSubmatch(string(body))
if title != nil { if title != nil {
return strings.TrimSpace(title[1]) return strings.TrimSpace(title[1])
} }
} }
} }
return "" return ""
} }
// ?url= // ?url=
func addFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func addFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
categories.LoadCategories(db) categories.LoadCategories(db)
flashes := GetFlashes(session) flashes := GetFlashes(session)
popup := session.Values["popup"] popup := session.Values["popup"]
delete(session.Values, "popup") delete(session.Values, "popup")
title := session.Values["title"] title := session.Values["title"]
delete(session.Values, "title") delete(session.Values, "title")
link := session.Values["link"] link := session.Values["link"]
@ -141,23 +141,23 @@ func addFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, ses
session.Save(r, w) session.Save(r, w)
if link != nil { if link != nil {
//TODO category_id //TODO category_id
ShowTemplate("add", w, map[string]interface{}{"user": user, "flashes": flashes, "categories": categories.CategoriesTree, "link": link, "title": title, "description": description, "popup": popup}) ShowTemplate("add", w, map[string]interface{}{"user": user, "flashes": flashes, "categories": categories.CategoriesTree, "link": link, "title": title, "description": description, "popup": popup})
return return
} }
var url = r.URL.Query().Get("url") var url = r.URL.Query().Get("url")
reHttp := regexp.MustCompile("^https?://") reHttp := regexp.MustCompile("^https?://")
if url != "" && ! reHttp.Match([]byte(url)) { if url != "" && !reHttp.Match([]byte(url)) {
url = "http://" + url url = "http://" + url
} }
title = r.URL.Query().Get("title") title = r.URL.Query().Get("title")
if title == "" && url != "" { if title == "" && url != "" {
title = getUrlTitle(url) title = getUrlTitle(url)
} }
popup = r.URL.Query().Get("popup") popup = r.URL.Query().Get("popup")
ShowTemplate("add", w, map[string]interface{}{"user": user, "flashes": flashes, "link": url, "categories": categories.CategoriesTree, "title": title, "popup": popup}) ShowTemplate("add", w, map[string]interface{}{"user": user, "flashes": flashes, "link": url, "categories": categories.CategoriesTree, "title": title, "popup": popup})
} }
@ -171,44 +171,44 @@ func addPostHandler(w http.ResponseWriter, r *http.Request, user *user.User, ses
popup := r.FormValue("popup") popup := r.FormValue("popup")
category_id, err := strconv.Atoi(r.FormValue("category")) category_id, err := strconv.Atoi(r.FormValue("category"))
if err != nil { if err != nil {
category_id = -1 category_id = -1
} }
news.Category_id = category_id news.Category_id = category_id
err = (&news).Insert(db) err = (&news).Insert(db)
if err != nil { if err != nil {
session.AddFlash("Error saving news: " + err.Error(), flash_err) session.AddFlash("Error saving news: "+err.Error(), flash_err)
session.Values["title"] = news.Title session.Values["title"] = news.Title
session.Values["link"] = news.Url session.Values["link"] = news.Url
session.Values["notes"] = news.Notes session.Values["notes"] = news.Notes
session.Values["popup"] = popup session.Values["popup"] = popup
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/add", http.StatusFound) http.Redirect(w, r, "/add", http.StatusFound)
} else { } else {
// TODO auto close? redirect // TODO auto close? redirect
session.AddFlash("Added news \""+news.Title+"\"", flash_info) session.AddFlash("Added news \""+news.Title+"\"", flash_info)
session.Save(r, w) session.Save(r, w)
if popup == "1" { if popup == "1" {
http.Redirect(w, r, "/added", http.StatusFound) http.Redirect(w, r, "/added", http.StatusFound)
} else { } else {
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
} }
} }
} }
func templateFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func templateFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
flashes := GetFlashes(session) flashes := GetFlashes(session)
session.Save(r, w) session.Save(r, w)
news, count, err := news.Unexported(db) news, count, err := news.Unexported(db)
if err != nil { if err != nil {
return return
} }
var templateBuf bytes.Buffer var templateBuf bytes.Buffer
template, err := txtTemplate.ParseFiles("templates/html_template.txt") template, err := txtTemplate.ParseFiles("templates/html_template.txt")
if err != nil { if err != nil {
fmt.Println("Error processing html_tempalte:" , err) fmt.Println("Error processing html_tempalte:", err)
} }
err = template.Execute(&templateBuf, map[string]interface{}{"news": news}) err = template.Execute(&templateBuf, map[string]interface{}{"news": news})
if err != nil { if err != nil {
@ -222,18 +222,18 @@ func exportHandler(w http.ResponseWriter, r *http.Request, user *user.User, sess
err := news.MarkExported(db) err := news.MarkExported(db)
if err != nil { if err != nil {
session.AddFlash("Error marking last batch of news exported", flash_err) session.AddFlash("Error marking last batch of news exported", flash_err)
} else { } else {
session.AddFlash("Last batch of news marked exported", flash_info) session.AddFlash("Last batch of news marked exported", flash_info)
} }
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
} }
func addedHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func addedHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
flashes := GetFlashes(session) flashes := GetFlashes(session)
session.Save(r, w) session.Save(r, w)
ShowTemplate("added", w, map[string]interface{}{"user": user, "flashes": flashes}) ShowTemplate("added", w, map[string]interface{}{"user": user, "flashes": flashes})
} }
func deleteHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func deleteHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
@ -242,39 +242,38 @@ func deleteHandler(w http.ResponseWriter, r *http.Request, user *user.User, sess
if idErr != nil { if idErr != nil {
session.AddFlash("Invalid news to delete", flash_err) session.AddFlash("Invalid news to delete", flash_err)
} else { } else {
err := news.Delete(db, id) err := news.Delete(db, id)
if err != nil { if err != nil {
session.AddFlash("Error commiting to Database", flash_err) session.AddFlash("Error commiting to Database", flash_err)
} else { } else {
session.AddFlash("Deleted news post", flash_info) session.AddFlash("Deleted news post", flash_info)
} }
} }
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(w, r, "/", http.StatusFound)
} }
func categoriesFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func categoriesFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
flashes := GetFlashes(session) flashes := GetFlashes(session)
session.Save(r, w) session.Save(r, w)
categories.LoadCategories(db) categories.LoadCategories(db)
ShowTemplate("categories", w, map[string]interface{}{"user": user, "flashes": flashes, "categories": categories.CategoriesTree}) ShowTemplate("categories", w, map[string]interface{}{"user": user, "flashes": flashes, "categories": categories.CategoriesTree})
} }
func categoriesPostHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func categoriesPostHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
http.Redirect(w, r, "/categories", http.StatusFound) http.Redirect(w, r, "/categories", http.StatusFound)
} }
func categoryFromReqArg(arg string) *categories.Category { func categoryFromReqArg(arg string) *categories.Category {
if cid, err := strconv.Atoi(arg); err != nil { if cid, err := strconv.Atoi(arg); err != nil {
return nil return nil
} else if category, ok := categories.CategoriesFlat[cid]; !ok { } else if category, ok := categories.CategoriesFlat[cid]; !ok {
return nil return nil
} else { } else {
return category return category
} }
} }
func categoryChangeParentHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func categoryChangeParentHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
@ -287,16 +286,16 @@ func categoryChangeParentHandler(w http.ResponseWriter, r *http.Request, user *u
} else if parent != nil && category.Id == parent.Id { } else if parent != nil && category.Id == parent.Id {
session.AddFlash("Cannot set category parent to itself", flash_err) session.AddFlash("Cannot set category parent to itself", flash_err)
} else { } else {
err := category.ChangeParent(db, parent) err := category.ChangeParent(db, parent)
if err != nil { if err != nil {
session.AddFlash("Error commiting to Database", flash_err) session.AddFlash("Error commiting to Database", flash_err)
} else { } else {
session.AddFlash("Changed category parent", flash_info) session.AddFlash("Changed category parent", flash_info)
} }
} }
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/categories", http.StatusFound) http.Redirect(w, r, "/categories", http.StatusFound)
} }
func categoryAddHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func categoryAddHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
@ -304,21 +303,21 @@ func categoryAddHandler(w http.ResponseWriter, r *http.Request, user *user.User,
parent, perr := strconv.Atoi(r.FormValue("parent")) parent, perr := strconv.Atoi(r.FormValue("parent"))
if perr != nil { if perr != nil {
parent = -1 parent = -1
} }
if name == "" { if name == "" {
session.AddFlash("Invalid category name", flash_err) session.AddFlash("Invalid category name", flash_err)
} else { } else {
err := categories.Add(db, name, parent) err := categories.Add(db, name, parent)
if err != nil { if err != nil {
session.AddFlash("Error commiting to Database", flash_err) session.AddFlash("Error commiting to Database", flash_err)
} else { } else {
session.AddFlash("Added category", flash_info) session.AddFlash("Added category", flash_info)
} }
} }
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/categories", http.StatusFound) http.Redirect(w, r, "/categories", http.StatusFound)
} }
func categoryDeleteHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func categoryDeleteHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
@ -327,45 +326,45 @@ func categoryDeleteHandler(w http.ResponseWriter, r *http.Request, user *user.Us
if idErr != nil { if idErr != nil {
session.AddFlash("Invalid category to delete", flash_err) session.AddFlash("Invalid category to delete", flash_err)
} else { } else {
err := categories.Delete(db, id) err := categories.Delete(db, id)
if err != nil { if err != nil {
session.AddFlash("Error commiting to Database", flash_err) session.AddFlash("Error commiting to Database", flash_err)
} else { } else {
session.AddFlash("Deleted category", flash_info) session.AddFlash("Deleted category", flash_info)
} }
} }
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/categories", http.StatusFound) http.Redirect(w, r, "/categories", http.StatusFound)
} }
func newsFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) { func newsFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
flashes := GetFlashes(session) flashes := GetFlashes(session)
session.Save(r, w) session.Save(r, w)
var offset = 0 var offset = 0
var amount = 100 var amount = 100
argOffset, eOffset := strconv.Atoi(r.FormValue("offset")) argOffset, eOffset := strconv.Atoi(r.FormValue("offset"))
if eOffset == nil { if eOffset == nil {
offset = amount * argOffset offset = amount * argOffset
}
news, count, err := news.LoadPage(db, offset, amount)
if err != nil {
session.AddFlash("Error loading news", flash_err)
} }
ShowTemplate("news", w, map[string]interface{}{"user": user, "flashes": flashes, "news": news, "count": count, "categories": categories.CategoriesFlat}) news, count, err := news.LoadPage(db, offset, amount)
if err != nil {
session.AddFlash("Error loading news", flash_err)
}
ShowTemplate("news", w, map[string]interface{}{"user": user, "flashes": flashes, "news": news, "count": count, "categories": categories.CategoriesFlat})
} }
func ServeFileHandler(res http.ResponseWriter, req *http.Request) { func ServeFileHandler(res http.ResponseWriter, req *http.Request) {
fname := path.Base(req.URL.Path) fname := path.Base(req.URL.Path)
http.ServeFile(res, req, "./"+fname) http.ServeFile(res, req, "./"+fname)
} }
func init_route_handlers() { func init_route_handlers() {
http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("js/")))) http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("js/"))))
http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("css/")))) http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("css/"))))
http.Handle("/fonts/", http.StripPrefix("/fonts", http.FileServer(http.Dir("fonts/")))) http.Handle("/fonts/", http.StripPrefix("/fonts", http.FileServer(http.Dir("fonts/"))))
http.HandleFunc("/favicon.ico", ServeFileHandler) http.HandleFunc("/favicon.ico", ServeFileHandler)

View File

@ -1,81 +1,80 @@
package main package main
import ( import (
"fmt" "errors"
"fmt"
"github.com/dballard/transmet/categories"
"html/template" "html/template"
"net/http"
"path/filepath" "path/filepath"
"regexp" "regexp"
"net/http"
"errors"
"time"
"strings" "strings"
"github.com/dballard/transmet/categories" "time"
) )
var ( var (
templates = map[string]*template.Template{} templates = map[string]*template.Template{}
) )
// template helper function // template helper function
func dict (values ...interface{}) (map[string]interface{}, error) { func dict(values ...interface{}) (map[string]interface{}, error) {
if len(values)%2 != 0 { if len(values)%2 != 0 {
return nil, errors.New("invalid dict call") return nil, errors.New("invalid dict call")
} }
dict := make(map[string]interface{}, len(values)/2) dict := make(map[string]interface{}, len(values)/2)
for i := 0; i < len(values); i+=2 { for i := 0; i < len(values); i += 2 {
key, ok := values[i].(string) key, ok := values[i].(string)
if !ok { if !ok {
return nil, errors.New("dict keys must be strings") return nil, errors.New("dict keys must be strings")
} }
dict[key] = values[i+1] dict[key] = values[i+1]
} }
return dict, nil return dict, nil
} }
// string multiplication // string multiplication
// stringTimes(3, "Foo") => "FooFooFoo" // stringTimes(3, "Foo") => "FooFooFoo"
func stringTimes(times int, str string) string { func stringTimes(times int, str string) string {
result := "" result := ""
for i := 0; i < times; i ++ { for i := 0; i < times; i++ {
result += str result += str
} }
return result return result
} }
// Turns a Time into a formated string // Turns a Time into a formated string
func dateFormat(t time.Time) string { func dateFormat(t time.Time) string {
return t.Format("2006.01.02 15:04:05") return t.Format("2006.01.02 15:04:05")
} }
// takes a category_id and returns "Root / Parent / Category" // takes a category_id and returns "Root / Parent / Category"
func fullCategoryPath(categoriesFlat map[int]*categories.Category, category_id int) string { func fullCategoryPath(categoriesFlat map[int]*categories.Category, category_id int) string {
var categoryNames []string = nil var categoryNames []string = nil
for category := categoriesFlat[category_id]; category != nil; category = categoriesFlat[int(category.Parent.Int64)] { for category := categoriesFlat[category_id]; category != nil; category = categoriesFlat[int(category.Parent.Int64)] {
categoryNames = append([]string{category.Name}, categoryNames...) categoryNames = append([]string{category.Name}, categoryNames...)
} }
return strings.Join(categoryNames, " / ") return strings.Join(categoryNames, " / ")
} }
// truncate a string // truncate a string
func truncate(str string, maxLen int) string { func truncate(str string, maxLen int) string {
if len(str) <= maxLen { if len(str) <= maxLen {
return str return str
} }
return str[0:maxLen] + "..." return str[0:maxLen] + "..."
} }
// Tempalte helper functions // Tempalte helper functions
var funcMap = template.FuncMap { var funcMap = template.FuncMap{
"add": func (x, y int) int { return x + y }, "add": func(x, y int) int { return x + y },
"minus": func (x, y int) int { return x - y }, "minus": func(x, y int) int { return x - y },
"dict": dict, "dict": dict,
"stringTimes": stringTimes, "stringTimes": stringTimes,
"dateFormat": dateFormat, "dateFormat": dateFormat,
"fullCategoryPath": fullCategoryPath, "fullCategoryPath": fullCategoryPath,
"truncate": truncate, "truncate": truncate,
} }
func initTemplates() { func initTemplates() {
files, _ := filepath.Glob("templates/pages/*.html") files, _ := filepath.Glob("templates/pages/*.html")
re := regexp.MustCompile("templates/pages/(.*).html") re := regexp.MustCompile("templates/pages/(.*).html")

View File

@ -7,8 +7,8 @@ import (
) )
type User struct { type User struct {
Username string Username string
db *sql.DB db *sql.DB
} }
func UsernameExists(db *sql.DB, username string) (bool, error) { func UsernameExists(db *sql.DB, username string) (bool, error) {
@ -39,7 +39,7 @@ func NewUserFromAuth(db *sql.DB, username, password string) *User {
fmt.Println("scan err: ", err) fmt.Println("scan err: ", err)
} }
} else { } else {
fmt.Println("no match") fmt.Println("no match")
return nil return nil
} }
return &user return &user