diff --git a/assets/index.html b/assets/index.html
index b7eb222..deada59 100644
--- a/assets/index.html
+++ b/assets/index.html
@@ -71,7 +71,7 @@
.form-container {
display: grid;
- grid-template-columns: repeat(3, 1fr);
+ grid-template-columns: repeat(4, 1fr);
}
.form-content {
@@ -81,6 +81,26 @@
color: red;
}
+ table {
+ border: 1px solid #dedeff;
+ }
+
+ table tr td {
+ padding: 5px;
+ }
+
+ table th {
+ background-color: #dedeff;
+ }
+
+ table tr:nth-child(even) {
+ background-color: #f6f8f9;
+ }
+
+ table tr:nth-child(odd) {
+ background-color: #fff;
+ }
+
header {
padding: 0 !important;
}
@@ -94,7 +114,6 @@
}
footer {
- text-align: center;
}
diff --git a/assets/main.min.js b/assets/main.min.js
index eeb2436..9b2299e 100644
--- a/assets/main.min.js
+++ b/assets/main.min.js
@@ -1 +1 @@
-!function(B){"use strict";function n(n,r,t){return t.a=n,t.f=r,t}function r(t){return n(2,t,function(r){return function(n){return t(r,n)}})}function t(e){return n(3,e,function(t){return function(r){return function(n){return e(t,r,n)}}})}function D(u){return n(4,u,function(e){return function(t){return function(r){return function(n){return u(e,t,r,n)}}}})}function R(a){return n(5,a,function(u){return function(e){return function(t){return function(r){return function(n){return a(u,e,t,r,n)}}}}})}function M(i){return n(6,i,function(a){return function(u){return function(e){return function(t){return function(r){return function(n){return i(a,u,e,t,r,n)}}}}}})}function F(o){return n(7,o,function(i){return function(a){return function(u){return function(e){return function(t){return function(r){return function(n){return o(i,a,u,e,t,r,n)}}}}}}})}function b(n,r,t){return 2===n.a?n.f(r,t):n(r)(t)}function s(n,r,t,e){return 3===n.a?n.f(r,t,e):n(r)(t)(e)}function v(n,r,t,e,u){return 4===n.a?n.f(r,t,e,u):n(r)(t)(e)(u)}function d(n,r,t,e,u,a){return 5===n.a?n.f(r,t,e,u,a):n(r)(t)(e)(u)(a)}function z(n,r,t,e,u,a,i){return 6===n.a?n.f(r,t,e,u,a,i):n(r)(t)(e)(u)(a)(i)}function H(n,r,t,e,u,a,i,o){return 7===n.a?n.f(r,t,e,u,a,i,o):n(r)(t)(e)(u)(a)(i)(o)}function P(n,r){for(var t,e=[],u=Y(n,r,0,e);u&&(t=e.pop());u=Y(t.a,t.b,0,e));return u}function Y(n,r,t,e){if(n!==r){if("object"!=typeof n||null===n||null===r)return"function"==typeof n&&Z(5),!1;if(100i)return u}var v=t.$;if(4===v){for(var d=t.k;4===d.$;)d=d.k;return n(r,d,e,u,a+1,i,r.elm_event_node_ref)}var l=t.e;var $=r.childNodes;for(var h=0;hi))return u;a=p}return u}(n,r,t,0,0,r.b,e)}function br(n,r,t,e){return 0===t.length?n:(sr(n,r,t,e),vr(n,t))}function vr(n,r){for(var t=0;t "),x(n.q),b(yu,$([Ze({$:5,a:n.ag})]),$([x(" ×")]))])),b(Cu,l,b(Yt,Kr,n.aG))]))]))])):x("")},Ju={$:16},qu=r(function(n,r){return b(O,l,$([s(ou,"Watches",Ju,b(O,l,$([d(hu,"Item: ","some string...","name",n.C.q,function(n){return{$:8,a:e(r,{q:n})}}),d(hu,"Repository: ","NixOS/nixpkgs","repo",n.C.T,function(n){return{$:8,a:e(r,{T:n})}})])))]))}),fn=kn({b4:function(n){return{a:Be,b:Xt($([Oe,xe]))}},cy:function(n){return De},cC:Q,cD:function(t){return b(O,l,$([b(Ve,l,$([b(O,$([S("grid")]),$([b(O,$([S("col")]),$([function(n){return b(O,l,$([b(ku,b(qu,n,n.C),b(tu,$([Ze(Eu)]),$([x(" ⟳")]))),n.aq.b?b(Cu,l,b(Yt,Nu,n.aq)):x("No watches found!")]))}(t)])),b(O,$([S("col")]),$([function(n){return b(O,l,$([b(ku,b(pu,n,n.u),b(tu,$([Ze(ru)]),$([x(" ⟳")]))),n.aj.b?b(O,$([S("icon-grid")]),b(Yt,ju,n.aj)):x("No links found!")]))}(t)]))])),b(O,$([S("grid")]),$([function(){var n,r=t.p;return 3===r.$?(r=r.a,b(O,$([(n=$([{a:"error",b:!0}]),S(b(st," ",b(Yt,Ot,b(Ie,We,n)))))]),$([x(r)]))):x("")}()]))])),b(Xe,l,$([b(Ue,l,$([b(nu,l,$([b(Ye,l,$([x("Maintenence")]))])),b(Ge,$([Ze(Pe)]),$([x("Update Icons")]))]))]))]))}});an={Main:{init:fn(Ft(0))(0)}},B.Elm?function n(r,t){for(var e in t)e in r?"init"==e?Z(6):n(r[e],t[e]):r[e]=t[e]}(B.Elm,an):B.Elm=an}(this);
\ No newline at end of file
+!function(W){"use strict";function R(n,r,t){return t.a=n,t.f=r,t}function r(t){return R(2,t,function(r){return function(n){return t(r,n)}})}function t(e){return R(3,e,function(t){return function(r){return function(n){return e(t,r,n)}}})}function n(u){return R(4,u,function(e){return function(t){return function(r){return function(n){return u(e,t,r,n)}}}})}function H(a){return R(5,a,function(u){return function(e){return function(t){return function(r){return function(n){return a(u,e,t,r,n)}}}}})}function F(c){return R(6,c,function(a){return function(u){return function(e){return function(t){return function(r){return function(n){return c(a,u,e,t,r,n)}}}}}})}function q(i){return R(7,i,function(c){return function(a){return function(u){return function(e){return function(t){return function(r){return function(n){return i(c,a,u,e,t,r,n)}}}}}}})}function s(n,r,t){return 2===n.a?n.f(r,t):n(r)(t)}function b(n,r,t,e){return 3===n.a?n.f(r,t,e):n(r)(t)(e)}function x(n,r,t,e,u){return 4===n.a?n.f(r,t,e,u):n(r)(t)(e)(u)}function v(n,r,t,e,u,a){return 5===n.a?n.f(r,t,e,u,a):n(r)(t)(e)(u)(a)}function D(n,r,t,e,u,a,c){return 6===n.a?n.f(r,t,e,u,a,c):n(r)(t)(e)(u)(a)(c)}function G(n,r,t,e,u,a,c,i){return 7===n.a?n.f(r,t,e,u,a,c,i):n(r)(t)(e)(u)(a)(c)(i)}function V(n,r){for(var t,e=[],u=I(n,r,0,e);u&&(t=e.pop());u=I(t.a,t.b,0,e));return u}function I(n,r,t,e){if(n!==r){if("object"!=typeof n||null===n||null===r)return"function"==typeof n&&tn(5),!1;if(100c)return u}var v=t.$;if(4===v){for(var l=t.k;4===l.$;)l=l.k;return n(r,l,e,u,a+1,c,r.elm_event_node_ref)}var d=t.e;var $=r.childNodes;for(var h=0;hc))return u;a=p}return u}(n,r,t,0,0,r.b,e)}function mr(n,r,t,e){return 0===t.length?n:(pr(n,r,t,e),wr(n,t))}function wr(n,r){for(var t=0;t "),B(n.bl),s(gu,d([S({$:5,a:n.cc})]),d([B(" ×")]))])),s(pa,l,s(_,vt,n.bC))]))]))])):B("")},Oa={$:20},ya=r(function(n,r){return s(Y,l,d([b(ra,"Watches",Oa,s(Y,l,d([v(ba,"Item: ","some string...","name",n.B.bl,function(n){return{$:10,a:e(r,{bl:n})}}),v(ba,"Repository: ","NixOS/nixpkgs","repo",n.B.cF,function(n){return{$:10,a:e(r,{cF:n})}})])))]))}),gn=bn({bl:"Action",Y:ln,_:function(n){return s($u,l,d([s(ou,d([S({$:5,a:n.cc})]),d([B("Delete")]))]))}}),_a=(u={aB:d([s(hn,"Name",function(n){return n.bl}),s(hn,"Repo",function(n){return n.cF}),gn]),aW:function(n){return n.bl},aX:function(n){return{$:24,a:n}}},en=u.aX,Q=u.aW,{aB:s(_,function(n){return n},u.aB),a3:rn,aW:Q,aX:en}),X=_n({cf:function(n){return{a:Qe,b:fe(d([Ue,Xe,Pe]))}},cO:function(n){return Ze},cT:un,cU:function(t){return s(Y,l,d([s(Au,l,d([s(Y,d([C("grid")]),d([s(Y,d([C("col")]),d([function(n){return s(Y,l,d([s(da,s(ya,n,n.B),s(Xu,d([S(ga)]),d([B(" ⟳")]))),n.aa.b?s(pa,l,s(_,ka,n.aa)):B("No watches found!")]))}(t)])),s(Y,d([C("col")]),d([function(n){return s(Y,l,d([s(da,s(va,n,n.s),s(Xu,d([S(Uu)]),d([B(" ⟳")]))),n.W.b?s(Y,d([C("icon-grid")]),s(_,ha,n.W)):B("No links found!")]))}(t)]))])),s(Y,d([C("grid")]),d([function(){var n,r=t.i;return 4===r.$?(r=r.a,s(Y,d([(n=d([{a:"error",b:!0}]),C(s(_t," ",s(_,Pt,s(bu,su,n)))))]),d([B(r)]))):B("")}()]))])),s(lu,l,d([s(vu,l,d([s(Lu,l,d([s(iu,l,d([B("Maintenence")]))])),s(Y,l,d([s(ou,d([S(cu)]),d([B("Update Icons")]))])),s(Y,l,d([s(du,l,d([B("Links")])),b(Pu,Nu,t.as,t.W)])),s(Y,l,d([s(du,l,d([B("Watched Items")])),b(Pu,_a,t.az,t.aa)])),s(Y,l,d([s(du,l,d([B("Watched Items Ignores")])),b(Pu,Tu,t.aq,t.ar)]))]))]))]))}});nn={Main:{init:X(re(0))(0)}},W.Elm?function n(r,t){for(var e in t)e in r?"init"==e?tn(6):n(r[e],t[e]):r[e]=t[e]}(W.Elm,nn):W.Elm=nn}(this);
\ No newline at end of file
diff --git a/data/queries.sql.go b/data/queries.sql.go
index 7563534..0d5defc 100644
--- a/data/queries.sql.go
+++ b/data/queries.sql.go
@@ -175,6 +175,23 @@ func (q *Queries) AddWatchItem(ctx context.Context, arg AddWatchItemParams) (Wat
return i, err
}
+const deleteIgnore = `-- name: DeleteIgnore :exec
+delete
+from pull_request_ignores
+where id = ?
+ and owner_id = ?
+`
+
+type DeleteIgnoreParams struct {
+ ID int64 `json:"id"`
+ OwnerID int64 `json:"owner_id"`
+}
+
+func (q *Queries) DeleteIgnore(ctx context.Context, arg DeleteIgnoreParams) error {
+ _, err := q.db.ExecContext(ctx, deleteIgnore, arg.ID, arg.OwnerID)
+ return err
+}
+
const deleteLink = `-- name: DeleteLink :exec
delete
from links
diff --git a/elm.json b/elm.json
index eea3262..e887362 100644
--- a/elm.json
+++ b/elm.json
@@ -6,6 +6,7 @@
"elm-version": "0.19.1",
"dependencies": {
"direct": {
+ "billstclair/elm-sortable-table": "1.2.1",
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
diff --git a/handlers.go b/handlers.go
index a4d1676..7fdf777 100644
--- a/handlers.go
+++ b/handlers.go
@@ -299,6 +299,50 @@ func linksPOST(w http.ResponseWriter, r *http.Request) {
}
}
+func prignoreGET(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+ ownerID, ok := ctx.Value(ownerKey).(int64)
+ if !ok {
+ http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
+ return
+ }
+ prIgnores, err := app.queries.GetAllPullRequestIgnores(app.ctx, ownerID)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ prJson, err := json.Marshal(prIgnores)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Add("Content-type", "application/json")
+ w.WriteHeader(200)
+ _, err = w.Write(prJson)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
+
+func prignoreDELETE(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+ ownerID, ok := ctx.Value(ownerKey).(int64)
+ if !ok {
+ http.Error(w, http.StatusText(http.StatusUnprocessableEntity), http.StatusUnprocessableEntity)
+ return
+ }
+ ignoreID, err := strconv.Atoi(chi.URLParam(r, "ignoreID"))
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ err = app.queries.DeleteIgnore(app.ctx, data.DeleteIgnoreParams{ID: int64(ignoreID), OwnerID: ownerID})
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+}
+
func prignorePOST(w http.ResponseWriter, r *http.Request) {
d := &data.AddPullRequestIgnoreParams{}
if err := render.Decode(r, d); err != nil {
diff --git a/main.go b/main.go
index f6d9679..6f0911f 100644
--- a/main.go
+++ b/main.go
@@ -156,6 +156,8 @@ func main() {
r.Route("/prignores", func(r chi.Router) {
r.Use(render.SetContentType(render.ContentTypeJSON))
r.Post("/", prignorePOST)
+ r.Get("/", prignoreGET)
+ r.Delete("/{ignoreID:[0-9]+}", prignoreDELETE)
})
r.Route("/icons", func(r chi.Router) {
r.Use(IconCacher)
diff --git a/queries.sql b/queries.sql
index d8b4d22..1a47e2a 100644
--- a/queries.sql
+++ b/queries.sql
@@ -82,6 +82,13 @@ from pull_requests
where id = ?
and owner_id = ?;
+-- name: DeleteIgnore :exec
+delete
+from pull_request_ignores
+where id = ?
+ and owner_id = ?;
+
+
-- name: GetAllPullRequestIgnores :many
select *
from pull_request_ignores
diff --git a/src/Ignores.elm b/src/Ignores.elm
new file mode 100644
index 0000000..a41f04e
--- /dev/null
+++ b/src/Ignores.elm
@@ -0,0 +1,39 @@
+module Ignores exposing (..)
+
+import Json.Decode
+ exposing
+ ( Decoder
+ , field
+ , int
+ , list
+ , map5
+ , string
+ )
+
+
+type alias Ignores =
+ List Ignore
+
+
+type alias Ignore =
+ { id : Int
+ , ownerId : Int
+ , createdAt : String
+ , repo : String
+ , number : Int
+ }
+
+
+ignoreListDecoder : Decoder Ignores
+ignoreListDecoder =
+ list ignoreDecoder
+
+
+ignoreDecoder : Decoder Ignore
+ignoreDecoder =
+ map5 Ignore
+ (field "id" int)
+ (field "owner_id" int)
+ (field "created_at" string)
+ (field "repo" string)
+ (field "number" int)
diff --git a/src/Links.elm b/src/Links.elm
new file mode 100644
index 0000000..9df0d65
--- /dev/null
+++ b/src/Links.elm
@@ -0,0 +1,50 @@
+module Links exposing (..)
+
+import Json.Decode
+ exposing
+ ( Decoder
+ , bool
+ , field
+ , int
+ , list
+ , map6
+ , string
+ )
+
+
+type alias Links =
+ List Link
+
+
+type alias NewLink =
+ { name : String
+ , url : String
+ , shared : Bool
+ , logo_url : String
+ }
+
+
+type alias Link =
+ { id : Int
+ , createdAt : String
+ , url : String
+ , name : String
+ , logoURL : String
+ , shared : Bool
+ }
+
+
+linkListDecoder : Decoder Links
+linkListDecoder =
+ list linkDecoder
+
+
+linkDecoder : Decoder Link
+linkDecoder =
+ map6 Link
+ (field "id" int)
+ (field "created_at" string)
+ (field "url" string)
+ (field "name" string)
+ (field "logo_url" string)
+ (field "shared" bool)
diff --git a/src/Main.elm b/src/Main.elm
index 08a6231..b635400 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -2,63 +2,25 @@ module Main exposing (..)
import Browser
import Html exposing (..)
-import Html.Attributes exposing (checked, class, classList, href, name, placeholder, src, type_, value)
+import Html.Attributes
+ exposing
+ ( checked
+ , class
+ , classList
+ , href
+ , name
+ , placeholder
+ , src
+ , type_
+ , value
+ )
import Html.Events exposing (..)
import Http
-import Json.Decode as Decode
- exposing
- ( Decoder
- , bool
- , field
- , int
- , list
- , map5
- , map6
- , string
- )
+import Ignores
import Json.Encode as Encode
-
-
-type alias Watches =
- List Watch
-
-
-type alias Links =
- List Link
-
-
-type alias Link =
- { id : Int
- , createdAt : String
- , url : String
- , name : String
- , logoURL : String
- , shared : Bool
- }
-
-
-type alias Watch =
- { id : Int
- , ownerId : Int
- , name : String
- , repo : String
- , resultCount : Int
- , results : List Node
- }
-
-
-type alias Node =
- { number : Int
- , createdAt : String
- , repository : RepoInfo
- , title : String
- , url : String
- }
-
-
-type alias RepoInfo =
- { nameWithOwner : String
- }
+import Links
+import Table exposing (defaultCustomizations)
+import Watches
main : Program () Model Msg
@@ -78,49 +40,47 @@ type Msg
| DeleteLink Int
| DeletedWatch (Result Http.Error ())
| DeleteWatch Int
- | GotLinks (Result Http.Error (List Link))
- | GotNewLink NewLink
- | GotNewWatch NewWatch
- | GotWatches (Result Http.Error (List Watch))
+ | DeletedIgnore (Result Http.Error ())
+ | DeleteIgnore Int
+ | GotLinks (Result Http.Error Links.Links)
+ | GotNewLink Links.NewLink
+ | GotNewWatch Watches.NewWatch
+ | GotWatches (Result Http.Error Watches.Watches)
+ | GotIgnores (Result Http.Error Ignores.Ignores)
| HideWatchedItem Int String
| HidItem (Result Http.Error ())
| Reload
| ReloadLinks
| ReloadWatches
+ | ReloadIgnores
| SubmitLink
| SubmitWatch
| FetchIcons
| LoadIcons (Result Http.Error ())
+ | SetLinkTableState Table.State
+ | SetWatchTableState Table.State
+ | SetIgnoreTableState Table.State
type Status
= Loading
- | LoadedWatches (List Watch)
- | LoadedLinks (List Link)
+ | LoadedWatches Watches.Watches
+ | LoadedIgnores Ignores.Ignores
+ | LoadedLinks Links.Links
| Errored String
-type alias NewWatch =
- { name : String
- , repo : String
- }
-
-
-type alias NewLink =
- { name : String
- , url : String
- , shared : Bool
- , logo_url : String
- }
-
-
type alias Model =
- { watches : List Watch
- , links : List Link
+ { watches : Watches.Watches
+ , links : Links.Links
+ , ignores : Ignores.Ignores
, errors : List String
, status : Status
- , newlink : NewLink
- , newwatch : NewWatch
+ , newlink : Links.NewLink
+ , newwatch : Watches.NewWatch
+ , linkTableState : Table.State
+ , watchTableState : Table.State
+ , ignoreTableState : Table.State
}
@@ -128,6 +88,7 @@ initialModel : Model
initialModel =
{ watches = []
, links = []
+ , ignores = []
, errors = []
, status = Loading
, newlink =
@@ -140,12 +101,15 @@ initialModel =
{ name = ""
, repo = ""
}
+ , linkTableState = Table.initialSort "Created"
+ , watchTableState = Table.initialSort "Created"
+ , ignoreTableState = Table.initialSort "Created"
}
init : () -> ( Model, Cmd Msg )
init _ =
- ( initialModel, Cmd.batch [ getLinks, getWatches ] )
+ ( initialModel, Cmd.batch [ getLinks, getWatches, getIgnores ] )
hideWatched : Int -> String -> Cmd Msg
@@ -222,6 +186,19 @@ deleteLink linkId =
}
+deleteIgnore : Int -> Cmd Msg
+deleteIgnore ignoreId =
+ Http.request
+ { url = "/prignores/" ++ String.fromInt ignoreId
+ , method = "DELETE"
+ , timeout = Nothing
+ , tracker = Nothing
+ , headers = []
+ , body = Http.emptyBody
+ , expect = Http.expectWhatever DeletedIgnore
+ }
+
+
deleteWatch : Int -> Cmd Msg
deleteWatch watchId =
Http.request
@@ -253,6 +230,9 @@ update msg model =
DeleteWatch watchId ->
( model, deleteWatch watchId )
+ DeleteIgnore ignoreId ->
+ ( model, deleteIgnore ignoreId )
+
GotNewWatch newwatch ->
( { model | newwatch = newwatch }, Cmd.none )
@@ -283,6 +263,12 @@ update msg model =
DeletedWatch (Err _) ->
( { model | status = Errored "Server error deleting watch!" }, Cmd.none )
+ DeletedIgnore (Ok _) ->
+ ( model, getIgnores )
+
+ DeletedIgnore (Err _) ->
+ ( { model | status = Errored "Server error deleting ignore!" }, Cmd.none )
+
HidItem (Err _) ->
( { model | status = Errored "Server error when hiding a watch item!" }, Cmd.none )
@@ -307,12 +293,18 @@ update msg model =
ReloadLinks ->
( model, getLinks )
+ ReloadIgnores ->
+ ( model, getIgnores )
+
GotWatches (Err _) ->
( { model | status = Errored "Server error when fetching watches!" }, Cmd.none )
GotLinks (Err _) ->
( { model | status = Errored "Server error when fetching links!" }, Cmd.none )
+ GotIgnores (Err _) ->
+ ( { model | status = Errored "Server error when fetching ignores!" }, Cmd.none )
+
GotWatches (Ok watches) ->
case watches of
_ :: _ ->
@@ -340,6 +332,28 @@ update msg model =
[] ->
( { model | status = Errored "No Links found" }, Cmd.none )
+ GotIgnores (Ok ignores) ->
+ case ignores of
+ _ :: _ ->
+ ( { model
+ | ignores = ignores
+ , status = LoadedIgnores ignores
+ }
+ , Cmd.none
+ )
+
+ [] ->
+ ( { model | status = Errored "No Watches found" }, Cmd.none )
+
+ SetLinkTableState newState ->
+ ( { model | linkTableState = newState }, Cmd.none )
+
+ SetWatchTableState newState ->
+ ( { model | watchTableState = newState }, Cmd.none )
+
+ SetIgnoreTableState newState ->
+ ( { model | ignoreTableState = newState }, Cmd.none )
+
subscriptions : Model -> Sub Msg
subscriptions _ =
@@ -381,18 +395,181 @@ view model =
, footer []
[ details []
[ summary []
- [ b [] [ text "Maintenence" ] ]
- , button [ onClick FetchIcons ] [ text "Update Icons" ]
+ [ b [] [ text "Maintenence" ]
+ ]
+ , div []
+ [ button [ onClick FetchIcons ] [ text "Update Icons" ]
+ ]
+ , div []
+ [ h3 [] [ text "Links" ]
+ , Table.view linkTableConfig model.linkTableState model.links
+ ]
+ , div []
+ [ h3 [] [ text "Watched Items" ]
+ , Table.view watchTableConfig model.watchTableState model.watches
+ ]
+ , div []
+ [ h3
+ []
+ [ text "Watched Items Ignores" ]
+ , Table.view ignoreTableConfig model.ignoreTableState model.ignores
+ ]
]
]
]
+shareTxt : Links.Link -> Table.HtmlDetails Msg
+shareTxt link =
+ if link.shared then
+ Table.HtmlDetails []
+ [ text "Yes" ]
+
+ else
+ Table.HtmlDetails []
+ [ text "No" ]
+
+
+shareColumn : Table.Column Links.Link Msg
+shareColumn =
+ Table.veryCustomColumn
+ { name = "Shared"
+ , viewData = \data -> shareTxt data
+ , sorter = Table.unsortable
+ }
+
+
+linkTimeColumn : Table.Column Links.Link Msg
+linkTimeColumn =
+ Table.customColumn
+ { name = "Created"
+ , viewData = .createdAt
+ , sorter = Table.decreasingOrIncreasingBy .createdAt
+ }
+
+
+deleteLinkColumn : Table.Column Links.Link Msg
+deleteLinkColumn =
+ Table.veryCustomColumn
+ { name = "Action"
+ , viewData = linkDeleteView
+ , sorter = Table.unsortable
+ }
+
+
+linkTableConfig : Table.Config Links.Link Msg
+linkTableConfig =
+ Table.customConfig
+ { toId = .name
+ , toMsg = SetLinkTableState
+ , columns =
+ [ Table.stringColumn "Name" .name
+ , Table.stringColumn "URL" .url
+ , shareColumn
+ , Table.stringColumn "Logo URL" .logoURL
+ , linkTimeColumn
+ , deleteLinkColumn
+ ]
+ , customizations = defaultCustomizations
+ }
+
+
+linkDeleteView : Links.Link -> Table.HtmlDetails Msg
+linkDeleteView { id } =
+ Table.HtmlDetails []
+ [ button
+ [ onClick (DeleteLink id) ]
+ [ text "Delete" ]
+ ]
+
+
+watchTableConfig : Table.Config Watches.Watch Msg
+watchTableConfig =
+ Table.config
+ { toId = .name
+ , toMsg = SetWatchTableState
+ , columns =
+ [ Table.stringColumn "Name" .name
+ , Table.stringColumn "Repo" .repo
+ , deleteWatchColumn
+ ]
+ }
+
+
+deleteWatchColumn : Table.Column Watches.Watch Msg
+deleteWatchColumn =
+ Table.veryCustomColumn
+ { name = "Action"
+ , viewData = watchDeleteView
+ , sorter = Table.unsortable
+ }
+
+
+watchDeleteView : Watches.Watch -> Table.HtmlDetails Msg
+watchDeleteView { id } =
+ Table.HtmlDetails []
+ [ button
+ [ onClick (DeleteWatch id) ]
+ [ text "Delete" ]
+ ]
+
+
+ignoreTimeColumn : Table.Column Ignores.Ignore Msg
+ignoreTimeColumn =
+ Table.customColumn
+ { name = "Created"
+ , viewData = .createdAt
+ , sorter = Table.decreasingOrIncreasingBy .createdAt
+ }
+
+
+deleteIgnoreColumn : Table.Column Ignores.Ignore Msg
+deleteIgnoreColumn =
+ Table.veryCustomColumn
+ { name = "Action"
+ , viewData = ignoreDeleteView
+ , sorter = Table.unsortable
+ }
+
+
+ignoreDeleteView : Ignores.Ignore -> Table.HtmlDetails Msg
+ignoreDeleteView { id } =
+ Table.HtmlDetails []
+ [ button
+ [ onClick (DeleteIgnore id) ]
+ [ text "Delete" ]
+ ]
+
+
+ignoreTableConfig : Table.Config Ignores.Ignore Msg
+ignoreTableConfig =
+ Table.customConfig
+ { toId = .createdAt
+ , toMsg = SetIgnoreTableState
+ , columns =
+ [ Table.intColumn "ID" .id
+ , Table.stringColumn "Repo" .repo
+ , Table.intColumn "Number" .number
+ , ignoreTimeColumn
+ , deleteIgnoreColumn
+ ]
+ , customizations = defaultCustomizations
+ }
+
+
+getIgnores : Cmd Msg
+getIgnores =
+ Http.get
+ { url = "/prignores"
+ , expect = Http.expectJson GotIgnores Ignores.ignoreListDecoder
+ }
+
+
getLinks : Cmd Msg
getLinks =
Http.get
{ url = "/links"
- , expect = Http.expectJson GotLinks linkListDecoder
+ , expect = Http.expectJson GotLinks Links.linkListDecoder
}
@@ -400,11 +577,11 @@ getWatches : Cmd Msg
getWatches =
Http.get
{ url = "/watches"
- , expect = Http.expectJson GotWatches watchListDecoder
+ , expect = Http.expectJson GotWatches Watches.watchListDecoder
}
-watchForm : Model -> NewWatch -> Html Msg
+watchForm : Model -> Watches.NewWatch -> Html Msg
watchForm model newwatch =
div []
[ createForm "Watches"
@@ -418,7 +595,7 @@ watchForm model newwatch =
]
-linkForm : Model -> NewLink -> Html Msg
+linkForm : Model -> Links.NewLink -> Html Msg
linkForm model newlink =
div []
[ createForm "Links"
@@ -514,7 +691,7 @@ viewWatches model =
]
-viewLink : Link -> Html Msg
+viewLink : Links.Link -> Html Msg
viewLink link =
div []
[ div [ class "icon" ]
@@ -532,7 +709,7 @@ viewLink link =
]
-viewWatch : Watch -> Html Msg
+viewWatch : Watches.Watch -> Html Msg
viewWatch watch =
case watch.results of
[] ->
@@ -555,7 +732,7 @@ viewWatch watch =
]
-viewResult : Node -> Html Msg
+viewResult : Watches.Node -> Html Msg
viewResult node =
li []
[ a [ href node.url ] [ text (String.fromInt node.number) ]
@@ -564,55 +741,3 @@ viewResult node =
, text " :: "
, text node.title
]
-
-
-
--- DECODERS
-
-
-linkListDecoder : Decoder (List Link)
-linkListDecoder =
- list linkDecoder
-
-
-linkDecoder : Decoder Link
-linkDecoder =
- map6 Link
- (field "id" int)
- (field "created_at" string)
- (field "url" string)
- (field "name" string)
- (field "logo_url" string)
- (field "shared" bool)
-
-
-watchListDecoder : Decoder (List Watch)
-watchListDecoder =
- list watchDecoder
-
-
-watchDecoder : Decoder Watch
-watchDecoder =
- map6 Watch
- (field "id" int)
- (field "owner_id" int)
- (field "name" string)
- (field "repo" string)
- (field "result_count" int)
- (field "results" <| list resultsDecoder)
-
-
-resultsDecoder : Decoder Node
-resultsDecoder =
- map5 Node
- (field "number" int)
- (field "createdAt" string)
- (field "repository" repoInfoDecoder)
- (field "title" string)
- (field "url" string)
-
-
-repoInfoDecoder : Decoder RepoInfo
-repoInfoDecoder =
- Decode.map RepoInfo
- (field "nameWithOwner" string)
diff --git a/src/Watches.elm b/src/Watches.elm
new file mode 100644
index 0000000..5d8bb33
--- /dev/null
+++ b/src/Watches.elm
@@ -0,0 +1,78 @@
+module Watches exposing (..)
+
+import Json.Decode as Decode
+ exposing
+ ( Decoder
+ , field
+ , int
+ , list
+ , map5
+ , map6
+ , string
+ )
+
+
+type alias NewWatch =
+ { name : String
+ , repo : String
+ }
+
+
+type alias Watches =
+ List Watch
+
+
+type alias Watch =
+ { id : Int
+ , ownerId : Int
+ , name : String
+ , repo : String
+ , resultCount : Int
+ , results : List Node
+ }
+
+
+type alias RepoInfo =
+ { nameWithOwner : String
+ }
+
+
+type alias Node =
+ { number : Int
+ , createdAt : String
+ , repository : RepoInfo
+ , title : String
+ , url : String
+ }
+
+
+watchListDecoder : Decoder Watches
+watchListDecoder =
+ list watchDecoder
+
+
+watchDecoder : Decoder Watch
+watchDecoder =
+ map6 Watch
+ (field "id" int)
+ (field "owner_id" int)
+ (field "name" string)
+ (field "repo" string)
+ (field "result_count" int)
+ (field "results" <| list resultsDecoder)
+
+
+resultsDecoder : Decoder Node
+resultsDecoder =
+ map5 Node
+ (field "number" int)
+ (field "createdAt" string)
+ (field "repository" repoInfoDecoder)
+ (field "title" string)
+ (field "url" string)
+
+
+repoInfoDecoder : Decoder RepoInfo
+repoInfoDecoder =
+ Decode.map RepoInfo
+ (field "nameWithOwner" string)