Ignore feature working

This commit is contained in:
Aaron Bieber 2022-12-04 19:03:59 -07:00
parent fab2d3f0cf
commit 7fd9a01a1a
No known key found for this signature in database
10 changed files with 116 additions and 3024 deletions

View File

@ -1,518 +0,0 @@
/**
* Bolt.css
* Version 0.5.0
* https://github.com/tbolt/boltcss
*
* Sections
* 1. Content sectioning
* 2. Text content
* 3. Inline text semantics
* 4. Image and multimedia
* 5. Tables
* 6. Forms
* 7. Interactive elements
*
*/
:root {
--highlight-border-radius: 7px;
--border-radius: 11px;
--links: #0f6dff;
--background-body: #fff;
--background-main: #f1f1f1;
--background-inputs: #fcfcfc;
--text: #1c1d1e;
--border: #dddddd;
--focus-highlight: #b8b8b8;
--shadow-color: #545454;
--table-highlight: #f1f1f1;
--select-icon-url: url("data:image/svg+xml,%3Csvg width='292' height='292' viewBox='0 0 292 292' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cpath id='Path' fill='%23222222' stroke='none' d='M 287 69 C 283.606537 65.469971 278.895844 63.513214 274 63.600006 L 18.4 63.600006 C 13.4 63.600006 9.1 65.400009 5.5 69 C 1.984143 72.328568 -0.005267 76.958466 -0 81.800003 C -0 86.800003 1.8 91.100006 5.4 94.699997 L 133.399994 222.600006 C 137 226.200012 141.199997 228 146.199997 228 C 151.199997 228 155.399994 226.200012 159 222.600006 L 287 94.600006 C 290.5 91.100006 292.399994 86.800003 292.399994 81.800003 C 292.399994 76.800003 290.5 72.600006 286.899994 69 Z'/%3E%3C/svg%3E");
}
@media (prefers-color-scheme: dark) {
:root {
--links: #4589ee;
--background-body: #0f0f0f;
--background-main: #222;
--background-inputs: #222;
--text: #efefef;
--border: #444;
--focus-highlight: #888;
--shadow-color: #bebebe;
--table-highlight: #222;
--select-icon-url: url("data:image/svg+xml,%3Csvg width='292' height='292' viewBox='0 0 292 292' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cpath id='Path' fill='%23ffffff' stroke='none' d='M 287 69 C 283.606537 65.469971 278.895844 63.513214 274 63.600006 L 18.4 63.600006 C 13.4 63.600006 9.1 65.400009 5.5 69 C 1.984143 72.328568 -0.005267 76.958466 -0 81.800003 C -0 86.800003 1.8 91.100006 5.4 94.699997 L 133.399994 222.600006 C 137 226.200012 141.199997 228 146.199997 228 C 151.199997 228 155.399994 226.200012 159 222.600006 L 287 94.600006 C 290.5 91.100006 292.399994 86.800003 292.399994 81.800003 C 292.399994 76.800003 290.5 72.600006 286.899994 69 Z'/%3E%3C/svg%3E");
}
}
*,
::after,
::before {
box-sizing: border-box;
}
html,
body {
margin: 0;
font-size: 12pt;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue",
sans-serif;
color: var(--text);
background: var(--background-body);
}
/* Content sectioning */
address {
font-style: normal;
line-height: 1.6rem;
}
/* Todo: Revisit this and try to find a way to handle margin depending on float direction */
aside {
width: 40%;
padding: 0.84rem;
margin: 0.16rem;
font-style: italic;
color: var(--text);
background-color: var(--background-main);
border-radius: var(--border-radius);
}
/* No styles provided */
footer {
}
header {
}
h1 {
font-size: 2.5rem;
}
h2 {
font-size: 2rem;
}
h3 {
font-size: 1.75rem;
}
h4 {
font-size: 1.5rem;
}
h5 {
font-size: 1.25rem;
font-weight: normal;
}
h6 {
font-size: 1rem;
font-weight: normal;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
h1,
h2,
h3,
h4,
b,
strong,
th {
font-weight: 700;
}
/* Not provided */
hgroup {
}
/* Not provided */
main {
}
/* Not provided */
nav {
}
/* Not provided */
section {
}
/* Text content */
blockquote {
position: relative;
padding-left: 1.5rem;
margin: 0;
}
blockquote:before {
content: "";
display: block;
position: absolute;
left: 0;
height: 100%;
border-left: 7px solid var(--border);
border-radius: 6px;
}
dd {
margin-left: 0;
padding-bottom: 11px;
}
dl {
}
dt {
font-weight: bold;
}
figcaption {
padding-top: 10px;
font-size: 0.8rem;
}
figure {
margin: 0;
}
hr {
border: 2px solid var(--border);
}
ul,
ol {
}
li {
line-height: 1.6em;
}
p {
display: block;
line-height: 1.6em;
}
/* Inline text elements */
a {
color: var(--links);
}
a:active,
a:hover,
a:focus {
text-decoration: none;
}
mark,
samp,
kbd,
code,
time {
border-radius: var(--highlight-border-radius, 4px);
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
}
mark {
background-color: #fffab7;
padding: 3px 5px;
}
samp {
display: inline-block;
font-weight: bold;
padding: 10px 20px;
background-color: var(--background-main);
color: var(--text);
}
kbd,
time {
padding: 2px 4px;
background-color: var(--background-main);
color: var(--text);
}
code,
pre {
font-size: 1em;
padding: 2px 4px;
background: var(--background-main);
border: 1px solid darkgray;
max-width: fit-content;
overflow-x: auto;
}
pre > code {
padding: 10px;
display: block;
overflow-x: auto;
}
pre {
margin: 0;
border-radius: var(--border-radius);
}
sup,
sub {
line-height: normal;
}
/* Image and multimedia */
audio,
img,
video {
border-radius: var(--border-radius);
max-width: 100%;
}
img {
height: auto;
}
/* Tables */
table {
width: fit-content;
border: 1px solid var(--background-main);
background: var(--background-main);
border-radius: var(--border-radius);
}
table tr:last-child td:first-child {
border-bottom-left-radius: 8px;
}
table tr:last-child td:last-child {
border-bottom-right-radius: 8px;
}
table tr:first-child th:first-child {
border-top-left-radius: 8px;
}
table tr:first-child th:last-child {
border-top-right-radius: 8px;
}
th {
background-color: var(--background-main);
}
td {
background: var(--background-body);
}
td,
th {
text-align: left;
padding: 8px;
}
thead {
border-collapse: collapse;
}
tfoot {
border-top: 1px solid black;
}
table tr:hover td,
tbody tr:nth-child(even):hover td {
background-color: var(--table-highlight);
}
/* Form elements */
input,
button,
select,
optgroup,
textarea {
margin: 0;
}
button,
select,
input[type="submit"],
input[type="button"],
input[type="checkbox"],
input[type="range"],
input[type="radio"] {
cursor: pointer;
}
button {
color: var(--text);
background-color: var(--background-main);
font-family: inherit;
font-size: inherit;
padding: 6px 15px 6px 15px;
border: 1px solid transparent;
border-radius: 6px;
box-shadow: 0px 1px 1.5px rgb(158 158 158 / 60%);
}
button:active {
box-shadow: none;
border: 1px solid var(--border);
}
button:disabled,
button[disabled] {
box-shadow: none;
border: 1px solid var(--border);
cursor: initial;
opacity: 0.55;
}
label {
display: block;
max-width: fit-content;
}
input {
font-size: 1em;
background-color: var(--background-inputs);
border: 1px solid var(--border);
color: var(--text);
margin: 6px 0px;
padding: 11px;
border-radius: var(--border-radius);
max-width: fit-content;
outline: none;
display: inline-block;
appearance: none;
}
input[type="checkbox"],
input[type="radio"] {
vertical-align: middle;
position: relative;
margin-right: 0.33em;
margin-top: 0.31em;
}
input[type="checkbox"] {
border-radius: 7px;
}
input[type="radio"] {
border-radius: 100%;
}
input[type="checkbox"]:checked,
input[type="radio"]:checked {
border: 1px solid var(--links);
background: var(--links);
}
input[type="checkbox"]:checked {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3.5' d='M6 10l3 3l6-6'/%3e%3c/svg%3e");
}
input[type="radio"]:checked {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e");
}
input[type="range"] {
vertical-align: middle;
padding: 0;
}
textarea {
font-family: inherit;
font-size: 1em;
background-color: var(--background-inputs);
border: 1px solid var(--border);
padding: 11px;
color: var(--text);
border-radius: var(--border-radius);
outline: none;
/* resize: none; Todo: research if there is a non-js way to style/move grippie */
max-width: 100%;
}
select {
display: inline-block;
vertical-align: middle;
font-size: 1rem;
color: var(--text);
padding: 0.6em 2em 0.5em 0.8em;
margin: 6px 0px;
max-width: fit-content;
box-sizing: border-box;
border: 1px solid var(--border);
box-shadow: 0 1px 0 1px rgba(0, 0, 0, 0.04);
border-radius: 0.5em;
appearance: none;
background-color: var(--background-inputs);
background-image: var(--select-icon-url);
background-repeat: no-repeat, repeat;
background-position: right 0.7em top 50%, 0 0;
background-size: 0.65em auto, 100%;
}
/* Todo: update styles when using multiple mode */
select:is([multiple]) {
background: none;
height: fit-content;
}
fieldset:focus-within,
input:focus-within,
textarea:focus-within,
select:focus-within {
border-color: var(--focus-highlight);
}
fieldset:hover,
input:hover,
textarea:hover,
select:hover {
border-color: var(--focus-highlight);
}
meter {
height: 2.2em;
vertical-align: middle;
}
fieldset {
border: 1px var(--border) solid;
border-radius: 6px;
margin: 0;
margin-bottom: 6px;
padding: 10px;
max-width: fit-content;
}
/* Interactive elements */
details {
border: 1px solid #aaa;
border-radius: 7px;
padding: 0.5em 0.5em 0;
}
summary {
font-weight: bold;
margin: -0.5em -0.5em 0;
padding: 0.5em;
}
details[open] {
padding: 0.5em;
}
details[open] summary {
border-bottom: 1px solid #aaa;
margin-bottom: 0.5em;
}

View File

@ -49,6 +49,7 @@ function postData(path, data) {
if (response.ok) {
console.log("added");
}
location.reload();
return [2 /*return*/, response];
}
});
@ -134,3 +135,20 @@ function sendPRData() {
});
});
}
function addIgnore(number, repo) {
return __awaiter(this, void 0, void 0, function () {
var data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
data = {};
data.Number = number;
data.Repo = repo;
return [4 /*yield*/, postData('/prignores', data)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
}

View File

@ -43,6 +43,9 @@ async function postData(path: string, data: Link|PullRequest|WatchItem|PullReque
if (response.ok) {
console.log("added")
}
location.reload();
return response
}
@ -88,3 +91,10 @@ async function sendPRData() {
data.Description = pd.value;
await postData('/pullrequests', data);
}
async function addIgnore(number, repo: string) {
let data = {} as PullRequestIgnore;
data.Number = number;
data.Repo = repo;
await postData('/prignores', data);
}

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,8 @@
version = "v0.0.0";
src = ./.;
vendorSha256 = "sha256-RNhu1gQ62Hg8Fhiw9uIS+b4YaAHtZMaqbelMKv+oZjM=";
vendorSha256 =
"sha256-aW7Ysx6ovAskiNHlnmmK3VsgeO+VYJYjXitVCPfSS9k=";
proxyVendor = true;
};
});
@ -32,7 +33,16 @@
PS1='\u@\h:\@; '
echo "Go `${pkgs.go}/bin/go version`"
'';
nativeBuildInputs = with pkgs; [ git go gopls go-tools sqlc sqlite rlwrap nodePackages.typescript ];
nativeBuildInputs = with pkgs; [
git
go
gopls
go-tools
sqlc
sqlite
rlwrap
nodePackages.typescript
];
};
});
};

