gitoriaLog in with ident

gitoria

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit4a2d71254a2d7125initial commitmre4a2d7125/components/tickets.hl

4.7 KB

  1. // components/tickets.hl — THE TICKETS of a repo (gitoria#10, gitoria#16): `/tickets` on <slug>.<domain>, its own
  2. // route, rendered on the SERVER with its list: the repo comes from the request's host, the tickets from
  3. // tickets.worldapi.org (tickets.hl — hl:fetch answers at once, so the list is in the first HTML and in every
  4. // hl:web navigation). Any named user opens a ticket (gitoria's own API token; the text says who); a ticket
  5. // opened here reaches every open tickets page of the repo (push `ticketOpened`).
  6. parent './main.hl'
  7. import { siteName } from '../project.hl'
  8. import RepoHead from './repohead.hl'
  9. import { repoAt, pageTitle } from '../repos.hl'
  10. import { loadTickets, openTicket } from '../tickets.hl'
  11. import { slugOfHost, infoOfSession, userOfSession } from '../users.hl'
  12. host = null
  13. session = null
  14. slug = slugOfHost(host)
  15. repo = repoAt(slug)
  16. hasRepo = repo != null
  17. me = infoOfSession(session)
  18. canCreate = me != null && me.named
  19. needsLogin = me == null
  20. loaded = repo != null ? loadTickets(slug) : null
  21. ticketsErrorShown = loaded != null && loaded.error != null
  22. ticketsError = loaded != null && loaded.error != null ? loaded.error : ''
  23. tickets = loaded != null && loaded.tickets != null ? loaded.tickets : []
  24. ticketsTruncated = loaded != null && loaded.truncated == true
  25. ticketsHref = loaded != null && loaded.url != null ? loaded.url : ''
  26. ticketsShown = tickets.length > 0
  27. ticketsNone = loaded != null && loaded.error == null && tickets.length == 0
  28. ticketError = ''
  29. ticketNotice = ''
  30. hasTicketNotice = false
  31. __title = pageTitle(siteName, slug, 'Tickets')
  32. View {
  33. repoPage {
  34. RepoHead { }
  35. if (hasRepo) {
  36. repoTickets { id = "tickets"
  37. if (ticketsErrorShown) { p { id = "ticketserror" class = "message" ticketsError } }
  38. if (canCreate) {
  39. details { id = "newticket"
  40. summary { "New ticket" }
  41. form { id = "newticketform"
  42. on submit(e) {
  43. e.preventDefault()
  44. emit openIt(e)
  45. }
  46. label { "Subject"
  47. input { id = "ticketsubject" name = "subject" required = "required" maxlength = "200" autocomplete = "off" }
  48. }
  49. label { "Text (Markdown, optional)"
  50. textarea { id = "ticketsummary" name = "summary" rows = "5" }
  51. }
  52. button { id = "ticketsave" type = "submit" "Open ticket" }
  53. p { id = "newticketerror" class = "message" ticketError }
  54. }
  55. }
  56. }
  57. if (needsLogin) { p { id = "ticketsloginhint" class = "muted" "Log in with ident (top right) to open a ticket." } }
  58. if (hasTicketNotice) { p { id = "ticketnotice" class = "notice" ticketNotice } }
  59. if (ticketsNone) { p { id = "noticketsyet" class = "empty" "No ticket yet — the first one creates this repository's project in tickets." } }
  60. if (ticketsShown) {
  61. ol { id = "ticketlist"
  62. for (t of tickets) {
  63. li {
  64. a { class = "number" href = t.url "#" t.number }
  65. a { class = "subject" href = t.url t.subject }
  66. span { class = "state" t.state }
  67. time { t.updated }
  68. }
  69. }
  70. }
  71. p { class = "muted" "Open a ticket to read and answer it in " a { id = "ticketsall" href = ticketsHref "tickets.worldapi.org" } "." }
  72. if (ticketsTruncated) { p { id = "ticketstruncated" class = "muted" "Only the latest tickets are listed here." } }
  73. }
  74. }
  75. }
  76. }
  77. }
  78. on openIt(e) {
  79. let f = e.target.elements
  80. let r = emit server gitoriaOpenTicket(slug, f.subject.value, f.summary.value)
  81. if (r == null || r.error != null) {
  82. ticketError = r != null ? r.error : 'could not open the ticket'
  83. return null
  84. }
  85. ticketError = ''
  86. f.subject.value = ''
  87. f.summary.value = ''
  88. ticketNotice = 'Opened ticket #' + r.ticket.number + '.'
  89. hasTicketNotice = true
  90. addTicket(r.ticket)
  91. }
  92. addTicket = (row) => {
  93. let next = [row]
  94. for (x of tickets) { if (x.number != row.number) { next.push(x) } }
  95. tickets = next
  96. ticketsShown = true
  97. ticketsNone = false
  98. }
  99. // a ticket opened here by anyone: every open tickets page of that repo follows
  100. on client ticketOpened(slugOf, row) {
  101. if (!hasRepo || slugOf != slug) { return null }
  102. addTicket(row)
  103. }
  104. // this session's tabs follow a login / name / logout (the shell's faces push them)
  105. on client gitoriaSignedIn(tag, info) {
  106. canCreate = info.named
  107. needsLogin = false
  108. }
  109. on client gitoriaSignedOut(tag) {
  110. canCreate = false
  111. needsLogin = true
  112. }
  113. on server gitoriaOpenTicket(slugOf, subject, summary, session) {
  114. if (repoAt(slugOf) == null) { return { error = 'no such repository' } }
  115. let u = userOfSession(session)
  116. if (u == null) { return { error = 'log in with ident (top right) to open a ticket' } }
  117. if (u.name == '') { return { error = 'choose a display name first (top of the page)' } }
  118. let r = openTicket(slugOf, u.name, subject, summary)
  119. if (r.error != null) { return { error = r.error } }
  120. emit client ticketOpened(slugOf, r.ticket)
  121. return r
  122. }

Branches

Latest commits

  • 4a2d7125initial commitmre