Compare commits
No commits in common. "master" and "csrf" have entirely different histories.
|
@ -1,7 +1,6 @@
|
||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
transmet
|
transmet
|
||||||
db/dbconf.yml
|
db/dbconf.yml
|
||||||
csrf-secret.txt
|
|
||||||
.Rhistory
|
.Rhistory
|
||||||
.project
|
.project
|
||||||
*.iml
|
*.iml
|
||||||
|
|
65
README.md
65
README.md
|
@ -1,4 +1,4 @@
|
||||||
# transmet ![thrree eyed smiley face](https://raw.githubusercontent.com/dballard/transmet/master/favicon.ico)
|
# transmet
|
||||||
Quick fast personal link store that exports to a HTML template for quick posting to a blog
|
Quick fast personal link store that exports to a HTML template for quick posting to a blog
|
||||||
|
|
||||||
Usecase: storing interesting news articles you come across during a week with at the moment notes/commentary and
|
Usecase: storing interesting news articles you come across during a week with at the moment notes/commentary and
|
||||||
|
@ -6,8 +6,8 @@ Usecase: storing interesting news articles you come across during a week with at
|
||||||
|
|
||||||
## Note
|
## Note
|
||||||
|
|
||||||
As this is a personal project, some of the niceities like user managment
|
As this is a personal project, some of the niceities like user managment and category managment
|
||||||
are left to be done in SQL. I needed a tool to store links and export
|
(that are one time tasks) are left to be done in SQL. I needed a tool to store links and export
|
||||||
to html so that's what I've focused on.
|
to html so that's what I've focused on.
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
|
@ -18,55 +18,56 @@ go get github.com/dballard/transmet
|
||||||
|
|
||||||
sudo apt-get install postgres postgresql-contrib
|
sudo apt-get install postgres postgresql-contrib
|
||||||
|
|
||||||
Setup postgres to handle a local connection for transmet in pg_hba.conf
|
Setup postgres to hadle a local connection for transmet in pg_hba.conf
|
||||||
either:
|
either:
|
||||||
host transmet transmet 127.0.0.1/32 md5
|
'''host transmet transmet 127.0.0.1/32 md5'''
|
||||||
or a more liberal:
|
or a more liberal:
|
||||||
host all all 127.0.0.1/32 md5
|
'''host all all 127.0.0.1/32 md5 '''
|
||||||
and do the same for
|
|
||||||
host all all ::1/128 md5
|
|
||||||
ipv6
|
|
||||||
|
|
||||||
create ssl certs and put them somewhere
|
create ssl certs and put them somewhere
|
||||||
|
|
||||||
enable SSL in postgresql.conf
|
enable SSL in postgresql.conf
|
||||||
|
'''
|
||||||
ssl = true
|
ssl = true
|
||||||
ssl_cert_file = 'WHER_YOU_PUT/server.crt'
|
ssl_cert_file = 'WHER_YOU_PUT/server.crt'
|
||||||
ssl_key_file = 'WHERE_YOU_PUT/server.key'
|
ssl_key_file = 'WHERE_YOU_PUT/server.key'
|
||||||
|
'''
|
||||||
|
|
||||||
Create postgress DB and user
|
Create postgress DB and user
|
||||||
|
|
||||||
sh
|
'''sh
|
||||||
sudo -u postgres --or-- sudo su - postgres
|
sudo -u postgres
|
||||||
createuser -S -P -E transmet
|
createuser -S -P -E transmet
|
||||||
createdb --owner transmet --encoding utf8 transmet
|
createdb --owner transmet --encoding utf8 transmet
|
||||||
psql
|
psql
|
||||||
\c transmet
|
\c transmet
|
||||||
CREATE EXTENSION pgcrypto;
|
CREATE EXTENSION pgcrypto;
|
||||||
|
'''
|
||||||
|
|
||||||
|
put DB details in
|
||||||
|
db/dbconf.yml (copied from db/dbconf.EXAMPLE)
|
||||||
|
config/prod.json (copied from config/local.json)
|
||||||
|
|
||||||
put DB details in:
|
go get bitbucket.org/liamstask/goose/cmd/goose
|
||||||
* db/dbconf.yml (copied from db/dbconf.EXAMPLE)
|
|
||||||
* config/prod.json (copied from config/local.json)
|
|
||||||
|
|
||||||
go get bitbucket.org/liamstask/goose/cmd/goose
|
goose up
|
||||||
|
|
||||||
goose up
|
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
Assumed `GOPATH=/opt/go`
|
Assumed GOPATH=/opt/go
|
||||||
|
|
||||||
edit transmet.conf to point to correct location
|
edit transmet.conf to point to correct location
|
||||||
|
|
||||||
sudo cp transmet.conf /etc/init
|
sudo cp transmet.conf /etc/init
|
||||||
./gen-csrf.sh
|
|
||||||
sudo service transmet start
|
sudo service transmet start
|
||||||
|
|
||||||
## Setup environment
|
## Setup environment
|
||||||
|
|
||||||
### Adding a user
|
### Adding a user
|
||||||
|
|
||||||
INSERT INTO users (username, password) VALUES('USERNAME', crypt('PASSWORD', gen_salt('bf')));
|
INSERT INTO users (username, password) VALUES('USERNAME', crypt('PASSWORD', gen_salt('bf')));
|
||||||
|
|
||||||
|
### Adding Categories
|
||||||
|
|
||||||
|
INSERT INTO categories (name, parent_id) VALUES ('NAME', [null or PARENT_ID]);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
RUN GEN-CSRF.SH TO INIT THIS FI
|
|
@ -1,39 +0,0 @@
|
||||||
/* Sticky footer styles
|
|
||||||
-------------------------------------------------- */
|
|
||||||
html {
|
|
||||||
position: relative;
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
/* Margin bottom by footer height */
|
|
||||||
margin-bottom: 60px;
|
|
||||||
}
|
|
||||||
.footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
/* Set the fixed height of the footer here */
|
|
||||||
height: 60px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Custom page CSS
|
|
||||||
-------------------------------------------------- */
|
|
||||||
/* Not required for template or sticky footer method. */
|
|
||||||
|
|
||||||
body > .container {
|
|
||||||
padding: 0px 15px 0;
|
|
||||||
}
|
|
||||||
.container .text-muted {
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer > .container {
|
|
||||||
padding-right: 15px;
|
|
||||||
padding-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 80%;
|
|
||||||
}
|
|
|
@ -38,27 +38,10 @@ body {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-content {
|
.post-preview {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
max-height: 5em;
|
|
||||||
overflow: hidden;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-content blockquote {
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-slider {
|
|
||||||
text-align: center;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 16px;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.post-delete, .post-edit {
|
.post-delete, .post-edit {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
dd if=/dev/urandom of=csrf-secret.txt count=32 bs=1
|
dd if=/dev/random of=csrf-secret.txt count=32 bs=1
|
||||||
|
|
12
js/funcs.js
12
js/funcs.js
|
@ -42,16 +42,4 @@ $(document).ready( function () {
|
||||||
form.submit();
|
form.submit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".content-slider").click(function (e) {
|
|
||||||
var contentDiv = $(this).parents('.news-row').find('.post-content');
|
|
||||||
if (contentDiv.hasClass("state-up")) {
|
|
||||||
contentDiv.removeClass('state-up').addClass('state-down').animate({'max-height': '100%', 'height': '100%'});
|
|
||||||
$(this).html('^');
|
|
||||||
} else {
|
|
||||||
contentDiv.removeClass('state-down').addClass('state-up').animate({height: '5em'});
|
|
||||||
$(this).html('v');
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
8
main.go
8
main.go
|
@ -107,15 +107,11 @@ func main() {
|
||||||
//errHandler := csrf.ErrorHandler( CSRFErrorHandler{} )
|
//errHandler := csrf.ErrorHandler( CSRFErrorHandler{} )
|
||||||
|
|
||||||
// Terrible. TODO: Get SSL for prod, and then wrap in if(dev) { {
|
// Terrible. TODO: Get SSL for prod, and then wrap in if(dev) { {
|
||||||
//csrfSecurityOption := csrf.Secure(false)
|
csrfSecurityOption := csrf.Secure(false)
|
||||||
//csrfMaxTimeOption := csrf.MaxAge(3600 * 24 * 3) // 3 Days - a little more wiggle room
|
|
||||||
|
|
||||||
fmt.Println("Listening on", config.Port, "...")
|
fmt.Println("Listening on", config.Port, "...")
|
||||||
|
|
||||||
// Disabled CSRF until SSL (and sorting why the popup is throwing CSRF errs
|
err := http.ListenAndServe(":"+config.Port, csrf.Protect([]byte(csrfSecret()) /*errHandler,*/, csrfSecurityOption)(muxRouter))
|
||||||
// for tor and FF with ublock + https everywhere)
|
|
||||||
//err := http.ListenAndServe(":"+config.Port, csrf.Protect([]byte(csrfSecret()), errHandler, csrfSecurityOption, csrfMaxTimeOption)(muxRouter))
|
|
||||||
err := http.ListenAndServe(":"+config.Port, muxRouter)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Fatal Error: ", err)
|
fmt.Println("Fatal Error: ", err)
|
||||||
}
|
}
|
||||||
|
|
12
news/news.go
12
news/news.go
|
@ -8,8 +8,6 @@ import (
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
"html/template"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type News struct {
|
type News struct {
|
||||||
|
@ -19,7 +17,6 @@ type News struct {
|
||||||
Category_id int
|
Category_id int
|
||||||
Date time.Time
|
Date time.Time
|
||||||
Notes string
|
Notes string
|
||||||
htmlNotes template.HTML
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -97,7 +94,7 @@ func Get(db *sql.DB, id int) (*News, error) {
|
||||||
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 " + SQL_NEWS_FIELDS + " FROM news ORDER BY timestamp DESC LIMIT $1 OFFSET $2", amount, offset)
|
rows, err := db.Query("SELECT " + SQL_NEWS_FIELDS + " FROM news order by timestamp DESC")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("DB errpr reading LoadPage news: ", err)
|
fmt.Println("DB errpr reading LoadPage news: ", err)
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
|
@ -141,10 +138,6 @@ func (news *News) Id() int {
|
||||||
return news.id
|
return news.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (news *News) HTMLNotes() template.HTML {
|
|
||||||
return news.htmlNotes
|
|
||||||
}
|
|
||||||
|
|
||||||
func nullStringToString(str *sql.NullString) string {
|
func nullStringToString(str *sql.NullString) string {
|
||||||
if str.Valid {
|
if str.Valid {
|
||||||
return str.String
|
return str.String
|
||||||
|
@ -189,9 +182,6 @@ func scanNews(rows *sql.Rows) (*News, error) {
|
||||||
news.Url = nullStringToString(&url)
|
news.Url = nullStringToString(&url)
|
||||||
news.Title = nullStringToString(&title)
|
news.Title = nullStringToString(&title)
|
||||||
news.Notes = nullStringToString(¬es)
|
news.Notes = nullStringToString(¬es)
|
||||||
// support wordpress style <quote> tags
|
|
||||||
news.Notes = strings.Replace(news.Notes, "quote>", "blockquote>", -1)
|
|
||||||
news.htmlNotes = template.HTML(news.Notes)
|
|
||||||
|
|
||||||
if category_id.Valid {
|
if category_id.Valid {
|
||||||
news.Category_id = int(category_id.Int64)
|
news.Category_id = int(category_id.Int64)
|
||||||
|
|
|
@ -145,16 +145,9 @@ func addFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, ses
|
||||||
title = getUrlTitle(url)
|
title = getUrlTitle(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
var notes = ""
|
|
||||||
selection := r.URL.Query().Get("selection")
|
|
||||||
if selection != "" {
|
|
||||||
notes = "<quote>" + selection + "</quote>"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
popup := r.URL.Query().Get("popup")
|
popup := r.URL.Query().Get("popup")
|
||||||
|
|
||||||
ShowTemplate("post", w, r, map[string]interface{}{"mode": "add", "user": user, "flashes": flashes, "link": url, "categories": categories.CategoriesTree, "title": title, "popup": popup, "category_id": -1, "notes": notes})
|
ShowTemplate("post", w, r, map[string]interface{}{"mode": "add", "user": user, "flashes": flashes, "link": url, "categories": categories.CategoriesTree, "title": title, "popup": popup, "category_id": -1})
|
||||||
}
|
}
|
||||||
|
|
||||||
func addPostHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
|
func addPostHandler(w http.ResponseWriter, r *http.Request, user *user.User, session *sessions.Session) {
|
||||||
|
@ -418,7 +411,7 @@ func newsFormHandler(w http.ResponseWriter, r *http.Request, user *user.User, se
|
||||||
session.AddFlash("Error loading news", flash_err)
|
session.AddFlash("Error loading news", flash_err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowTemplate("news", w, r, map[string]interface{}{"user": user, "flashes": flashes, "news": news, "count": count, "offset": argOffset, "amount": amount, "categories": categories.CategoriesFlat, "url": config.Url})
|
ShowTemplate("news", w, r, 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) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dballard/transmet/categories"
|
"github.com/dballard/transmet/categories"
|
||||||
"github.com/gorilla/csrf"
|
"github.com/gorilla/csrf"
|
||||||
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
<!-- Bootstrap -->
|
<!-- Bootstrap -->
|
||||||
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<link href="/css/sticky-footer-navbar.css" rel="stylesheet">
|
|
||||||
<link href="/css/jquery-ui.min.css" rel="stylesheet">
|
<link href="/css/jquery-ui.min.css" rel="stylesheet">
|
||||||
<link href="/css/template.css" rel="stylesheet">
|
<link href="/css/template.css" rel="stylesheet">
|
||||||
<link href="/css/signin.css" rel="stylesheet">
|
<link href="/css/signin.css" rel="stylesheet">
|
||||||
|
@ -19,9 +18,10 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
|
|
||||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
|
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
|
||||||
<span class="sr-only">Toggle navigation</span>
|
<span class="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
|
@ -32,34 +32,27 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
{{if .user}}
|
<li><a href="/news/add">add</a></li>
|
||||||
<li><a href="/news/add">add</a></li>
|
<li><a href="/news/export">export</a></li>
|
||||||
<li><a href="/news/export">export</a></li>
|
<li><a href="/categories">categories</a></li>
|
||||||
<li><a href="/categories">categories</a></li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
{{if .user}}
|
{{if .user}}
|
||||||
<li><a href="">{{.user.Username}}</a></li>
|
<li>{{.user.Username}}</li>
|
||||||
<li><form method="POST" action="/logout">{{ .csrfField }}<input type="submit" value="Logout" class="btn-sm btn-primary btn-block" /></form></li>
|
<li><form method="POST" action="/logout">{{ .csrfField }}<input type="submit" value="Logout" class="btn btn-sm btn-primary btn-block" /></form></li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li><a href="/login">Log in</a></li>
|
<li><a href="/login">Log in</a></li>
|
||||||
{{end}}
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{template "body" .}}
|
{{template "body" .}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="footer">
|
|
||||||
<div class="container">
|
|
||||||
<p class="text-muted">Powered by <a href="https://github.com/dballard/transmet">transmet</a> <img src="/favicon.ico" />
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||||
<script src="/js/jquery.min.js"></script>
|
<script src="/js/jquery.min.js"></script>
|
||||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
|
|
@ -35,7 +35,7 @@ new category select
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-1">
|
<div class="col-xs-1">
|
||||||
<form method="POST" action="/categories/{{.category.Id}}/delete" class="cat-delete">{{ $.csrfField }}
|
<form method="POST" action="/categories/{{.category.Id}}/delete" class="cat-delete">{{ $.csrfField }}
|
||||||
<input type="submit" class="btn btn-default btn-sm btn-block" value="Delete" />
|
<input type="submit" class="btn btn-sm btn-block" value="Delete" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-3">
|
<div class="col-xs-3">
|
||||||
|
|
|
@ -7,14 +7,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-xs-6">
|
<div class="col-xs-6">
|
||||||
Drag this bookmarklet to bookmark bar and click anywhere to add a link
|
Drag this link to bookmark bar and click anywhere to add a link
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-4"></div>
|
<div class="col-xs-4"></div>
|
||||||
|
|
||||||
{{template "pager" .}}
|
|
||||||
|
|
||||||
<div class="col-xs-12"> </div>
|
<div class="col-xs-12"> </div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="news-posts">
|
<div class="news-posts">
|
||||||
{{range $news_post := .news}}
|
{{range $news_post := .news}}
|
||||||
|
@ -22,10 +18,6 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
{{template "pager" .}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<!-- print a news row -->
|
<!-- print a news row -->
|
||||||
|
@ -47,39 +39,21 @@
|
||||||
<div class="col-xs-8 post-url">
|
<div class="col-xs-8 post-url">
|
||||||
<a href="{{.post.Url}}">{{truncate .post.Url 100}}</a>
|
<a href="{{.post.Url}}">{{truncate .post.Url 100}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-2 post-edit"><a href="/news/{{.post.Id}}/edit" class="btn btn-default btn-sm btn-block">Edit</a></div>
|
<div class="col-xs-2 post-edit"><a href="/news/{{.post.Id}}/edit" class="btn btn-sm btn-block">Edit</a></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-2"> </div>
|
<div class="col-xs-2"> </div>
|
||||||
<div class="col-xs-8 post-content state-up"> {{ .post.HTMLNotes }}</div>
|
<div class="col-xs-8 post-preview">{{truncate .post.Notes 500}}</div>
|
||||||
<div class="col-xs-2 post-delete">
|
<div class="col-xs-2 post-delete">
|
||||||
<form method="POST" action="/news/{{.post.Id}}/delete" class="confirm-news-delete">{{ .csrfField }}
|
<form method="POST" action="/news/{{.post.Id}}/delete" class="confirm-news-delete">{{ .csrfField }}
|
||||||
<input type="submit" class="btn btn-default btn-sm btn-block" value="Delete" />
|
<input type="submit" class="btn btn-sm btn-block" value="Delete" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-2"> </div>
|
|
||||||
<div class="col-xs-8 btn-default btn content-slider state-up">v</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "pager"}}
|
|
||||||
<div class="col-xs-12"> </div>
|
|
||||||
|
|
||||||
<div class="col-xs-2">
|
|
||||||
{{if ge .count .amount }}
|
|
||||||
<a href="?offset={{ add .offset 1}}">< Prev</a>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-8"> </div>
|
|
||||||
<div class="col-xs-2">
|
|
||||||
{{ if ne .offset 0 }}
|
|
||||||
<a href="?offset={{ minus .offset 1 }}">Next ></a>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<!-- JS for the launcher of the add bookmarklet -->
|
<!-- JS for the launcher of the add bookmarklet -->
|
||||||
{{define "launch-add"}}javascript:(function() { var d=document,w=window,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),f='{{.url}}/news/add',l=d.location,e=encodeURIComponent,u=f+'?popup=1&url='+e(l.href)+'&title='+e(d.title)+'&selection='+e(s);a=function(){if(!w.open(u,'t','toolbar=0,resizable=1,scrollbars=1,status=1,width=720,height=480'))l.href=u;};if (/Firefox/.test(navigator.userAgent)) setTimeout(a, 0); else a();void(0) })();{{end}}
|
{{define "launch-add"}}
|
||||||
|
javascript:var d=document,w=window,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),f='{{.url}}news/add',l=d.location,e=encodeURIComponent,u=f+'?popup=1&url='+e(l.href)+'&title='+e(d.title);a=function(){if(!w.open(u,'t','toolbar=0,resizable=1,scrollbars=1,status=1,width=720,height=410'))l.href=u;};if (/Firefox/.test(navigator.userAgent)) setTimeout(a, 0); else a();void(0)
|
||||||
|
{{end}}
|
Loading…
Reference in New Issue