View File

@ -3,7 +3,6 @@ package main
import (
"context"
"encoding/json"
"fmt"
"html/template"
"net/http"
"strconv"
@ -226,8 +225,6 @@ func linksPOST(w http.ResponseWriter, r *http.Request) {
d.OwnerID = ownerID
fmt.Printf("\n\n%#v\n\n", d)
_, err := app.queries.AddLink(app.ctx, *d)
if err != nil {
http.Error(w, http.StatusText(422), 422)
@ -235,6 +232,28 @@ func linksPOST(w http.ResponseWriter, r *http.Request) {
}
}
func prignorePOST(w http.ResponseWriter, r *http.Request) {
d := &data.AddPullRequestIgnoreParams{}
if err := render.Decode(r, d); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ctx := r.Context()
ownerID, ok := ctx.Value("ownerid").(int64)
if !ok {
http.Error(w, http.StatusText(422), 422)
return
}
d.OwnerID = ownerID
_, err := app.queries.AddPullRequestIgnore(app.ctx, *d)
if err != nil {
http.Error(w, http.StatusText(422), 422)
return
}
}
func linkDELETE(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ownerID, ok := ctx.Value("ownerid").(int64)
@ -252,6 +271,17 @@ func linkDELETE(w http.ResponseWriter, r *http.Request) {
}
}
var templateFuncs = template.FuncMap{
"includeWatch": func(repo string, number int, ignoreList []data.PullRequestIgnore) bool {
for _, pri := range ignoreList {
if pri.Repo == repo && pri.Number == int64(number) {
return false
}
}
return true
},
}
func index(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
owner, err := app.getOwner(r)
@ -280,6 +310,12 @@ func index(w http.ResponseWriter, r *http.Request) {
return
}
ignores, err := app.queries.GetAllPullRequestIgnores(ctx, ownerID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
stuff := &Page{
Node: *owner,
Title: "StartPage",
@ -287,12 +323,18 @@ func index(w http.ResponseWriter, r *http.Request) {
PullRequests: prs,
Watches: app.watches.forID(ownerID),
CurrentLimits: app.watches.GetLimits(),
Ignores: ignores,
}
stuff.Sort()
tmpl := template.Must(template.ParseFS(templates, "templates/main.html"))
err = tmpl.Execute(w, stuff)
tmpl := template.Must(
template.New("").Funcs(templateFuncs).ParseFS(templates, "templates/main.html"),
)
//tmpl = tmpl.Funcs(templateFuncs)
err = tmpl.ExecuteTemplate(w, "main.html", stuff)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return

View File

@ -119,6 +119,10 @@ func main() {
r.Delete("/{watchID:[0-9]+}", watchitemDELETE)
r.Post("/", watchitemPOST)
})
r.Route("/prignores", func(r chi.Router) {
r.Use(render.SetContentType(render.ContentTypeJSON))
r.Post("/", prignorePOST)
})
r.Route("/icons", func(r chi.Router) {
r.Get("/{linkID:[0-9]+}", iconGET)
})

14
page.go
View File

@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"sort"
"time"
@ -80,7 +81,12 @@ func getData(q GQLQuery, token string) (*WatchResult, error) {
return nil, err
}
defer res.Body.Close()
defer func() {
err := res.Body.Close()
if err != nil {
log.Fatal(err)
}
}()
if err = json.NewDecoder(res.Body).Decode(re); err != nil {
return nil, err
@ -96,6 +102,7 @@ type Page struct {
Node tailcfg.Node
Watches WatchResults
CurrentLimits *RateLimit
Ignores []data.PullRequestIgnore
}
func (p *Page) Sort() {
@ -117,9 +124,9 @@ func (p *Page) Sort() {
type WatchResults []WatchResult
func (w WatchResults) forID(ownerID int64) WatchResults {
func (w *WatchResults) forID(ownerID int64) WatchResults {
newResults := WatchResults{}
for _, r := range w {
for _, r := range *w {
if r.OwnerID == ownerID {
newResults = append(newResults, r)
}
@ -186,6 +193,7 @@ type Search struct {
IssueCount int `json:"issueCount,omitempty"`
Edges []Edges `json:"edges,omitempty"`
}
type RateLimit struct {
Remaining int `json:"remaining,omitempty"`
ResetAt time.Time `json:"resetAt,omitempty"`

View File

@ -1,6 +1,5 @@
<html lang="en">
<head>
<!-- <link rel="stylesheet" href="assets/pico.css">-->
<style>
.icon {
cursor: pointer;
@ -43,6 +42,10 @@
main {
padding: 5px !important;
}
ul li span {
cursor: pointer;
}
</style>
<title>{{.Title}}::{{.Node.ComputedName}}</title>
</head>
@ -71,10 +74,17 @@
<li><b>{{.Repo}} :: {{.Name}}</b>
<ul>
{{range .Data.Search.Edges}}
<li><b><a href="{{.Node.URL}}">{{.Node.Number}}</a></b> :: <span>+</span> <span>-</span> ::
{{if includeWatch .Node.Repository.NameWithOwner .Node.Number $.Ignores}}
<li>
<b>
<a href="{{.Node.URL}}">{{.Node.Number}}</a>
</b> ::
<span></span>
<span onclick="addIgnore({{.Node.Number}}, '{{.Node.Repository.NameWithOwner}}')"></span> ::
{{.Node.Title}}
</li>
{{end}}
{{end}}
</ul>
</li>
{{end}}
@ -89,6 +99,7 @@
<a href="{{.Url}}">
<div class="icon">
<header>
<!-- TODO: make this not ghetto -->
<img src="/icons/{{.ID}}"/>
</header>
{{.Name}}