// HandleHome displays a list of stories using gravity to order them // used for the home page for gravity rank see votes.go // responds to GET / func HandleHome(context router.Context) error { // Build a query q := stories.Query().Limit(listLimit) // Select only above 0 points, Order by rank, then points, then name q.Where("points > 0").Order("rank desc, points desc, id desc") // Set the offset in pages if we have one page := int(context.ParamInt("page")) if page > 0 { q.Offset(listLimit * page) } // Fetch the stories results, err := stories.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) setStoriesMetadata(view, context.Request()) view.AddKey("page", page) view.AddKey("stories", results) view.Template("stories/views/index.html.got") if context.Param("format") == ".xml" { view.Layout("") view.Template("stories/views/index.xml.got") } return view.Render() }
// HandleHome serves a get request at / func HandleHome(context router.Context) error { // Setup context for template view := view.New(context) // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // If nothing exists, redirect to set up page if missingUsersAndPages() { return router.Redirect(context, "/fragmenta/setup") } page, err := pages.Find(1) if err != nil { return router.InternalError(err) } view.AddKey("page", page) view.AddKey("meta_title", page.Name) view.AddKey("meta_desc", page.Summary) view.AddKey("meta_keywords", page.Keywords) return view.Render() }
// HandleShow displays a single story func HandleShow(context router.Context) error { // Find the story story, err := stories.Find(context.ParamInt("id")) if err != nil { return router.InternalError(err) } // Find the comments for this story // Fetch the comments q := comments.Where("story_id=?", story.Id).Order(comments.RankOrder) rootComments, err := comments.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) view.AddKey("story", story) view.AddKey("meta_title", story.Name) view.AddKey("meta_desc", story.Summary) view.AddKey("meta_keywords", story.Name) view.AddKey("comments", rootComments) view.AddKey("authenticity_token", authorise.CreateAuthenticityToken(context)) return view.Render() }
// HandleShow displays a single story func HandleShow(context router.Context) error { // Find the story story, err := stories.Find(context.ParamInt("id")) if err != nil { return router.InternalError(err) } // Redirect requests to the canonical url if context.Path() != story.URLShow() { return router.Redirect(context, story.URLShow()) } // Find the comments for this story // Fetch the comments q := comments.Where("story_id=?", story.Id).Order(comments.RankOrder) rootComments, err := comments.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) view.AddKey("story", story) view.AddKey("meta_title", story.Name) view.AddKey("meta_desc", story.Summary) view.AddKey("meta_keywords", story.Name) view.AddKey("comments", rootComments) return view.Render() }
// errHandler renders an error using error templates if available func errHandler(context router.Context, e error) { // Cast the error to a status error if it is one, if not wrap it in a Status 500 error err := router.ToStatusError(e) view := view.New(context) view.AddKey("title", err.Title) view.AddKey("message", err.Message) if !context.Production() { view.AddKey("status", err.Status) view.AddKey("file", err.FileLine()) view.AddKey("error", err.Err) } view.Template("app/views/error.html.got") // Log 404 as info only if err.Status == 404 { context.Logf("#info %s\n", err) } else { context.Logf("#error %s\n", err) } view.Render() }
// HandleUpdateShow renders the form to update a post func HandleUpdateShow(context router.Context) error { // Find the post post, err := posts.Find(context.ParamInt("id")) if err != nil { return router.NotFoundError(err) } // Authorise update post err = authorise.Resource(context, post) if err != nil { return router.NotAuthorizedError(err) } // Find users for author details users, err := users.FindAll(users.Admins()) if err != nil { return router.NotFoundError(err) } // Render the template view := view.New(context) view.AddKey("post", post) view.AddKey("users", users) return view.Render() }
// HandleShowHome serves our home page func homeHandler(context router.Context) error { view := view.New(context) view.AddKey("title", "Fragmenta app") view.Template("app/views/home.html.got") return view.Render() }
// HandleIndex displays a list of files func HandleIndex(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Find the current user and check status u := authorise.CurrentUser(context) if u.Anon() { // return router.NotAuthorizedError(err) } // For admins, show all files, order by date desc q := files.Query().Order("updated_at desc") // otherwise show just the logged in user's files if !u.Admin() { // Find the files for this user, unless q = files.Where("user_id=?", u.Id) } // Fetch the files results, err := files.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) view.AddKey("files", results) return view.Render() }
// HandleHome displays a list of stories using gravity to order them // used for the home page for gravity rank see votes.go func HandleHome(context router.Context) error { // Build a query q := stories.Query().Limit(listLimit) // Select only above 0 points, Order by rank, then points, then name q.Where("points > 0").Order("rank desc, points desc, id desc") // Fetch the stories results, err := stories.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) view.AddKey("stories", results) view.AddKey("meta_title", "Golang News") view.AddKey("meta_desc", "News for Go Hackers, in the style of Hacker News. A curated selection of the latest links about the Go programming language.") view.AddKey("meta_keywords", "golang news, blog, links, go developers, go web apps, web applications, fragmenta") view.AddKey("authenticity_token", authorise.CreateAuthenticityToken(context)) view.Template("stories/views/index.html.got") return view.Render() }
// HandleIndex serves a get request at /pages func HandleIndex(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Fetch the pages q := pages.Query().Order("url asc") // Filter if necessary filter := context.Param("filter") if len(filter) > 0 { filter = strings.Replace(filter, "&", "", -1) filter = strings.Replace(filter, " ", "", -1) filter = strings.Replace(filter, " ", " & ", -1) q.Where("(to_tsvector(name) || to_tsvector(summary) || to_tsvector(url) @@ to_tsquery(?) )", filter) } pageList, err := pages.FindAll(q) if err != nil { context.Logf("#error Error indexing pages %s", err) return router.InternalError(err) } // Serve template view := view.New(context) view.AddKey("filter", filter) view.AddKey("pages", pageList) return view.Render() }
// HandleShow serve a get request at /users/1 func HandleShow(context router.Context) error { // Find the user user, err := users.Find(context.ParamInt("id")) if err != nil { context.Logf("#error parsing user id: %s", err) return router.NotFoundError(err) } userMeta := fmt.Sprintf("%s – %s", user.Name, user.Summary) // Set up view view := view.New(context) // Find the first image which matches this user image, err := images.Find(user.ImageID) if err == nil { // only add image key if we have one view.AddKey("image", image) } // Render the Template view.AddKey("user", user) view.AddKey("meta_title", userMeta) view.AddKey("meta_desc", userMeta) view.AddKey("meta_keywords", user.Keywords()) return view.Render() }
// errHandler renders an error using error templates if available func errHandler(context router.Context, e error) { // Cast the error to a status error if it is one, if not wrap it in a Status 500 error err := router.ToStatusError(e) view := view.New(context) view.AddKey("title", err.Title) view.AddKey("message", err.Message) if !context.Production() { view.AddKey("status", err.Status) view.AddKey("file", err.FileLine()) view.AddKey("error", err.Err) } // Set the status correctly for errors context.Writer().WriteHeader(err.Status) // Use our error template view.Template("app/views/error.html.got") context.Logf("#error %s\n", err) view.Render() }
// HandleCreateShow serves the create form via GET for posts func HandleCreateShow(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Find users for author details users, err := users.FindAll(users.Admins()) if err != nil { return router.NotFoundError(err) } // Render the template view := view.New(context) post := posts.New() user := authorise.CurrentUser(context) if user != nil { post.AuthorId = user.Id } view.AddKey("post", post) view.AddKey("users", users) return view.Render() }
// Serve a get request at /images // // func HandleIndex(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Setup context for template view := view.New(context) // Build a query q := images.Query() // Show only published (defaults to showing all) // q.Apply(status.WherePublished) // Order by required order, or default to id asc switch context.Param("order") { case "1": q.Order("created_at desc") case "2": q.Order("updated_at desc") case "3": q.Order("name asc") default: q.Order("id desc") } // Filter if necessary - this assumes name and summary cols filter := context.Param("filter") if len(filter) > 0 { filter = strings.Replace(filter, "&", "", -1) filter = strings.Replace(filter, " ", "", -1) filter = strings.Replace(filter, " ", " & ", -1) q.Where("( to_tsvector(name) || to_tsvector(summary) @@ to_tsquery(?) )", filter) } // Fetch the images imagesList, err := images.FindAll(q) if err != nil { return router.InternalError(err) } // Serve template view.AddKey("filter", filter) view.AddKey("images", imagesList) // Can we add these programatically? view.AddKey("admin_links", helpers.Link("Create image", images.New().URLCreate())) return view.Render() }
// HandleCreateShow serves the create form via GET for users func HandleCreateShow(context router.Context) error { // Render the template view := view.New(context) user := users.New() view.AddKey("user", user) return view.Render() }
// render the given page, with metadata set func render(context router.Context, page *pages.Page) error { // Render the template view := view.New(context) view.AddKey("page", page) view.AddKey("page", page) view.AddKey("meta_title", page.Name) view.AddKey("meta_desc", page.Summary) view.AddKey("meta_keywords", page.Keywords) view.Template("pages/views/show.html.got") return view.Render() }
// HandleCreateShow handles GET users/create func HandleCreateShow(context router.Context) error { // No auth as anyone can create users in this app // Setup view := view.New(context) user := users.New() view.AddKey("user", user) // Serve return view.Render() }
// HandleIndex displays a list of stories at /stories func HandleIndex(context router.Context) error { // Build a query q := stories.Query().Limit(listLimit) // Order by date by default q.Where("points > -6").Order("created_at desc") // Filter if necessary - this assumes name and summary cols filter := context.Param("q") if len(filter) > 0 { // Replace special characters with escaped sequence filter = strings.Replace(filter, "_", "\\_", -1) filter = strings.Replace(filter, "%", "\\%", -1) wildcard := "%" + filter + "%" // Perform a wildcard search for name or url q.Where("stories.name ILIKE ? OR stories.url ILIKE ?", wildcard, wildcard) // If filtering, order by rank, not by date q.Order("rank desc, points desc, id desc") } // Set the offset in pages if we have one page := int(context.ParamInt("page")) if page > 0 { q.Offset(listLimit * page) } // Fetch the stories results, err := stories.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) setStoriesMetadata(view, context.Request()) view.AddKey("page", page) view.AddKey("stories", results) if context.Param("format") == ".xml" { view.Layout("") view.Template("stories/views/index.xml.got") } return view.Render() }
// HandleShowSetup shows the setup page at /fragmenta/setup func HandleShowSetup(context router.Context) error { // Setup context for template view := view.New(context) // If we have pages or users already, do not proceed if !missingUsersAndPages() { return router.NotAuthorizedError(nil) } view.Template("pages/views/setup.html.got") return view.Render() }
// HandleCreateShow handles GET users/create func HandleCreateShow(context router.Context) error { // No auth as anyone can create users in this app // Setup view := view.New(context) user := users.New() view.AddKey("user", user) view.AddKey("authenticity_token", authorise.CreateAuthenticityToken(context)) // Serve return view.Render() }
// HandleShow displays a single user func HandleShow(context router.Context) error { // Find the user user, err := users.Find(context.ParamInt("id")) if err != nil { return router.NotFoundError(err) } // Render the template view := view.New(context) view.AddKey("user", user) return view.Render() }
// HandleLoginShow handles GET /users/login func HandleLoginShow(context router.Context) error { // Check we have no current user u := authorise.CurrentUser(context) if !u.Anon() { return router.Redirect(context, fmt.Sprintf("/users/%d", u.Id)) } // Render the template view := view.New(context) view.AddKey("error", context.Param("error")) return view.Render() }
// HandleCreateShow serves GET images/create func HandleCreateShow(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Serve the template view := view.New(context) image := images.New() view.AddKey("image", image) return view.Render() }
// HandleIndex displays a list of posts func HandleIndex(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Build a query q := posts.Query() // Order by required order, or default to id asc switch context.Param("order") { case "1": q.Order("created desc") case "2": q.Order("updated desc") case "3": q.Order("name asc") default: q.Order("id asc") } // Filter if necessary - this assumes name and summary cols filter := context.Param("filter") if len(filter) > 0 { filter = strings.Replace(filter, "&", "", -1) filter = strings.Replace(filter, " ", "", -1) filter = strings.Replace(filter, " ", " & ", -1) q.Where("( to_tsvector(name) || to_tsvector(summary) @@ to_tsquery(?) )", filter) } // Fetch the posts results, err := posts.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) view.AddKey("filter", filter) view.AddKey("posts", results) return view.Render() }
// HandleShowName displays a single user by name func HandleShowName(context router.Context) error { // Find the user user, err := users.FindName(context.Param("name")) if err != nil { return router.NotFoundError(err) } // Render the template view := view.New(context) view.AddKey("user", user) view.Template("users/views/show.html.got") return view.Render() }
// GET pages/create func HandleCreateShow(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Setup view := view.New(context) page := pages.New() view.AddKey("page", page) // Serve return view.Render() }
// HandleShow displays a single comment func HandleShow(context router.Context) error { // Find the comment comment, err := comments.Find(context.ParamInt("id")) if err != nil { return router.InternalError(err) } // No auth as all are public - if we restricted by status we might need to authorise here // Render the template view := view.New(context) view.AddKey("comment", comment) view.AddKey("authenticity_token", authorise.CreateAuthenticityToken(context)) return view.Render() }
// HandleCreateShow serves the create form via GET for stories func HandleCreateShow(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { return router.NotAuthorizedError(err) } // Render the template view := view.New(context) story := stories.New() view.AddKey("story", story) view.AddKey("meta_title", "Go Hacker News Submit") view.AddKey("authenticity_token", authorise.CreateAuthenticityToken(context)) return view.Render() }
// HandleUpvoted displays a list of stories the user has upvoted in the past func HandleUpvoted(context router.Context) error { // Build a query q := stories.Query().Limit(listLimit) // Select only above 0 points, Order by rank, then points, then name q.Where("points > 0").Order("rank desc, points desc, id desc") // Select only stories which the user has upvoted user := authorise.CurrentUser(context) if !user.Anon() { // Can we use a join instead? v := query.New("votes", "story_id").Select("select story_id as id from votes").Where("user_id=? AND story_id IS NOT NULL AND points > 0", user.Id) storyIDs := v.ResultIDs() if len(storyIDs) > 0 { q.WhereIn("id", storyIDs) } } // Set the offset in pages if we have one page := int(context.ParamInt("page")) if page > 0 { q.Offset(listLimit * page) } // Fetch the stories results, err := stories.FindAll(q) if err != nil { return router.InternalError(err) } // Render the template view := view.New(context) setStoriesMetadata(view, context.Request()) view.AddKey("page", page) view.AddKey("stories", results) view.Template("stories/views/index.html.got") if context.Param("format") == ".xml" { view.Layout("") view.Template("stories/views/index.xml.got") } return view.Render() }
// HandleCreateShow serves the create form via GET for stories func HandleCreateShow(context router.Context) error { // Authorise err := authorise.Path(context) if err != nil { // When not allowed to post stories, redirect to register screen router.Redirect(context, "/users/create") } // Render the template view := view.New(context) story := stories.New() view.AddKey("story", story) view.AddKey("meta_title", "Go Hacker News Submit") return view.Render() }