This commit is contained in:
+80
-12
@@ -97,10 +97,18 @@ type PageData struct {
|
||||
Board []BoardColumn
|
||||
BoardTags []BoardTag
|
||||
ArchivedTasks []BoardTask
|
||||
BoardFilter BoardFilter
|
||||
}
|
||||
|
||||
type Stats struct{ Present, Remote, Leave int }
|
||||
|
||||
type BoardFilter struct {
|
||||
TagID int64
|
||||
AssigneeID int64
|
||||
Priority string
|
||||
Active bool
|
||||
}
|
||||
|
||||
type ReportTotals struct {
|
||||
Present int
|
||||
Remote int
|
||||
@@ -217,6 +225,14 @@ func New(cfg Config) (*Server, error) {
|
||||
}
|
||||
return false
|
||||
},
|
||||
"hasUser": func(users []User, id int64) bool {
|
||||
for _, user := range users {
|
||||
if user.ID == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
}
|
||||
tmpl, err := template.New("root").Funcs(funcs).ParseFS(assets, "templates/*.html")
|
||||
if err != nil {
|
||||
@@ -275,6 +291,7 @@ func (s *Server) routes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("POST /board/tasks/{id}/restore", s.requireAuth(s.csrf(s.restoreBoardTask)))
|
||||
mux.HandleFunc("POST /board/tasks/{id}/delete", s.requireAuth(s.csrf(s.deleteBoardTask)))
|
||||
mux.HandleFunc("POST /board/tasks/{id}/tags", s.requireAuth(s.csrf(s.setBoardTaskTags)))
|
||||
mux.HandleFunc("POST /board/tasks/{id}/details", s.requireAuth(s.csrf(s.setBoardTaskDetails)))
|
||||
mux.HandleFunc("POST /board/tags", s.requireAuth(s.csrf(s.createBoardTag)))
|
||||
mux.HandleFunc("POST /board/tags/{id}/delete", s.requireAuth(s.csrf(s.deleteBoardTag)))
|
||||
mux.HandleFunc("GET /admin/requests", s.requireAdmin(s.adminPage))
|
||||
@@ -763,6 +780,22 @@ func (s *Server) boardPage(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "could not load board tags", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
filter := BoardFilter{Priority: r.URL.Query().Get("priority")}
|
||||
filter.TagID, _ = strconv.ParseInt(r.URL.Query().Get("tag"), 10, 64)
|
||||
filter.AssigneeID, _ = strconv.ParseInt(r.URL.Query().Get("assignee"), 10, 64)
|
||||
if !validBoardPriority(filter.Priority) {
|
||||
filter.Priority = ""
|
||||
}
|
||||
filter.Active = filter.TagID > 0 || filter.AssigneeID > 0 || filter.Priority != ""
|
||||
if filter.Active {
|
||||
filtered := make([]BoardTask, 0, len(tasks))
|
||||
for _, task := range tasks {
|
||||
if boardTaskMatchesFilter(task, filter) {
|
||||
filtered = append(filtered, task)
|
||||
}
|
||||
}
|
||||
tasks = filtered
|
||||
}
|
||||
columns := []BoardColumn{
|
||||
{Status: "backlog", Title: "Backlog", Hint: "Ready to pick up"},
|
||||
{Status: "in_progress", Title: "In progress", Hint: "Actively being worked"},
|
||||
@@ -779,26 +812,52 @@ func (s *Server) boardPage(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
s.render(w, "board.html", PageData{
|
||||
Title: "Team board", User: currentUser(r), CSRF: csrfToken(r), Users: users, Board: columns, BoardTags: tags,
|
||||
ArchivedTasks: archivedTasks,
|
||||
TodayJalali: jalali.FromTime(time.Now()).String(), Error: r.URL.Query().Get("error"),
|
||||
ArchivedTasks: archivedTasks, BoardFilter: filter,
|
||||
TodayJalali: jalali.FromTime(time.Now()).String(), Error: r.URL.Query().Get("error"),
|
||||
Flash: r.URL.Query().Get("flash"), SelectedSection: "board",
|
||||
})
|
||||
}
|
||||
|
||||
func validBoardPriority(priority string) bool {
|
||||
return priority == "" || priority == "low" || priority == "normal" || priority == "high" || priority == "urgent"
|
||||
}
|
||||
|
||||
func boardTaskMatchesFilter(task BoardTask, filter BoardFilter) bool {
|
||||
if filter.Priority != "" && task.Importance != filter.Priority {
|
||||
return false
|
||||
}
|
||||
if filter.TagID > 0 {
|
||||
found := false
|
||||
for _, tag := range task.Tags {
|
||||
if tag.ID == filter.TagID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if filter.AssigneeID > 0 {
|
||||
found := false
|
||||
for _, assignee := range task.Assignees {
|
||||
if assignee.ID == filter.AssigneeID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Server) createBoardTask(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.TrimSpace(r.FormValue("title")) == "" {
|
||||
http.Redirect(w, r, "/board?error=Task+title+is+required", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
var assigneeID *int64
|
||||
if raw := r.FormValue("assignee_id"); raw != "" {
|
||||
id, err := strconv.ParseInt(raw, 10, 64)
|
||||
if err != nil || id < 1 {
|
||||
http.Redirect(w, r, "/board?error=Choose+a+valid+assignee", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
assigneeID = &id
|
||||
}
|
||||
dueDate := ""
|
||||
if rawDue := strings.TrimSpace(r.FormValue("due_date")); rawDue != "" {
|
||||
parsed, ok := parseUserDate(rawDue)
|
||||
@@ -819,7 +878,7 @@ func (s *Server) createBoardTask(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
taskID, err := s.store.CreateBoardTask(
|
||||
currentUser(r).ID, r.FormValue("title"), r.FormValue("description"),
|
||||
r.FormValue("status"), assigneeID, dueDate,
|
||||
r.FormValue("status"), r.FormValue("importance"), parseIDList(r.Form["assignee_ids"]), dueDate,
|
||||
)
|
||||
if err != nil {
|
||||
http.Redirect(w, r, "/board?error="+url.QueryEscape(err.Error()), http.StatusSeeOther)
|
||||
@@ -892,6 +951,15 @@ func (s *Server) setBoardTaskTags(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/board?flash=Task+labels+updated", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (s *Server) setBoardTaskDetails(w http.ResponseWriter, r *http.Request) {
|
||||
id, _ := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err := s.store.SetBoardTaskDetails(id, parseIDList(r.Form["assignee_ids"]), r.FormValue("importance")); err != nil {
|
||||
http.Redirect(w, r, "/board?error="+url.QueryEscape(err.Error()), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/board?flash=Card+details+updated", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (s *Server) createBoardTag(w http.ResponseWriter, r *http.Request) {
|
||||
if err := s.store.CreateBoardTag(r.FormValue("name"), r.FormValue("color")); err != nil {
|
||||
http.Redirect(w, r, "/board?error="+url.QueryEscape(err.Error()), http.StatusSeeOther)
|
||||
|
||||
Reference in New Issue
Block a user