ДЗ4 начато
parent
4b6be61eea
commit
f766c1dd6e
|
@ -25,7 +25,7 @@ func init() {
|
|||
func main() {
|
||||
log.Println("Starting...")
|
||||
m := martini.Classic()
|
||||
app, err := application.New("", "APP")
|
||||
app, err := application.New("application.conf", "APP")
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("can't build app: %w", err).Error())
|
||||
}
|
||||
|
@ -72,6 +72,11 @@ func main() {
|
|||
m.Get("/search", handlers.GetUserList)
|
||||
m.Post("/search", handlers.PostUserSearch)
|
||||
|
||||
m.Get("/addPost", auth.LoginRequired, handlers.GetAddPost)
|
||||
m.Post("/addPost", auth.LoginRequired, handlers.PostAddPost)
|
||||
|
||||
m.Get("/feed", auth.LoginRequired, handlers.GetFeed)
|
||||
|
||||
m.NotFound(func(r render.Render) {
|
||||
r.HTML(404, "404", nil)
|
||||
})
|
||||
|
|
|
@ -84,6 +84,18 @@ func dbInit(db *sql.DB) error {
|
|||
) ENGINE=InnoDB DEFAULT CHARSET=utf8`); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS posts (
|
||||
Id INT(11) NOT NULL AUTO_INCREMENT,
|
||||
Author INT(11) NULL DEFAULT NULL,
|
||||
Created TIMESTAMP NULL DEFAULT NULL,
|
||||
Subject VARCHAR(50) NULL DEFAULT NULL,
|
||||
Body MEDIUMTEXT NULL DEFAULT NULL,
|
||||
PRIMARY KEY (Id) USING BTREE,
|
||||
INDEX AuthorID (author) USING BTREE,
|
||||
CONSTRAINT AuthorID FOREIGN KEY (author) REFERENCES app.users (Id) ON UPDATE RESTRICT ON DELETE RESTRICT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_unicode_ci`); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println("All tables exists")
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/martini-contrib/render"
|
||||
"github.com/tiburon-777/OTUS_HighLoad/internal/application"
|
||||
"github.com/tiburon-777/OTUS_HighLoad/internal/auth"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetFeed(app application.App, r render.Render, user auth.User) {
|
||||
h := user.(*auth.UserModel).BirthDate
|
||||
user.(*auth.UserModel).YearsOld = int(time.Since(h).Hours() / 8760)
|
||||
doc := make(map[string]interface{})
|
||||
doc["user"] = user.(*auth.UserModel)
|
||||
var tmpTime string
|
||||
var post Post
|
||||
var posts []Post
|
||||
var results, err = app.DBMaster.Query(`SELECT
|
||||
posts.Id AS Id,
|
||||
users.Username AS Author,
|
||||
posts.Created AS Created,
|
||||
posts.Subject AS Subject,
|
||||
posts.Body AS Body
|
||||
FROM
|
||||
users JOIN relations JOIN posts
|
||||
WHERE
|
||||
relations.friendId=users.Id
|
||||
AND posts.Author=relations.friendId
|
||||
AND relations.userId=?
|
||||
ORDER by Created DESC`,
|
||||
user.(*auth.UserModel).Id)
|
||||
if err != nil || results == nil {
|
||||
err500("can't get feed from DB: ", err, r)
|
||||
}
|
||||
defer results.Close()
|
||||
for results.Next() {
|
||||
err = results.Scan(&post.Id, &post.Author, &tmpTime, &post.Subject, &post.Body)
|
||||
if err != nil {
|
||||
err500("can't scan result from DB: ", err, r)
|
||||
}
|
||||
post.Created = str2Time(tmpTime, r)
|
||||
posts = append(posts, post)
|
||||
}
|
||||
doc["posts"] = posts
|
||||
|
||||
r.HTML(200, "feed", doc)
|
||||
}
|
||||
|
|
@ -10,10 +10,17 @@ import (
|
|||
"golang.org/x/crypto/bcrypt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Post struct{
|
||||
Id int `db:"Id"`
|
||||
Author string `db:"Author"`
|
||||
Created time.Time `db:"Created"`
|
||||
Subject string `db:"Subject"`
|
||||
Body string `db:"Body"`
|
||||
}
|
||||
|
||||
func GetHome(app application.App, r render.Render, user auth.User) {
|
||||
h := user.(*auth.UserModel).BirthDate
|
||||
user.(*auth.UserModel).YearsOld = int(time.Since(h).Hours() / 8760)
|
||||
|
@ -51,6 +58,23 @@ func GetHome(app application.App, r render.Render, user auth.User) {
|
|||
}
|
||||
doc["table"] = users
|
||||
|
||||
var post Post
|
||||
var posts []Post
|
||||
results, err = app.DBMaster.Query(`SELECT Id, Created, Subject, Body FROM posts WHERE Author=? ORDER BY Created DESC;`, user.(*auth.UserModel).Id)
|
||||
if err != nil || results == nil {
|
||||
err500("can't get user list from DB: ", err, r)
|
||||
}
|
||||
defer results.Close()
|
||||
for results.Next() {
|
||||
err = results.Scan(&post.Id, &tmpTime, &post.Subject, &post.Body)
|
||||
if err != nil {
|
||||
err500("can't scan result from DB: ", err, r)
|
||||
}
|
||||
post.Created = str2Time(tmpTime, r)
|
||||
posts = append(posts, post)
|
||||
}
|
||||
doc["posts"] = posts
|
||||
|
||||
r.HTML(200, "index", doc)
|
||||
}
|
||||
|
||||
|
@ -96,129 +120,6 @@ func PostSignup(app application.App, postedUser auth.UserModel, r render.Render)
|
|||
r.Redirect("/login")
|
||||
}
|
||||
|
||||
func GetUserList(app application.App, r render.Render) {
|
||||
doc := make(map[string]interface{})
|
||||
doc["UsersFound"] = 0
|
||||
var tmp int
|
||||
if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&tmp); err != nil {
|
||||
err500("can't get total of user profiles from DB: ", err, r)
|
||||
}
|
||||
doc["UsersTotal"] = tmp
|
||||
r.HTML(200, "list", doc)
|
||||
}
|
||||
|
||||
func PostUserList(app application.App, user auth.User, r render.Render, req *http.Request) {
|
||||
postName := req.FormValue("name")
|
||||
postSurname := req.FormValue("surname")
|
||||
doc := make(map[string]interface{})
|
||||
doc["user"] = user.(*auth.UserModel)
|
||||
var users []auth.UserModel
|
||||
var tmp auth.UserModel
|
||||
var tmpTime string
|
||||
var results, err = app.DBMaster.Query(`SELECT
|
||||
users.id as id,
|
||||
users.name as name,
|
||||
users.surname as surname,
|
||||
users.birthdate as birthdate,
|
||||
users.gender as gender,
|
||||
users.city as city
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
NOT users.id=?
|
||||
AND users.id NOT IN (
|
||||
SELECT
|
||||
relations.friendId
|
||||
FROM
|
||||
relations
|
||||
WHERE
|
||||
relations.userId=?)
|
||||
AND ( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`,
|
||||
user.(*auth.UserModel).Id,
|
||||
user.(*auth.UserModel).Id,
|
||||
postName,
|
||||
postSurname,
|
||||
)
|
||||
if err != nil || results == nil {
|
||||
err500("can't get user list from DB: ", err, r)
|
||||
}
|
||||
defer results.Close()
|
||||
for results.Next() {
|
||||
err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City)
|
||||
if err != nil {
|
||||
err500("can't scan result from DB: ", err, r)
|
||||
}
|
||||
tmp.BirthDate = str2Time(tmpTime, r)
|
||||
tmp.YearsOld = int(time.Since(tmp.BirthDate).Hours() / 8760)
|
||||
users = append(users, tmp)
|
||||
if len(users) >= 100 {
|
||||
doc["msg"] = "( Too much rows in result. We will display only the first 100. )"
|
||||
break
|
||||
}
|
||||
}
|
||||
doc["table"] = users
|
||||
doc["UsersFound"] = len(users)
|
||||
var uTotal int
|
||||
if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil {
|
||||
err500("can't get total of user profiles from DB: ", err, r)
|
||||
}
|
||||
doc["UsersTotal"] = uTotal
|
||||
r.HTML(200, "list", doc)
|
||||
}
|
||||
|
||||
func PostUserSearch(app application.App, r render.Render, req *http.Request) {
|
||||
db := app.DBMaster
|
||||
if app.Config.DSN.Slave1!="" {
|
||||
db = app.DBSlave1
|
||||
}
|
||||
|
||||
postName := req.FormValue("name")
|
||||
postSurname := req.FormValue("surname")
|
||||
doc := make(map[string]interface{})
|
||||
var users []auth.UserModel
|
||||
var tmp auth.UserModel
|
||||
var tmpTime string
|
||||
var results, err = db.Query(`SELECT
|
||||
users.id as id,
|
||||
users.name as name,
|
||||
users.surname as surname,
|
||||
users.birthdate as birthdate,
|
||||
users.gender as gender,
|
||||
users.city as city
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`,
|
||||
postName,
|
||||
postSurname,
|
||||
)
|
||||
if err != nil || results == nil {
|
||||
err500("can't get user list from DB: ", err, r)
|
||||
}
|
||||
defer results.Close()
|
||||
for results.Next() {
|
||||
err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City)
|
||||
if err != nil {
|
||||
err500("can't scan result from DB: ", err, r)
|
||||
}
|
||||
tmp.BirthDate = str2Time(tmpTime, r)
|
||||
tmp.YearsOld = int(time.Since(tmp.BirthDate).Hours() / 8760)
|
||||
users = append(users, tmp)
|
||||
if len(users) >= 100 {
|
||||
doc["msg"] = "( Too much rows in result. We will display only the first 100. )"
|
||||
break
|
||||
}
|
||||
}
|
||||
doc["table"] = users
|
||||
doc["UsersFound"] = len(users)
|
||||
var uTotal int
|
||||
if err := db.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil {
|
||||
err500("can't get total of user profiles from DB: ", err, r)
|
||||
}
|
||||
doc["UsersTotal"] = uTotal
|
||||
r.HTML(200, "list", doc)
|
||||
}
|
||||
|
||||
func PostLogin(app application.App, session sessions.Session, postedUser auth.UserModel, r render.Render, req *http.Request) {
|
||||
user := auth.UserModel{}
|
||||
err1 := app.DBMaster.QueryRow("SELECT id, password FROM users WHERE username=?", postedUser.Username).Scan(&user.Id, &user.Password)
|
||||
|
@ -242,43 +143,6 @@ func PostLogin(app application.App, session sessions.Session, postedUser auth.Us
|
|||
}
|
||||
}
|
||||
|
||||
func GetSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) {
|
||||
sid, ok := req.URL.Query()["id"]
|
||||
if !ok {
|
||||
err500("can't parce URL query", nil, r)
|
||||
}
|
||||
did, err := strconv.Atoi(sid[0])
|
||||
if err != nil {
|
||||
err500("can't convert URL query value: ", err, r)
|
||||
}
|
||||
_, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, user.(*auth.UserModel).Id, did)
|
||||
if err != nil {
|
||||
err500("can't create relation in DB: ", err, r)
|
||||
}
|
||||
_, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, did, user.(*auth.UserModel).Id)
|
||||
if err != nil {
|
||||
err500("can't create relation in DB: ", err, r)
|
||||
}
|
||||
r.Redirect("/list")
|
||||
}
|
||||
|
||||
func GetUnSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) {
|
||||
sid, ok := req.URL.Query()["id"]
|
||||
if !ok {
|
||||
err500("can't parce URL query", nil, r)
|
||||
}
|
||||
did, err := strconv.Atoi(sid[0])
|
||||
if err != nil {
|
||||
err500("can't convert URL query value: ", err, r)
|
||||
}
|
||||
_, err = app.DBMaster.Exec(`DELETE FROM relations WHERE (userId,friendId) IN ((?, ?),(?, ?))`, user.(*auth.UserModel).Id, did, did, user.(*auth.UserModel).Id)
|
||||
if err != nil {
|
||||
err500("can't remove relation from DB: ", err, r)
|
||||
}
|
||||
r.Redirect("/")
|
||||
|
||||
}
|
||||
|
||||
func str2Time(s string, r render.Render) time.Time {
|
||||
t, err := time.Parse("2006-01-02 15:04:05", s)
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/martini-contrib/render"
|
||||
"github.com/tiburon-777/OTUS_HighLoad/internal/application"
|
||||
"github.com/tiburon-777/OTUS_HighLoad/internal/auth"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetAddPost(app application.App, r render.Render) {
|
||||
r.HTML(200, "postadd", nil)
|
||||
}
|
||||
|
||||
func PostAddPost(app application.App, user auth.User, r render.Render, req *http.Request) {
|
||||
postSubj := req.FormValue("subj")
|
||||
postBody := req.FormValue("body")
|
||||
var results, err = app.DBMaster.Query(`INSERT INTO posts (Author, Created, Subject, Body) VALUES (
|
||||
?, ?, ?, ?)`,
|
||||
user.(*auth.UserModel).Id,
|
||||
time.Now().Format("2006-01-02 15:04:05"),
|
||||
postSubj,
|
||||
postBody,
|
||||
)
|
||||
if err != nil || results == nil {
|
||||
err500("can't add new post: ", err, r)
|
||||
}
|
||||
r.Redirect("/",302)
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/martini-contrib/render"
|
||||
"github.com/tiburon-777/OTUS_HighLoad/internal/application"
|
||||
"github.com/tiburon-777/OTUS_HighLoad/internal/auth"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetUserList(app application.App, r render.Render) {
|
||||
doc := make(map[string]interface{})
|
||||
doc["UsersFound"] = 0
|
||||
var tmp int
|
||||
if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&tmp); err != nil {
|
||||
err500("can't get total of user profiles from DB: ", err, r)
|
||||
}
|
||||
doc["UsersTotal"] = tmp
|
||||
r.HTML(200, "list", doc)
|
||||
}
|
||||
|
||||
func PostUserList(app application.App, user auth.User, r render.Render, req *http.Request) {
|
||||
postName := req.FormValue("name")
|
||||
postSurname := req.FormValue("surname")
|
||||
doc := make(map[string]interface{})
|
||||
doc["user"] = user.(*auth.UserModel)
|
||||
var users []auth.UserModel
|
||||
var tmp auth.UserModel
|
||||
var tmpTime string
|
||||
var results, err = app.DBMaster.Query(`SELECT
|
||||
users.id as id,
|
||||
users.name as name,
|
||||
users.surname as surname,
|
||||
users.birthdate as birthdate,
|
||||
users.gender as gender,
|
||||
users.city as city
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
NOT users.id=?
|
||||
AND users.id NOT IN (
|
||||
SELECT
|
||||
relations.friendId
|
||||
FROM
|
||||
relations
|
||||
WHERE
|
||||
relations.userId=?)
|
||||
AND ( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`,
|
||||
user.(*auth.UserModel).Id,
|
||||
user.(*auth.UserModel).Id,
|
||||
postName,
|
||||
postSurname,
|
||||
)
|
||||
if err != nil || results == nil {
|
||||
err500("can't get user list from DB: ", err, r)
|
||||
}
|
||||
defer results.Close()
|
||||
for results.Next() {
|
||||
err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City)
|
||||
if err != nil {
|
||||
err500("can't scan result from DB: ", err, r)
|
||||
}
|
||||
tmp.BirthDate = str2Time(tmpTime, r)
|
||||
tmp.YearsOld = int(time.Since(tmp.BirthDate).Hours() / 8760)
|
||||
users = append(users, tmp)
|
||||
if len(users) >= 100 {
|
||||
doc["msg"] = "( Too much rows in result. We will display only the first 100. )"
|
||||
break
|
||||
}
|
||||
}
|
||||
doc["table"] = users
|
||||
doc["UsersFound"] = len(users)
|
||||
var uTotal int
|
||||
if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil {
|
||||
err500("can't get total of user profiles from DB: ", err, r)
|
||||
}
|
||||
doc["UsersTotal"] = uTotal
|
||||
r.HTML(200, "list", doc)
|
||||
}
|
||||
|
||||
func PostUserSearch(app application.App, r render.Render, req *http.Request) {
|
||||
db := app.DBMaster
|
||||
if app.Config.DSN.Slave1!="" {
|
||||
db = app.DBSlave1
|
||||
}
|
||||
|
||||
postName := req.FormValue("name")
|
||||
postSurname := req.FormValue("surname")
|
||||
doc := make(map[string]interface{})
|
||||
var users []auth.UserModel
|
||||
var tmp auth.UserModel
|
||||
var tmpTime string
|
||||
var results, err = db.Query(`SELECT
|
||||
users.id as id,
|
||||
users.name as name,
|
||||
users.surname as surname,
|
||||
users.birthdate as birthdate,
|
||||
users.gender as gender,
|
||||
users.city as city
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`,
|
||||
postName,
|
||||
postSurname,
|
||||
)
|
||||
if err != nil || results == nil {
|
||||
err500("can't get user list from DB: ", err, r)
|
||||
}
|
||||
defer results.Close()
|
||||
for results.Next() {
|
||||
err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City)
|
||||
if err != nil {
|
||||
err500("can't scan result from DB: ", err, r)
|
||||
}
|
||||
tmp.BirthDate = str2Time(tmpTime, r)
|
||||
tmp.YearsOld = int(time.Since(tmp.BirthDate).Hours() / 8760)
|
||||
users = append(users, tmp)
|
||||
if len(users) >= 100 {
|
||||
doc["msg"] = "( Too much rows in result. We will display only the first 100. )"
|
||||
break
|
||||
}
|
||||
}
|
||||
doc["table"] = users
|
||||
doc["UsersFound"] = len(users)
|
||||
var uTotal int
|
||||
if err := db.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil {
|
||||
err500("can't get total of user profiles from DB: ", err, r)
|
||||
}
|
||||
doc["UsersTotal"] = uTotal
|
||||
r.HTML(200, "list", doc)
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/martini-contrib/render"
|
||||
"github.com/tiburon-777/OTUS_HighLoad/internal/application"
|
||||
"github.com/tiburon-777/OTUS_HighLoad/internal/auth"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func GetSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) {
|
||||
sid, ok := req.URL.Query()["id"]
|
||||
if !ok {
|
||||
err500("can't parce URL query", nil, r)
|
||||
}
|
||||
did, err := strconv.Atoi(sid[0])
|
||||
if err != nil {
|
||||
err500("can't convert URL query value: ", err, r)
|
||||
}
|
||||
_, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, user.(*auth.UserModel).Id, did)
|
||||
if err != nil {
|
||||
err500("can't create relation in DB: ", err, r)
|
||||
}
|
||||
_, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, did, user.(*auth.UserModel).Id)
|
||||
if err != nil {
|
||||
err500("can't create relation in DB: ", err, r)
|
||||
}
|
||||
r.Redirect("/list")
|
||||
}
|
||||
|
||||
func GetUnSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) {
|
||||
sid, ok := req.URL.Query()["id"]
|
||||
if !ok {
|
||||
err500("can't parce URL query", nil, r)
|
||||
}
|
||||
did, err := strconv.Atoi(sid[0])
|
||||
if err != nil {
|
||||
err500("can't convert URL query value: ", err, r)
|
||||
}
|
||||
_, err = app.DBMaster.Exec(`DELETE FROM relations WHERE (userId,friendId) IN ((?, ?),(?, ?))`, user.(*auth.UserModel).Id, did, did, user.(*auth.UserModel).Id)
|
||||
if err != nil {
|
||||
err500("can't remove relation from DB: ", err, r)
|
||||
}
|
||||
r.Redirect("/")
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid black;
|
||||
width: 100%;
|
||||
background-color: azure;
|
||||
}
|
||||
table th {
|
||||
border: 1px solid black;
|
||||
background-color: aquamarine;
|
||||
}
|
||||
table td {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Feed of your friend's news</h2>
|
||||
{{ range $post:=.posts }}
|
||||
<a><b>{{ $post.Author }} wrote at {{ $post.Created }}:</b></a><br/>
|
||||
<a><b>{{ $post.Subject }}</b><br/><a>{{ $post.Body }}</a>
|
||||
<br/><br/>
|
||||
{{ end }}
|
||||
|
||||
<h2>Available actions:</h2>
|
||||
<input type="button" onclick="location.href='/';" value="Home" />
|
||||
</body>
|
||||
</html>
|
|
@ -25,6 +25,12 @@
|
|||
<p>You now live in <b>{{ .user.City }}</b></p>
|
||||
<p>You interests is: <b>{{ .user.Interests }}</b></p>
|
||||
|
||||
<h2>Available actions:</h2>
|
||||
<input type="button" onclick="location.href='/addPost';" value="Create Post" />
|
||||
<input type="button" onclick="location.href='/feed';" value="Friend Feed" />
|
||||
<input type="button" onclick="location.href='/list';" value="User list" />
|
||||
<input type="button" onclick="location.href='/logout';" value="Logout" /><br />
|
||||
|
||||
<h2> You have friends:</h2>
|
||||
<table>
|
||||
<thead>
|
||||
|
@ -49,8 +55,11 @@
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Available actions:</h2>
|
||||
<input type="button" onclick="location.href='/list';" value="User list" />
|
||||
<input type="button" onclick="location.href='/logout';" value="Logout" /><br />
|
||||
<h2> Your posts:</h2>
|
||||
{{ range $post:=.posts }}
|
||||
<a><b>{{ $post.Subject }}</b><br/><a>{{ $post.Body }}</a>
|
||||
<br/><br/>
|
||||
{{ end }}
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.3/moment.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Create post</h2>
|
||||
<p style="color: red;"><b>{{ .msg }}</b></p>
|
||||
<form method="POST">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Тема</td>
|
||||
<td><input type="text" name="subj" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Текст</td>
|
||||
<td><textarea rows="10" cols="45" name="body"></textarea></td>
|
||||
</tr>
|
||||
</table>
|
||||
<button>Отправить</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -7,7 +7,14 @@
|
|||
- работа с очередями;
|
||||
- проектирование масштабируемых архитектур.
|
||||
|
||||
Разработать ленту новостей. Создается отдельная страница, куда пишутся все обновления друзей. Для этого нужно хранить подписчиков. Лента формируется на уровне кешей. Формирование ленты производить через постановку задачи в очередь на часть подписчиков, чтобы избежать эффекта леди Гаги. В ленте держать последние 1000 обновлений друзей. Лента должна кешироваться.
|
||||
# План выполнения:
|
||||
1) Разработать страницу добавления поста.
|
||||
2) Разработать ленту новостей, содержащую посты пользователей на которых подписан текущий пользователь.
|
||||
- Создается отдельная страница, куда пишутся все обновления друзей. Для этого нужно хранить подписчиков.
|
||||
- Лента формируется на уровне кешей.
|
||||
- Формирование ленты производить через постановку задачи в очередь на часть подписчиков, чтобы избежать эффекта леди Гаги.
|
||||
- В ленте держать последние 1000 обновлений друзей.
|
||||
- Лента должна кешироваться.
|
||||
|
||||
ДЗ сдается в виде ссылки на гитлаб и демонстрации работающего проекта, развернутого в интернете.
|
||||
Критерии оценки: Оценка происходит по принципу зачет/незачет.
|
||||
|
|
Loading…
Reference in New Issue