feature: remove sidebar & redesign top navbar
This commit is contained in:
parent
fd7c006b73
commit
57382de9d0
27
.tmuxinator.yml
Normal file
27
.tmuxinator.yml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: citadel
|
||||||
|
root: .
|
||||||
|
|
||||||
|
on_project_start: docker start test-db
|
||||||
|
|
||||||
|
windows:
|
||||||
|
- services:
|
||||||
|
root: ./
|
||||||
|
panes:
|
||||||
|
- api:
|
||||||
|
- cd api
|
||||||
|
- go run cmd/citadel/main.go
|
||||||
|
- yarn:
|
||||||
|
- cd web
|
||||||
|
- yarn start
|
||||||
|
- web/editor:
|
||||||
|
root: ./web
|
||||||
|
panes:
|
||||||
|
- vim src/index.tsx
|
||||||
|
- api/editor:
|
||||||
|
root: ./api
|
||||||
|
panes:
|
||||||
|
- vim cmd/citadel/main.go
|
||||||
|
- database:
|
||||||
|
root: ./api
|
||||||
|
panes:
|
||||||
|
- docker container exec -it test-db psql -U postgres citadel
|
@ -1,10 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "github.com/lib/pq"
|
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
_ "github.com/lib/pq"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/jordanknott/project-citadel/api/router"
|
"github.com/jordanknott/project-citadel/api/router"
|
||||||
@ -20,6 +20,10 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
db.SetMaxOpenConns(25)
|
||||||
|
db.SetMaxIdleConns(25)
|
||||||
|
db.SetConnMaxLifetime(5 * time.Minute)
|
||||||
|
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
fmt.Println("starting graphql server on http://localhost:3333")
|
fmt.Println("starting graphql server on http://localhost:3333")
|
||||||
fmt.Println("starting graphql playground on http://localhost:3333/__graphql")
|
fmt.Println("starting graphql playground on http://localhost:3333/__graphql")
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
// "context"
|
||||||
"fmt"
|
// "fmt"
|
||||||
"io/ioutil"
|
// "io/ioutil"
|
||||||
|
|
||||||
|
"github.com/jordan-wright/email"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
"net/smtp"
|
||||||
"github.com/jmoiron/sqlx"
|
// "github.com/jmoiron/sqlx"
|
||||||
"github.com/jordanknott/project-citadel/api/pg"
|
// "github.com/jordanknott/project-citadel/api/pg"
|
||||||
|
// "github.com/BurntSushi/toml"
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
// "github.com/jordanknott/project-citadel/api/router"
|
// "github.com/jordanknott/project-citadel/api/router"
|
||||||
// "time"
|
// "time"
|
||||||
)
|
)
|
||||||
@ -26,6 +26,14 @@ type colors struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
e := email.NewEmail()
|
||||||
|
e.From = "Jordan Knott <no-reply@citadel.com>"
|
||||||
|
e.To = []string{"jordan@jordanthedev.com"}
|
||||||
|
e.Subject = "Jordan Knott (@jordanthedev) invited you to join the team \"Paradox\" on Citadel"
|
||||||
|
e.Text = []byte("Text Body is, of course, supported!")
|
||||||
|
e.HTML = []byte("<h1>Fancy HTML is supported, too!</h1>")
|
||||||
|
e.Send("localhost:1025", smtp.PlainAuth("", "test@gmail.com", "password123", "localhost"))
|
||||||
// dur := time.Hour * 24 * 7 * 30
|
// dur := time.Hour * 24 * 7 * 30
|
||||||
// token, err := router.NewAccessTokenCustomExpiration("21345076-6423-4a00-a6bd-cd9f830e2764", dur)
|
// token, err := router.NewAccessTokenCustomExpiration("21345076-6423-4a00-a6bd-cd9f830e2764", dur)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
@ -33,23 +41,23 @@ func main() {
|
|||||||
// }
|
// }
|
||||||
// fmt.Println(token)
|
// fmt.Println(token)
|
||||||
|
|
||||||
fmt.Println("seeding database...")
|
// fmt.Println("seeding database...")
|
||||||
|
|
||||||
dat, err := ioutil.ReadFile("data/colors.toml")
|
// dat, err := ioutil.ReadFile("data/colors.toml")
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
var labelColors colors
|
// var labelColors colors
|
||||||
_, err = toml.Decode(string(dat), &labelColors)
|
// _, err = toml.Decode(string(dat), &labelColors)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
db, err := sqlx.Connect("postgres", "user=postgres password=test host=0.0.0.0 dbname=citadel sslmode=disable")
|
// db, err := sqlx.Connect("postgres", "user=postgres password=test host=0.0.0.0 dbname=citadel sslmode=disable")
|
||||||
repository := pg.NewRepository(db)
|
// repository := pg.NewRepository(db)
|
||||||
for _, color := range labelColors.Color {
|
// for _, color := range labelColors.Color {
|
||||||
fmt.Printf("%v\n", color)
|
// fmt.Printf("%v\n", color)
|
||||||
repository.CreateLabelColor(context.Background(), pg.CreateLabelColorParams{color.Name, color.Color, float64(color.Position)})
|
// repository.CreateLabelColor(context.Background(), pg.CreateLabelColorParams{color.Name, color.Color, float64(color.Position)})
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
8
api/docker-compose.yml
Normal file
8
api/docker-compose.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
mailhog:
|
||||||
|
image: mailhog/mailhog:latest
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 1025:1025
|
||||||
|
- 8025:8025
|
@ -5,17 +5,25 @@ go 1.13
|
|||||||
require (
|
require (
|
||||||
github.com/99designs/gqlgen v0.11.3
|
github.com/99designs/gqlgen v0.11.3
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/BurntSushi/toml v0.3.1
|
||||||
|
github.com/boyter/scc v2.12.0+incompatible // indirect
|
||||||
|
github.com/dbaggerman/cuba v0.3.2 // indirect
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/go-chi/chi v3.3.2+incompatible
|
github.com/go-chi/chi v3.3.2+incompatible
|
||||||
github.com/go-chi/cors v1.0.0
|
github.com/go-chi/cors v1.0.0
|
||||||
github.com/google/martian v2.1.0+incompatible
|
github.com/google/martian v2.1.0+incompatible
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
github.com/jmoiron/sqlx v1.2.0
|
github.com/jmoiron/sqlx v1.2.0
|
||||||
|
github.com/jordan-wright/email v0.0.0-20200602115436-fd8a7622303e
|
||||||
github.com/lib/pq v1.0.0
|
github.com/lib/pq v1.0.0
|
||||||
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
||||||
|
github.com/monochromegane/go-gitignore v0.0.0-20200525100937-58356a36e03f // indirect
|
||||||
github.com/pelletier/go-toml v1.8.0
|
github.com/pelletier/go-toml v1.8.0
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/sirupsen/logrus v1.4.2
|
github.com/sirupsen/logrus v1.4.2
|
||||||
|
github.com/spf13/cobra v1.0.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/urfave/cli v1.20.0 // indirect
|
github.com/urfave/cli v1.20.0 // indirect
|
||||||
github.com/vektah/gqlparser/v2 v2.0.1
|
github.com/vektah/gqlparser/v2 v2.0.1
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||||
|
golang.org/x/text v0.3.3 // indirect
|
||||||
)
|
)
|
||||||
|
129
api/go.sum
129
api/go.sum
@ -1,29 +1,64 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=
|
github.com/99designs/gqlgen v0.11.1 h1:QoSL8/AAJ2T3UOeQbdnBR32JcG4pO08+P/g5jdbFkUg=
|
||||||
github.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=
|
github.com/99designs/gqlgen v0.11.1/go.mod h1:vjFOyBZ7NwDl+GdSD4PFn7BQn5Fy7ohJwXn7Vk8zz+c=
|
||||||
github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4=
|
github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4=
|
||||||
github.com/99designs/gqlgen v0.11.3/go.mod h1:RgX5GRRdDWNkh4pBrdzNpNPFVsdoUFY2+adM6nb1N+4=
|
github.com/99designs/gqlgen v0.11.3/go.mod h1:RgX5GRRdDWNkh4pBrdzNpNPFVsdoUFY2+adM6nb1N+4=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||||
github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=
|
github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=
|
||||||
github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=
|
github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||||
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/boyter/scc v2.12.0+incompatible h1:Sxhi1Ry3gdreoaF0xEITQSdjR+pJT0cXHXhlDw5FHT0=
|
||||||
|
github.com/boyter/scc v2.12.0+incompatible/go.mod h1:VB5w4e0dahmIiKnpZ7LRh/sjauoY0BmCWjIzZcShNY0=
|
||||||
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dbaggerman/cuba v0.3.2 h1:6ZbQX3FNvkocR222YyoAIZ8wi4avrb7JcJkPvVI2AS4=
|
||||||
|
github.com/dbaggerman/cuba v0.3.2/go.mod h1:t9Oo05XRZGcjaVqsA/gFeNAOm7DYZYNhI17unI5FlwY=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-chi/chi v3.3.2+incompatible h1:uQNcQN3NsV1j4ANsPh42P4ew4t6rnRbJb8frvpp31qQ=
|
github.com/go-chi/chi v3.3.2+incompatible h1:uQNcQN3NsV1j4ANsPh42P4ew4t6rnRbJb8frvpp31qQ=
|
||||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||||
github.com/go-chi/cors v1.0.0 h1:e6x8k7uWbUwYs+aXDoiUzeQFT6l0cygBYyNhD7/1Tg0=
|
github.com/go-chi/cors v1.0.0 h1:e6x8k7uWbUwYs+aXDoiUzeQFT6l0cygBYyNhD7/1Tg0=
|
||||||
github.com/go-chi/cors v1.0.0/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I=
|
github.com/go-chi/cors v1.0.0/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
|
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
@ -32,12 +67,28 @@ github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB
|
|||||||
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
|
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
|
||||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||||
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/jordan-wright/email v0.0.0-20200602115436-fd8a7622303e h1:OGunVjqY7y4U4laftpEHv+mvZBlr7UGimJXKEGQtg48=
|
||||||
|
github.com/jordan-wright/email v0.0.0-20200602115436-fd8a7622303e/go.mod h1:Fy2gCFfZhay8jplf/Csj6cyH/oshQTkLQYZbKkcV+SY=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
@ -46,6 +97,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|||||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg=
|
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg=
|
||||||
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
@ -53,16 +105,39 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
|||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
|
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
|
||||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
|
||||||
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=
|
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/monochromegane/go-gitignore v0.0.0-20200525100937-58356a36e03f h1:0HN0GKijN4mr9SmYoW/Ni3ozuNeHiSxo2s7drhv7obY=
|
||||||
|
github.com/monochromegane/go-gitignore v0.0.0-20200525100937-58356a36e03f/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
|
github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
|
||||||
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
|
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
@ -71,14 +146,30 @@ github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJ
|
|||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||||
|
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
|
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
|
||||||
@ -87,15 +178,36 @@ github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWp
|
|||||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||||
github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=
|
github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=
|
||||||
github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=
|
github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=
|
||||||
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -104,18 +216,35 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtD
|
|||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=
|
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=
|
||||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||||
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -59,6 +59,10 @@ type DeleteProjectPayload struct {
|
|||||||
Project *pg.Project `json:"project"`
|
Project *pg.Project `json:"project"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeleteTaskChecklist struct {
|
||||||
|
TaskChecklistID uuid.UUID `json:"taskChecklistID"`
|
||||||
|
}
|
||||||
|
|
||||||
type DeleteTaskChecklistItem struct {
|
type DeleteTaskChecklistItem struct {
|
||||||
TaskChecklistItemID uuid.UUID `json:"taskChecklistItemID"`
|
TaskChecklistItemID uuid.UUID `json:"taskChecklistItemID"`
|
||||||
}
|
}
|
||||||
@ -68,6 +72,11 @@ type DeleteTaskChecklistItemPayload struct {
|
|||||||
TaskChecklistItem *pg.TaskChecklistItem `json:"taskChecklistItem"`
|
TaskChecklistItem *pg.TaskChecklistItem `json:"taskChecklistItem"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeleteTaskChecklistPayload struct {
|
||||||
|
Ok bool `json:"ok"`
|
||||||
|
TaskChecklist *pg.TaskChecklist `json:"taskChecklist"`
|
||||||
|
}
|
||||||
|
|
||||||
type DeleteTaskGroupInput struct {
|
type DeleteTaskGroupInput struct {
|
||||||
TaskGroupID uuid.UUID `json:"taskGroupID"`
|
TaskGroupID uuid.UUID `json:"taskGroupID"`
|
||||||
}
|
}
|
||||||
@ -86,6 +95,25 @@ type DeleteTaskPayload struct {
|
|||||||
TaskID string `json:"taskID"`
|
TaskID string `json:"taskID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeleteTeam struct {
|
||||||
|
TeamID uuid.UUID `json:"teamID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteTeamPayload struct {
|
||||||
|
Ok bool `json:"ok"`
|
||||||
|
Team *pg.Team `json:"team"`
|
||||||
|
Projects []pg.Project `json:"projects"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteUserAccount struct {
|
||||||
|
UserID uuid.UUID `json:"userID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteUserAccountPayload struct {
|
||||||
|
Ok bool `json:"ok"`
|
||||||
|
UserAccount *pg.UserAccount `json:"userAccount"`
|
||||||
|
}
|
||||||
|
|
||||||
type FindProject struct {
|
type FindProject struct {
|
||||||
ProjectID string `json:"projectId"`
|
ProjectID string `json:"projectId"`
|
||||||
}
|
}
|
||||||
@ -94,6 +122,10 @@ type FindTask struct {
|
|||||||
TaskID uuid.UUID `json:"taskID"`
|
TaskID uuid.UUID `json:"taskID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FindTeam struct {
|
||||||
|
TeamID uuid.UUID `json:"teamID"`
|
||||||
|
}
|
||||||
|
|
||||||
type FindUser struct {
|
type FindUser struct {
|
||||||
UserID string `json:"userId"`
|
UserID string `json:"userId"`
|
||||||
}
|
}
|
||||||
@ -167,7 +199,7 @@ type ProjectMember struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProjectsFilter struct {
|
type ProjectsFilter struct {
|
||||||
TeamID *string `json:"teamID"`
|
TeamID *uuid.UUID `json:"teamID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveTaskLabelInput struct {
|
type RemoveTaskLabelInput struct {
|
||||||
@ -229,6 +261,11 @@ type UpdateTaskChecklistItemName struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateTaskChecklistName struct {
|
||||||
|
TaskChecklistID uuid.UUID `json:"taskChecklistID"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
type UpdateTaskDescriptionInput struct {
|
type UpdateTaskDescriptionInput struct {
|
||||||
TaskID uuid.UUID `json:"taskID"`
|
TaskID uuid.UUID `json:"taskID"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
|
@ -103,7 +103,7 @@ type Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input ProjectsFilter {
|
input ProjectsFilter {
|
||||||
teamID: String
|
teamID: UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
input FindUser {
|
input FindUser {
|
||||||
@ -123,6 +123,10 @@ type Organization {
|
|||||||
name: String!
|
name: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input FindTeam {
|
||||||
|
teamID: UUID!
|
||||||
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
organizations: [Organization!]!
|
organizations: [Organization!]!
|
||||||
users: [UserAccount!]!
|
users: [UserAccount!]!
|
||||||
@ -130,6 +134,7 @@ type Query {
|
|||||||
findProject(input: FindProject!): Project!
|
findProject(input: FindProject!): Project!
|
||||||
findTask(input: FindTask!): Task!
|
findTask(input: FindTask!): Task!
|
||||||
projects(input: ProjectsFilter): [Project!]!
|
projects(input: ProjectsFilter): [Project!]!
|
||||||
|
findTeam(input: FindTeam!): Team!
|
||||||
teams: [Team!]!
|
teams: [Team!]!
|
||||||
labelColors: [LabelColor!]!
|
labelColors: [LabelColor!]!
|
||||||
taskGroups: [TaskGroup!]!
|
taskGroups: [TaskGroup!]!
|
||||||
@ -356,11 +361,43 @@ type DeleteProjectPayload {
|
|||||||
project: Project!
|
project: Project!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input DeleteTeam {
|
||||||
|
teamID: UUID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteTeamPayload {
|
||||||
|
ok: Boolean!
|
||||||
|
team: Team!
|
||||||
|
projects: [Project!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
input DeleteUserAccount {
|
||||||
|
userID: UUID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteUserAccountPayload {
|
||||||
|
ok: Boolean!
|
||||||
|
userAccount: UserAccount!
|
||||||
|
}
|
||||||
|
|
||||||
|
input UpdateTaskChecklistName {
|
||||||
|
taskChecklistID: UUID!
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
input DeleteTaskChecklist {
|
||||||
|
taskChecklistID: UUID!
|
||||||
|
}
|
||||||
|
type DeleteTaskChecklistPayload {
|
||||||
|
ok: Boolean!
|
||||||
|
taskChecklist: TaskChecklist!
|
||||||
|
}
|
||||||
type Mutation {
|
type Mutation {
|
||||||
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
createRefreshToken(input: NewRefreshToken!): RefreshToken!
|
||||||
|
|
||||||
createUserAccount(input: NewUserAccount!): UserAccount!
|
createUserAccount(input: NewUserAccount!): UserAccount!
|
||||||
|
deleteUserAccount(input: DeleteUserAccount!): DeleteUserAccountPayload!
|
||||||
|
|
||||||
|
deleteTeam(input: DeleteTeam!): DeleteTeamPayload!
|
||||||
createTeam(input: NewTeam!): Team!
|
createTeam(input: NewTeam!): Team!
|
||||||
clearProfileAvatar: UserAccount!
|
clearProfileAvatar: UserAccount!
|
||||||
|
|
||||||
@ -386,6 +423,8 @@ type Mutation {
|
|||||||
toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
|
toggleTaskLabel(input: ToggleTaskLabelInput!): ToggleTaskLabelPayload!
|
||||||
|
|
||||||
createTaskChecklist(input: CreateTaskChecklist!): TaskChecklist!
|
createTaskChecklist(input: CreateTaskChecklist!): TaskChecklist!
|
||||||
|
deleteTaskChecklist(input: DeleteTaskChecklist!): DeleteTaskChecklistPayload!
|
||||||
|
updateTaskChecklistName(input: UpdateTaskChecklistName!): TaskChecklist!
|
||||||
createTaskChecklistItem(input: CreateTaskChecklistItem!): TaskChecklistItem!
|
createTaskChecklistItem(input: CreateTaskChecklistItem!): TaskChecklistItem!
|
||||||
updateTaskChecklistItemName(input: UpdateTaskChecklistItemName!): TaskChecklistItem!
|
updateTaskChecklistItemName(input: UpdateTaskChecklistItemName!): TaskChecklistItem!
|
||||||
setTaskChecklistItemComplete(input: SetTaskChecklistItemComplete!): TaskChecklistItem!
|
setTaskChecklistItemComplete(input: SetTaskChecklistItemComplete!): TaskChecklistItem!
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/jordanknott/project-citadel/api/pg"
|
"github.com/jordanknott/project-citadel/api/pg"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *labelColorResolver) ID(ctx context.Context, obj *pg.LabelColor) (uuid.UUID, error) {
|
func (r *labelColorResolver) ID(ctx context.Context, obj *pg.LabelColor) (uuid.UUID, error) {
|
||||||
@ -29,17 +30,54 @@ func (r *mutationResolver) CreateRefreshToken(ctx context.Context, input NewRefr
|
|||||||
|
|
||||||
func (r *mutationResolver) CreateUserAccount(ctx context.Context, input NewUserAccount) (*pg.UserAccount, error) {
|
func (r *mutationResolver) CreateUserAccount(ctx context.Context, input NewUserAccount) (*pg.UserAccount, error) {
|
||||||
createdAt := time.Now().UTC()
|
createdAt := time.Now().UTC()
|
||||||
|
hashedPwd, err := bcrypt.GenerateFromPassword([]byte(input.Password), 14)
|
||||||
|
if err != nil {
|
||||||
|
return &pg.UserAccount{}, err
|
||||||
|
}
|
||||||
userAccount, err := r.Repository.CreateUserAccount(ctx, pg.CreateUserAccountParams{
|
userAccount, err := r.Repository.CreateUserAccount(ctx, pg.CreateUserAccountParams{
|
||||||
FullName: input.FullName,
|
FullName: input.FullName,
|
||||||
Initials: input.Initials,
|
Initials: input.Initials,
|
||||||
Email: input.Email,
|
Email: input.Email,
|
||||||
Username: input.Username,
|
Username: input.Username,
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
PasswordHash: input.Password,
|
PasswordHash: string(hashedPwd),
|
||||||
})
|
})
|
||||||
return &userAccount, err
|
return &userAccount, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) DeleteUserAccount(ctx context.Context, input DeleteUserAccount) (*DeleteUserAccountPayload, error) {
|
||||||
|
user, err := r.Repository.GetUserAccountByID(ctx, input.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return &DeleteUserAccountPayload{Ok: false}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.Repository.DeleteUserAccountByID(ctx, input.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return &DeleteUserAccountPayload{Ok: false}, err
|
||||||
|
}
|
||||||
|
return &DeleteUserAccountPayload{UserAccount: &user, Ok: true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) DeleteTeam(ctx context.Context, input DeleteTeam) (*DeleteTeamPayload, error) {
|
||||||
|
team, err := r.Repository.GetTeamByID(ctx, input.TeamID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return &DeleteTeamPayload{Ok: false}, err
|
||||||
|
}
|
||||||
|
projects, err := r.Repository.GetAllProjectsForTeam(ctx, input.TeamID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return &DeleteTeamPayload{Ok: false}, err
|
||||||
|
}
|
||||||
|
err = r.Repository.DeleteTeamByID(ctx, input.TeamID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return &DeleteTeamPayload{Ok: false}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DeleteTeamPayload{Ok: true, Team: &team, Projects: projects}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) CreateTeam(ctx context.Context, input NewTeam) (*pg.Team, error) {
|
func (r *mutationResolver) CreateTeam(ctx context.Context, input NewTeam) (*pg.Team, error) {
|
||||||
createdAt := time.Now().UTC()
|
createdAt := time.Now().UTC()
|
||||||
team, err := r.Repository.CreateTeam(ctx, pg.CreateTeamParams{input.OrganizationID, createdAt, input.Name})
|
team, err := r.Repository.CreateTeam(ctx, pg.CreateTeamParams{input.OrganizationID, createdAt, input.Name})
|
||||||
@ -277,6 +315,26 @@ func (r *mutationResolver) CreateTaskChecklist(ctx context.Context, input Create
|
|||||||
return &taskChecklist, nil
|
return &taskChecklist, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) DeleteTaskChecklist(ctx context.Context, input DeleteTaskChecklist) (*DeleteTaskChecklistPayload, error) {
|
||||||
|
taskChecklist, err := r.Repository.GetTaskChecklistByID(ctx, input.TaskChecklistID)
|
||||||
|
if err != nil {
|
||||||
|
return &DeleteTaskChecklistPayload{Ok: false}, err
|
||||||
|
}
|
||||||
|
err = r.Repository.DeleteTaskChecklistByID(ctx, input.TaskChecklistID)
|
||||||
|
if err != nil {
|
||||||
|
return &DeleteTaskChecklistPayload{Ok: false}, err
|
||||||
|
}
|
||||||
|
return &DeleteTaskChecklistPayload{Ok: true, TaskChecklist: &taskChecklist}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) UpdateTaskChecklistName(ctx context.Context, input UpdateTaskChecklistName) (*pg.TaskChecklist, error) {
|
||||||
|
checklist, err := r.Repository.UpdateTaskChecklistName(ctx, pg.UpdateTaskChecklistNameParams{TaskChecklistID: input.TaskChecklistID, Name: input.Name})
|
||||||
|
if err != nil {
|
||||||
|
return &pg.TaskChecklist{}, err
|
||||||
|
}
|
||||||
|
return &checklist, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) CreateTaskChecklistItem(ctx context.Context, input CreateTaskChecklistItem) (*pg.TaskChecklistItem, error) {
|
func (r *mutationResolver) CreateTaskChecklistItem(ctx context.Context, input CreateTaskChecklistItem) (*pg.TaskChecklistItem, error) {
|
||||||
createdAt := time.Now().UTC()
|
createdAt := time.Now().UTC()
|
||||||
taskChecklistItem, err := r.Repository.CreateTaskChecklistItem(ctx, pg.CreateTaskChecklistItemParams{
|
taskChecklistItem, err := r.Repository.CreateTaskChecklistItem(ctx, pg.CreateTaskChecklistItemParams{
|
||||||
@ -475,6 +533,9 @@ func (r *projectResolver) TaskGroups(ctx context.Context, obj *pg.Project) ([]pg
|
|||||||
func (r *projectResolver) Members(ctx context.Context, obj *pg.Project) ([]ProjectMember, error) {
|
func (r *projectResolver) Members(ctx context.Context, obj *pg.Project) ([]ProjectMember, error) {
|
||||||
user, err := r.Repository.GetUserAccountByID(ctx, obj.Owner)
|
user, err := r.Repository.GetUserAccountByID(ctx, obj.Owner)
|
||||||
members := []ProjectMember{}
|
members := []ProjectMember{}
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return members, nil
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return members, err
|
return members, err
|
||||||
}
|
}
|
||||||
@ -561,15 +622,19 @@ func (r *queryResolver) FindTask(ctx context.Context, input FindTask) (*pg.Task,
|
|||||||
|
|
||||||
func (r *queryResolver) Projects(ctx context.Context, input *ProjectsFilter) ([]pg.Project, error) {
|
func (r *queryResolver) Projects(ctx context.Context, input *ProjectsFilter) ([]pg.Project, error) {
|
||||||
if input != nil {
|
if input != nil {
|
||||||
teamID, err := uuid.Parse(*input.TeamID)
|
return r.Repository.GetAllProjectsForTeam(ctx, *input.TeamID)
|
||||||
if err != nil {
|
|
||||||
return []pg.Project{}, err
|
|
||||||
}
|
|
||||||
return r.Repository.GetAllProjectsForTeam(ctx, teamID)
|
|
||||||
}
|
}
|
||||||
return r.Repository.GetAllProjects(ctx)
|
return r.Repository.GetAllProjects(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *queryResolver) FindTeam(ctx context.Context, input FindTeam) (*pg.Team, error) {
|
||||||
|
team, err := r.Repository.GetTeamByID(ctx, input.TeamID)
|
||||||
|
if err != nil {
|
||||||
|
return &pg.Team{}, err
|
||||||
|
}
|
||||||
|
return &team, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Teams(ctx context.Context) ([]pg.Team, error) {
|
func (r *queryResolver) Teams(ctx context.Context) ([]pg.Team, error) {
|
||||||
return r.Repository.GetAllTeams(ctx)
|
return r.Repository.GetAllTeams(ctx)
|
||||||
}
|
}
|
||||||
@ -727,6 +792,9 @@ func (r *teamResolver) ID(ctx context.Context, obj *pg.Team) (uuid.UUID, error)
|
|||||||
func (r *teamResolver) Members(ctx context.Context, obj *pg.Team) ([]ProjectMember, error) {
|
func (r *teamResolver) Members(ctx context.Context, obj *pg.Team) ([]ProjectMember, error) {
|
||||||
teamMembers, err := r.Repository.GetTeamMembersForTeamID(ctx, obj.TeamID)
|
teamMembers, err := r.Repository.GetTeamMembersForTeamID(ctx, obj.TeamID)
|
||||||
var projectMembers []ProjectMember
|
var projectMembers []ProjectMember
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return projectMembers, nil
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return projectMembers, err
|
return projectMembers, err
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
ALTER TABLE project DROP CONSTRAINT project_team_id_fkey;
|
||||||
|
ALTER TABLE project
|
||||||
|
ADD CONSTRAINT project_team_id_fkey
|
||||||
|
FOREIGN KEY (team_id)
|
||||||
|
REFERENCES team(team_id)
|
||||||
|
ON DELETE CASCADE;
|
@ -0,0 +1,6 @@
|
|||||||
|
ALTER TABLE task_assigned DROP CONSTRAINT task_assigned_user_id_fkey;
|
||||||
|
ALTER TABLE task_assigned
|
||||||
|
ADD CONSTRAINT task_assigned_user_id_fkey
|
||||||
|
FOREIGN KEY (user_id)
|
||||||
|
REFERENCES user_account(user_id)
|
||||||
|
ON DELETE CASCADE;
|
@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE refresh_token
|
||||||
|
ADD CONSTRAINT refresh_token_user_id_fkey
|
||||||
|
FOREIGN KEY (user_id)
|
||||||
|
REFERENCES user_account(user_id)
|
||||||
|
ON DELETE CASCADE;
|
@ -17,7 +17,11 @@ type Repository interface {
|
|||||||
GetAllTeams(ctx context.Context) ([]Team, error)
|
GetAllTeams(ctx context.Context) ([]Team, error)
|
||||||
|
|
||||||
DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error
|
DeleteProjectByID(ctx context.Context, projectID uuid.UUID) error
|
||||||
|
DeleteUserAccountByID(ctx context.Context, userID uuid.UUID) error
|
||||||
|
|
||||||
|
GetTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) (TaskChecklist, error)
|
||||||
|
DeleteTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) error
|
||||||
|
UpdateTaskChecklistName(ctx context.Context, arg UpdateTaskChecklistNameParams) (TaskChecklist, error)
|
||||||
CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error)
|
CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error)
|
||||||
GetAllProjects(ctx context.Context) ([]Project, error)
|
GetAllProjects(ctx context.Context) ([]Project, error)
|
||||||
GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
|
GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
|
||||||
|
@ -30,6 +30,7 @@ type Querier interface {
|
|||||||
DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
|
DeleteRefreshTokenByUserID(ctx context.Context, userID uuid.UUID) error
|
||||||
DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error)
|
DeleteTaskAssignedByID(ctx context.Context, arg DeleteTaskAssignedByIDParams) (TaskAssigned, error)
|
||||||
DeleteTaskByID(ctx context.Context, taskID uuid.UUID) error
|
DeleteTaskByID(ctx context.Context, taskID uuid.UUID) error
|
||||||
|
DeleteTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) error
|
||||||
DeleteTaskChecklistItem(ctx context.Context, taskChecklistItemID uuid.UUID) error
|
DeleteTaskChecklistItem(ctx context.Context, taskChecklistItemID uuid.UUID) error
|
||||||
DeleteTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
DeleteTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
||||||
DeleteTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) error
|
DeleteTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) error
|
||||||
@ -37,6 +38,7 @@ type Querier interface {
|
|||||||
DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) (int64, error)
|
||||||
DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
|
DeleteTeamByID(ctx context.Context, teamID uuid.UUID) error
|
||||||
DeleteTeamMemberByUserID(ctx context.Context, userID uuid.UUID) error
|
DeleteTeamMemberByUserID(ctx context.Context, userID uuid.UUID) error
|
||||||
|
DeleteUserAccountByID(ctx context.Context, userID uuid.UUID) error
|
||||||
GetAllOrganizations(ctx context.Context) ([]Organization, error)
|
GetAllOrganizations(ctx context.Context) ([]Organization, error)
|
||||||
GetAllProjects(ctx context.Context) ([]Project, error)
|
GetAllProjects(ctx context.Context) ([]Project, error)
|
||||||
GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
|
GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
|
||||||
@ -52,6 +54,7 @@ type Querier interface {
|
|||||||
GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error)
|
GetProjectLabelsForProject(ctx context.Context, projectID uuid.UUID) ([]ProjectLabel, error)
|
||||||
GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error)
|
GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error)
|
||||||
GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error)
|
GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error)
|
||||||
|
GetTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) (TaskChecklist, error)
|
||||||
GetTaskChecklistItemByID(ctx context.Context, taskChecklistItemID uuid.UUID) (TaskChecklistItem, error)
|
GetTaskChecklistItemByID(ctx context.Context, taskChecklistItemID uuid.UUID) (TaskChecklistItem, error)
|
||||||
GetTaskChecklistItemsForTaskChecklist(ctx context.Context, taskChecklistID uuid.UUID) ([]TaskChecklistItem, error)
|
GetTaskChecklistItemsForTaskChecklist(ctx context.Context, taskChecklistID uuid.UUID) ([]TaskChecklistItem, error)
|
||||||
GetTaskChecklistsForTask(ctx context.Context, taskID uuid.UUID) ([]TaskChecklist, error)
|
GetTaskChecklistsForTask(ctx context.Context, taskID uuid.UUID) ([]TaskChecklist, error)
|
||||||
@ -74,6 +77,7 @@ type Querier interface {
|
|||||||
UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error)
|
UpdateProjectLabelName(ctx context.Context, arg UpdateProjectLabelNameParams) (ProjectLabel, error)
|
||||||
UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error)
|
UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNameByIDParams) (Project, error)
|
||||||
UpdateTaskChecklistItemName(ctx context.Context, arg UpdateTaskChecklistItemNameParams) (TaskChecklistItem, error)
|
UpdateTaskChecklistItemName(ctx context.Context, arg UpdateTaskChecklistItemNameParams) (TaskChecklistItem, error)
|
||||||
|
UpdateTaskChecklistName(ctx context.Context, arg UpdateTaskChecklistNameParams) (TaskChecklist, error)
|
||||||
UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescriptionParams) (Task, error)
|
UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescriptionParams) (Task, error)
|
||||||
UpdateTaskDueDate(ctx context.Context, arg UpdateTaskDueDateParams) (Task, error)
|
UpdateTaskDueDate(ctx context.Context, arg UpdateTaskDueDateParams) (Task, error)
|
||||||
UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
|
UpdateTaskGroupLocation(ctx context.Context, arg UpdateTaskGroupLocationParams) (TaskGroup, error)
|
||||||
|
@ -72,6 +72,15 @@ func (q *Queries) CreateTaskChecklistItem(ctx context.Context, arg CreateTaskChe
|
|||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deleteTaskChecklistByID = `-- name: DeleteTaskChecklistByID :exec
|
||||||
|
DELETE FROM task_checklist WHERE task_checklist_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) DeleteTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, deleteTaskChecklistByID, taskChecklistID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
const deleteTaskChecklistItem = `-- name: DeleteTaskChecklistItem :exec
|
const deleteTaskChecklistItem = `-- name: DeleteTaskChecklistItem :exec
|
||||||
DELETE FROM task_checklist_item WHERE task_checklist_item_id = $1
|
DELETE FROM task_checklist_item WHERE task_checklist_item_id = $1
|
||||||
`
|
`
|
||||||
@ -81,6 +90,23 @@ func (q *Queries) DeleteTaskChecklistItem(ctx context.Context, taskChecklistItem
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getTaskChecklistByID = `-- name: GetTaskChecklistByID :one
|
||||||
|
SELECT task_checklist_id, task_id, created_at, name, position FROM task_checklist WHERE task_checklist_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetTaskChecklistByID(ctx context.Context, taskChecklistID uuid.UUID) (TaskChecklist, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, getTaskChecklistByID, taskChecklistID)
|
||||||
|
var i TaskChecklist
|
||||||
|
err := row.Scan(
|
||||||
|
&i.TaskChecklistID,
|
||||||
|
&i.TaskID,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.Name,
|
||||||
|
&i.Position,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
const getTaskChecklistItemByID = `-- name: GetTaskChecklistItemByID :one
|
const getTaskChecklistItemByID = `-- name: GetTaskChecklistItemByID :one
|
||||||
SELECT task_checklist_item_id, task_checklist_id, created_at, complete, name, position, due_date FROM task_checklist_item WHERE task_checklist_item_id = $1
|
SELECT task_checklist_item_id, task_checklist_id, created_at, complete, name, position, due_date FROM task_checklist_item WHERE task_checklist_item_id = $1
|
||||||
`
|
`
|
||||||
@ -217,3 +243,26 @@ func (q *Queries) UpdateTaskChecklistItemName(ctx context.Context, arg UpdateTas
|
|||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateTaskChecklistName = `-- name: UpdateTaskChecklistName :one
|
||||||
|
UPDATE task_checklist SET name = $2 WHERE task_checklist_id = $1
|
||||||
|
RETURNING task_checklist_id, task_id, created_at, name, position
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateTaskChecklistNameParams struct {
|
||||||
|
TaskChecklistID uuid.UUID `json:"task_checklist_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) UpdateTaskChecklistName(ctx context.Context, arg UpdateTaskChecklistNameParams) (TaskChecklist, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, updateTaskChecklistName, arg.TaskChecklistID, arg.Name)
|
||||||
|
var i TaskChecklist
|
||||||
|
err := row.Scan(
|
||||||
|
&i.TaskChecklistID,
|
||||||
|
&i.TaskID,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.Name,
|
||||||
|
&i.Position,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
@ -49,6 +49,15 @@ func (q *Queries) CreateUserAccount(ctx context.Context, arg CreateUserAccountPa
|
|||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deleteUserAccountByID = `-- name: DeleteUserAccountByID :exec
|
||||||
|
DELETE FROM user_account WHERE user_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) DeleteUserAccountByID(ctx context.Context, userID uuid.UUID) error {
|
||||||
|
_, err := q.db.ExecContext(ctx, deleteUserAccountByID, userID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
const getAllUserAccounts = `-- name: GetAllUserAccounts :many
|
const getAllUserAccounts = `-- name: GetAllUserAccounts :many
|
||||||
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url FROM user_account
|
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url FROM user_account
|
||||||
`
|
`
|
||||||
|
@ -5,6 +5,16 @@ INSERT INTO task_checklist (task_id, created_at, name, position) VALUES ($1, $2,
|
|||||||
-- name: GetTaskChecklistsForTask :many
|
-- name: GetTaskChecklistsForTask :many
|
||||||
SELECT * FROM task_checklist WHERE task_id = $1;
|
SELECT * FROM task_checklist WHERE task_id = $1;
|
||||||
|
|
||||||
|
-- name: UpdateTaskChecklistName :one
|
||||||
|
UPDATE task_checklist SET name = $2 WHERE task_checklist_id = $1
|
||||||
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: DeleteTaskChecklistByID :exec
|
||||||
|
DELETE FROM task_checklist WHERE task_checklist_id = $1;
|
||||||
|
|
||||||
|
-- name: GetTaskChecklistByID :one
|
||||||
|
SELECT * FROM task_checklist WHERE task_checklist_id = $1;
|
||||||
|
|
||||||
-- name: CreateTaskChecklistItem :one
|
-- name: CreateTaskChecklistItem :one
|
||||||
INSERT INTO task_checklist_item (task_checklist_id, created_at, name, position, complete, due_date) VALUES ($1, $2, $3, $4, false, null)
|
INSERT INTO task_checklist_item (task_checklist_id, created_at, name, position, complete, due_date) VALUES ($1, $2, $3, $4, false, null)
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
@ -14,3 +14,6 @@ INSERT INTO user_account(full_name, initials, email, username, created_at, passw
|
|||||||
-- name: UpdateUserAccountProfileAvatarURL :one
|
-- name: UpdateUserAccountProfileAvatarURL :one
|
||||||
UPDATE user_account SET profile_avatar_url = $2 WHERE user_id = $1
|
UPDATE user_account SET profile_avatar_url = $2 WHERE user_id = $1
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
|
||||||
|
-- name: DeleteUserAccountByID :exec
|
||||||
|
DELETE FROM user_account WHERE user_id = $1;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@apollo/client": "^3.0.0-rc.8",
|
||||||
"@apollo/react-common": "^3.1.4",
|
"@apollo/react-common": "^3.1.4",
|
||||||
"@apollo/react-hooks": "^3.1.3",
|
"@apollo/react-hooks": "^3.1.3",
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.27",
|
"@fortawesome/fontawesome-svg-core": "^1.2.27",
|
||||||
|
471
web/report.20200621.183857.68808.0.001.json
Normal file
471
web/report.20200621.183857.68808.0.001.json
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
|
||||||
|
{
|
||||||
|
"header": {
|
||||||
|
"reportVersion": 1,
|
||||||
|
"event": "Allocation failed - JavaScript heap out of memory",
|
||||||
|
"trigger": "FatalError",
|
||||||
|
"filename": "report.20200621.183857.68808.0.001.json",
|
||||||
|
"dumpEventTime": "2020-06-21T18:38:57Z",
|
||||||
|
"dumpEventTimeStamp": "1592782737343",
|
||||||
|
"processId": 68808,
|
||||||
|
"cwd": "/home/jordan/Projects/project-citadel/web",
|
||||||
|
"commandLine": [
|
||||||
|
"/usr/bin/node",
|
||||||
|
"/home/jordan/.config/coc/extensions/node_modules/coc-tsserver/bin/tsserverForkStart",
|
||||||
|
"/home/jordan/Projects/project-citadel/web/node_modules/typescript/lib/tsserver.js",
|
||||||
|
"--allowLocalPluginLoads",
|
||||||
|
"--useInferredProjectPerProjectRoot",
|
||||||
|
"--cancellationPipeName",
|
||||||
|
"/tmp/coc-nvim-tscancellation-49e6b7aafa04f6c486f4.sock*",
|
||||||
|
"--npmLocation",
|
||||||
|
"\"/usr/bin/npm\"",
|
||||||
|
"--noGetErrOnBackgroundUpdate",
|
||||||
|
"--validateDefaultNpmLocation"
|
||||||
|
],
|
||||||
|
"nodejsVersion": "v13.8.0",
|
||||||
|
"glibcVersionRuntime": "2.30",
|
||||||
|
"glibcVersionCompiler": "2.30",
|
||||||
|
"wordSize": 64,
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "linux",
|
||||||
|
"componentVersions": {
|
||||||
|
"node": "13.8.0",
|
||||||
|
"v8": "7.9.317.25-node.28",
|
||||||
|
"uv": "1.34.1",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"brotli": "1.0.7",
|
||||||
|
"ares": "1.15.0",
|
||||||
|
"modules": "79",
|
||||||
|
"nghttp2": "1.39.2",
|
||||||
|
"napi": "5",
|
||||||
|
"llhttp": "2.0.4",
|
||||||
|
"openssl": "1.1.1d",
|
||||||
|
"cldr": "36.0",
|
||||||
|
"icu": "65.1",
|
||||||
|
"tz": "2019c",
|
||||||
|
"unicode": "12.1"
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"name": "node",
|
||||||
|
"headersUrl": "https://nodejs.org/download/release/v13.8.0/node-v13.8.0-headers.tar.gz",
|
||||||
|
"sourceUrl": "https://nodejs.org/download/release/v13.8.0/node-v13.8.0.tar.gz"
|
||||||
|
},
|
||||||
|
"osName": "Linux",
|
||||||
|
"osRelease": "4.19.101-1-lts",
|
||||||
|
"osVersion": "#1 SMP Sat, 01 Feb 2020 16:35:36 +0000",
|
||||||
|
"osMachine": "x86_64",
|
||||||
|
"cpus": [
|
||||||
|
{
|
||||||
|
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||||
|
"speed": 2646,
|
||||||
|
"user": 48577700,
|
||||||
|
"nice": 14200,
|
||||||
|
"sys": 8014100,
|
||||||
|
"idle": 166454900,
|
||||||
|
"irq": 735500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||||
|
"speed": 2646,
|
||||||
|
"user": 48745100,
|
||||||
|
"nice": 19200,
|
||||||
|
"sys": 7840700,
|
||||||
|
"idle": 42737200,
|
||||||
|
"irq": 528800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||||
|
"speed": 2647,
|
||||||
|
"user": 48543900,
|
||||||
|
"nice": 15800,
|
||||||
|
"sys": 7804900,
|
||||||
|
"idle": 42914200,
|
||||||
|
"irq": 530200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz",
|
||||||
|
"speed": 2726,
|
||||||
|
"user": 48996200,
|
||||||
|
"nice": 19900,
|
||||||
|
"sys": 7808300,
|
||||||
|
"idle": 42957300,
|
||||||
|
"irq": 390800
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"networkInterfaces": [
|
||||||
|
{
|
||||||
|
"name": "lo",
|
||||||
|
"internal": true,
|
||||||
|
"mac": "00:00:00:00:00:00",
|
||||||
|
"address": "127.0.0.1",
|
||||||
|
"netmask": "255.0.0.0",
|
||||||
|
"family": "IPv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wlp3s0",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "7c:b0:c2:fe:93:86",
|
||||||
|
"address": "192.168.43.5",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"family": "IPv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "docker0",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "02:42:13:a9:89:9d",
|
||||||
|
"address": "172.17.0.1",
|
||||||
|
"netmask": "255.255.0.0",
|
||||||
|
"family": "IPv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "br-e929893879ec",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "02:42:48:f4:23:30",
|
||||||
|
"address": "172.19.0.1",
|
||||||
|
"netmask": "255.255.0.0",
|
||||||
|
"family": "IPv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lo",
|
||||||
|
"internal": true,
|
||||||
|
"mac": "00:00:00:00:00:00",
|
||||||
|
"address": "::1",
|
||||||
|
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
|
||||||
|
"family": "IPv6",
|
||||||
|
"scopeid": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wlp3s0",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "7c:b0:c2:fe:93:86",
|
||||||
|
"address": "2600:100b:b000:9bf1:7eb0:c2ff:fefe:9386",
|
||||||
|
"netmask": "ffff:ffff:ffff:ffff::",
|
||||||
|
"family": "IPv6",
|
||||||
|
"scopeid": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wlp3s0",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "7c:b0:c2:fe:93:86",
|
||||||
|
"address": "fe80::7eb0:c2ff:fefe:9386",
|
||||||
|
"netmask": "ffff:ffff:ffff:ffff::",
|
||||||
|
"family": "IPv6",
|
||||||
|
"scopeid": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "docker0",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "02:42:13:a9:89:9d",
|
||||||
|
"address": "fe80::42:13ff:fea9:899d",
|
||||||
|
"netmask": "ffff:ffff:ffff:ffff::",
|
||||||
|
"family": "IPv6",
|
||||||
|
"scopeid": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "veth79cfd83",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "a2:e9:86:a8:58:bb",
|
||||||
|
"address": "fe80::a0e9:86ff:fea8:58bb",
|
||||||
|
"netmask": "ffff:ffff:ffff:ffff::",
|
||||||
|
"family": "IPv6",
|
||||||
|
"scopeid": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "br-e929893879ec",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "02:42:48:f4:23:30",
|
||||||
|
"address": "fe80::42:48ff:fef4:2330",
|
||||||
|
"netmask": "ffff:ffff:ffff:ffff::",
|
||||||
|
"family": "IPv6",
|
||||||
|
"scopeid": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "vethe27cc3e",
|
||||||
|
"internal": false,
|
||||||
|
"mac": "c6:bd:d7:3b:6c:96",
|
||||||
|
"address": "fe80::c4bd:d7ff:fe3b:6c96",
|
||||||
|
"netmask": "ffff:ffff:ffff:ffff::",
|
||||||
|
"family": "IPv6",
|
||||||
|
"scopeid": 10
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"host": "archlinux"
|
||||||
|
},
|
||||||
|
"javascriptStack": {
|
||||||
|
"message": "No stack.",
|
||||||
|
"stack": [
|
||||||
|
"Unavailable."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nativeStack": [
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee1dae8a",
|
||||||
|
"symbol": "report::TriggerNodeReport(v8::Isolate*, node::Environment*, char const*, char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, v8::Local<v8::String>) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee09bd48",
|
||||||
|
"symbol": "node::OnFatalError(char const*, char const*) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee20f382",
|
||||||
|
"symbol": "v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee20f5e8",
|
||||||
|
"symbol": "v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee399906",
|
||||||
|
"symbol": " [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee399a49",
|
||||||
|
"symbol": " [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee3ac22d",
|
||||||
|
"symbol": "v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee3acf58",
|
||||||
|
"symbol": "v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee3af48c",
|
||||||
|
"symbol": "v8::internal::Heap::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee3af4f4",
|
||||||
|
"symbol": "v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee37499b",
|
||||||
|
"symbol": "v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee6a5540",
|
||||||
|
"symbol": "v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/usr/bin/node]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pc": "0x0000557aee9febd9",
|
||||||
|
"symbol": " [/usr/bin/node]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"javascriptHeap": {
|
||||||
|
"totalMemory": 2152407040,
|
||||||
|
"totalCommittedMemory": 2150546232,
|
||||||
|
"usedMemory": 2137632424,
|
||||||
|
"availableMemory": 47662336,
|
||||||
|
"memoryLimit": 2197815296,
|
||||||
|
"heapSpaces": {
|
||||||
|
"read_only_space": {
|
||||||
|
"memorySize": 262144,
|
||||||
|
"committedMemory": 33328,
|
||||||
|
"capacity": 33040,
|
||||||
|
"used": 33040,
|
||||||
|
"available": 0
|
||||||
|
},
|
||||||
|
"new_space": {
|
||||||
|
"memorySize": 2097152,
|
||||||
|
"committedMemory": 1029144,
|
||||||
|
"capacity": 1047424,
|
||||||
|
"used": 21136,
|
||||||
|
"available": 1026288
|
||||||
|
},
|
||||||
|
"old_space": {
|
||||||
|
"memorySize": 2058231808,
|
||||||
|
"committedMemory": 2057888048,
|
||||||
|
"capacity": 2048399928,
|
||||||
|
"used": 2048219560,
|
||||||
|
"available": 180368
|
||||||
|
},
|
||||||
|
"code_space": {
|
||||||
|
"memorySize": 9080832,
|
||||||
|
"committedMemory": 8864320,
|
||||||
|
"capacity": 7755264,
|
||||||
|
"used": 7755264,
|
||||||
|
"available": 0
|
||||||
|
},
|
||||||
|
"map_space": {
|
||||||
|
"memorySize": 1052672,
|
||||||
|
"committedMemory": 1048960,
|
||||||
|
"capacity": 740080,
|
||||||
|
"used": 740080,
|
||||||
|
"available": 0
|
||||||
|
},
|
||||||
|
"large_object_space": {
|
||||||
|
"memorySize": 81305600,
|
||||||
|
"committedMemory": 81305600,
|
||||||
|
"capacity": 80548528,
|
||||||
|
"used": 80548528,
|
||||||
|
"available": 0
|
||||||
|
},
|
||||||
|
"code_large_object_space": {
|
||||||
|
"memorySize": 376832,
|
||||||
|
"committedMemory": 376832,
|
||||||
|
"capacity": 314816,
|
||||||
|
"used": 314816,
|
||||||
|
"available": 0
|
||||||
|
},
|
||||||
|
"new_large_object_space": {
|
||||||
|
"memorySize": 0,
|
||||||
|
"committedMemory": 0,
|
||||||
|
"capacity": 1047424,
|
||||||
|
"used": 0,
|
||||||
|
"available": 1047424
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resourceUsage": {
|
||||||
|
"userCpuSeconds": 3484.11,
|
||||||
|
"kernelCpuSeconds": 64.7409,
|
||||||
|
"cpuConsumptionPercent": 35.606,
|
||||||
|
"maxRss": 2330890240,
|
||||||
|
"pageFaults": {
|
||||||
|
"IORequired": 31,
|
||||||
|
"IONotRequired": 9729381
|
||||||
|
},
|
||||||
|
"fsActivity": {
|
||||||
|
"reads": 53144,
|
||||||
|
"writes": 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uvthreadResourceUsage": {
|
||||||
|
"userCpuSeconds": 2308.89,
|
||||||
|
"kernelCpuSeconds": 31.2857,
|
||||||
|
"cpuConsumptionPercent": 23.4792,
|
||||||
|
"fsActivity": {
|
||||||
|
"reads": 53248,
|
||||||
|
"writes": 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libuv": [
|
||||||
|
],
|
||||||
|
"environmentVariables": {
|
||||||
|
"COLORTERM": "truecolor",
|
||||||
|
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
|
||||||
|
"DESKTOP_SESSION": "awesome",
|
||||||
|
"DISPLAY": ":0.0",
|
||||||
|
"EDITOR": "nano",
|
||||||
|
"FZF_DEFAULT_COMMAND": "ag --hidden --ignore .git -g \"\"",
|
||||||
|
"GDMSESSION": "awesome",
|
||||||
|
"GO111MODULE": "on",
|
||||||
|
"GOBIN": "/home/jordan/go/bin",
|
||||||
|
"GREP_COLOR": "37;45",
|
||||||
|
"GREP_COLORS": "mt=37;45",
|
||||||
|
"GTK_MODULES": "canberra-gtk-module",
|
||||||
|
"HOME": "/home/jordan",
|
||||||
|
"LANG": "C",
|
||||||
|
"LESS": "-F -g -i -M -R -S -w -X -z-4",
|
||||||
|
"LESS_TERMCAP_mb": "\u001b[01;31m",
|
||||||
|
"LESS_TERMCAP_md": "\u001b[01;31m",
|
||||||
|
"LESS_TERMCAP_me": "\u001b[0m",
|
||||||
|
"LESS_TERMCAP_se": "\u001b[0m",
|
||||||
|
"LESS_TERMCAP_so": "\u001b[00;47;30m",
|
||||||
|
"LESS_TERMCAP_ue": "\u001b[0m",
|
||||||
|
"LESS_TERMCAP_us": "\u001b[01;32m",
|
||||||
|
"LOGNAME": "jordan",
|
||||||
|
"LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:",
|
||||||
|
"MAIL": "/var/spool/mail/jordan",
|
||||||
|
"OLDPWD": "/home/jordan/Projects/project-citadel/web",
|
||||||
|
"PAGER": "less",
|
||||||
|
"PATH": "/home/jordan/.local/bin:/usr/local/bin:/usr/local/sbin:/home/nightwolf/Programs/cmake/bin:/home/nightwolf/Programs/idea-IU-163.13906.18/bin:/home/nightwolf/Programs/wpcli:/home/nightwolf/neovim/bin:/home/nightwolf/Programs/Postman:/home/nightwolf/Programs/Android_SDK/tools/bin:/home/nightwolf/Development/PhantomJS/bin:/home/nightwolf/Programs/node/bin:/home/nightwolf/pyenv/bin:/home/nightwolf/Programs/vv:/usr/bin:/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/usr/local/go/bin:/home/jordan/go/bin:/home/jordan/.garden/bin:~/Programs/node/bin:~/.utilities:/home/jordan/.fzf/bin:/home/jordan/.gem/ruby/2.6.0/bin:/home/jordan/.garden/bin:~/Programs/node/bin:~/.utilities:/home/jordan/.gem/ruby/2.6.0/bin",
|
||||||
|
"PWD": "/home/jordan/Projects/project-citadel/web",
|
||||||
|
"SHELL": "/usr/bin/zsh",
|
||||||
|
"SHLVL": "2",
|
||||||
|
"SSH_AGENT_PID": "773",
|
||||||
|
"SSH_AUTH_SOCK": "/tmp/ssh-agent.sock.1000",
|
||||||
|
"TERM": "xterm-256color",
|
||||||
|
"TMUX": "/tmp/tmux-1000/default,13203,1",
|
||||||
|
"TMUX_PANE": "%2",
|
||||||
|
"USER": "jordan",
|
||||||
|
"VIRTUALENVWRAPPER_PYTHON": "/usr/bin/python3",
|
||||||
|
"VIRTUAL_ENV_DISABLE_PROMPT": "12",
|
||||||
|
"VISUAL": "nano",
|
||||||
|
"VTE_VERSION": "5602",
|
||||||
|
"WINDOWID": "6291459",
|
||||||
|
"WORKON_HOME": "/home/jordan/.virtualenvs",
|
||||||
|
"XAUTHORITY": "/home/jordan/.Xauthority",
|
||||||
|
"XDG_GREETER_DATA_DIR": "/var/lib/lightdm-data/jordan",
|
||||||
|
"XDG_RUNTIME_DIR": "/run/user/1000",
|
||||||
|
"XDG_SEAT": "seat0",
|
||||||
|
"XDG_SEAT_PATH": "/org/freedesktop/DisplayManager/Seat0",
|
||||||
|
"XDG_SESSION_CLASS": "user",
|
||||||
|
"XDG_SESSION_DESKTOP": "awesome",
|
||||||
|
"XDG_SESSION_ID": "1",
|
||||||
|
"XDG_SESSION_PATH": "/org/freedesktop/DisplayManager/Session0",
|
||||||
|
"XDG_SESSION_TYPE": "x11",
|
||||||
|
"XDG_VTNR": "7",
|
||||||
|
"_": "/usr/bin/nvim",
|
||||||
|
"is_vim": "ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'",
|
||||||
|
"tmux_version": "$(tmux -V | sed -En \"s/^tmux ([0-9]+(.[0-9]+)?).*/\\1/p\")",
|
||||||
|
"LC_MESSAGES": "",
|
||||||
|
"VIMRUNTIME": "/usr/share/nvim/runtime",
|
||||||
|
"NVIM_LISTEN_ADDRESS": "/tmp/nvimaHxiZq/0",
|
||||||
|
"MYVIMRC": "/home/jordan/.config/nvim/init.vim",
|
||||||
|
"COC_VIMCONFIG": "/home/jordan/.config/nvim",
|
||||||
|
"COC_DATA_HOME": "/home/jordan/.config/coc",
|
||||||
|
"TSS_LOG": "-level verbose -file /tmp/coc-nvim-tsc.log",
|
||||||
|
"NODE_PATH": "/home/jordan/Projects/project-citadel/web/node_modules"
|
||||||
|
},
|
||||||
|
"userLimits": {
|
||||||
|
"core_file_size_blocks": {
|
||||||
|
"soft": "unlimited",
|
||||||
|
"hard": "unlimited"
|
||||||
|
},
|
||||||
|
"data_seg_size_kbytes": {
|
||||||
|
"soft": "unlimited",
|
||||||
|
"hard": "unlimited"
|
||||||
|
},
|
||||||
|
"file_size_blocks": {
|
||||||
|
"soft": "unlimited",
|
||||||
|
"hard": "unlimited"
|
||||||
|
},
|
||||||
|
"max_locked_memory_bytes": {
|
||||||
|
"soft": 65536,
|
||||||
|
"hard": 65536
|
||||||
|
},
|
||||||
|
"max_memory_size_kbytes": {
|
||||||
|
"soft": "unlimited",
|
||||||
|
"hard": "unlimited"
|
||||||
|
},
|
||||||
|
"open_files": {
|
||||||
|
"soft": 524288,
|
||||||
|
"hard": 524288
|
||||||
|
},
|
||||||
|
"stack_size_bytes": {
|
||||||
|
"soft": 8388608,
|
||||||
|
"hard": "unlimited"
|
||||||
|
},
|
||||||
|
"cpu_time_seconds": {
|
||||||
|
"soft": "unlimited",
|
||||||
|
"hard": "unlimited"
|
||||||
|
},
|
||||||
|
"max_user_processes": {
|
||||||
|
"soft": 31138,
|
||||||
|
"hard": 31138
|
||||||
|
},
|
||||||
|
"virtual_memory_kbytes": {
|
||||||
|
"soft": "unlimited",
|
||||||
|
"hard": "unlimited"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sharedObjects": [
|
||||||
|
"linux-vdso.so.1",
|
||||||
|
"/usr/lib/libz.so.1",
|
||||||
|
"/usr/lib/libcares.so.2",
|
||||||
|
"/usr/lib/libnghttp2.so.14",
|
||||||
|
"/usr/lib/libcrypto.so.1.1",
|
||||||
|
"/usr/lib/libssl.so.1.1",
|
||||||
|
"/usr/lib/libicui18n.so.65",
|
||||||
|
"/usr/lib/libicuuc.so.65",
|
||||||
|
"/usr/lib/libdl.so.2",
|
||||||
|
"/usr/lib/libstdc++.so.6",
|
||||||
|
"/usr/lib/libm.so.6",
|
||||||
|
"/usr/lib/libgcc_s.so.1",
|
||||||
|
"/usr/lib/libpthread.so.0",
|
||||||
|
"/usr/lib/libc.so.6",
|
||||||
|
"/usr/lib/libicudata.so.65",
|
||||||
|
"/lib64/ld-linux-x86-64.so.2"
|
||||||
|
]
|
||||||
|
}
|
158
web/src/Admin/index.tsx
Normal file
158
web/src/Admin/index.tsx
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import Admin from 'shared/components/Admin';
|
||||||
|
import GlobalTopNavbar from 'App/TopNavbar';
|
||||||
|
import { useUsersQuery, useCreateUserAccountMutation, UsersDocument } from 'shared/generated/graphql';
|
||||||
|
import Input from 'shared/components/Input';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import Button from 'shared/components/Button';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||||
|
import produce from 'immer';
|
||||||
|
|
||||||
|
type CreateUserData = {
|
||||||
|
email: string;
|
||||||
|
username: string;
|
||||||
|
fullName: string;
|
||||||
|
initials: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
const CreateUserForm = styled.form`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
`;
|
||||||
|
const CreateUserButton = styled(Button)`
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const AddUserInput = styled(Input)`
|
||||||
|
margin-bottom: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const InputError = styled.span`
|
||||||
|
color: rgba(${props => props.theme.colors.danger});
|
||||||
|
font-size: 12px;
|
||||||
|
`;
|
||||||
|
type AddUserPopupProps = {
|
||||||
|
onAddUser: (user: CreateUserData) => void;
|
||||||
|
};
|
||||||
|
const AddUserPopup: React.FC<AddUserPopupProps> = ({ onAddUser }) => {
|
||||||
|
const { register, handleSubmit, errors } = useForm<CreateUserData>();
|
||||||
|
const createUser = (data: CreateUserData) => {
|
||||||
|
onAddUser(data);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<CreateUserForm onSubmit={handleSubmit(createUser)}>
|
||||||
|
<AddUserInput
|
||||||
|
floatingLabel
|
||||||
|
width="100%"
|
||||||
|
label="Full Name"
|
||||||
|
id="fullName"
|
||||||
|
name="fullName"
|
||||||
|
variant="alternate"
|
||||||
|
ref={register({ required: 'Full name is required' })}
|
||||||
|
/>
|
||||||
|
{errors.fullName && <InputError>{errors.fullName.message}</InputError>}
|
||||||
|
<AddUserInput
|
||||||
|
floatingLabel
|
||||||
|
width="100%"
|
||||||
|
label="Email"
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
variant="alternate"
|
||||||
|
ref={register({ required: 'Email is required' })}
|
||||||
|
/>
|
||||||
|
{errors.email && <InputError>{errors.email.message}</InputError>}
|
||||||
|
<AddUserInput
|
||||||
|
floatingLabel
|
||||||
|
width="100%"
|
||||||
|
label="Username"
|
||||||
|
id="username"
|
||||||
|
name="username"
|
||||||
|
variant="alternate"
|
||||||
|
ref={register({ required: 'Username is required' })}
|
||||||
|
/>
|
||||||
|
{errors.username && <InputError>{errors.username.message}</InputError>}
|
||||||
|
<AddUserInput
|
||||||
|
floatingLabel
|
||||||
|
width="100%"
|
||||||
|
label="Initials"
|
||||||
|
id="initials"
|
||||||
|
name="initials"
|
||||||
|
variant="alternate"
|
||||||
|
ref={register({ required: 'Initials is required' })}
|
||||||
|
/>
|
||||||
|
{errors.initials && <InputError>{errors.initials.message}</InputError>}
|
||||||
|
<AddUserInput
|
||||||
|
floatingLabel
|
||||||
|
width="100%"
|
||||||
|
label="Password"
|
||||||
|
id="password"
|
||||||
|
name="password"
|
||||||
|
variant="alternate"
|
||||||
|
ref={register({ required: 'Password is required' })}
|
||||||
|
/>
|
||||||
|
{errors.password && <InputError>{errors.password.message}</InputError>}
|
||||||
|
<CreateUserButton type="submit">Create</CreateUserButton>
|
||||||
|
</CreateUserForm>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AdminRoute = () => {
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = 'Citadel | Admin';
|
||||||
|
}, []);
|
||||||
|
const { loading, data } = useUsersQuery();
|
||||||
|
const { showPopup, hidePopup } = usePopup();
|
||||||
|
const [createUser] = useCreateUserAccountMutation({
|
||||||
|
update: (client, createData) => {
|
||||||
|
const cacheData: any = client.readQuery({
|
||||||
|
query: UsersDocument,
|
||||||
|
});
|
||||||
|
console.log(cacheData);
|
||||||
|
console.log(createData);
|
||||||
|
const newData = produce(cacheData, (draftState: any) => {
|
||||||
|
draftState.users = [...draftState.users, { ...createData.data.createUserAccount }];
|
||||||
|
});
|
||||||
|
|
||||||
|
client.writeQuery({
|
||||||
|
query: UsersDocument,
|
||||||
|
data: {
|
||||||
|
...newData,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (loading) {
|
||||||
|
return <GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />;
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />
|
||||||
|
<Admin
|
||||||
|
initialTab={1}
|
||||||
|
users={data.users.map((user: any) => ({ ...user, role: 'TBD' }))}
|
||||||
|
onInviteUser={() => {}}
|
||||||
|
onAddUser={$target => {
|
||||||
|
showPopup(
|
||||||
|
$target,
|
||||||
|
<Popup tab={0} title="Add member" onClose={() => hidePopup()}>
|
||||||
|
<AddUserPopup
|
||||||
|
onAddUser={user => {
|
||||||
|
createUser({ variables: { ...user } });
|
||||||
|
hidePopup();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popup>,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <span>error</span>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AdminRoute;
|
@ -15,7 +15,7 @@ const GlobalNavbar = () => {
|
|||||||
<ButtonContainer>
|
<ButtonContainer>
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<ActionButton name="Home">
|
<ActionButton name="Home">
|
||||||
<Home size={28} color="#c2c6dc" />
|
<Home width={28} height={28} />
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/projects">
|
<Link to="/projects">
|
||||||
|
@ -3,14 +3,16 @@ import { Router, Switch, Route } from 'react-router-dom';
|
|||||||
import * as H from 'history';
|
import * as H from 'history';
|
||||||
|
|
||||||
import Dashboard from 'Dashboard';
|
import Dashboard from 'Dashboard';
|
||||||
|
import Admin from 'Admin';
|
||||||
import Projects from 'Projects';
|
import Projects from 'Projects';
|
||||||
import Project from 'Projects/Project';
|
import Project from 'Projects/Project';
|
||||||
|
import Teams from 'Teams';
|
||||||
import Login from 'Auth';
|
import Login from 'Auth';
|
||||||
import Profile from 'Profile';
|
import Profile from 'Profile';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const MainContent = styled.div`
|
const MainContent = styled.div`
|
||||||
padding: 0 0 0 80px;
|
padding: 0 0 0 0;
|
||||||
background: #262c49;
|
background: #262c49;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -28,7 +30,9 @@ const Routes = ({ history }: RoutesProps) => (
|
|||||||
<Route exact path="/" component={Dashboard} />
|
<Route exact path="/" component={Dashboard} />
|
||||||
<Route exact path="/projects" component={Projects} />
|
<Route exact path="/projects" component={Projects} />
|
||||||
<Route path="/projects/:projectID" component={Project} />
|
<Route path="/projects/:projectID" component={Project} />
|
||||||
|
<Route path="/teams/:teamID" component={Teams} />
|
||||||
<Route path="/profile" component={Profile} />
|
<Route path="/profile" component={Profile} />
|
||||||
|
<Route path="/admin" component={Admin} />
|
||||||
</MainContent>
|
</MainContent>
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
|
@ -1,24 +1,172 @@
|
|||||||
import React, { useState, useContext } from 'react';
|
import React, { useState, useContext, useEffect } from 'react';
|
||||||
import TopNavbar from 'shared/components/TopNavbar';
|
import TopNavbar from 'shared/components/TopNavbar';
|
||||||
|
import styled from 'styled-components/macro';
|
||||||
import DropdownMenu, { ProfileMenu } from 'shared/components/DropdownMenu';
|
import DropdownMenu, { ProfileMenu } from 'shared/components/DropdownMenu';
|
||||||
import ProjectSettings, { DeleteProject } from 'shared/components/ProjectSettings';
|
import ProjectSettings, { DeleteConfirm, DELETE_INFO } from 'shared/components/ProjectSettings';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
import UserIDContext from 'App/context';
|
import UserIDContext from 'App/context';
|
||||||
import { useMeQuery, useDeleteProjectMutation, GetProjectsDocument } from 'shared/generated/graphql';
|
import {
|
||||||
|
useMeQuery,
|
||||||
|
useDeleteProjectMutation,
|
||||||
|
useGetProjectsQuery,
|
||||||
|
GetProjectsDocument,
|
||||||
|
} from 'shared/generated/graphql';
|
||||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||||
|
import { History } from 'history';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
type GlobalTopNavbarProps = {
|
const TeamContainer = styled.div`
|
||||||
projectID: string | null;
|
display: flex;
|
||||||
name: string | null;
|
flex-direction: column;
|
||||||
projectMembers?: null | Array<TaskUser>;
|
`;
|
||||||
onSaveProjectName?: (projectName: string) => void;
|
|
||||||
|
const TeamTitle = styled.h3`
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TeamProjects = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TeamProjectLink = styled(Link)`
|
||||||
|
display: flex;
|
||||||
|
font-weight: 700;
|
||||||
|
height: 36px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
text-decoration: none;
|
||||||
|
user-select: none;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TeamProjectBackground = styled.div<{ color: string }>`
|
||||||
|
background-image: url(null);
|
||||||
|
background-color: ${props => props.color};
|
||||||
|
|
||||||
|
background-size: cover;
|
||||||
|
background-position: 50%;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 36px;
|
||||||
|
opacity: 1;
|
||||||
|
border-radius: 3px;
|
||||||
|
&:before {
|
||||||
|
background: rgba(${props => props.theme.colors.bg.secondary});
|
||||||
|
bottom: 0;
|
||||||
|
content: '';
|
||||||
|
left: 0;
|
||||||
|
opacity: 0.88;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TeamProjectAvatar = styled.div<{ color: string }>`
|
||||||
|
background-image: url(null);
|
||||||
|
background-color: ${props => props.color};
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
background-size: cover;
|
||||||
|
border-radius: 3px 0 0 3px;
|
||||||
|
height: 36px;
|
||||||
|
width: 36px;
|
||||||
|
position: relative;
|
||||||
|
opacity: 0.7;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TeamProjectContent = styled.div`
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
padding: 9px 0 9px 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TeamProjectTitle = styled.div`
|
||||||
|
font-weight: 700;
|
||||||
|
display: block;
|
||||||
|
padding-right: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TeamProjectContainer = styled.div`
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 3px;
|
||||||
|
position: relative;
|
||||||
|
margin: 0 4px 4px 0;
|
||||||
|
min-width: 0;
|
||||||
|
&:hover ${TeamProjectTitle} {
|
||||||
|
color: rgba(${props => props.theme.colors.text.secondary});
|
||||||
|
}
|
||||||
|
&:hover ${TeamProjectAvatar} {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
&:hover ${TeamProjectBackground}:before {
|
||||||
|
opacity: 0.78;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const colors = ['#e362e3', '#7a6ff0', '#37c5ab', '#aa62e3', '#e8384f'];
|
||||||
|
|
||||||
|
const ProjectFinder = () => {
|
||||||
|
const { loading, data } = useGetProjectsQuery();
|
||||||
|
if (loading) {
|
||||||
|
return <span>loading</span>;
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
const { projects, teams, organizations } = data;
|
||||||
|
const projectTeams = teams.map(team => {
|
||||||
|
return {
|
||||||
|
id: team.id,
|
||||||
|
name: team.name,
|
||||||
|
projects: projects.filter(project => project.team.id === team.id),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{projectTeams.map(team => (
|
||||||
|
<TeamContainer>
|
||||||
|
<TeamTitle>{team.name}</TeamTitle>
|
||||||
|
<TeamProjects>
|
||||||
|
{team.projects.map((project, idx) => (
|
||||||
|
<TeamProjectContainer>
|
||||||
|
<TeamProjectLink to={`/projects/${project.id}`}>
|
||||||
|
<TeamProjectBackground color={colors[idx % 5]} />
|
||||||
|
<TeamProjectAvatar color={colors[idx % 5]} />
|
||||||
|
<TeamProjectContent>
|
||||||
|
<TeamProjectTitle>{project.name}</TeamProjectTitle>
|
||||||
|
</TeamProjectContent>
|
||||||
|
</TeamProjectLink>
|
||||||
|
</TeamProjectContainer>
|
||||||
|
))}
|
||||||
|
</TeamProjects>
|
||||||
|
</TeamContainer>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <span>error</span>;
|
||||||
};
|
};
|
||||||
const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ projectID, name, projectMembers, onSaveProjectName }) => {
|
type ProjectPopupProps = {
|
||||||
const { loading, data } = useMeQuery();
|
history: History<History.PoorMansUnknown>;
|
||||||
const { showPopup, hidePopup, setTab } = usePopup();
|
name: string;
|
||||||
const history = useHistory();
|
projectID: string;
|
||||||
const { userID, setUserID } = useContext(UserIDContext);
|
};
|
||||||
|
|
||||||
|
export const ProjectPopup: React.FC<ProjectPopupProps> = ({ history, name, projectID }) => {
|
||||||
|
const { hidePopup, setTab } = usePopup();
|
||||||
const [deleteProject] = useDeleteProjectMutation({
|
const [deleteProject] = useDeleteProjectMutation({
|
||||||
update: (client, deleteData) => {
|
update: (client, deleteData) => {
|
||||||
const cacheData: any = client.readQuery({
|
const cacheData: any = client.readQuery({
|
||||||
@ -42,6 +190,62 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ projectID, name, proj
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Popup title={null} tab={0}>
|
||||||
|
<ProjectSettings
|
||||||
|
onDeleteProject={() => {
|
||||||
|
setTab(1);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popup>
|
||||||
|
<Popup title={`Delete the "${name}" project?`} tab={1}>
|
||||||
|
<DeleteConfirm
|
||||||
|
description={DELETE_INFO.DELETE_PROJECTS.description}
|
||||||
|
deletedItems={DELETE_INFO.DELETE_PROJECTS.deletedItems}
|
||||||
|
onConfirmDelete={() => {
|
||||||
|
if (projectID) {
|
||||||
|
deleteProject({ variables: { projectID } });
|
||||||
|
hidePopup();
|
||||||
|
history.push('/projects');
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popup>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type GlobalTopNavbarProps = {
|
||||||
|
nameOnly?: boolean;
|
||||||
|
projectID: string | null;
|
||||||
|
name: string | null;
|
||||||
|
initialTab?: number;
|
||||||
|
popupContent?: JSX.Element;
|
||||||
|
menuType?: Array<string>;
|
||||||
|
projectMembers?: null | Array<TaskUser>;
|
||||||
|
onSaveProjectName?: (projectName: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({
|
||||||
|
initialTab,
|
||||||
|
menuType,
|
||||||
|
projectID,
|
||||||
|
name,
|
||||||
|
popupContent,
|
||||||
|
projectMembers,
|
||||||
|
onSaveProjectName,
|
||||||
|
nameOnly,
|
||||||
|
}) => {
|
||||||
|
console.log(popupContent);
|
||||||
|
const { loading, data } = useMeQuery();
|
||||||
|
const { showPopup, hidePopup, setTab } = usePopup();
|
||||||
|
const history = useHistory();
|
||||||
|
const [currentTab, setCurrentTab] = useState(initialTab);
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentTab(initialTab);
|
||||||
|
}, [initialTab]);
|
||||||
|
const { userID, setUserID } = useContext(UserIDContext);
|
||||||
const onLogout = () => {
|
const onLogout = () => {
|
||||||
fetch('http://localhost:3333/auth/logout', {
|
fetch('http://localhost:3333/auth/logout', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -61,42 +265,26 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ projectID, name, proj
|
|||||||
<Popup title={null} tab={0}>
|
<Popup title={null} tab={0}>
|
||||||
<ProfileMenu
|
<ProfileMenu
|
||||||
onLogout={onLogout}
|
onLogout={onLogout}
|
||||||
|
onAdminConsole={() => {
|
||||||
|
history.push('/admin');
|
||||||
|
hidePopup();
|
||||||
|
}}
|
||||||
onProfile={() => {
|
onProfile={() => {
|
||||||
history.push('/profile');
|
history.push('/profile');
|
||||||
hidePopup();
|
hidePopup();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Popup>,
|
</Popup>,
|
||||||
185,
|
195,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOpenSettings = ($target: React.RefObject<HTMLElement>) => {
|
const onOpenSettings = ($target: React.RefObject<HTMLElement>) => {
|
||||||
showPopup(
|
console.log('maybe firing popup');
|
||||||
$target,
|
if (popupContent) {
|
||||||
<>
|
console.log('showing popup');
|
||||||
<Popup title={null} tab={0}>
|
showPopup($target, popupContent, 185);
|
||||||
<ProjectSettings
|
}
|
||||||
onDeleteProject={() => {
|
|
||||||
setTab(1, 325);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Popup>
|
|
||||||
<Popup title={`Delete the "${name}" project?`} tab={1}>
|
|
||||||
<DeleteProject
|
|
||||||
name={name ?? ''}
|
|
||||||
onDeleteProject={() => {
|
|
||||||
if (projectID) {
|
|
||||||
deleteProject({ variables: { projectID } });
|
|
||||||
hidePopup();
|
|
||||||
history.push('/projects');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Popup>
|
|
||||||
</>,
|
|
||||||
185,
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!userID) {
|
if (!userID) {
|
||||||
@ -105,12 +293,25 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({ projectID, name, proj
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TopNavbar
|
<TopNavbar
|
||||||
projectName={name}
|
name={name}
|
||||||
|
menuType={menuType}
|
||||||
|
onOpenProjectFinder={$target => {
|
||||||
|
showPopup(
|
||||||
|
$target,
|
||||||
|
<Popup tab={0} title={null}>
|
||||||
|
<ProjectFinder />
|
||||||
|
</Popup>,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
currentTab={currentTab}
|
||||||
user={data ? data.me : null}
|
user={data ? data.me : null}
|
||||||
onNotificationClick={() => {}}
|
onNotificationClick={() => {}}
|
||||||
|
onDashboardClick={() => {
|
||||||
|
history.push('/');
|
||||||
|
}}
|
||||||
projectMembers={projectMembers}
|
projectMembers={projectMembers}
|
||||||
onProfileClick={onProfileClick}
|
onProfileClick={onProfileClick}
|
||||||
onSaveProjectName={onSaveProjectName}
|
onSaveName={onSaveProjectName}
|
||||||
onOpenSettings={onOpenSettings}
|
onOpenSettings={onOpenSettings}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -41,20 +41,19 @@ const App = () => {
|
|||||||
<>
|
<>
|
||||||
<UserIDContext.Provider value={{ userID, setUserID }}>
|
<UserIDContext.Provider value={{ userID, setUserID }}>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<PopupProvider>
|
<NormalizeStyles />
|
||||||
<NormalizeStyles />
|
<BaseStyles />
|
||||||
<BaseStyles />
|
<Router history={history}>
|
||||||
<Router history={history}>
|
<PopupProvider>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div>loading</div>
|
<div>loading</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Navbar />
|
|
||||||
<Routes history={history} />
|
<Routes history={history} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Router>
|
</PopupProvider>
|
||||||
</PopupProvider>
|
</Router>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</UserIDContext.Provider>
|
</UserIDContext.Provider>
|
||||||
</>
|
</>
|
||||||
|
@ -5,6 +5,9 @@ import PopupMenu, { Popup, usePopup } from 'shared/components/PopupMenu';
|
|||||||
import MemberManager from 'shared/components/MemberManager';
|
import MemberManager from 'shared/components/MemberManager';
|
||||||
import { useRouteMatch, useHistory } from 'react-router';
|
import { useRouteMatch, useHistory } from 'react-router';
|
||||||
import {
|
import {
|
||||||
|
useDeleteTaskChecklistMutation,
|
||||||
|
useUpdateTaskChecklistNameMutation,
|
||||||
|
useCreateTaskChecklistMutation,
|
||||||
useFindTaskQuery,
|
useFindTaskQuery,
|
||||||
useUpdateTaskDueDateMutation,
|
useUpdateTaskDueDateMutation,
|
||||||
useSetTaskCompleteMutation,
|
useSetTaskCompleteMutation,
|
||||||
@ -20,6 +23,82 @@ import UserIDContext from 'App/context';
|
|||||||
import MiniProfile from 'shared/components/MiniProfile';
|
import MiniProfile from 'shared/components/MiniProfile';
|
||||||
import DueDateManager from 'shared/components/DueDateManager';
|
import DueDateManager from 'shared/components/DueDateManager';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import Button from 'shared/components/Button';
|
||||||
|
import Input from 'shared/components/Input';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
|
||||||
|
const calculateChecklistBadge = (draftState: any) => {
|
||||||
|
const total = draftState.checklists.reduce((prev: any, next: any) => {
|
||||||
|
return (
|
||||||
|
prev +
|
||||||
|
next.items.reduce((innerPrev: any, _item: any) => {
|
||||||
|
return innerPrev + 1;
|
||||||
|
}, 0)
|
||||||
|
);
|
||||||
|
}, 0);
|
||||||
|
const complete = draftState.checklists.reduce(
|
||||||
|
(prev: any, next: any) =>
|
||||||
|
prev +
|
||||||
|
next.items.reduce((innerPrev: any, item: any) => {
|
||||||
|
return innerPrev + (item.complete ? 1 : 0);
|
||||||
|
}, 0),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
return { total, complete };
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeleteChecklistButton = styled(Button)`
|
||||||
|
width: 100%;
|
||||||
|
padding: 6px 12px;
|
||||||
|
margin-top: 8px;
|
||||||
|
`;
|
||||||
|
type CreateChecklistData = {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
const CreateChecklistForm = styled.form`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CreateChecklistButton = styled(Button)`
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CreateChecklistInput = styled(Input)`
|
||||||
|
margin-bottom: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const InputError = styled.span`
|
||||||
|
color: rgba(${props => props.theme.colors.danger});
|
||||||
|
font-size: 12px;
|
||||||
|
`;
|
||||||
|
type CreateChecklistPopupProps = {
|
||||||
|
onCreateChecklist: (data: CreateChecklistData) => void;
|
||||||
|
};
|
||||||
|
const CreateChecklistPopup: React.FC<CreateChecklistPopupProps> = ({ onCreateChecklist }) => {
|
||||||
|
const { register, handleSubmit, errors } = useForm<CreateChecklistData>();
|
||||||
|
const createUser = (data: CreateChecklistData) => {
|
||||||
|
onCreateChecklist(data);
|
||||||
|
};
|
||||||
|
console.log(errors);
|
||||||
|
return (
|
||||||
|
<CreateChecklistForm onSubmit={handleSubmit(createUser)}>
|
||||||
|
<CreateChecklistInput
|
||||||
|
floatingLabel
|
||||||
|
width="100%"
|
||||||
|
label="Name"
|
||||||
|
id="name"
|
||||||
|
name="name"
|
||||||
|
variant="alternate"
|
||||||
|
ref={register({ required: 'Checklist name is required' })}
|
||||||
|
/>
|
||||||
|
<CreateChecklistButton type="submit">Create</CreateChecklistButton>
|
||||||
|
</CreateChecklistForm>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type DetailsProps = {
|
type DetailsProps = {
|
||||||
taskID: string;
|
taskID: string;
|
||||||
@ -50,8 +129,93 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
const match = useRouteMatch();
|
const match = useRouteMatch();
|
||||||
const [currentMemberTask, setCurrentMemberTask] = useState('');
|
const [currentMemberTask, setCurrentMemberTask] = useState('');
|
||||||
const [memberPopupData, setMemberPopupData] = useState(initialMemberPopupState);
|
const [memberPopupData, setMemberPopupData] = useState(initialMemberPopupState);
|
||||||
const [setTaskChecklistItemComplete] = useSetTaskChecklistItemCompleteMutation();
|
const [setTaskChecklistItemComplete] = useSetTaskChecklistItemCompleteMutation({
|
||||||
|
update: client => {
|
||||||
|
const cacheData: any = client.readQuery({
|
||||||
|
query: FindTaskDocument,
|
||||||
|
variables: { taskID },
|
||||||
|
});
|
||||||
|
const newData = produce(cacheData.findTask, (draftState: any) => {
|
||||||
|
const { complete, total } = calculateChecklistBadge(draftState);
|
||||||
|
if (!draftState.badges) {
|
||||||
|
draftState.badges = {
|
||||||
|
checklist: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
draftState.badges.checklist = {
|
||||||
|
__typename: 'ChecklistBadge',
|
||||||
|
complete,
|
||||||
|
total,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
client.writeQuery({
|
||||||
|
query: FindTaskDocument,
|
||||||
|
variables: { taskID },
|
||||||
|
data: {
|
||||||
|
findTask: newData,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const [deleteTaskChecklist] = useDeleteTaskChecklistMutation({
|
||||||
|
update: (client, deleteData) => {
|
||||||
|
const cacheData: any = client.readQuery({
|
||||||
|
query: FindTaskDocument,
|
||||||
|
variables: { taskID },
|
||||||
|
});
|
||||||
|
console.log(deleteData);
|
||||||
|
|
||||||
|
const newData = produce(cacheData.findTask, (draftState: any) => {
|
||||||
|
draftState.checklists = cacheData.findTask.checklists.filter(
|
||||||
|
(checklist: any) => checklist.id !== deleteData.data.deleteTaskChecklist.taskChecklist.id,
|
||||||
|
);
|
||||||
|
const { complete, total } = calculateChecklistBadge(draftState);
|
||||||
|
if (!draftState.badges) {
|
||||||
|
draftState.badges = {
|
||||||
|
checklist: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
draftState.badges.checklist = {
|
||||||
|
__typename: 'ChecklistBadge',
|
||||||
|
complete,
|
||||||
|
total,
|
||||||
|
};
|
||||||
|
if (complete === 0 && total === 0) {
|
||||||
|
draftState.badges.checklist = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
client.writeQuery({
|
||||||
|
query: FindTaskDocument,
|
||||||
|
variables: { taskID },
|
||||||
|
data: {
|
||||||
|
findTask: newData,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
const [updateTaskChecklistItemName] = useUpdateTaskChecklistItemNameMutation();
|
const [updateTaskChecklistItemName] = useUpdateTaskChecklistItemNameMutation();
|
||||||
|
const [createTaskChecklist] = useCreateTaskChecklistMutation({
|
||||||
|
update: (client, createData) => {
|
||||||
|
const cacheData: any = client.readQuery({
|
||||||
|
query: FindTaskDocument,
|
||||||
|
variables: { taskID },
|
||||||
|
});
|
||||||
|
console.log(createData);
|
||||||
|
|
||||||
|
const newData = {
|
||||||
|
findTask: {
|
||||||
|
...cacheData.findTask,
|
||||||
|
checklists: [...cacheData.findTask.checklists, { ...createData.data.createTaskChecklist }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
client.writeQuery({
|
||||||
|
query: FindTaskDocument,
|
||||||
|
variables: { taskID },
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const [updateTaskChecklistName] = useUpdateTaskChecklistNameMutation();
|
||||||
const [deleteTaskChecklistItem] = useDeleteTaskChecklistItemMutation({
|
const [deleteTaskChecklistItem] = useDeleteTaskChecklistItemMutation({
|
||||||
update: (client, deleteData) => {
|
update: (client, deleteData) => {
|
||||||
const cacheData: any = client.readQuery({
|
const cacheData: any = client.readQuery({
|
||||||
@ -69,6 +233,17 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
draftState.checklists[idx].items = cacheData.findTask.checklists[idx].items.filter(
|
draftState.checklists[idx].items = cacheData.findTask.checklists[idx].items.filter(
|
||||||
(item: any) => item.id !== deleteData.data.deleteTaskChecklistItem.taskChecklistItem.id,
|
(item: any) => item.id !== deleteData.data.deleteTaskChecklistItem.taskChecklistItem.id,
|
||||||
);
|
);
|
||||||
|
const { complete, total } = calculateChecklistBadge(draftState);
|
||||||
|
if (!draftState.badges) {
|
||||||
|
draftState.badges = {
|
||||||
|
checklist: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
draftState.badges.checklist = {
|
||||||
|
__typename: 'ChecklistBadge',
|
||||||
|
complete,
|
||||||
|
total,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
client.writeQuery({
|
client.writeQuery({
|
||||||
@ -97,8 +272,23 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
...cacheData.findTask.checklists[idx].items,
|
...cacheData.findTask.checklists[idx].items,
|
||||||
{ ...newTaskItem.data.createTaskChecklistItem },
|
{ ...newTaskItem.data.createTaskChecklistItem },
|
||||||
];
|
];
|
||||||
|
console.log(draftState.checklists.map((item: any) => item.items));
|
||||||
|
const { complete, total } = calculateChecklistBadge(draftState);
|
||||||
|
if (!draftState.badges) {
|
||||||
|
draftState.badges = {
|
||||||
|
checklist: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
draftState.badges.checklist = {
|
||||||
|
__typename: 'ChecklistBadge',
|
||||||
|
complete,
|
||||||
|
total,
|
||||||
|
};
|
||||||
|
console.log(draftState.badges.checklist);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(newData);
|
||||||
client.writeQuery({
|
client.writeQuery({
|
||||||
query: FindTaskDocument,
|
query: FindTaskDocument,
|
||||||
variables: { taskID },
|
variables: { taskID },
|
||||||
@ -156,11 +346,24 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
updateTaskChecklistItemName({ variables: { taskChecklistItemID: itemID, name: itemName } });
|
updateTaskChecklistItemName({ variables: { taskChecklistItemID: itemID, name: itemName } });
|
||||||
}}
|
}}
|
||||||
onCloseModal={() => history.push(projectURL)}
|
onCloseModal={() => history.push(projectURL)}
|
||||||
|
onChangeChecklistName={(checklistID, newName) => {
|
||||||
|
updateTaskChecklistName({ variables: { taskChecklistID: checklistID, name: newName } });
|
||||||
|
}}
|
||||||
onDeleteItem={itemID => {
|
onDeleteItem={itemID => {
|
||||||
deleteTaskChecklistItem({ variables: { taskChecklistItemID: itemID } });
|
deleteTaskChecklistItem({ variables: { taskChecklistItemID: itemID } });
|
||||||
}}
|
}}
|
||||||
onToggleChecklistItem={(itemID, complete) => {
|
onToggleChecklistItem={(itemID, complete) => {
|
||||||
setTaskChecklistItemComplete({ variables: { taskChecklistItemID: itemID, complete } });
|
setTaskChecklistItemComplete({
|
||||||
|
variables: { taskChecklistItemID: itemID, complete },
|
||||||
|
optimisticResponse: {
|
||||||
|
__typename: 'Mutation',
|
||||||
|
setTaskChecklistItemComplete: {
|
||||||
|
__typename: 'TaskChecklistItem',
|
||||||
|
id: itemID,
|
||||||
|
complete,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
onAddItem={(taskChecklistID, name, position) => {
|
onAddItem={(taskChecklistID, name, position) => {
|
||||||
createTaskChecklistItem({ variables: { taskChecklistID, name, position } });
|
createTaskChecklistItem({ variables: { taskChecklistID, name, position } });
|
||||||
@ -202,6 +405,57 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onOpenAddLabelPopup={onOpenAddLabelPopup}
|
onOpenAddLabelPopup={onOpenAddLabelPopup}
|
||||||
|
onOpenAddChecklistPopup={(_task, $target) => {
|
||||||
|
showPopup(
|
||||||
|
$target,
|
||||||
|
<Popup
|
||||||
|
title={'Add checklist'}
|
||||||
|
tab={0}
|
||||||
|
onClose={() => {
|
||||||
|
hidePopup();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CreateChecklistPopup
|
||||||
|
onCreateChecklist={checklistData => {
|
||||||
|
let position = 65535;
|
||||||
|
console.log(data.findTask.checklists);
|
||||||
|
if (data.findTask.checklists) {
|
||||||
|
const [lastChecklist] = data.findTask.checklists.slice(-1);
|
||||||
|
console.log(`lastCheclist ${lastChecklist}`);
|
||||||
|
if (lastChecklist) {
|
||||||
|
position = lastChecklist.position * 2 + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createTaskChecklist({
|
||||||
|
variables: {
|
||||||
|
taskID: data.findTask.id,
|
||||||
|
name: checklistData.name,
|
||||||
|
position,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
hidePopup();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popup>,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
onDeleteChecklist={($target, checklistID) => {
|
||||||
|
showPopup(
|
||||||
|
$target,
|
||||||
|
<Popup tab={0} title="Delete checklist?" onClose={() => hidePopup()}>
|
||||||
|
<p>Deleting a checklist is permanent and there is no way to get it back.</p>
|
||||||
|
<DeleteChecklistButton
|
||||||
|
color="danger"
|
||||||
|
onClick={() => {
|
||||||
|
deleteTaskChecklist({ variables: { taskChecklistID: checklistID } });
|
||||||
|
hidePopup();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Delete Checklist
|
||||||
|
</DeleteChecklistButton>
|
||||||
|
</Popup>,
|
||||||
|
);
|
||||||
|
}}
|
||||||
onOpenDueDatePopop={(task, $targetRef) => {
|
onOpenDueDatePopop={(task, $targetRef) => {
|
||||||
showPopup(
|
showPopup(
|
||||||
$targetRef,
|
$targetRef,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import React, { useState, useRef, useContext, useEffect } from 'react';
|
import React, { useState, useRef, useContext, useEffect } from 'react';
|
||||||
import GlobalTopNavbar from 'App/TopNavbar';
|
import { MENU_TYPES } from 'shared/components/TopNavbar';
|
||||||
|
import GlobalTopNavbar, { ProjectPopup } from 'App/TopNavbar';
|
||||||
import styled from 'styled-components/macro';
|
import styled from 'styled-components/macro';
|
||||||
import { Bolt, ToggleOn, Tags } from 'shared/icons';
|
import { DataProxy } from '@apollo/client';
|
||||||
|
import { Bolt, ToggleOn, Tags, CheckCircle, Sort, Filter } from 'shared/icons';
|
||||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||||
import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps } from 'react-router-dom';
|
import { useParams, Route, useRouteMatch, useHistory, RouteComponentProps } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
@ -26,6 +28,7 @@ import {
|
|||||||
useCreateProjectLabelMutation,
|
useCreateProjectLabelMutation,
|
||||||
useUnassignTaskMutation,
|
useUnassignTaskMutation,
|
||||||
useUpdateTaskDueDateMutation,
|
useUpdateTaskDueDateMutation,
|
||||||
|
FindProjectQuery,
|
||||||
} from 'shared/generated/graphql';
|
} from 'shared/generated/graphql';
|
||||||
|
|
||||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
import TaskAssignee from 'shared/components/TaskAssignee';
|
||||||
@ -42,11 +45,35 @@ import produce from 'immer';
|
|||||||
import MiniProfile from 'shared/components/MiniProfile';
|
import MiniProfile from 'shared/components/MiniProfile';
|
||||||
import Details from './Details';
|
import Details from './Details';
|
||||||
import { useApolloClient } from '@apollo/react-hooks';
|
import { useApolloClient } from '@apollo/react-hooks';
|
||||||
|
import { DocumentNode } from 'graphql';
|
||||||
import UserIDContext from 'App/context';
|
import UserIDContext from 'App/context';
|
||||||
import DueDateManager from 'shared/components/DueDateManager';
|
import DueDateManager from 'shared/components/DueDateManager';
|
||||||
|
|
||||||
|
type UpdateCacheFn<T> = (cache: T) => T;
|
||||||
|
function updateApolloCache<T>(client: DataProxy, document: DocumentNode, update: UpdateCacheFn<T>, variables?: object) {
|
||||||
|
let queryArgs: DataProxy.Query<any>;
|
||||||
|
if (variables) {
|
||||||
|
queryArgs = {
|
||||||
|
query: document,
|
||||||
|
variables,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
queryArgs = {
|
||||||
|
query: document,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const cache: T | null = client.readQuery(queryArgs);
|
||||||
|
if (cache) {
|
||||||
|
const newCache = update(cache);
|
||||||
|
client.writeQuery({
|
||||||
|
...queryArgs,
|
||||||
|
data: newCache,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const getCacheData = (client: any, projectID: string) => {
|
const getCacheData = (client: any, projectID: string) => {
|
||||||
const cacheData: any = client.readQuery({
|
const cacheData: FindProjectQuery = client.readQuery({
|
||||||
query: FindProjectDocument,
|
query: FindProjectDocument,
|
||||||
variables: {
|
variables: {
|
||||||
projectId: projectID,
|
projectId: projectID,
|
||||||
@ -220,7 +247,7 @@ const initialQuickCardEditorState: QuickCardEditorState = {
|
|||||||
const ProjectBar = styled.div`
|
const ProjectBar = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: space-between;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
`;
|
`;
|
||||||
@ -302,13 +329,17 @@ const Project = () => {
|
|||||||
const [createTaskGroup] = useCreateTaskGroupMutation({
|
const [createTaskGroup] = useCreateTaskGroupMutation({
|
||||||
onCompleted: newTaskGroupData => {},
|
onCompleted: newTaskGroupData => {},
|
||||||
update: (client, newTaskGroupData) => {
|
update: (client, newTaskGroupData) => {
|
||||||
const cacheData = getCacheData(client, projectID);
|
updateApolloCache<FindProjectQuery>(
|
||||||
const newData = {
|
client,
|
||||||
...cacheData.findProject,
|
FindProjectDocument,
|
||||||
taskGroups: [...cacheData.findProject.taskGroups, { ...newTaskGroupData.data.createTaskGroup, tasks: [] }],
|
cache => {
|
||||||
};
|
console.log(cache);
|
||||||
|
return produce(cache, draftCache => {
|
||||||
writeCacheData(client, projectID, cacheData, newData);
|
draftCache.findProject.taskGroups.push({ ...newTaskGroupData.data.createTaskGroup, tasks: [] });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ projectId: projectID },
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -316,7 +347,7 @@ const Project = () => {
|
|||||||
onCompleted: newTaskData => {},
|
onCompleted: newTaskData => {},
|
||||||
update: (client, newTaskData) => {
|
update: (client, newTaskData) => {
|
||||||
const cacheData = getCacheData(client, projectID);
|
const cacheData = getCacheData(client, projectID);
|
||||||
const newTaskGroups = produce(cacheData.findProject.taskGroups, (draftState: any) => {
|
const newTaskGroups = produce(cacheData.findProject.taskGroups, draftState => {
|
||||||
const targetIndex = draftState.findIndex(
|
const targetIndex = draftState.findIndex(
|
||||||
(taskGroup: any) => taskGroup.id === newTaskData.data.createTask.taskGroup.id,
|
(taskGroup: any) => taskGroup.id === newTaskData.data.createTask.taskGroup.id,
|
||||||
);
|
);
|
||||||
@ -388,14 +419,18 @@ const Project = () => {
|
|||||||
createTask: {
|
createTask: {
|
||||||
__typename: 'Task',
|
__typename: 'Task',
|
||||||
id: '' + Math.round(Math.random() * -1000000),
|
id: '' + Math.round(Math.random() * -1000000),
|
||||||
name: name,
|
name,
|
||||||
|
complete: false,
|
||||||
taskGroup: {
|
taskGroup: {
|
||||||
__typename: 'TaskGroup',
|
__typename: 'TaskGroup',
|
||||||
id: taskGroup.id,
|
id: taskGroup.id,
|
||||||
name: taskGroup.name,
|
name: taskGroup.name,
|
||||||
position: taskGroup.position,
|
position: taskGroup.position,
|
||||||
},
|
},
|
||||||
position: position,
|
badges: {
|
||||||
|
checklist: null,
|
||||||
|
},
|
||||||
|
position,
|
||||||
dueDate: null,
|
dueDate: null,
|
||||||
description: null,
|
description: null,
|
||||||
labels: [],
|
labels: [],
|
||||||
@ -509,11 +544,28 @@ const Project = () => {
|
|||||||
onSaveProjectName={projectName => {
|
onSaveProjectName={projectName => {
|
||||||
updateProjectName({ variables: { projectID, name: projectName } });
|
updateProjectName({ variables: { projectID, name: projectName } });
|
||||||
}}
|
}}
|
||||||
|
popupContent={<ProjectPopup history={history} name={data.findProject.name} projectID={projectID} />}
|
||||||
|
menuType={MENU_TYPES.PROJECT_MENU}
|
||||||
|
initialTab={0}
|
||||||
projectMembers={data.findProject.members}
|
projectMembers={data.findProject.members}
|
||||||
projectID={projectID}
|
projectID={projectID}
|
||||||
name={data.findProject.name}
|
name={data.findProject.name}
|
||||||
/>
|
/>
|
||||||
<ProjectBar>
|
<ProjectBar>
|
||||||
|
<ProjectActions>
|
||||||
|
<ProjectAction>
|
||||||
|
<CheckCircle width={13} height={13} />
|
||||||
|
<ProjectActionText>All Tasks</ProjectActionText>
|
||||||
|
</ProjectAction>
|
||||||
|
<ProjectAction>
|
||||||
|
<Filter width={13} height={13} />
|
||||||
|
<ProjectActionText>Filter</ProjectActionText>
|
||||||
|
</ProjectAction>
|
||||||
|
<ProjectAction>
|
||||||
|
<Sort width={13} height={13} />
|
||||||
|
<ProjectActionText>Sort</ProjectActionText>
|
||||||
|
</ProjectAction>
|
||||||
|
</ProjectActions>
|
||||||
<ProjectActions>
|
<ProjectActions>
|
||||||
<ProjectAction
|
<ProjectAction
|
||||||
ref={$labelsRef}
|
ref={$labelsRef}
|
||||||
|
@ -137,6 +137,7 @@ const ProjectTileName = styled.div<{ centered?: boolean }>`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@ -146,10 +147,24 @@ const Wrapper = styled.div`
|
|||||||
const ProjectSectionTitleWrapper = styled.div`
|
const ProjectSectionTitleWrapper = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin-top: 16px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const SectionActions = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const SectionAction = styled(Button)`
|
||||||
|
padding: 6px 12px;
|
||||||
|
`;
|
||||||
|
const SectionActionLink = styled(Link)`
|
||||||
|
margin-right: 8px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ProjectSectionTitle = styled.h3`
|
const ProjectSectionTitle = styled.h3`
|
||||||
@ -171,13 +186,19 @@ const ProjectGrid = styled.div`
|
|||||||
`;
|
`;
|
||||||
const AddTeamButton = styled(Button)`
|
const AddTeamButton = styled(Button)`
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
float: right;
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
right: 12px;
|
||||||
`;
|
`;
|
||||||
|
type ShowNewProject = {
|
||||||
|
open: boolean;
|
||||||
|
initialTeamID: null | string;
|
||||||
|
};
|
||||||
|
|
||||||
const ProjectLink = styled(Link)``;
|
const ProjectLink = styled(Link)``;
|
||||||
|
|
||||||
const Projects = () => {
|
const Projects = () => {
|
||||||
const { showPopup } = usePopup();
|
const { showPopup, hidePopup } = usePopup();
|
||||||
const { loading, data } = useGetProjectsQuery();
|
const { loading, data } = useGetProjectsQuery();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = 'Citadel';
|
document.title = 'Citadel';
|
||||||
@ -202,9 +223,24 @@ const Projects = () => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const [showNewProject, setShowNewProject] = useState(false);
|
|
||||||
|
const [showNewProject, setShowNewProject] = useState<ShowNewProject>({ open: false, initialTeamID: null });
|
||||||
const { userID, setUserID } = useContext(UserIDContext);
|
const { userID, setUserID } = useContext(UserIDContext);
|
||||||
const [createTeam] = useCreateTeamMutation();
|
const [createTeam] = useCreateTeamMutation({
|
||||||
|
update: (client, createData) => {
|
||||||
|
const cacheData: any = client.readQuery({
|
||||||
|
query: GetProjectsDocument,
|
||||||
|
});
|
||||||
|
const newData = {
|
||||||
|
...cacheData,
|
||||||
|
teams: [...cacheData.teams, { ...createData.data.createTeam }],
|
||||||
|
};
|
||||||
|
client.writeQuery({
|
||||||
|
query: GetProjectsDocument,
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -234,11 +270,18 @@ const Projects = () => {
|
|||||||
onClick={$target => {
|
onClick={$target => {
|
||||||
showPopup(
|
showPopup(
|
||||||
$target,
|
$target,
|
||||||
<Popup title="Create team" tab={0}>
|
<Popup
|
||||||
|
title="Create team"
|
||||||
|
tab={0}
|
||||||
|
onClose={() => {
|
||||||
|
hidePopup();
|
||||||
|
}}
|
||||||
|
>
|
||||||
<CreateTeamForm
|
<CreateTeamForm
|
||||||
onCreateTeam={teamName => {
|
onCreateTeam={teamName => {
|
||||||
if (organizationID) {
|
if (organizationID) {
|
||||||
createTeam({ variables: { name: teamName, organizationID } });
|
createTeam({ variables: { name: teamName, organizationID } });
|
||||||
|
hidePopup();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -253,6 +296,17 @@ const Projects = () => {
|
|||||||
<div key={team.id}>
|
<div key={team.id}>
|
||||||
<ProjectSectionTitleWrapper>
|
<ProjectSectionTitleWrapper>
|
||||||
<ProjectSectionTitle>{team.name}</ProjectSectionTitle>
|
<ProjectSectionTitle>{team.name}</ProjectSectionTitle>
|
||||||
|
<SectionActions>
|
||||||
|
<SectionActionLink to={`/teams/${team.id}`}>
|
||||||
|
<SectionAction variant="outline">Projects</SectionAction>
|
||||||
|
</SectionActionLink>
|
||||||
|
<SectionActionLink to="/">
|
||||||
|
<SectionAction variant="outline">Members</SectionAction>
|
||||||
|
</SectionActionLink>
|
||||||
|
<SectionActionLink to="/">
|
||||||
|
<SectionAction variant="outline">Settings</SectionAction>
|
||||||
|
</SectionActionLink>
|
||||||
|
</SectionActions>
|
||||||
</ProjectSectionTitleWrapper>
|
</ProjectSectionTitleWrapper>
|
||||||
<ProjectList>
|
<ProjectList>
|
||||||
{team.projects.map((project, idx) => (
|
{team.projects.map((project, idx) => (
|
||||||
@ -268,7 +322,7 @@ const Projects = () => {
|
|||||||
<ProjectListItem>
|
<ProjectListItem>
|
||||||
<ProjectAddTile
|
<ProjectAddTile
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowNewProject(true);
|
setShowNewProject({ open: true, initialTeamID: team.id });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProjectTileFade />
|
<ProjectTileFade />
|
||||||
@ -281,16 +335,17 @@ const Projects = () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{showNewProject && (
|
{showNewProject.open && (
|
||||||
<NewProject
|
<NewProject
|
||||||
|
initialTeamID={showNewProject.initialTeamID}
|
||||||
onCreateProject={(name, teamID) => {
|
onCreateProject={(name, teamID) => {
|
||||||
if (userID) {
|
if (userID) {
|
||||||
createProject({ variables: { teamID, name, userID } });
|
createProject({ variables: { teamID, name, userID } });
|
||||||
setShowNewProject(false);
|
setShowNewProject({ open: false, initialTeamID: null });
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setShowNewProject(false);
|
setShowNewProject({ open: false, initialTeamID: null });
|
||||||
}}
|
}}
|
||||||
teams={teams}
|
teams={teams}
|
||||||
/>
|
/>
|
||||||
|
227
web/src/Teams/index.tsx
Normal file
227
web/src/Teams/index.tsx
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
import React, { useState, useContext, useEffect } from 'react';
|
||||||
|
import styled from 'styled-components/macro';
|
||||||
|
import { MENU_TYPES } from 'shared/components/TopNavbar';
|
||||||
|
import GlobalTopNavbar from 'App/TopNavbar';
|
||||||
|
import { useGetTeamQuery, useDeleteTeamMutation, GetProjectsDocument } from 'shared/generated/graphql';
|
||||||
|
import { useParams, useHistory } from 'react-router';
|
||||||
|
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||||
|
import { History } from 'history';
|
||||||
|
import produce from 'immer';
|
||||||
|
import { TeamSettings, DeleteConfirm, DELETE_INFO } from 'shared/components/ProjectSettings';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
const ProjectAddTile = styled.div`
|
||||||
|
background-color: rgba(${props => props.theme.colors.bg.primary}, 0.4);
|
||||||
|
background-size: cover;
|
||||||
|
background-position: 50%;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 20px;
|
||||||
|
padding: 8px;
|
||||||
|
position: relative;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
border-radius: 3px;
|
||||||
|
display: block;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ProjectTile = styled(Link)<{ color: string }>`
|
||||||
|
background-color: ${props => props.color};
|
||||||
|
background-size: cover;
|
||||||
|
background-position: 50%;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 20px;
|
||||||
|
padding: 8px;
|
||||||
|
position: relative;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
border-radius: 3px;
|
||||||
|
display: block;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ProjectTileFade = styled.div`
|
||||||
|
background-color: rgba(0, 0, 0, 0.15);
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ProjectListItem = styled.li`
|
||||||
|
width: 23.5%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 2% 2% 0;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover ${ProjectTileFade} {
|
||||||
|
background-color: rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ProjectList = styled.ul`
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
& ${ProjectListItem}:nth-of-type(4n) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ProjectTileDetails = styled.div`
|
||||||
|
display: flex;
|
||||||
|
height: 80px;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ProjectAddTileDetails = styled.div`
|
||||||
|
display: flex;
|
||||||
|
height: 80px;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ProjectTileName = styled.div<{ centered?: boolean }>`
|
||||||
|
flex: 0 0 auto;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: inline-block;
|
||||||
|
overflow: hidden;
|
||||||
|
max-height: 40px;
|
||||||
|
width: 100%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
${props => props.centered && 'text-align: center;'}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
type TeamPopupProps = {
|
||||||
|
history: History<History.PoorMansUnknown>;
|
||||||
|
name: string;
|
||||||
|
teamID: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TeamPopup: React.FC<TeamPopupProps> = ({ history, name, teamID }) => {
|
||||||
|
const { hidePopup, setTab } = usePopup();
|
||||||
|
const [deleteTeam] = useDeleteTeamMutation({
|
||||||
|
update: (client, deleteData) => {
|
||||||
|
const cacheData: any = client.readQuery({
|
||||||
|
query: GetProjectsDocument,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(cacheData);
|
||||||
|
console.log(deleteData);
|
||||||
|
|
||||||
|
const newData = produce(cacheData, (draftState: any) => {
|
||||||
|
draftState.teams = draftState.teams.filter((team: any) => team.id !== deleteData.data.deleteTeam.team.id);
|
||||||
|
draftState.projects = draftState.projects.filter(
|
||||||
|
(project: any) => project.team.id !== deleteData.data.deleteTeam.team.id,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.writeQuery({
|
||||||
|
query: GetProjectsDocument,
|
||||||
|
data: {
|
||||||
|
...newData,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Popup title={null} tab={0}>
|
||||||
|
<TeamSettings
|
||||||
|
onDeleteTeam={() => {
|
||||||
|
setTab(1, 340);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popup>
|
||||||
|
<Popup title={`Delete the "${name}" team?`} tab={1} onClose={() => hidePopup()}>
|
||||||
|
<DeleteConfirm
|
||||||
|
description={DELETE_INFO.DELETE_TEAMS.description}
|
||||||
|
deletedItems={DELETE_INFO.DELETE_TEAMS.deletedItems}
|
||||||
|
onConfirmDelete={() => {
|
||||||
|
if (teamID) {
|
||||||
|
deleteTeam({ variables: { teamID } });
|
||||||
|
hidePopup();
|
||||||
|
history.push('/projects');
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popup>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProjectsContainer = styled.div`
|
||||||
|
margin: 40px 16px 0;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 825px;
|
||||||
|
min-width: 288px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
type TeamsRouteProps = {
|
||||||
|
teamID: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const colors = ['#e362e3', '#7a6ff0', '#37c5ab', '#aa62e3', '#e8384f'];
|
||||||
|
const Projects = () => {
|
||||||
|
const { teamID } = useParams<TeamsRouteProps>();
|
||||||
|
const history = useHistory();
|
||||||
|
const { loading, data } = useGetTeamQuery({ variables: { teamID } });
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = 'Citadel | Teams';
|
||||||
|
}, []);
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span>loading</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<GlobalTopNavbar
|
||||||
|
menuType={MENU_TYPES.TEAM_MENU}
|
||||||
|
initialTab={0}
|
||||||
|
popupContent={<TeamPopup history={history} name={data.findTeam.name} teamID={teamID} />}
|
||||||
|
onSaveProjectName={() => {}}
|
||||||
|
projectID={null}
|
||||||
|
name={data.findTeam.name}
|
||||||
|
/>
|
||||||
|
<Wrapper>
|
||||||
|
<ProjectsContainer>
|
||||||
|
<ProjectList>
|
||||||
|
{data.projects.map((project, idx) => (
|
||||||
|
<ProjectListItem key={project.id}>
|
||||||
|
<ProjectTile color={colors[idx % 5]} to={`/projects/${project.id}`}>
|
||||||
|
<ProjectTileFade />
|
||||||
|
<ProjectTileDetails>
|
||||||
|
<ProjectTileName>{project.name}</ProjectTileName>
|
||||||
|
</ProjectTileDetails>
|
||||||
|
</ProjectTile>
|
||||||
|
</ProjectListItem>
|
||||||
|
))}
|
||||||
|
</ProjectList>
|
||||||
|
</ProjectsContainer>
|
||||||
|
</Wrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <div>Error!</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Projects;
|
9
web/src/citadel.d.ts
vendored
9
web/src/citadel.d.ts
vendored
@ -17,6 +17,15 @@ type ContextMenuEvent = {
|
|||||||
taskGroupID: string;
|
taskGroupID: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type User = {
|
||||||
|
id: string;
|
||||||
|
fullName: string;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
role: string;
|
||||||
|
profileIcon: ProfileIcon;
|
||||||
|
};
|
||||||
|
|
||||||
type TaskUser = {
|
type TaskUser = {
|
||||||
id: string;
|
id: string;
|
||||||
fullName: string;
|
fullName: string;
|
||||||
|
10
web/src/projects.d.ts
vendored
10
web/src/projects.d.ts
vendored
@ -47,10 +47,20 @@ type TaskChecklistItem = {
|
|||||||
dueDate?: null | string;
|
dueDate?: null | string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ChecklistBadge = {
|
||||||
|
complete: number;
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TaskBadges = {
|
||||||
|
checklist?: ChecklistBadge | null;
|
||||||
|
};
|
||||||
|
|
||||||
type Task = {
|
type Task = {
|
||||||
id: string;
|
id: string;
|
||||||
taskGroup: InnerTaskGroup;
|
taskGroup: InnerTaskGroup;
|
||||||
name: string;
|
name: string;
|
||||||
|
badges?: TaskBadges;
|
||||||
position: number;
|
position: number;
|
||||||
dueDate?: string;
|
dueDate?: string;
|
||||||
complete?: boolean;
|
complete?: boolean;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import Admin from '.';
|
import Admin from '.';
|
||||||
|
import { theme } from 'App/ThemeStyles';
|
||||||
import NormalizeStyles from 'App/NormalizeStyles';
|
import NormalizeStyles from 'App/NormalizeStyles';
|
||||||
import BaseStyles from 'App/BaseStyles';
|
import BaseStyles from 'App/BaseStyles';
|
||||||
|
import { ThemeProvider } from 'styled-components';
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
component: Admin,
|
component: Admin,
|
||||||
@ -19,7 +22,27 @@ export const Default = () => {
|
|||||||
<>
|
<>
|
||||||
<NormalizeStyles />
|
<NormalizeStyles />
|
||||||
<BaseStyles />
|
<BaseStyles />
|
||||||
<Admin />
|
<ThemeProvider theme={theme}>
|
||||||
|
<Admin
|
||||||
|
onInviteUser={action('invite user')}
|
||||||
|
initialTab={1}
|
||||||
|
users={[
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
username: 'jordanthedev',
|
||||||
|
email: 'jordan@jordanthedev.com',
|
||||||
|
role: 'Admin',
|
||||||
|
fullName: 'Jordan Knott',
|
||||||
|
profileIcon: {
|
||||||
|
bgColor: '#fff',
|
||||||
|
initials: 'JK',
|
||||||
|
url: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onAddUser={action('add user')}
|
||||||
|
/>
|
||||||
|
</ThemeProvider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,34 +1,28 @@
|
|||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { User, Plus } from 'shared/icons';
|
import { User, Plus, Lock, Pencil, Trash } from 'shared/icons';
|
||||||
import { AgGridReact } from 'ag-grid-react';
|
import { AgGridReact } from 'ag-grid-react';
|
||||||
|
|
||||||
import 'ag-grid-community/dist/styles/ag-grid.css';
|
import 'ag-grid-community/dist/styles/ag-grid.css';
|
||||||
import 'ag-grid-community/dist/styles/ag-theme-material.css';
|
import 'ag-grid-community/dist/styles/ag-theme-material.css';
|
||||||
|
import Button from 'shared/components/Button';
|
||||||
|
|
||||||
const NewUserButton = styled.button`
|
const NewUserButton = styled(Button)`
|
||||||
outline: none;
|
padding: 6px 12px;
|
||||||
border: none;
|
margin-right: 12px;
|
||||||
cursor: pointer;
|
|
||||||
line-height: 20px;
|
|
||||||
padding: 0.75rem;
|
|
||||||
background-color: transparent;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(115, 103, 240);
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: transparent;
|
|
||||||
border-image: initial;
|
|
||||||
border-color: rgba(115, 103, 240);
|
|
||||||
span {
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const InviteUserButton = styled(Button)`
|
||||||
|
padding: 6px 12px;
|
||||||
|
margin-right: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const MemberActions = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
const GridTable = styled.div`
|
const GridTable = styled.div`
|
||||||
height: 620px;
|
height: 620px;
|
||||||
`;
|
`;
|
||||||
@ -93,8 +87,29 @@ const Header = styled.div`
|
|||||||
min-height: 112px;
|
min-height: 112px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ActionButtonsContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const EditUserIcon = styled(Pencil)`
|
||||||
|
margin-right: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const LockUserIcon = styled(Lock)`
|
||||||
|
margin-right: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DeleteUserIcon = styled(Trash)``;
|
||||||
|
|
||||||
const ActionButtons = () => {
|
const ActionButtons = () => {
|
||||||
return <span>Hello!</span>;
|
return (
|
||||||
|
<>
|
||||||
|
<EditUserIcon width={16} height={16} />
|
||||||
|
<LockUserIcon width={16} height={16} />
|
||||||
|
<DeleteUserIcon width={16} height={16} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
const data = {
|
const data = {
|
||||||
defaultColDef: {
|
defaultColDef: {
|
||||||
@ -103,16 +118,14 @@ const data = {
|
|||||||
},
|
},
|
||||||
columnDefs: [
|
columnDefs: [
|
||||||
{
|
{
|
||||||
minWidth: 125,
|
minWidth: 55,
|
||||||
width: 125,
|
width: 55,
|
||||||
headerCheckboxSelection: true,
|
headerCheckboxSelection: true,
|
||||||
checkboxSelection: true,
|
checkboxSelection: true,
|
||||||
headerName: 'ID',
|
|
||||||
field: 'id',
|
|
||||||
},
|
},
|
||||||
{ minWidth: 210, headerName: 'Username', editable: true, field: 'username' },
|
{ minWidth: 210, headerName: 'Username', editable: true, field: 'username' },
|
||||||
{ minWidth: 225, headerName: 'Email', field: 'email' },
|
{ minWidth: 225, headerName: 'Email', field: 'email' },
|
||||||
{ minWidth: 200, headerName: 'Name', editable: true, field: 'full_name' },
|
{ minWidth: 200, headerName: 'Name', editable: true, field: 'fullName' },
|
||||||
{ minWidth: 200, headerName: 'Role', editable: true, field: 'role' },
|
{ minWidth: 200, headerName: 'Role', editable: true, field: 'role' },
|
||||||
{
|
{
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
@ -123,14 +136,13 @@ const data = {
|
|||||||
frameworkComponents: {
|
frameworkComponents: {
|
||||||
actionButtons: ActionButtons,
|
actionButtons: ActionButtons,
|
||||||
},
|
},
|
||||||
rowData: [
|
|
||||||
{ id: '1', full_name: 'Jordan Knott', username: 'jordan', email: 'jordan@jordanthedev.com', role: 'Admin' },
|
|
||||||
{ id: '2', full_name: 'Jordan Test', username: 'jordantest', email: 'jordan@jordanthedev.com', role: 'Admin' },
|
|
||||||
{ id: '3', full_name: 'Jordan Other', username: 'alphatest1050', email: 'jordan@jordanthedev.com', role: 'Admin' },
|
|
||||||
{ id: '5', full_name: 'Jordan French', username: 'other', email: 'jordan@jordanthedev.com', role: 'Admin' },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
const ListTable = () => {
|
|
||||||
|
type ListTableProps = {
|
||||||
|
users: Array<User>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ListTable: React.FC<ListTableProps> = ({ users }) => {
|
||||||
return (
|
return (
|
||||||
<Root>
|
<Root>
|
||||||
<div className="ag-theme-material" style={{ height: '296px', width: '100%' }}>
|
<div className="ag-theme-material" style={{ height: '296px', width: '100%' }}>
|
||||||
@ -138,7 +150,7 @@ const ListTable = () => {
|
|||||||
rowSelection="multiple"
|
rowSelection="multiple"
|
||||||
defaultColDef={data.defaultColDef}
|
defaultColDef={data.defaultColDef}
|
||||||
columnDefs={data.columnDefs}
|
columnDefs={data.columnDefs}
|
||||||
rowData={data.rowData}
|
rowData={users}
|
||||||
frameworkComponents={data.frameworkComponents}
|
frameworkComponents={data.frameworkComponents}
|
||||||
onFirstDataRendered={params => {
|
onFirstDataRendered={params => {
|
||||||
params.api.sizeColumnsToFit();
|
params.api.sizeColumnsToFit();
|
||||||
@ -146,7 +158,7 @@ const ListTable = () => {
|
|||||||
onGridSizeChanged={params => {
|
onGridSizeChanged={params => {
|
||||||
params.api.sizeColumnsToFit();
|
params.api.sizeColumnsToFit();
|
||||||
}}
|
}}
|
||||||
></AgGridReact>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Root>
|
</Root>
|
||||||
);
|
);
|
||||||
@ -184,6 +196,7 @@ const TabNavContent = styled.ul`
|
|||||||
|
|
||||||
const TabNavItem = styled.li`
|
const TabNavItem = styled.li`
|
||||||
padding: 0.35rem 0.3rem;
|
padding: 0.35rem 0.3rem;
|
||||||
|
height: 48px;
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
@ -282,9 +295,16 @@ const NavItem: React.FC<NavItemProps> = ({ active, name, tab, onClick }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Admin = () => {
|
type AdminProps = {
|
||||||
const [currentTop, setTop] = useState(0);
|
initialTab: number;
|
||||||
const [currentTab, setTab] = useState(0);
|
onAddUser: ($target: React.RefObject<HTMLElement>) => void;
|
||||||
|
onInviteUser: ($target: React.RefObject<HTMLElement>) => void;
|
||||||
|
users: Array<User>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Admin: React.FC<AdminProps> = ({ initialTab, onAddUser, onInviteUser, users }) => {
|
||||||
|
const [currentTop, setTop] = useState(initialTab * 48);
|
||||||
|
const [currentTab, setTab] = useState(initialTab);
|
||||||
const $tabNav = useRef<HTMLDivElement>(null);
|
const $tabNav = useRef<HTMLDivElement>(null);
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
@ -309,11 +329,17 @@ const Admin = () => {
|
|||||||
</TabNav>
|
</TabNav>
|
||||||
<TabContentWrapper>
|
<TabContentWrapper>
|
||||||
<TabContent>
|
<TabContent>
|
||||||
<NewUserButton>
|
<MemberActions>
|
||||||
<Plus color="rgba(115, 103, 240)" size={10} />
|
<NewUserButton variant="outline" onClick={onAddUser}>
|
||||||
<span>Add New</span>
|
<Plus color="rgba(115, 103, 240)" size={10} />
|
||||||
</NewUserButton>
|
<span style={{ paddingLeft: '5px' }}>Create member</span>
|
||||||
<ListTable />
|
</NewUserButton>
|
||||||
|
<InviteUserButton variant="outline" onClick={onInviteUser}>
|
||||||
|
<Plus color="rgba(115, 103, 240)" size={10} />
|
||||||
|
<span style={{ paddingLeft: '5px' }}>Invite member</span>
|
||||||
|
</InviteUserButton>
|
||||||
|
</MemberActions>
|
||||||
|
<ListTable users={users} />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
</TabContentWrapper>
|
</TabContentWrapper>
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -42,7 +42,7 @@ type Props = {
|
|||||||
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
description?: null | string;
|
description?: null | string;
|
||||||
dueDate?: DueDate;
|
dueDate?: DueDate;
|
||||||
checklists?: Checklist;
|
checklists?: Checklist | null;
|
||||||
labels?: Array<ProjectLabel>;
|
labels?: Array<ProjectLabel>;
|
||||||
watched?: boolean;
|
watched?: boolean;
|
||||||
wrapperProps?: any;
|
wrapperProps?: any;
|
||||||
|
@ -501,7 +501,7 @@ const ChecklistTitleEditor = React.forwardRef(
|
|||||||
);
|
);
|
||||||
type ChecklistProps = {
|
type ChecklistProps = {
|
||||||
checklistID: string;
|
checklistID: string;
|
||||||
onDeleteChecklist: (checklistID: string) => void;
|
onDeleteChecklist: ($target: React.RefObject<HTMLElement>, checklistID: string) => void;
|
||||||
name: string;
|
name: string;
|
||||||
onChangeName: (item: string) => void;
|
onChangeName: (item: string) => void;
|
||||||
onToggleItem: (taskID: string, complete: boolean) => void;
|
onToggleItem: (taskID: string, complete: boolean) => void;
|
||||||
@ -554,8 +554,8 @@ const Checklist: React.FC<ChecklistProps> = ({
|
|||||||
<WindowTitleText onClick={() => setEditting(true)}>{name}</WindowTitleText>
|
<WindowTitleText onClick={() => setEditting(true)}>{name}</WindowTitleText>
|
||||||
<WindowOptions>
|
<WindowOptions>
|
||||||
<DeleteButton
|
<DeleteButton
|
||||||
onClick={() => {
|
onClick={$target => {
|
||||||
onDeleteChecklist(checklistID);
|
onDeleteChecklist($target, checklistID);
|
||||||
}}
|
}}
|
||||||
color="danger"
|
color="danger"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
@ -51,6 +51,7 @@ export const Default = () => {
|
|||||||
</Container>
|
</Container>
|
||||||
{menu.isOpen && (
|
{menu.isOpen && (
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
|
onAdminConsole={action('admin')}
|
||||||
onCloseDropdown={() => {
|
onCloseDropdown={() => {
|
||||||
setMenu({ top: 0, left: 0, isOpen: false });
|
setMenu({ top: 0, left: 0, isOpen: false });
|
||||||
}}
|
}}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
||||||
import { Exit, User } from 'shared/icons';
|
import { Exit, User, Cog } from 'shared/icons';
|
||||||
import { Separator, Container, WrapperDiamond, Wrapper, ActionsList, ActionItem, ActionTitle } from './Styles';
|
import { Separator, Container, WrapperDiamond, Wrapper, ActionsList, ActionItem, ActionTitle } from './Styles';
|
||||||
|
|
||||||
type DropdownMenuProps = {
|
type DropdownMenuProps = {
|
||||||
@ -8,15 +8,16 @@ type DropdownMenuProps = {
|
|||||||
top: number;
|
top: number;
|
||||||
onLogout: () => void;
|
onLogout: () => void;
|
||||||
onCloseDropdown: () => void;
|
onCloseDropdown: () => void;
|
||||||
|
onAdminConsole: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DropdownMenu: React.FC<DropdownMenuProps> = ({ left, top, onLogout, onCloseDropdown }) => {
|
const DropdownMenu: React.FC<DropdownMenuProps> = ({ left, top, onLogout, onCloseDropdown, onAdminConsole }) => {
|
||||||
const $containerRef = useRef<HTMLDivElement>(null);
|
const $containerRef = useRef<HTMLDivElement>(null);
|
||||||
useOnOutsideClick($containerRef, true, onCloseDropdown, null);
|
useOnOutsideClick($containerRef, true, onCloseDropdown, null);
|
||||||
return (
|
return (
|
||||||
<Container ref={$containerRef} left={left} top={top}>
|
<Container ref={$containerRef} left={left} top={top}>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<ActionItem>
|
<ActionItem onClick={onAdminConsole}>
|
||||||
<User size={16} color="#c2c6dc" />
|
<User size={16} color="#c2c6dc" />
|
||||||
<ActionTitle>Profile</ActionTitle>
|
<ActionTitle>Profile</ActionTitle>
|
||||||
</ActionItem>
|
</ActionItem>
|
||||||
@ -36,16 +37,21 @@ const DropdownMenu: React.FC<DropdownMenuProps> = ({ left, top, onLogout, onClos
|
|||||||
type ProfileMenuProps = {
|
type ProfileMenuProps = {
|
||||||
onProfile: () => void;
|
onProfile: () => void;
|
||||||
onLogout: () => void;
|
onLogout: () => void;
|
||||||
|
onAdminConsole: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ProfileMenu: React.FC<ProfileMenuProps> = ({ onProfile, onLogout }) => {
|
const ProfileMenu: React.FC<ProfileMenuProps> = ({ onAdminConsole, onProfile, onLogout }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<ActionItem onClick={onAdminConsole}>
|
||||||
|
<Cog size={16} color="#c2c6dc" />
|
||||||
|
<ActionTitle>Admin Console</ActionTitle>
|
||||||
|
</ActionItem>
|
||||||
|
<Separator />
|
||||||
<ActionItem onClick={onProfile}>
|
<ActionItem onClick={onProfile}>
|
||||||
<User size={16} color="#c2c6dc" />
|
<User size={16} color="#c2c6dc" />
|
||||||
<ActionTitle>Profile</ActionTitle>
|
<ActionTitle>Profile</ActionTitle>
|
||||||
</ActionItem>
|
</ActionItem>
|
||||||
<Separator />
|
|
||||||
<ActionsList>
|
<ActionsList>
|
||||||
<ActionItem onClick={onLogout}>
|
<ActionItem onClick={onLogout}>
|
||||||
<Exit size={16} color="#c2c6dc" />
|
<Exit size={16} color="#c2c6dc" />
|
||||||
|
@ -80,8 +80,10 @@ type InputProps = {
|
|||||||
variant?: 'normal' | 'alternate';
|
variant?: 'normal' | 'alternate';
|
||||||
label?: string;
|
label?: string;
|
||||||
width?: string;
|
width?: string;
|
||||||
|
floatingLabel?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
icon?: JSX.Element;
|
icon?: JSX.Element;
|
||||||
|
autocomplete?: boolean;
|
||||||
id?: string;
|
id?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -95,6 +97,7 @@ const Input = React.forwardRef(
|
|||||||
{
|
{
|
||||||
width = 'auto',
|
width = 'auto',
|
||||||
variant = 'normal',
|
variant = 'normal',
|
||||||
|
autocomplete,
|
||||||
label,
|
label,
|
||||||
placeholder,
|
placeholder,
|
||||||
icon,
|
icon,
|
||||||
@ -102,6 +105,7 @@ const Input = React.forwardRef(
|
|||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
onClick,
|
onClick,
|
||||||
|
floatingLabel,
|
||||||
value: initialValue,
|
value: initialValue,
|
||||||
id,
|
id,
|
||||||
}: InputProps,
|
}: InputProps,
|
||||||
@ -124,12 +128,13 @@ const Input = React.forwardRef(
|
|||||||
return (
|
return (
|
||||||
<InputWrapper className={className} width={width}>
|
<InputWrapper className={className} width={width}>
|
||||||
<InputInput
|
<InputInput
|
||||||
hasValue={value !== ''}
|
hasValue={floatingLabel || value !== ''}
|
||||||
ref={$ref}
|
ref={$ref}
|
||||||
id={id}
|
id={id}
|
||||||
name={name}
|
name={name}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
autoComplete={autocomplete ? 'on' : 'off'}
|
||||||
value={value}
|
value={value}
|
||||||
hasIcon={typeof icon !== 'undefined'}
|
hasIcon={typeof icon !== 'undefined'}
|
||||||
width={width}
|
width={width}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const Container = styled.div`
|
export const Container = styled.div`
|
||||||
|
flex: 1;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
@ -181,6 +181,7 @@ const SimpleLists: React.FC<SimpleProps> = ({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
onTaskClick(task);
|
onTaskClick(task);
|
||||||
}}
|
}}
|
||||||
|
checklists={task.badges && task.badges.checklist}
|
||||||
onCardMemberClick={onCardMemberClick}
|
onCardMemberClick={onCardMemberClick}
|
||||||
onContextMenu={onQuickEditorOpen}
|
onContextMenu={onQuickEditorOpen}
|
||||||
/>
|
/>
|
||||||
|
@ -38,7 +38,7 @@ const Login = ({ onSubmit }: LoginProps) => {
|
|||||||
<LoginFormWrapper>
|
<LoginFormWrapper>
|
||||||
<LoginFormContainer>
|
<LoginFormContainer>
|
||||||
<LogoWrapper>
|
<LogoWrapper>
|
||||||
<Citadel size={42} />
|
<Citadel width={42} height={42} />
|
||||||
<LogoTitle>Citadel</LogoTitle>
|
<LogoTitle>Citadel</LogoTitle>
|
||||||
</LogoWrapper>
|
</LogoWrapper>
|
||||||
<Title>Login</Title>
|
<Title>Login</Title>
|
||||||
@ -66,7 +66,7 @@ const Login = ({ onSubmit }: LoginProps) => {
|
|||||||
ref={register({ required: 'Password is required' })}
|
ref={register({ required: 'Password is required' })}
|
||||||
/>
|
/>
|
||||||
<FormIcon>
|
<FormIcon>
|
||||||
<Lock color="#c2c6dc" size={20} />
|
<Lock width={20} height={20} />
|
||||||
</FormIcon>
|
</FormIcon>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
{errors.password && <FormError>{errors.password.message}</FormError>}
|
{errors.password && <FormError>{errors.password.message}</FormError>}
|
||||||
|
@ -28,10 +28,10 @@ export const Default = () => {
|
|||||||
<PrimaryLogo />
|
<PrimaryLogo />
|
||||||
<ButtonContainer>
|
<ButtonContainer>
|
||||||
<ActionButton name="Home">
|
<ActionButton name="Home">
|
||||||
<Home size={28} color="#c2c6dc" />
|
<Home width={28} height={28} />
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
<ActionButton name="Home">
|
<ActionButton name="Home">
|
||||||
<Home size={28} color="#c2c6dc" />
|
<Home width={28} height={28} />
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</ButtonContainer>
|
</ButtonContainer>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
|
@ -35,7 +35,7 @@ export const ButtonContainer: React.FC = ({ children }) => (
|
|||||||
export const PrimaryLogo = () => {
|
export const PrimaryLogo = () => {
|
||||||
return (
|
return (
|
||||||
<LogoWrapper>
|
<LogoWrapper>
|
||||||
<Citadel size={42} />
|
<Citadel width={42} height={42} />
|
||||||
<LogoTitle>Citadel</LogoTitle>
|
<LogoTitle>Citadel</LogoTitle>
|
||||||
</LogoWrapper>
|
</LogoWrapper>
|
||||||
);
|
);
|
||||||
|
@ -23,6 +23,7 @@ export const Default = () => {
|
|||||||
<NormalizeStyles />
|
<NormalizeStyles />
|
||||||
<BaseStyles />
|
<BaseStyles />
|
||||||
<NewProject
|
<NewProject
|
||||||
|
initialTeamID={null}
|
||||||
onCreateProject={action('create project')}
|
onCreateProject={action('create project')}
|
||||||
teams={[{ name: 'General', id: 'general', createdAt: '' }]}
|
teams={[{ name: 'General', id: 'general', createdAt: '' }]}
|
||||||
onClose={() => {}}
|
onClose={() => {}}
|
||||||
|
@ -207,14 +207,15 @@ const CreateButton = styled.button`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
type NewProjectProps = {
|
type NewProjectProps = {
|
||||||
|
initialTeamID: string | null;
|
||||||
teams: Array<Team>;
|
teams: Array<Team>;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onCreateProject: (projectName: string, teamID: string) => void;
|
onCreateProject: (projectName: string, teamID: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NewProject: React.FC<NewProjectProps> = ({ teams, onClose, onCreateProject }) => {
|
const NewProject: React.FC<NewProjectProps> = ({ initialTeamID, teams, onClose, onCreateProject }) => {
|
||||||
const [projectName, setProjectName] = useState('');
|
const [projectName, setProjectName] = useState('');
|
||||||
const [team, setTeam] = useState<null | string>(null);
|
const [team, setTeam] = useState<null | string>(initialTeamID);
|
||||||
const options = teams.map(t => ({ label: t.name, value: t.id }));
|
const options = teams.map(t => ({ label: t.name, value: t.id }));
|
||||||
return (
|
return (
|
||||||
<Overlay>
|
<Overlay>
|
||||||
|
@ -58,7 +58,7 @@ const LabelManager: React.FC<Props> = ({ labels, taskLabels, onLabelToggle, onLa
|
|||||||
onLabelEdit(label.id);
|
onLabelEdit(label.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Pencil color="#c2c6dc" />
|
<Pencil width={16} height={16} />
|
||||||
</LabelIcon>
|
</LabelIcon>
|
||||||
<CardLabel
|
<CardLabel
|
||||||
key={label.id}
|
key={label.id}
|
||||||
|
@ -42,7 +42,6 @@ export const HeaderTitle = styled.span`
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: #c2c6dc;
|
color: #c2c6dc;
|
||||||
display: block;
|
display: block;
|
||||||
line-height: 40px;
|
|
||||||
border-bottom: 1px solid #414561;
|
border-bottom: 1px solid #414561;
|
||||||
margin: 0 12px;
|
margin: 0 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -51,6 +50,13 @@ export const HeaderTitle = styled.span`
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
height: 40px;
|
||||||
|
line-height: 18px;
|
||||||
|
font-size: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Content = styled.div`
|
export const Content = styled.div`
|
||||||
@ -138,7 +144,7 @@ export const CardLabel = styled.span<{ active: boolean; color: string }>`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const CloseButton = styled.div`
|
export const CloseButton = styled.div`
|
||||||
padding: 10px 12px 10px 8px;
|
padding: 18px 18px 14px 12px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -312,7 +318,7 @@ export const CreateLabelButton = styled.button`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const PreviousButton = styled.div`
|
export const PreviousButton = styled.div`
|
||||||
padding: 10px 12px 10px 8px;
|
padding: 18px 18px 14px 12px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -2,7 +2,6 @@ import React, { useRef } from 'react';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const Container = styled.div<{ size: number | string; bgColor: string | null; backgroundURL: string | null }>`
|
export const Container = styled.div<{ size: number | string; bgColor: string | null; backgroundURL: string | null }>`
|
||||||
margin-left: 10px;
|
|
||||||
width: ${props => props.size}px;
|
width: ${props => props.size}px;
|
||||||
height: ${props => props.size}px;
|
height: ${props => props.size}px;
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
|
@ -52,6 +52,21 @@ const ProjectSettings: React.FC<Props> = ({ onDeleteProject }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type TeamSettingsProps = {
|
||||||
|
onDeleteTeam: () => void;
|
||||||
|
};
|
||||||
|
export const TeamSettings: React.FC<TeamSettingsProps> = ({ onDeleteTeam }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ListActionsWrapper>
|
||||||
|
<ListActionItemWrapper onClick={() => onDeleteTeam()}>
|
||||||
|
<ListActionItem>Delete Team</ListActionItem>
|
||||||
|
</ListActionItemWrapper>
|
||||||
|
</ListActionsWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const ConfirmWrapper = styled.div``;
|
const ConfirmWrapper = styled.div``;
|
||||||
|
|
||||||
const ConfirmSubTitle = styled.h3`
|
const ConfirmSubTitle = styled.h3`
|
||||||
@ -76,25 +91,40 @@ const ConfirmDeleteButton = styled(Button)`
|
|||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type DeleteProjectProps = {
|
type DeleteConfirmProps = {
|
||||||
name: string;
|
description: string;
|
||||||
onDeleteProject: () => void;
|
deletedItems: Array<string>;
|
||||||
|
onConfirmDelete: () => void;
|
||||||
};
|
};
|
||||||
const DeleteProject: React.FC<DeleteProjectProps> = ({ name, onDeleteProject }) => {
|
|
||||||
|
export const DELETE_INFO = {
|
||||||
|
DELETE_PROJECTS: {
|
||||||
|
description: 'Deleting the project will also delete the following:',
|
||||||
|
deletedItems: ['Task groups and tasks'],
|
||||||
|
},
|
||||||
|
DELETE_TEAMS: {
|
||||||
|
description: 'Deleting the team will also delete the following:',
|
||||||
|
deletedItems: ['Projects under the team', 'All task groups & tasks associated with the team projects'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeleteConfirm: React.FC<DeleteConfirmProps> = ({ description, deletedItems, onConfirmDelete }) => {
|
||||||
return (
|
return (
|
||||||
<ConfirmWrapper>
|
<ConfirmWrapper>
|
||||||
<ConfirmDescription>
|
<ConfirmDescription>
|
||||||
Deleting the project will also delete the following:
|
{description}
|
||||||
<DeleteList>
|
<DeleteList>
|
||||||
<DeleteListItem>Task groups and tasks</DeleteListItem>
|
{deletedItems.map(item => (
|
||||||
|
<DeleteListItem>{item}</DeleteListItem>
|
||||||
|
))}
|
||||||
</DeleteList>
|
</DeleteList>
|
||||||
</ConfirmDescription>
|
</ConfirmDescription>
|
||||||
<ConfirmDeleteButton onClick={() => onDeleteProject()} color="danger">
|
<ConfirmDeleteButton onClick={() => onConfirmDelete()} color="danger">
|
||||||
Delete
|
Delete
|
||||||
</ConfirmDeleteButton>
|
</ConfirmDeleteButton>
|
||||||
</ConfirmWrapper>
|
</ConfirmWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { DeleteProject };
|
export { DeleteConfirm };
|
||||||
export default ProjectSettings;
|
export default ProjectSettings;
|
||||||
|
@ -71,6 +71,9 @@ export const Default = () => {
|
|||||||
onToggleTaskComplete={action('toggle task complete')}
|
onToggleTaskComplete={action('toggle task complete')}
|
||||||
onToggleChecklistItem={action('toggle checklist item')}
|
onToggleChecklistItem={action('toggle checklist item')}
|
||||||
onOpenAddLabelPopup={action('open add label popup')}
|
onOpenAddLabelPopup={action('open add label popup')}
|
||||||
|
onChangeChecklistName={action('change checklist name')}
|
||||||
|
onDeleteChecklist={action('delete checklist')}
|
||||||
|
onOpenAddChecklistPopup={action(' open checklist')}
|
||||||
onOpenDueDatePopop={action('open due date popup')}
|
onOpenDueDatePopop={action('open due date popup')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -140,13 +140,19 @@ type TaskDetailsProps = {
|
|||||||
onOpenAddMemberPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
|
onOpenAddMemberPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
|
||||||
onOpenAddLabelPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
|
onOpenAddLabelPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
|
||||||
onOpenDueDatePopop: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
|
onOpenDueDatePopop: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
|
||||||
|
onOpenAddChecklistPopup: (task: Task, $targetRef: React.RefObject<HTMLElement>) => void;
|
||||||
onMemberProfile: ($targetRef: React.RefObject<HTMLElement>, memberID: string) => void;
|
onMemberProfile: ($targetRef: React.RefObject<HTMLElement>, memberID: string) => void;
|
||||||
|
onChangeChecklistName: (checklistID: string, name: string) => void;
|
||||||
|
onDeleteChecklist: ($target: React.RefObject<HTMLElement>, checklistID: string) => void;
|
||||||
onCloseModal: () => void;
|
onCloseModal: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TaskDetails: React.FC<TaskDetailsProps> = ({
|
const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||||
task,
|
task,
|
||||||
|
onDeleteChecklist,
|
||||||
onTaskNameChange,
|
onTaskNameChange,
|
||||||
|
onOpenAddChecklistPopup,
|
||||||
|
onChangeChecklistName,
|
||||||
onToggleTaskComplete,
|
onToggleTaskComplete,
|
||||||
onTaskDescriptionChange,
|
onTaskDescriptionChange,
|
||||||
onChangeItemName,
|
onChangeItemName,
|
||||||
@ -183,6 +189,9 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
|||||||
const onAddMember = ($target: React.RefObject<HTMLElement>) => {
|
const onAddMember = ($target: React.RefObject<HTMLElement>) => {
|
||||||
onOpenAddMemberPopup(task, $target);
|
onOpenAddMemberPopup(task, $target);
|
||||||
};
|
};
|
||||||
|
const onAddChecklist = ($target: React.RefObject<HTMLElement>) => {
|
||||||
|
onOpenAddChecklistPopup(task, $target)
|
||||||
|
}
|
||||||
const $dueDateLabel = useRef<HTMLDivElement>(null);
|
const $dueDateLabel = useRef<HTMLDivElement>(null);
|
||||||
const $addLabelRef = useRef<HTMLDivElement>(null);
|
const $addLabelRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
@ -290,16 +299,16 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
|||||||
name={checklist.name}
|
name={checklist.name}
|
||||||
checklistID={checklist.id}
|
checklistID={checklist.id}
|
||||||
items={checklist.items}
|
items={checklist.items}
|
||||||
onDeleteChecklist={() => {}}
|
onDeleteChecklist={onDeleteChecklist}
|
||||||
onChangeName={() => {}}
|
onChangeName={newName => onChangeChecklistName(checklist.id, newName)}
|
||||||
onToggleItem={onToggleChecklistItem}
|
onToggleItem={onToggleChecklistItem}
|
||||||
onDeleteItem={onDeleteItem}
|
onDeleteItem={onDeleteItem}
|
||||||
onAddItem={n => {
|
onAddItem={n => {
|
||||||
if (task.checklists) {
|
if (task.checklists) {
|
||||||
let position = 1;
|
let position = 65535;
|
||||||
const lastChecklist = task.checklists.sort((a, b) => a.position - b.position)[-1];
|
const [lastItem] = checklist.items.sort((a, b) => a.position - b.position).slice(-1);
|
||||||
if (lastChecklist) {
|
if (lastItem) {
|
||||||
position = lastChecklist.position * 2 + 1;
|
position = lastItem.position * 2 + 1;
|
||||||
}
|
}
|
||||||
onAddItem(checklist.id, n, position);
|
onAddItem(checklist.id, n, position);
|
||||||
}
|
}
|
||||||
@ -317,7 +326,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
|||||||
</ActionButton>
|
</ActionButton>
|
||||||
<ActionButton onClick={$target => onAddMember($target)}>Members</ActionButton>
|
<ActionButton onClick={$target => onAddMember($target)}>Members</ActionButton>
|
||||||
<ActionButton onClick={$target => onAddLabel($target)}>Labels</ActionButton>
|
<ActionButton onClick={$target => onAddLabel($target)}>Labels</ActionButton>
|
||||||
<ActionButton>Checklist</ActionButton>
|
<ActionButton onClick={$target => onAddChecklist($target)}>Checklist</ActionButton>
|
||||||
<ActionButton onClick={$target => onOpenDueDatePopop(task, $target)}>Due Date</ActionButton>
|
<ActionButton onClick={$target => onOpenDueDatePopop(task, $target)}>Due Date</ActionButton>
|
||||||
<ActionButton>Attachment</ActionButton>
|
<ActionButton>Attachment</ActionButton>
|
||||||
<ActionButton>Cover</ActionButton>
|
<ActionButton>Cover</ActionButton>
|
||||||
|
@ -2,6 +2,8 @@ import styled, { css } from 'styled-components';
|
|||||||
import TextareaAutosize from 'react-autosize-textarea';
|
import TextareaAutosize from 'react-autosize-textarea';
|
||||||
import { mixin } from 'shared/utils/styles';
|
import { mixin } from 'shared/utils/styles';
|
||||||
import Button from 'shared/components/Button';
|
import Button from 'shared/components/Button';
|
||||||
|
import { Citadel } from 'shared/icons';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
export const NavbarWrapper = styled.div`
|
export const NavbarWrapper = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -9,7 +11,6 @@ export const NavbarWrapper = styled.div`
|
|||||||
|
|
||||||
export const ProjectMembers = styled.div`
|
export const ProjectMembers = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-right: 18px;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
export const NavbarHeader = styled.header`
|
export const NavbarHeader = styled.header`
|
||||||
@ -34,9 +35,9 @@ export const BreadcrumpSeparator = styled.span`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const ProjectActions = styled.div`
|
export const ProjectActions = styled.div`
|
||||||
|
flex: 1;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-width: 1px;
|
min-width: 1px;
|
||||||
`;
|
`;
|
||||||
@ -56,10 +57,11 @@ export const ProfileNameWrapper = styled.div`
|
|||||||
line-height: 1.25;
|
line-height: 1.25;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const NotificationContainer = styled.div`
|
export const IconContainer = styled.div`
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ProfileNamePrimary = styled.div`
|
export const ProfileNamePrimary = styled.div`
|
||||||
color: #c2c6dc;
|
color: #c2c6dc;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -70,7 +72,6 @@ export const ProfileNameSecondary = styled.small`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const ProfileIcon = styled.div<{ bgColor: string | null; backgroundURL: string | null }>`
|
export const ProfileIcon = styled.div<{ bgColor: string | null; backgroundURL: string | null }>`
|
||||||
margin-left: 10px;
|
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
@ -84,9 +85,9 @@ export const ProfileIcon = styled.div<{ bgColor: string | null; backgroundURL: s
|
|||||||
background-size: contain;
|
background-size: contain;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ProjectMeta = styled.div`
|
export const ProjectMeta = styled.div<{ nameOnly?: boolean }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-top: 9px;
|
${props => !props.nameOnly && 'padding-top: 9px;'}
|
||||||
margin-left: -14px;
|
margin-left: -14px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@ -188,7 +189,7 @@ export const ProjectSwitcher = styled.button`
|
|||||||
|
|
||||||
export const Separator = styled.div`
|
export const Separator = styled.div`
|
||||||
color: #c2c6dc;
|
color: #c2c6dc;
|
||||||
font-size: 16px;
|
font-size: 20px;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
`;
|
`;
|
||||||
@ -214,3 +215,36 @@ export const InviteButton = styled(Button)`
|
|||||||
margin: 0 0 0 8px;
|
margin: 0 0 0 8px;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const ProjectFinder = styled(Button)`
|
||||||
|
margin-right: 20px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const NavSeparator = styled.div`
|
||||||
|
width: 1px;
|
||||||
|
background: rgba(${props => props.theme.colors.border});
|
||||||
|
height: 34px;
|
||||||
|
margin: 0 20px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LogoContainer = styled(Link)`
|
||||||
|
display: block;
|
||||||
|
left: 50%;
|
||||||
|
position: absolute;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CitadelTitle = styled.h2`
|
||||||
|
margin-left: 5px;
|
||||||
|
color: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
font-size: 20px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CitadelLogo = styled(Citadel)`
|
||||||
|
fill: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
stroke: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
`;
|
||||||
|
@ -26,7 +26,8 @@ export const Default = () => {
|
|||||||
<NormalizeStyles />
|
<NormalizeStyles />
|
||||||
<BaseStyles />
|
<BaseStyles />
|
||||||
<TopNavbar
|
<TopNavbar
|
||||||
projectName="Projects"
|
onOpenProjectFinder={action('finder')}
|
||||||
|
name="Projects"
|
||||||
user={{
|
user={{
|
||||||
id: '1',
|
id: '1',
|
||||||
fullName: 'Jordan Knott',
|
fullName: 'Jordan Knott',
|
||||||
@ -38,6 +39,7 @@ export const Default = () => {
|
|||||||
}}
|
}}
|
||||||
onNotificationClick={action('notifications click')}
|
onNotificationClick={action('notifications click')}
|
||||||
onOpenSettings={action('open settings')}
|
onOpenSettings={action('open settings')}
|
||||||
|
onDashboardClick={action('open dashboard')}
|
||||||
onProfileClick={action('profile click')}
|
onProfileClick={action('profile click')}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -1,22 +1,27 @@
|
|||||||
import React, { useRef, useState, useEffect } from 'react';
|
import React, { useRef, useState, useEffect } from 'react';
|
||||||
import { Star, Ellipsis, Bell, Cog, AngleDown } from 'shared/icons';
|
import { Home, Star, Bell, AngleDown, BarChart, CheckCircle } from 'shared/icons';
|
||||||
|
import styled from 'styled-components';
|
||||||
import ProfileIcon from 'shared/components/ProfileIcon';
|
import ProfileIcon from 'shared/components/ProfileIcon';
|
||||||
|
import TaskAssignee from 'shared/components/TaskAssignee';
|
||||||
|
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||||
|
import MiniProfile from 'shared/components/MiniProfile';
|
||||||
import {
|
import {
|
||||||
NotificationContainer,
|
CitadelLogo,
|
||||||
|
CitadelTitle,
|
||||||
|
ProjectFinder,
|
||||||
|
LogoContainer,
|
||||||
|
NavSeparator,
|
||||||
|
IconContainer,
|
||||||
ProjectNameTextarea,
|
ProjectNameTextarea,
|
||||||
InviteButton,
|
InviteButton,
|
||||||
GlobalActions,
|
GlobalActions,
|
||||||
ProjectActions,
|
ProjectActions,
|
||||||
ProjectSwitcher,
|
|
||||||
Separator,
|
|
||||||
ProjectMeta,
|
ProjectMeta,
|
||||||
ProjectName,
|
ProjectName,
|
||||||
ProjectTabs,
|
ProjectTabs,
|
||||||
ProjectTab,
|
ProjectTab,
|
||||||
NavbarWrapper,
|
NavbarWrapper,
|
||||||
NavbarHeader,
|
NavbarHeader,
|
||||||
Breadcrumbs,
|
|
||||||
BreadcrumpSeparator,
|
|
||||||
ProjectSettingsButton,
|
ProjectSettingsButton,
|
||||||
ProfileContainer,
|
ProfileContainer,
|
||||||
ProfileNameWrapper,
|
ProfileNameWrapper,
|
||||||
@ -24,18 +29,20 @@ import {
|
|||||||
ProfileNameSecondary,
|
ProfileNameSecondary,
|
||||||
ProjectMembers,
|
ProjectMembers,
|
||||||
} from './Styles';
|
} from './Styles';
|
||||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
import { Link } from 'react-router-dom';
|
||||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
|
||||||
import MiniProfile from 'shared/components/MiniProfile';
|
const HomeDashboard = styled(Home)``;
|
||||||
|
|
||||||
type ProjectHeadingProps = {
|
type ProjectHeadingProps = {
|
||||||
projectName: string;
|
onFavorite?: () => void;
|
||||||
|
name: string;
|
||||||
onSaveProjectName?: (projectName: string) => void;
|
onSaveProjectName?: (projectName: string) => void;
|
||||||
onOpenSettings: ($target: React.RefObject<HTMLElement>) => void;
|
onOpenSettings: ($target: React.RefObject<HTMLElement>) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ProjectHeading: React.FC<ProjectHeadingProps> = ({
|
const ProjectHeading: React.FC<ProjectHeadingProps> = ({
|
||||||
projectName: initialProjectName,
|
onFavorite,
|
||||||
|
name: initialProjectName,
|
||||||
onSaveProjectName,
|
onSaveProjectName,
|
||||||
onOpenSettings,
|
onOpenSettings,
|
||||||
}) => {
|
}) => {
|
||||||
@ -73,7 +80,6 @@ const ProjectHeading: React.FC<ProjectHeadingProps> = ({
|
|||||||
const $settings = useRef<HTMLButtonElement>(null);
|
const $settings = useRef<HTMLButtonElement>(null);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Separator>»</Separator>
|
|
||||||
{isEditProjectName ? (
|
{isEditProjectName ? (
|
||||||
<ProjectNameTextarea
|
<ProjectNameTextarea
|
||||||
ref={$projectName}
|
ref={$projectName}
|
||||||
@ -100,28 +106,54 @@ const ProjectHeading: React.FC<ProjectHeadingProps> = ({
|
|||||||
>
|
>
|
||||||
<AngleDown color="#c2c6dc" />
|
<AngleDown color="#c2c6dc" />
|
||||||
</ProjectSettingsButton>
|
</ProjectSettingsButton>
|
||||||
<ProjectSettingsButton>
|
{onFavorite && (
|
||||||
<Star width={16} height={16} color="#c2c6dc" />
|
<ProjectSettingsButton onClick={() => onFavorite()}>
|
||||||
</ProjectSettingsButton>
|
<Star width={16} height={16} color="#c2c6dc" />
|
||||||
|
</ProjectSettingsButton>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type MenuType = {
|
||||||
|
[key: number]: string;
|
||||||
|
};
|
||||||
|
type MenuTypes = {
|
||||||
|
[key: string]: Array<string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MENU_TYPES: MenuTypes = {
|
||||||
|
PROJECT_MENU: ['Board', 'Timeline', 'Calender'],
|
||||||
|
TEAM_MENU: ['Projects', 'Members', 'Settings'],
|
||||||
|
};
|
||||||
|
|
||||||
type NavBarProps = {
|
type NavBarProps = {
|
||||||
projectName: string | null;
|
menuType?: Array<string> | null;
|
||||||
|
name: string | null;
|
||||||
|
currentTab?: number;
|
||||||
|
onOpenProjectFinder: ($target: React.RefObject<HTMLElement>) => void;
|
||||||
|
onFavorite?: () => void;
|
||||||
onProfileClick: ($target: React.RefObject<HTMLElement>) => void;
|
onProfileClick: ($target: React.RefObject<HTMLElement>) => void;
|
||||||
onSaveProjectName?: (projectName: string) => void;
|
onTabClick?: (tab: number) => void;
|
||||||
|
onSaveName?: (name: string) => void;
|
||||||
onNotificationClick: () => void;
|
onNotificationClick: () => void;
|
||||||
|
onDashboardClick: () => void;
|
||||||
user: TaskUser | null;
|
user: TaskUser | null;
|
||||||
onOpenSettings: ($target: React.RefObject<HTMLElement>) => void;
|
onOpenSettings: ($target: React.RefObject<HTMLElement>) => void;
|
||||||
projectMembers?: Array<TaskUser> | null;
|
projectMembers?: Array<TaskUser> | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NavBar: React.FC<NavBarProps> = ({
|
const NavBar: React.FC<NavBarProps> = ({
|
||||||
projectName,
|
menuType,
|
||||||
onSaveProjectName,
|
currentTab,
|
||||||
|
onOpenProjectFinder,
|
||||||
|
onFavorite,
|
||||||
|
onTabClick,
|
||||||
|
name,
|
||||||
|
onSaveName,
|
||||||
onProfileClick,
|
onProfileClick,
|
||||||
onNotificationClick,
|
onNotificationClick,
|
||||||
|
onDashboardClick,
|
||||||
user,
|
user,
|
||||||
projectMembers,
|
projectMembers,
|
||||||
onOpenSettings,
|
onOpenSettings,
|
||||||
@ -152,45 +184,61 @@ const NavBar: React.FC<NavBarProps> = ({
|
|||||||
<NavbarHeader>
|
<NavbarHeader>
|
||||||
<ProjectActions>
|
<ProjectActions>
|
||||||
<ProjectMeta>
|
<ProjectMeta>
|
||||||
<ProjectSwitcher>Projects</ProjectSwitcher>
|
{name && (
|
||||||
{projectName && (
|
|
||||||
<ProjectHeading
|
<ProjectHeading
|
||||||
|
onFavorite={onFavorite}
|
||||||
onOpenSettings={onOpenSettings}
|
onOpenSettings={onOpenSettings}
|
||||||
projectName={projectName}
|
name={name}
|
||||||
onSaveProjectName={onSaveProjectName}
|
onSaveProjectName={onSaveName}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ProjectMeta>
|
</ProjectMeta>
|
||||||
{projectName && (
|
{name && (
|
||||||
<ProjectTabs>
|
<ProjectTabs>
|
||||||
<ProjectTab active>Board</ProjectTab>
|
{menuType &&
|
||||||
<ProjectTab>Calender</ProjectTab>
|
menuType.map((name, idx) => {
|
||||||
<ProjectTab>Timeline</ProjectTab>
|
console.log(`${name} : ${idx} === ${currentTab}`);
|
||||||
<ProjectTab>Wiki</ProjectTab>
|
return <ProjectTab active={currentTab === idx}>{name}</ProjectTab>;
|
||||||
|
})}
|
||||||
</ProjectTabs>
|
</ProjectTabs>
|
||||||
)}
|
)}
|
||||||
</ProjectActions>
|
</ProjectActions>
|
||||||
|
<LogoContainer to="/">
|
||||||
|
<CitadelLogo width={24} height={24} />
|
||||||
|
<CitadelTitle>Citadel</CitadelTitle>
|
||||||
|
</LogoContainer>
|
||||||
<GlobalActions>
|
<GlobalActions>
|
||||||
{projectMembers && (
|
{projectMembers && (
|
||||||
<ProjectMembers>
|
<>
|
||||||
{projectMembers.map(member => (
|
<ProjectMembers>
|
||||||
<TaskAssignee key={member.id} size={28} member={member} onMemberProfile={onMemberProfile} />
|
{projectMembers.map(member => (
|
||||||
))}
|
<TaskAssignee key={member.id} size={28} member={member} onMemberProfile={onMemberProfile} />
|
||||||
<InviteButton variant="outline">Invite</InviteButton>
|
))}
|
||||||
</ProjectMembers>
|
<InviteButton variant="outline">Invite</InviteButton>
|
||||||
|
</ProjectMembers>
|
||||||
|
<NavSeparator />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<NotificationContainer onClick={onNotificationClick}>
|
<ProjectFinder onClick={onOpenProjectFinder} variant="gradient">
|
||||||
|
Projects
|
||||||
|
</ProjectFinder>
|
||||||
|
<IconContainer onClick={onDashboardClick}>
|
||||||
|
<HomeDashboard width={20} height={20} />
|
||||||
|
</IconContainer>
|
||||||
|
<IconContainer>
|
||||||
|
<CheckCircle width={20} height={20} />
|
||||||
|
</IconContainer>
|
||||||
|
<IconContainer onClick={onNotificationClick}>
|
||||||
<Bell color="#c2c6dc" size={20} />
|
<Bell color="#c2c6dc" size={20} />
|
||||||
</NotificationContainer>
|
</IconContainer>
|
||||||
|
<IconContainer>
|
||||||
|
<BarChart width={20} height={20} />
|
||||||
|
</IconContainer>
|
||||||
|
|
||||||
{user && (
|
{user && (
|
||||||
<ProfileContainer>
|
<IconContainer>
|
||||||
<ProfileNameWrapper>
|
<ProfileIcon user={user} size={30} onProfileClick={handleProfileClick} />
|
||||||
<ProfileNamePrimary>{user.fullName}</ProfileNamePrimary>
|
</IconContainer>
|
||||||
<ProfileNameSecondary>Manager</ProfileNameSecondary>
|
|
||||||
</ProfileNameWrapper>
|
|
||||||
<ProfileIcon user={user} size={40} onProfileClick={handleProfileClick} />}
|
|
||||||
</ProfileContainer>
|
|
||||||
)}
|
)}
|
||||||
</GlobalActions>
|
</GlobalActions>
|
||||||
</NavbarHeader>
|
</NavbarHeader>
|
||||||
|
@ -131,7 +131,7 @@ export type Task = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ProjectsFilter = {
|
export type ProjectsFilter = {
|
||||||
teamID?: Maybe<Scalars['String']>;
|
teamID?: Maybe<Scalars['UUID']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FindUser = {
|
export type FindUser = {
|
||||||
@ -152,6 +152,10 @@ export type Organization = {
|
|||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FindTeam = {
|
||||||
|
teamID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
export type Query = {
|
export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
organizations: Array<Organization>;
|
organizations: Array<Organization>;
|
||||||
@ -160,6 +164,7 @@ export type Query = {
|
|||||||
findProject: Project;
|
findProject: Project;
|
||||||
findTask: Task;
|
findTask: Task;
|
||||||
projects: Array<Project>;
|
projects: Array<Project>;
|
||||||
|
findTeam: Team;
|
||||||
teams: Array<Team>;
|
teams: Array<Team>;
|
||||||
labelColors: Array<LabelColor>;
|
labelColors: Array<LabelColor>;
|
||||||
taskGroups: Array<TaskGroup>;
|
taskGroups: Array<TaskGroup>;
|
||||||
@ -186,6 +191,11 @@ export type QueryProjectsArgs = {
|
|||||||
input?: Maybe<ProjectsFilter>;
|
input?: Maybe<ProjectsFilter>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryFindTeamArgs = {
|
||||||
|
input: FindTeam;
|
||||||
|
};
|
||||||
|
|
||||||
export type NewRefreshToken = {
|
export type NewRefreshToken = {
|
||||||
userId: Scalars['String'];
|
userId: Scalars['String'];
|
||||||
};
|
};
|
||||||
@ -419,10 +429,48 @@ export type DeleteProjectPayload = {
|
|||||||
project: Project;
|
project: Project;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DeleteTeam = {
|
||||||
|
teamID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DeleteTeamPayload = {
|
||||||
|
__typename?: 'DeleteTeamPayload';
|
||||||
|
ok: Scalars['Boolean'];
|
||||||
|
team: Team;
|
||||||
|
projects: Array<Project>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DeleteUserAccount = {
|
||||||
|
userID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DeleteUserAccountPayload = {
|
||||||
|
__typename?: 'DeleteUserAccountPayload';
|
||||||
|
ok: Scalars['Boolean'];
|
||||||
|
userAccount: UserAccount;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UpdateTaskChecklistName = {
|
||||||
|
taskChecklistID: Scalars['UUID'];
|
||||||
|
name: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DeleteTaskChecklist = {
|
||||||
|
taskChecklistID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DeleteTaskChecklistPayload = {
|
||||||
|
__typename?: 'DeleteTaskChecklistPayload';
|
||||||
|
ok: Scalars['Boolean'];
|
||||||
|
taskChecklist: TaskChecklist;
|
||||||
|
};
|
||||||
|
|
||||||
export type Mutation = {
|
export type Mutation = {
|
||||||
__typename?: 'Mutation';
|
__typename?: 'Mutation';
|
||||||
createRefreshToken: RefreshToken;
|
createRefreshToken: RefreshToken;
|
||||||
createUserAccount: UserAccount;
|
createUserAccount: UserAccount;
|
||||||
|
deleteUserAccount: DeleteUserAccountPayload;
|
||||||
|
deleteTeam: DeleteTeamPayload;
|
||||||
createTeam: Team;
|
createTeam: Team;
|
||||||
clearProfileAvatar: UserAccount;
|
clearProfileAvatar: UserAccount;
|
||||||
createTeamMember: CreateTeamMemberPayload;
|
createTeamMember: CreateTeamMemberPayload;
|
||||||
@ -442,6 +490,8 @@ export type Mutation = {
|
|||||||
removeTaskLabel: Task;
|
removeTaskLabel: Task;
|
||||||
toggleTaskLabel: ToggleTaskLabelPayload;
|
toggleTaskLabel: ToggleTaskLabelPayload;
|
||||||
createTaskChecklist: TaskChecklist;
|
createTaskChecklist: TaskChecklist;
|
||||||
|
deleteTaskChecklist: DeleteTaskChecklistPayload;
|
||||||
|
updateTaskChecklistName: TaskChecklist;
|
||||||
createTaskChecklistItem: TaskChecklistItem;
|
createTaskChecklistItem: TaskChecklistItem;
|
||||||
updateTaskChecklistItemName: TaskChecklistItem;
|
updateTaskChecklistItemName: TaskChecklistItem;
|
||||||
setTaskChecklistItemComplete: TaskChecklistItem;
|
setTaskChecklistItemComplete: TaskChecklistItem;
|
||||||
@ -469,6 +519,16 @@ export type MutationCreateUserAccountArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationDeleteUserAccountArgs = {
|
||||||
|
input: DeleteUserAccount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationDeleteTeamArgs = {
|
||||||
|
input: DeleteTeam;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateTeamArgs = {
|
export type MutationCreateTeamArgs = {
|
||||||
input: NewTeam;
|
input: NewTeam;
|
||||||
};
|
};
|
||||||
@ -559,6 +619,16 @@ export type MutationCreateTaskChecklistArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationDeleteTaskChecklistArgs = {
|
||||||
|
input: DeleteTaskChecklist;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUpdateTaskChecklistNameArgs = {
|
||||||
|
input: UpdateTaskChecklistName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateTaskChecklistItemArgs = {
|
export type MutationCreateTaskChecklistItemArgs = {
|
||||||
input: CreateTaskChecklistItem;
|
input: CreateTaskChecklistItem;
|
||||||
};
|
};
|
||||||
@ -699,43 +769,6 @@ export type CreateProjectLabelMutation = (
|
|||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
export type CreateTaskMutationVariables = {
|
|
||||||
taskGroupID: Scalars['String'];
|
|
||||||
name: Scalars['String'];
|
|
||||||
position: Scalars['Float'];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export type CreateTaskMutation = (
|
|
||||||
{ __typename?: 'Mutation' }
|
|
||||||
& { createTask: (
|
|
||||||
{ __typename?: 'Task' }
|
|
||||||
& Pick<Task, 'id' | 'name' | 'position' | 'description' | 'dueDate'>
|
|
||||||
& { taskGroup: (
|
|
||||||
{ __typename?: 'TaskGroup' }
|
|
||||||
& Pick<TaskGroup, 'id' | 'name' | 'position'>
|
|
||||||
), labels: Array<(
|
|
||||||
{ __typename?: 'TaskLabel' }
|
|
||||||
& Pick<TaskLabel, 'id' | 'assignedDate'>
|
|
||||||
& { projectLabel: (
|
|
||||||
{ __typename?: 'ProjectLabel' }
|
|
||||||
& Pick<ProjectLabel, 'id' | 'name' | 'createdDate'>
|
|
||||||
& { labelColor: (
|
|
||||||
{ __typename?: 'LabelColor' }
|
|
||||||
& Pick<LabelColor, 'id' | 'colorHex' | 'position' | 'name'>
|
|
||||||
) }
|
|
||||||
) }
|
|
||||||
)>, assigned: Array<(
|
|
||||||
{ __typename?: 'ProjectMember' }
|
|
||||||
& Pick<ProjectMember, 'id' | 'fullName'>
|
|
||||||
& { profileIcon: (
|
|
||||||
{ __typename?: 'ProfileIcon' }
|
|
||||||
& Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
|
|
||||||
) }
|
|
||||||
)> }
|
|
||||||
) }
|
|
||||||
);
|
|
||||||
|
|
||||||
export type CreateTaskGroupMutationVariables = {
|
export type CreateTaskGroupMutationVariables = {
|
||||||
projectID: Scalars['String'];
|
projectID: Scalars['String'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
@ -849,6 +882,12 @@ export type FindTaskQuery = (
|
|||||||
& { taskGroup: (
|
& { taskGroup: (
|
||||||
{ __typename?: 'TaskGroup' }
|
{ __typename?: 'TaskGroup' }
|
||||||
& Pick<TaskGroup, 'id'>
|
& Pick<TaskGroup, 'id'>
|
||||||
|
), badges: (
|
||||||
|
{ __typename?: 'TaskBadges' }
|
||||||
|
& { checklist?: Maybe<(
|
||||||
|
{ __typename?: 'ChecklistBadge' }
|
||||||
|
& Pick<ChecklistBadge, 'total' | 'complete'>
|
||||||
|
)> }
|
||||||
), checklists: Array<(
|
), checklists: Array<(
|
||||||
{ __typename?: 'TaskChecklist' }
|
{ __typename?: 'TaskChecklist' }
|
||||||
& Pick<TaskChecklist, 'id' | 'name' | 'position'>
|
& Pick<TaskChecklist, 'id' | 'name' | 'position'>
|
||||||
@ -881,9 +920,15 @@ export type FindTaskQuery = (
|
|||||||
export type TaskFieldsFragment = (
|
export type TaskFieldsFragment = (
|
||||||
{ __typename?: 'Task' }
|
{ __typename?: 'Task' }
|
||||||
& Pick<Task, 'id' | 'name' | 'description' | 'dueDate' | 'complete' | 'position'>
|
& Pick<Task, 'id' | 'name' | 'description' | 'dueDate' | 'complete' | 'position'>
|
||||||
& { taskGroup: (
|
& { badges: (
|
||||||
|
{ __typename?: 'TaskBadges' }
|
||||||
|
& { checklist?: Maybe<(
|
||||||
|
{ __typename?: 'ChecklistBadge' }
|
||||||
|
& Pick<ChecklistBadge, 'complete' | 'total'>
|
||||||
|
)> }
|
||||||
|
), taskGroup: (
|
||||||
{ __typename?: 'TaskGroup' }
|
{ __typename?: 'TaskGroup' }
|
||||||
& Pick<TaskGroup, 'id'>
|
& Pick<TaskGroup, 'id' | 'name' | 'position'>
|
||||||
), labels: Array<(
|
), labels: Array<(
|
||||||
{ __typename?: 'TaskLabel' }
|
{ __typename?: 'TaskLabel' }
|
||||||
& Pick<TaskLabel, 'id' | 'assignedDate'>
|
& Pick<TaskLabel, 'id' | 'assignedDate'>
|
||||||
@ -958,6 +1003,40 @@ export type DeleteProjectMutation = (
|
|||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export type CreateTaskMutationVariables = {
|
||||||
|
taskGroupID: Scalars['String'];
|
||||||
|
name: Scalars['String'];
|
||||||
|
position: Scalars['Float'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type CreateTaskMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { createTask: (
|
||||||
|
{ __typename?: 'Task' }
|
||||||
|
& TaskFieldsFragment
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
|
export type CreateTaskChecklistMutationVariables = {
|
||||||
|
taskID: Scalars['UUID'];
|
||||||
|
name: Scalars['String'];
|
||||||
|
position: Scalars['Float'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type CreateTaskChecklistMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { createTaskChecklist: (
|
||||||
|
{ __typename?: 'TaskChecklist' }
|
||||||
|
& Pick<TaskChecklist, 'id' | 'name' | 'position'>
|
||||||
|
& { items: Array<(
|
||||||
|
{ __typename?: 'TaskChecklistItem' }
|
||||||
|
& Pick<TaskChecklistItem, 'id' | 'name' | 'taskChecklistID' | 'complete' | 'position'>
|
||||||
|
)> }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type CreateTaskChecklistItemMutationVariables = {
|
export type CreateTaskChecklistItemMutationVariables = {
|
||||||
taskChecklistID: Scalars['UUID'];
|
taskChecklistID: Scalars['UUID'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
@ -973,6 +1052,23 @@ export type CreateTaskChecklistItemMutation = (
|
|||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export type DeleteTaskChecklistMutationVariables = {
|
||||||
|
taskChecklistID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type DeleteTaskChecklistMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { deleteTaskChecklist: (
|
||||||
|
{ __typename?: 'DeleteTaskChecklistPayload' }
|
||||||
|
& Pick<DeleteTaskChecklistPayload, 'ok'>
|
||||||
|
& { taskChecklist: (
|
||||||
|
{ __typename?: 'TaskChecklist' }
|
||||||
|
& Pick<TaskChecklist, 'id'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type DeleteTaskChecklistItemMutationVariables = {
|
export type DeleteTaskChecklistItemMutationVariables = {
|
||||||
taskChecklistItemID: Scalars['UUID'];
|
taskChecklistItemID: Scalars['UUID'];
|
||||||
};
|
};
|
||||||
@ -1000,7 +1096,7 @@ export type SetTaskChecklistItemCompleteMutation = (
|
|||||||
{ __typename?: 'Mutation' }
|
{ __typename?: 'Mutation' }
|
||||||
& { setTaskChecklistItemComplete: (
|
& { setTaskChecklistItemComplete: (
|
||||||
{ __typename?: 'TaskChecklistItem' }
|
{ __typename?: 'TaskChecklistItem' }
|
||||||
& Pick<TaskChecklistItem, 'id' | 'name' | 'taskChecklistID' | 'complete' | 'position'>
|
& Pick<TaskChecklistItem, 'id' | 'complete'>
|
||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1032,6 +1128,24 @@ export type UpdateTaskChecklistItemNameMutation = (
|
|||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export type UpdateTaskChecklistNameMutationVariables = {
|
||||||
|
taskChecklistID: Scalars['UUID'];
|
||||||
|
name: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type UpdateTaskChecklistNameMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { updateTaskChecklistName: (
|
||||||
|
{ __typename?: 'TaskChecklist' }
|
||||||
|
& Pick<TaskChecklist, 'id' | 'name' | 'position'>
|
||||||
|
& { items: Array<(
|
||||||
|
{ __typename?: 'TaskChecklistItem' }
|
||||||
|
& Pick<TaskChecklistItem, 'id' | 'name' | 'taskChecklistID' | 'complete' | 'position'>
|
||||||
|
)> }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
export type UpdateTaskGroupNameMutationVariables = {
|
export type UpdateTaskGroupNameMutationVariables = {
|
||||||
taskGroupID: Scalars['UUID'];
|
taskGroupID: Scalars['UUID'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
@ -1060,6 +1174,43 @@ export type CreateTeamMutation = (
|
|||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export type DeleteTeamMutationVariables = {
|
||||||
|
teamID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type DeleteTeamMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { deleteTeam: (
|
||||||
|
{ __typename?: 'DeleteTeamPayload' }
|
||||||
|
& Pick<DeleteTeamPayload, 'ok'>
|
||||||
|
& { team: (
|
||||||
|
{ __typename?: 'Team' }
|
||||||
|
& Pick<Team, 'id'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
|
export type GetTeamQueryVariables = {
|
||||||
|
teamID: Scalars['UUID'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type GetTeamQuery = (
|
||||||
|
{ __typename?: 'Query' }
|
||||||
|
& { findTeam: (
|
||||||
|
{ __typename?: 'Team' }
|
||||||
|
& Pick<Team, 'id' | 'createdAt' | 'name'>
|
||||||
|
), projects: Array<(
|
||||||
|
{ __typename?: 'Project' }
|
||||||
|
& Pick<Project, 'id' | 'name'>
|
||||||
|
& { team: (
|
||||||
|
{ __typename?: 'Team' }
|
||||||
|
& Pick<Team, 'id' | 'name'>
|
||||||
|
) }
|
||||||
|
)> }
|
||||||
|
);
|
||||||
|
|
||||||
export type ToggleTaskLabelMutationVariables = {
|
export type ToggleTaskLabelMutationVariables = {
|
||||||
taskID: Scalars['UUID'];
|
taskID: Scalars['UUID'];
|
||||||
projectLabelID: Scalars['UUID'];
|
projectLabelID: Scalars['UUID'];
|
||||||
@ -1220,6 +1371,42 @@ export type UpdateTaskNameMutation = (
|
|||||||
) }
|
) }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export type CreateUserAccountMutationVariables = {
|
||||||
|
username: Scalars['String'];
|
||||||
|
email: Scalars['String'];
|
||||||
|
fullName: Scalars['String'];
|
||||||
|
initials: Scalars['String'];
|
||||||
|
password: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type CreateUserAccountMutation = (
|
||||||
|
{ __typename?: 'Mutation' }
|
||||||
|
& { createUserAccount: (
|
||||||
|
{ __typename?: 'UserAccount' }
|
||||||
|
& Pick<UserAccount, 'id' | 'email' | 'fullName' | 'initials' | 'username'>
|
||||||
|
& { profileIcon: (
|
||||||
|
{ __typename?: 'ProfileIcon' }
|
||||||
|
& Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
|
||||||
|
) }
|
||||||
|
) }
|
||||||
|
);
|
||||||
|
|
||||||
|
export type UsersQueryVariables = {};
|
||||||
|
|
||||||
|
|
||||||
|
export type UsersQuery = (
|
||||||
|
{ __typename?: 'Query' }
|
||||||
|
& { users: Array<(
|
||||||
|
{ __typename?: 'UserAccount' }
|
||||||
|
& Pick<UserAccount, 'id' | 'email' | 'fullName' | 'username'>
|
||||||
|
& { profileIcon: (
|
||||||
|
{ __typename?: 'ProfileIcon' }
|
||||||
|
& Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
|
||||||
|
) }
|
||||||
|
)> }
|
||||||
|
);
|
||||||
|
|
||||||
export const TaskFieldsFragmentDoc = gql`
|
export const TaskFieldsFragmentDoc = gql`
|
||||||
fragment TaskFields on Task {
|
fragment TaskFields on Task {
|
||||||
id
|
id
|
||||||
@ -1228,8 +1415,16 @@ export const TaskFieldsFragmentDoc = gql`
|
|||||||
dueDate
|
dueDate
|
||||||
complete
|
complete
|
||||||
position
|
position
|
||||||
|
badges {
|
||||||
|
checklist {
|
||||||
|
complete
|
||||||
|
total
|
||||||
|
}
|
||||||
|
}
|
||||||
taskGroup {
|
taskGroup {
|
||||||
id
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
}
|
}
|
||||||
labels {
|
labels {
|
||||||
id
|
id
|
||||||
@ -1412,73 +1607,6 @@ export function useCreateProjectLabelMutation(baseOptions?: ApolloReactHooks.Mut
|
|||||||
export type CreateProjectLabelMutationHookResult = ReturnType<typeof useCreateProjectLabelMutation>;
|
export type CreateProjectLabelMutationHookResult = ReturnType<typeof useCreateProjectLabelMutation>;
|
||||||
export type CreateProjectLabelMutationResult = ApolloReactCommon.MutationResult<CreateProjectLabelMutation>;
|
export type CreateProjectLabelMutationResult = ApolloReactCommon.MutationResult<CreateProjectLabelMutation>;
|
||||||
export type CreateProjectLabelMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateProjectLabelMutation, CreateProjectLabelMutationVariables>;
|
export type CreateProjectLabelMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateProjectLabelMutation, CreateProjectLabelMutationVariables>;
|
||||||
export const CreateTaskDocument = gql`
|
|
||||||
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
|
||||||
createTask(input: {taskGroupID: $taskGroupID, name: $name, position: $position}) {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
position
|
|
||||||
description
|
|
||||||
dueDate
|
|
||||||
taskGroup {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
position
|
|
||||||
}
|
|
||||||
labels {
|
|
||||||
id
|
|
||||||
assignedDate
|
|
||||||
projectLabel {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
createdDate
|
|
||||||
labelColor {
|
|
||||||
id
|
|
||||||
colorHex
|
|
||||||
position
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assigned {
|
|
||||||
id
|
|
||||||
fullName
|
|
||||||
profileIcon {
|
|
||||||
url
|
|
||||||
initials
|
|
||||||
bgColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
export type CreateTaskMutationFn = ApolloReactCommon.MutationFunction<CreateTaskMutation, CreateTaskMutationVariables>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* __useCreateTaskMutation__
|
|
||||||
*
|
|
||||||
* To run a mutation, you first call `useCreateTaskMutation` within a React component and pass it any options that fit your needs.
|
|
||||||
* When your component renders, `useCreateTaskMutation` returns a tuple that includes:
|
|
||||||
* - A mutate function that you can call at any time to execute the mutation
|
|
||||||
* - An object with fields that represent the current status of the mutation's execution
|
|
||||||
*
|
|
||||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const [createTaskMutation, { data, loading, error }] = useCreateTaskMutation({
|
|
||||||
* variables: {
|
|
||||||
* taskGroupID: // value for 'taskGroupID'
|
|
||||||
* name: // value for 'name'
|
|
||||||
* position: // value for 'position'
|
|
||||||
* },
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
export function useCreateTaskMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateTaskMutation, CreateTaskMutationVariables>) {
|
|
||||||
return ApolloReactHooks.useMutation<CreateTaskMutation, CreateTaskMutationVariables>(CreateTaskDocument, baseOptions);
|
|
||||||
}
|
|
||||||
export type CreateTaskMutationHookResult = ReturnType<typeof useCreateTaskMutation>;
|
|
||||||
export type CreateTaskMutationResult = ApolloReactCommon.MutationResult<CreateTaskMutation>;
|
|
||||||
export type CreateTaskMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskMutation, CreateTaskMutationVariables>;
|
|
||||||
export const CreateTaskGroupDocument = gql`
|
export const CreateTaskGroupDocument = gql`
|
||||||
mutation createTaskGroup($projectID: String!, $name: String!, $position: Float!) {
|
mutation createTaskGroup($projectID: String!, $name: String!, $position: Float!) {
|
||||||
createTaskGroup(input: {projectID: $projectID, name: $name, position: $position}) {
|
createTaskGroup(input: {projectID: $projectID, name: $name, position: $position}) {
|
||||||
@ -1698,6 +1826,12 @@ export const FindTaskDocument = gql`
|
|||||||
taskGroup {
|
taskGroup {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
badges {
|
||||||
|
checklist {
|
||||||
|
total
|
||||||
|
complete
|
||||||
|
}
|
||||||
|
}
|
||||||
checklists {
|
checklists {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@ -1882,6 +2016,83 @@ export function useDeleteProjectMutation(baseOptions?: ApolloReactHooks.Mutation
|
|||||||
export type DeleteProjectMutationHookResult = ReturnType<typeof useDeleteProjectMutation>;
|
export type DeleteProjectMutationHookResult = ReturnType<typeof useDeleteProjectMutation>;
|
||||||
export type DeleteProjectMutationResult = ApolloReactCommon.MutationResult<DeleteProjectMutation>;
|
export type DeleteProjectMutationResult = ApolloReactCommon.MutationResult<DeleteProjectMutation>;
|
||||||
export type DeleteProjectMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteProjectMutation, DeleteProjectMutationVariables>;
|
export type DeleteProjectMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteProjectMutation, DeleteProjectMutationVariables>;
|
||||||
|
export const CreateTaskDocument = gql`
|
||||||
|
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
||||||
|
createTask(input: {taskGroupID: $taskGroupID, name: $name, position: $position}) {
|
||||||
|
...TaskFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TaskFieldsFragmentDoc}`;
|
||||||
|
export type CreateTaskMutationFn = ApolloReactCommon.MutationFunction<CreateTaskMutation, CreateTaskMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useCreateTaskMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useCreateTaskMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useCreateTaskMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [createTaskMutation, { data, loading, error }] = useCreateTaskMutation({
|
||||||
|
* variables: {
|
||||||
|
* taskGroupID: // value for 'taskGroupID'
|
||||||
|
* name: // value for 'name'
|
||||||
|
* position: // value for 'position'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useCreateTaskMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateTaskMutation, CreateTaskMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<CreateTaskMutation, CreateTaskMutationVariables>(CreateTaskDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type CreateTaskMutationHookResult = ReturnType<typeof useCreateTaskMutation>;
|
||||||
|
export type CreateTaskMutationResult = ApolloReactCommon.MutationResult<CreateTaskMutation>;
|
||||||
|
export type CreateTaskMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskMutation, CreateTaskMutationVariables>;
|
||||||
|
export const CreateTaskChecklistDocument = gql`
|
||||||
|
mutation createTaskChecklist($taskID: UUID!, $name: String!, $position: Float!) {
|
||||||
|
createTaskChecklist(input: {taskID: $taskID, name: $name, position: $position}) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
|
items {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
taskChecklistID
|
||||||
|
complete
|
||||||
|
position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type CreateTaskChecklistMutationFn = ApolloReactCommon.MutationFunction<CreateTaskChecklistMutation, CreateTaskChecklistMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useCreateTaskChecklistMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useCreateTaskChecklistMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useCreateTaskChecklistMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [createTaskChecklistMutation, { data, loading, error }] = useCreateTaskChecklistMutation({
|
||||||
|
* variables: {
|
||||||
|
* taskID: // value for 'taskID'
|
||||||
|
* name: // value for 'name'
|
||||||
|
* position: // value for 'position'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useCreateTaskChecklistMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateTaskChecklistMutation, CreateTaskChecklistMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<CreateTaskChecklistMutation, CreateTaskChecklistMutationVariables>(CreateTaskChecklistDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type CreateTaskChecklistMutationHookResult = ReturnType<typeof useCreateTaskChecklistMutation>;
|
||||||
|
export type CreateTaskChecklistMutationResult = ApolloReactCommon.MutationResult<CreateTaskChecklistMutation>;
|
||||||
|
export type CreateTaskChecklistMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskChecklistMutation, CreateTaskChecklistMutationVariables>;
|
||||||
export const CreateTaskChecklistItemDocument = gql`
|
export const CreateTaskChecklistItemDocument = gql`
|
||||||
mutation createTaskChecklistItem($taskChecklistID: UUID!, $name: String!, $position: Float!) {
|
mutation createTaskChecklistItem($taskChecklistID: UUID!, $name: String!, $position: Float!) {
|
||||||
createTaskChecklistItem(input: {taskChecklistID: $taskChecklistID, name: $name, position: $position}) {
|
createTaskChecklistItem(input: {taskChecklistID: $taskChecklistID, name: $name, position: $position}) {
|
||||||
@ -1920,6 +2131,41 @@ export function useCreateTaskChecklistItemMutation(baseOptions?: ApolloReactHook
|
|||||||
export type CreateTaskChecklistItemMutationHookResult = ReturnType<typeof useCreateTaskChecklistItemMutation>;
|
export type CreateTaskChecklistItemMutationHookResult = ReturnType<typeof useCreateTaskChecklistItemMutation>;
|
||||||
export type CreateTaskChecklistItemMutationResult = ApolloReactCommon.MutationResult<CreateTaskChecklistItemMutation>;
|
export type CreateTaskChecklistItemMutationResult = ApolloReactCommon.MutationResult<CreateTaskChecklistItemMutation>;
|
||||||
export type CreateTaskChecklistItemMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskChecklistItemMutation, CreateTaskChecklistItemMutationVariables>;
|
export type CreateTaskChecklistItemMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTaskChecklistItemMutation, CreateTaskChecklistItemMutationVariables>;
|
||||||
|
export const DeleteTaskChecklistDocument = gql`
|
||||||
|
mutation deleteTaskChecklist($taskChecklistID: UUID!) {
|
||||||
|
deleteTaskChecklist(input: {taskChecklistID: $taskChecklistID}) {
|
||||||
|
ok
|
||||||
|
taskChecklist {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type DeleteTaskChecklistMutationFn = ApolloReactCommon.MutationFunction<DeleteTaskChecklistMutation, DeleteTaskChecklistMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useDeleteTaskChecklistMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useDeleteTaskChecklistMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useDeleteTaskChecklistMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [deleteTaskChecklistMutation, { data, loading, error }] = useDeleteTaskChecklistMutation({
|
||||||
|
* variables: {
|
||||||
|
* taskChecklistID: // value for 'taskChecklistID'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useDeleteTaskChecklistMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<DeleteTaskChecklistMutation, DeleteTaskChecklistMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<DeleteTaskChecklistMutation, DeleteTaskChecklistMutationVariables>(DeleteTaskChecklistDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type DeleteTaskChecklistMutationHookResult = ReturnType<typeof useDeleteTaskChecklistMutation>;
|
||||||
|
export type DeleteTaskChecklistMutationResult = ApolloReactCommon.MutationResult<DeleteTaskChecklistMutation>;
|
||||||
|
export type DeleteTaskChecklistMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteTaskChecklistMutation, DeleteTaskChecklistMutationVariables>;
|
||||||
export const DeleteTaskChecklistItemDocument = gql`
|
export const DeleteTaskChecklistItemDocument = gql`
|
||||||
mutation deleteTaskChecklistItem($taskChecklistItemID: UUID!) {
|
mutation deleteTaskChecklistItem($taskChecklistItemID: UUID!) {
|
||||||
deleteTaskChecklistItem(input: {taskChecklistItemID: $taskChecklistItemID}) {
|
deleteTaskChecklistItem(input: {taskChecklistItemID: $taskChecklistItemID}) {
|
||||||
@ -1960,10 +2206,7 @@ export const SetTaskChecklistItemCompleteDocument = gql`
|
|||||||
mutation setTaskChecklistItemComplete($taskChecklistItemID: UUID!, $complete: Boolean!) {
|
mutation setTaskChecklistItemComplete($taskChecklistItemID: UUID!, $complete: Boolean!) {
|
||||||
setTaskChecklistItemComplete(input: {taskChecklistItemID: $taskChecklistItemID, complete: $complete}) {
|
setTaskChecklistItemComplete(input: {taskChecklistItemID: $taskChecklistItemID, complete: $complete}) {
|
||||||
id
|
id
|
||||||
name
|
|
||||||
taskChecklistID
|
|
||||||
complete
|
complete
|
||||||
position
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -2060,6 +2303,48 @@ export function useUpdateTaskChecklistItemNameMutation(baseOptions?: ApolloReact
|
|||||||
export type UpdateTaskChecklistItemNameMutationHookResult = ReturnType<typeof useUpdateTaskChecklistItemNameMutation>;
|
export type UpdateTaskChecklistItemNameMutationHookResult = ReturnType<typeof useUpdateTaskChecklistItemNameMutation>;
|
||||||
export type UpdateTaskChecklistItemNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskChecklistItemNameMutation>;
|
export type UpdateTaskChecklistItemNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskChecklistItemNameMutation>;
|
||||||
export type UpdateTaskChecklistItemNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskChecklistItemNameMutation, UpdateTaskChecklistItemNameMutationVariables>;
|
export type UpdateTaskChecklistItemNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskChecklistItemNameMutation, UpdateTaskChecklistItemNameMutationVariables>;
|
||||||
|
export const UpdateTaskChecklistNameDocument = gql`
|
||||||
|
mutation updateTaskChecklistName($taskChecklistID: UUID!, $name: String!) {
|
||||||
|
updateTaskChecklistName(input: {taskChecklistID: $taskChecklistID, name: $name}) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
|
items {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
taskChecklistID
|
||||||
|
complete
|
||||||
|
position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type UpdateTaskChecklistNameMutationFn = ApolloReactCommon.MutationFunction<UpdateTaskChecklistNameMutation, UpdateTaskChecklistNameMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useUpdateTaskChecklistNameMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useUpdateTaskChecklistNameMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useUpdateTaskChecklistNameMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [updateTaskChecklistNameMutation, { data, loading, error }] = useUpdateTaskChecklistNameMutation({
|
||||||
|
* variables: {
|
||||||
|
* taskChecklistID: // value for 'taskChecklistID'
|
||||||
|
* name: // value for 'name'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useUpdateTaskChecklistNameMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<UpdateTaskChecklistNameMutation, UpdateTaskChecklistNameMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<UpdateTaskChecklistNameMutation, UpdateTaskChecklistNameMutationVariables>(UpdateTaskChecklistNameDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type UpdateTaskChecklistNameMutationHookResult = ReturnType<typeof useUpdateTaskChecklistNameMutation>;
|
||||||
|
export type UpdateTaskChecklistNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskChecklistNameMutation>;
|
||||||
|
export type UpdateTaskChecklistNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskChecklistNameMutation, UpdateTaskChecklistNameMutationVariables>;
|
||||||
export const UpdateTaskGroupNameDocument = gql`
|
export const UpdateTaskGroupNameDocument = gql`
|
||||||
mutation updateTaskGroupName($taskGroupID: UUID!, $name: String!) {
|
mutation updateTaskGroupName($taskGroupID: UUID!, $name: String!) {
|
||||||
updateTaskGroupName(input: {taskGroupID: $taskGroupID, name: $name}) {
|
updateTaskGroupName(input: {taskGroupID: $taskGroupID, name: $name}) {
|
||||||
@ -2129,6 +2414,84 @@ export function useCreateTeamMutation(baseOptions?: ApolloReactHooks.MutationHoo
|
|||||||
export type CreateTeamMutationHookResult = ReturnType<typeof useCreateTeamMutation>;
|
export type CreateTeamMutationHookResult = ReturnType<typeof useCreateTeamMutation>;
|
||||||
export type CreateTeamMutationResult = ApolloReactCommon.MutationResult<CreateTeamMutation>;
|
export type CreateTeamMutationResult = ApolloReactCommon.MutationResult<CreateTeamMutation>;
|
||||||
export type CreateTeamMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTeamMutation, CreateTeamMutationVariables>;
|
export type CreateTeamMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateTeamMutation, CreateTeamMutationVariables>;
|
||||||
|
export const DeleteTeamDocument = gql`
|
||||||
|
mutation deleteTeam($teamID: UUID!) {
|
||||||
|
deleteTeam(input: {teamID: $teamID}) {
|
||||||
|
ok
|
||||||
|
team {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type DeleteTeamMutationFn = ApolloReactCommon.MutationFunction<DeleteTeamMutation, DeleteTeamMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useDeleteTeamMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useDeleteTeamMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useDeleteTeamMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [deleteTeamMutation, { data, loading, error }] = useDeleteTeamMutation({
|
||||||
|
* variables: {
|
||||||
|
* teamID: // value for 'teamID'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useDeleteTeamMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<DeleteTeamMutation, DeleteTeamMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<DeleteTeamMutation, DeleteTeamMutationVariables>(DeleteTeamDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type DeleteTeamMutationHookResult = ReturnType<typeof useDeleteTeamMutation>;
|
||||||
|
export type DeleteTeamMutationResult = ApolloReactCommon.MutationResult<DeleteTeamMutation>;
|
||||||
|
export type DeleteTeamMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteTeamMutation, DeleteTeamMutationVariables>;
|
||||||
|
export const GetTeamDocument = gql`
|
||||||
|
query getTeam($teamID: UUID!) {
|
||||||
|
findTeam(input: {teamID: $teamID}) {
|
||||||
|
id
|
||||||
|
createdAt
|
||||||
|
name
|
||||||
|
}
|
||||||
|
projects(input: {teamID: $teamID}) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
team {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useGetTeamQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useGetTeamQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useGetTeamQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useGetTeamQuery({
|
||||||
|
* variables: {
|
||||||
|
* teamID: // value for 'teamID'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useGetTeamQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<GetTeamQuery, GetTeamQueryVariables>) {
|
||||||
|
return ApolloReactHooks.useQuery<GetTeamQuery, GetTeamQueryVariables>(GetTeamDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export function useGetTeamLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<GetTeamQuery, GetTeamQueryVariables>) {
|
||||||
|
return ApolloReactHooks.useLazyQuery<GetTeamQuery, GetTeamQueryVariables>(GetTeamDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type GetTeamQueryHookResult = ReturnType<typeof useGetTeamQuery>;
|
||||||
|
export type GetTeamLazyQueryHookResult = ReturnType<typeof useGetTeamLazyQuery>;
|
||||||
|
export type GetTeamQueryResult = ApolloReactCommon.QueryResult<GetTeamQuery, GetTeamQueryVariables>;
|
||||||
export const ToggleTaskLabelDocument = gql`
|
export const ToggleTaskLabelDocument = gql`
|
||||||
mutation toggleTaskLabel($taskID: UUID!, $projectLabelID: UUID!) {
|
mutation toggleTaskLabel($taskID: UUID!, $projectLabelID: UUID!) {
|
||||||
toggleTaskLabel(input: {taskID: $taskID, projectLabelID: $projectLabelID}) {
|
toggleTaskLabel(input: {taskID: $taskID, projectLabelID: $projectLabelID}) {
|
||||||
@ -2473,3 +2836,88 @@ export function useUpdateTaskNameMutation(baseOptions?: ApolloReactHooks.Mutatio
|
|||||||
export type UpdateTaskNameMutationHookResult = ReturnType<typeof useUpdateTaskNameMutation>;
|
export type UpdateTaskNameMutationHookResult = ReturnType<typeof useUpdateTaskNameMutation>;
|
||||||
export type UpdateTaskNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskNameMutation>;
|
export type UpdateTaskNameMutationResult = ApolloReactCommon.MutationResult<UpdateTaskNameMutation>;
|
||||||
export type UpdateTaskNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskNameMutation, UpdateTaskNameMutationVariables>;
|
export type UpdateTaskNameMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskNameMutation, UpdateTaskNameMutationVariables>;
|
||||||
|
export const CreateUserAccountDocument = gql`
|
||||||
|
mutation createUserAccount($username: String!, $email: String!, $fullName: String!, $initials: String!, $password: String!) {
|
||||||
|
createUserAccount(input: {username: $username, email: $email, fullName: $fullName, initials: $initials, password: $password}) {
|
||||||
|
id
|
||||||
|
email
|
||||||
|
fullName
|
||||||
|
initials
|
||||||
|
username
|
||||||
|
profileIcon {
|
||||||
|
url
|
||||||
|
initials
|
||||||
|
bgColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type CreateUserAccountMutationFn = ApolloReactCommon.MutationFunction<CreateUserAccountMutation, CreateUserAccountMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useCreateUserAccountMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useCreateUserAccountMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useCreateUserAccountMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [createUserAccountMutation, { data, loading, error }] = useCreateUserAccountMutation({
|
||||||
|
* variables: {
|
||||||
|
* username: // value for 'username'
|
||||||
|
* email: // value for 'email'
|
||||||
|
* fullName: // value for 'fullName'
|
||||||
|
* initials: // value for 'initials'
|
||||||
|
* password: // value for 'password'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useCreateUserAccountMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateUserAccountMutation, CreateUserAccountMutationVariables>) {
|
||||||
|
return ApolloReactHooks.useMutation<CreateUserAccountMutation, CreateUserAccountMutationVariables>(CreateUserAccountDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type CreateUserAccountMutationHookResult = ReturnType<typeof useCreateUserAccountMutation>;
|
||||||
|
export type CreateUserAccountMutationResult = ApolloReactCommon.MutationResult<CreateUserAccountMutation>;
|
||||||
|
export type CreateUserAccountMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateUserAccountMutation, CreateUserAccountMutationVariables>;
|
||||||
|
export const UsersDocument = gql`
|
||||||
|
query users {
|
||||||
|
users {
|
||||||
|
id
|
||||||
|
email
|
||||||
|
fullName
|
||||||
|
username
|
||||||
|
profileIcon {
|
||||||
|
url
|
||||||
|
initials
|
||||||
|
bgColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useUsersQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useUsersQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useUsersQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useUsersQuery({
|
||||||
|
* variables: {
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useUsersQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<UsersQuery, UsersQueryVariables>) {
|
||||||
|
return ApolloReactHooks.useQuery<UsersQuery, UsersQueryVariables>(UsersDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export function useUsersLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<UsersQuery, UsersQueryVariables>) {
|
||||||
|
return ApolloReactHooks.useLazyQuery<UsersQuery, UsersQueryVariables>(UsersDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type UsersQueryHookResult = ReturnType<typeof useUsersQuery>;
|
||||||
|
export type UsersLazyQueryHookResult = ReturnType<typeof useUsersLazyQuery>;
|
||||||
|
export type UsersQueryResult = ApolloReactCommon.QueryResult<UsersQuery, UsersQueryVariables>;
|
@ -1,38 +0,0 @@
|
|||||||
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
|
||||||
createTask(input: { taskGroupID: $taskGroupID, name: $name, position: $position }) {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
position
|
|
||||||
description
|
|
||||||
dueDate
|
|
||||||
taskGroup {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
position
|
|
||||||
}
|
|
||||||
labels {
|
|
||||||
id
|
|
||||||
assignedDate
|
|
||||||
projectLabel {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
createdDate
|
|
||||||
labelColor {
|
|
||||||
id
|
|
||||||
colorHex
|
|
||||||
position
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assigned {
|
|
||||||
id
|
|
||||||
fullName
|
|
||||||
profileIcon {
|
|
||||||
url
|
|
||||||
initials
|
|
||||||
bgColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,6 +9,12 @@ query findTask($taskID: UUID!) {
|
|||||||
taskGroup {
|
taskGroup {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
badges {
|
||||||
|
checklist {
|
||||||
|
total
|
||||||
|
complete
|
||||||
|
}
|
||||||
|
}
|
||||||
checklists {
|
checklists {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
@ -8,8 +8,16 @@ const TASK_FRAGMENT = gql`
|
|||||||
dueDate
|
dueDate
|
||||||
complete
|
complete
|
||||||
position
|
position
|
||||||
|
badges {
|
||||||
|
checklist {
|
||||||
|
complete
|
||||||
|
total
|
||||||
|
}
|
||||||
|
}
|
||||||
taskGroup {
|
taskGroup {
|
||||||
id
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
}
|
}
|
||||||
labels {
|
labels {
|
||||||
id
|
id
|
||||||
|
13
web/src/shared/graphql/task/createTask.ts
Normal file
13
web/src/shared/graphql/task/createTask.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
import TASK_FRAGMENT from '../fragments/task';
|
||||||
|
|
||||||
|
const CREATE_TASK_MUTATION = gql`
|
||||||
|
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
||||||
|
createTask(input: { taskGroupID: $taskGroupID, name: $name, position: $position }) {
|
||||||
|
...TaskFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
${TASK_FRAGMENT}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default CREATE_TASK_MUTATION;
|
20
web/src/shared/graphql/task/createTaskChecklist.ts
Normal file
20
web/src/shared/graphql/task/createTaskChecklist.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
const CREATE_TASK_CHECKLIST_MUTATION = gql`
|
||||||
|
mutation createTaskChecklist($taskID: UUID!, $name: String!, $position: Float!) {
|
||||||
|
createTaskChecklist(input: { taskID: $taskID, name: $name, position: $position }) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
|
items {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
taskChecklistID
|
||||||
|
complete
|
||||||
|
position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default CREATE_TASK_CHECKLIST_MUTATION;
|
14
web/src/shared/graphql/task/deleteTaskChecklist.ts
Normal file
14
web/src/shared/graphql/task/deleteTaskChecklist.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
const DELETE_TASK_CHECKLIST_MUTATION = gql`
|
||||||
|
mutation deleteTaskChecklist($taskChecklistID: UUID!) {
|
||||||
|
deleteTaskChecklist(input: { taskChecklistID: $taskChecklistID }) {
|
||||||
|
ok
|
||||||
|
taskChecklist {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default DELETE_TASK_CHECKLIST_MUTATION;
|
@ -4,10 +4,7 @@ const SET_TASK_CHECKLIST_ITEM_COMPLETE = gql`
|
|||||||
mutation setTaskChecklistItemComplete($taskChecklistItemID: UUID!, $complete: Boolean!) {
|
mutation setTaskChecklistItemComplete($taskChecklistItemID: UUID!, $complete: Boolean!) {
|
||||||
setTaskChecklistItemComplete(input: { taskChecklistItemID: $taskChecklistItemID, complete: $complete }) {
|
setTaskChecklistItemComplete(input: { taskChecklistItemID: $taskChecklistItemID, complete: $complete }) {
|
||||||
id
|
id
|
||||||
name
|
|
||||||
taskChecklistID
|
|
||||||
complete
|
complete
|
||||||
position
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
19
web/src/shared/graphql/task/updateTaskChecklistName.ts
Normal file
19
web/src/shared/graphql/task/updateTaskChecklistName.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
const UPDATE_TASK_CHECKLIST_NAME_MUTATION = gql`
|
||||||
|
mutation updateTaskChecklistName($taskChecklistID: UUID!, $name: String!) {
|
||||||
|
updateTaskChecklistName(input: { taskChecklistID: $taskChecklistID, name: $name }) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
position
|
||||||
|
items {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
taskChecklistID
|
||||||
|
complete
|
||||||
|
position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export default UPDATE_TASK_CHECKLIST_NAME_MUTATION;
|
14
web/src/shared/graphql/team/deleteTeam.ts
Normal file
14
web/src/shared/graphql/team/deleteTeam.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
export const DELETE_TEAM_MUTATION = gql`
|
||||||
|
mutation deleteTeam($teamID: UUID!) {
|
||||||
|
deleteTeam(input: { teamID: $teamID }) {
|
||||||
|
ok
|
||||||
|
team {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default DELETE_TEAM_MUTATION;
|
21
web/src/shared/graphql/team/getTeam.ts
Normal file
21
web/src/shared/graphql/team/getTeam.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
export const GET_TEAM_QUERY = gql`
|
||||||
|
query getTeam($teamID: UUID!) {
|
||||||
|
findTeam(input: { teamID: $teamID }) {
|
||||||
|
id
|
||||||
|
createdAt
|
||||||
|
name
|
||||||
|
}
|
||||||
|
projects(input: { teamID: $teamID }) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
team {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default GET_TEAM_QUERY;
|
28
web/src/shared/graphql/user/createUser.ts
Normal file
28
web/src/shared/graphql/user/createUser.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
export const CREATE_USER_MUTATION = gql`
|
||||||
|
mutation createUserAccount(
|
||||||
|
$username: String!
|
||||||
|
$email: String!
|
||||||
|
$fullName: String!
|
||||||
|
$initials: String!
|
||||||
|
$password: String!
|
||||||
|
) {
|
||||||
|
createUserAccount(
|
||||||
|
input: { username: $username, email: $email, fullName: $fullName, initials: $initials, password: $password }
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
email
|
||||||
|
fullName
|
||||||
|
initials
|
||||||
|
username
|
||||||
|
profileIcon {
|
||||||
|
url
|
||||||
|
initials
|
||||||
|
bgColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default CREATE_USER_MUTATION;
|
14
web/src/shared/graphql/users.graphqls
Normal file
14
web/src/shared/graphql/users.graphqls
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
query users {
|
||||||
|
users {
|
||||||
|
id
|
||||||
|
email
|
||||||
|
fullName
|
||||||
|
username
|
||||||
|
profileIcon {
|
||||||
|
url
|
||||||
|
initials
|
||||||
|
bgColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
12
web/src/shared/icons/BarChart.tsx
Normal file
12
web/src/shared/icons/BarChart.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const BarChart: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 512 512">
|
||||||
|
<path d="M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BarChart;
|
@ -1,29 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
type Props = {
|
const Citadel: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
size: number | string;
|
|
||||||
color: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Citadel = ({ size, color }: Props) => {
|
|
||||||
return (
|
return (
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 12.7 12.7">
|
<Icon width={width} height={height} className={className} viewBox="0 0 12.7 12.7">
|
||||||
<g transform="translate(-.26 -24.137) scale(.1249)">
|
<g transform="translate(-.26 -24.137) scale(.1249)">
|
||||||
<path
|
<path d="M50.886 286.515l-40.4-44.46 44.459-40.401 40.401 44.46z" fill="none" strokeWidth="11.90597031" />
|
||||||
d="M50.886 286.515l-40.4-44.46 44.459-40.401 40.401 44.46z"
|
<circle cx="52.917" cy="244.083" r="11.025" />
|
||||||
fill="none"
|
|
||||||
stroke={color}
|
|
||||||
strokeWidth="11.90597031"
|
|
||||||
/>
|
|
||||||
<circle cx="52.917" cy="244.083" r="11.025" fill={color} />
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</Icon>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Citadel.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#7367f0',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Citadel;
|
export default Citadel;
|
||||||
|
12
web/src/shared/icons/Filter.tsx
Normal file
12
web/src/shared/icons/Filter.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const Filter: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 512 512">
|
||||||
|
<path d="M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Filter;
|
@ -1,21 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
type Props = {
|
const Checkmark: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
size: number | string;
|
|
||||||
color: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Home = ({ size, color }: Props) => {
|
|
||||||
return (
|
return (
|
||||||
<svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 16 16">
|
<Icon width={width} height={height} className={className} viewBox="0 0 576 512">
|
||||||
<path d="M16 9.226l-8-6.21-8 6.21v-2.532l8-6.21 8 6.21zM14 9v6h-4v-4h-4v4h-4v-6l6-4.5z" />
|
<path d="M280.37 148.26L96 300.11V464a16 16 0 0 0 16 16l112.06-.29a16 16 0 0 0 15.92-16V368a16 16 0 0 1 16-16h64a16 16 0 0 1 16 16v95.64a16 16 0 0 0 16 16.05L464 480a16 16 0 0 0 16-16V300L295.67 148.26a12.19 12.19 0 0 0-15.3 0zM571.6 251.47L488 182.56V44.05a12 12 0 0 0-12-12h-56a12 12 0 0 0-12 12v72.61L318.47 43a48 48 0 0 0-61 0L4.34 251.47a12 12 0 0 0-1.6 16.9l25.5 31A12 12 0 0 0 45.15 301l235.22-193.74a12.19 12.19 0 0 1 15.3 0L530.9 301a12 12 0 0 0 16.9-1.6l25.5-31a12 12 0 0 0-1.7-16.93z" />
|
||||||
</svg>
|
</Icon>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Home.defaultProps = {
|
export default Checkmark;
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Home;
|
|
||||||
|
@ -18,6 +18,7 @@ type Props = {
|
|||||||
|
|
||||||
const Svg = styled.svg`
|
const Svg = styled.svg`
|
||||||
fill: rgba(${props => props.theme.colors.text.primary});
|
fill: rgba(${props => props.theme.colors.text.primary});
|
||||||
|
stroke: rgba(${props => props.theme.colors.text.primary});
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Icon: React.FC<Props> = ({ width, height, viewBox, className, onClick, children }) => {
|
const Icon: React.FC<Props> = ({ width, height, viewBox, className, onClick, children }) => {
|
||||||
|
@ -1,21 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
type Props = {
|
const Lock: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
size: number | string;
|
|
||||||
color: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Lock = ({ size, color }: Props) => {
|
|
||||||
return (
|
return (
|
||||||
<svg fill={color} xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 16 16">
|
<Icon width={width} height={height} className={className} viewBox="0 0 448 512">
|
||||||
<path d="M9.25 7h-0.25v-3c0-1.654-1.346-3-3-3h-2c-1.654 0-3 1.346-3 3v3h-0.25c-0.412 0-0.75 0.338-0.75 0.75v7.5c0 0.412 0.338 0.75 0.75 0.75h8.5c0.412 0 0.75-0.338 0.75-0.75v-7.5c0-0.412-0.338-0.75-0.75-0.75zM3 4c0-0.551 0.449-1 1-1h2c0.551 0 1 0.449 1 1v3h-4v-3z" />
|
<path d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z" />
|
||||||
</svg>
|
</Icon>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Lock.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Lock;
|
export default Lock;
|
||||||
|
@ -1,21 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
type Props = {
|
const Sort: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
size: number | string;
|
|
||||||
color: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Pencil = ({ size, color }: Props) => {
|
|
||||||
return (
|
return (
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill={color} width={size} height={size} viewBox="0 0 16 16">
|
<Icon width={width} height={height} className={className} viewBox="0 0 512 512">
|
||||||
<path d="M13.5 0c1.381 0 2.5 1.119 2.5 2.5 0 0.563-0.186 1.082-0.5 1.5l-1 1-3.5-3.5 1-1c0.418-0.314 0.937-0.5 1.5-0.5zM1 11.5l-1 4.5 4.5-1 9.25-9.25-3.5-3.5-9.25 9.25zM11.181 5.681l-7 7-0.862-0.862 7-7 0.862 0.862z" />
|
<path d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z" />
|
||||||
</svg>
|
</Icon>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Pencil.defaultProps = {
|
export default Sort;
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Pencil;
|
|
||||||
|
12
web/src/shared/icons/Sort.tsx
Normal file
12
web/src/shared/icons/Sort.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Icon, { IconProps } from './Icon';
|
||||||
|
|
||||||
|
const Sort: React.FC<IconProps> = ({ width = '16px', height = '16px', className }) => {
|
||||||
|
return (
|
||||||
|
<Icon width={width} height={height} className={className} viewBox="0 0 320 512">
|
||||||
|
<path d="M41 288h238c21.4 0 32.1 25.9 17 41L177 448c-9.4 9.4-24.6 9.4-33.9 0L24 329c-15.1-15.1-4.4-41 17-41zm255-105L177 64c-9.4-9.4-24.6-9.4-33.9 0L24 183c-15.1 15.1-4.4 41 17 41h238c21.4 0 32.1-25.9 17-41z" />
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Sort;
|
@ -1,5 +1,8 @@
|
|||||||
import Cross from './Cross';
|
import Cross from './Cross';
|
||||||
import Cog from './Cog';
|
import Cog from './Cog';
|
||||||
|
import Sort from './Sort';
|
||||||
|
import Filter from './Filter';
|
||||||
|
import BarChart from './BarChart';
|
||||||
import Trash from './Trash';
|
import Trash from './Trash';
|
||||||
import CheckCircle from './CheckCircle';
|
import CheckCircle from './CheckCircle';
|
||||||
import Clock from './Clock';
|
import Clock from './Clock';
|
||||||
@ -58,6 +61,9 @@ export {
|
|||||||
Clock,
|
Clock,
|
||||||
CheckSquareOutline,
|
CheckSquareOutline,
|
||||||
CheckSquare,
|
CheckSquare,
|
||||||
|
BarChart,
|
||||||
Square,
|
Square,
|
||||||
|
Filter,
|
||||||
|
Sort,
|
||||||
ToggleOn,
|
ToggleOn,
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,21 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@apollo/client@^3.0.0-rc.8":
|
||||||
|
version "3.0.0-rc.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.0.0-rc.8.tgz#70643547ed8bb10d1d96f64320c3510a57f0cf6a"
|
||||||
|
integrity sha512-8Sw4Htao2mZb4vERbvMj9GOf4x/+CLYNuF5gULY7TtMWG4ZANLxbe1DeFCicxVo2xRVQ960nf5vVJhxKcjDOQA==
|
||||||
|
dependencies:
|
||||||
|
"@types/zen-observable" "^0.8.0"
|
||||||
|
"@wry/equality" "^0.1.9"
|
||||||
|
fast-json-stable-stringify "^2.0.0"
|
||||||
|
graphql-tag "^2.10.2"
|
||||||
|
optimism "^0.12.1"
|
||||||
|
symbol-observable "^1.2.0"
|
||||||
|
ts-invariant "^0.4.4"
|
||||||
|
tslib "^1.10.0"
|
||||||
|
zen-observable "^0.8.14"
|
||||||
|
|
||||||
"@apollo/federation@0.13.2":
|
"@apollo/federation@0.13.2":
|
||||||
version "0.13.2"
|
version "0.13.2"
|
||||||
resolved "https://registry.yarnpkg.com/@apollo/federation/-/federation-0.13.2.tgz#a9f842abd1619fe5cd732c56cfbc45dab0ae784a"
|
resolved "https://registry.yarnpkg.com/@apollo/federation/-/federation-0.13.2.tgz#a9f842abd1619fe5cd732c56cfbc45dab0ae784a"
|
||||||
@ -3637,6 +3652,13 @@
|
|||||||
"@types/node" ">=6"
|
"@types/node" ">=6"
|
||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
|
|
||||||
|
"@wry/context@^0.5.2":
|
||||||
|
version "0.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.5.2.tgz#f2a5d5ab9227343aa74c81e06533c1ef84598ec7"
|
||||||
|
integrity sha512-B/JLuRZ/vbEKHRUiGj6xiMojST1kHhu4WcreLfNN7q9DqQFrb97cWgf/kiYsPSUCAMVN0HzfFc8XjJdzgZzfjw==
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.9.3"
|
||||||
|
|
||||||
"@wry/equality@^0.1.2", "@wry/equality@^0.1.9":
|
"@wry/equality@^0.1.2", "@wry/equality@^0.1.9":
|
||||||
version "0.1.9"
|
version "0.1.9"
|
||||||
resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.9.tgz#b13e18b7a8053c6858aa6c85b54911fb31e3a909"
|
resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.9.tgz#b13e18b7a8053c6858aa6c85b54911fb31e3a909"
|
||||||
@ -8349,7 +8371,7 @@ graphql-request@^1.5.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
cross-fetch "2.2.2"
|
cross-fetch "2.2.2"
|
||||||
|
|
||||||
graphql-tag@2.10.3, graphql-tag@^2.10.1, graphql-tag@^2.10.3:
|
graphql-tag@2.10.3, graphql-tag@^2.10.1, graphql-tag@^2.10.2, graphql-tag@^2.10.3:
|
||||||
version "2.10.3"
|
version "2.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.3.tgz#ea1baba5eb8fc6339e4c4cf049dabe522b0edf03"
|
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.3.tgz#ea1baba5eb8fc6339e4c4cf049dabe522b0edf03"
|
||||||
integrity sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA==
|
integrity sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA==
|
||||||
@ -11668,6 +11690,13 @@ optimism@^0.10.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@wry/context" "^0.4.0"
|
"@wry/context" "^0.4.0"
|
||||||
|
|
||||||
|
optimism@^0.12.1:
|
||||||
|
version "0.12.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.12.1.tgz#933f9467b9aef0e601655adb9638f893e486ad02"
|
||||||
|
integrity sha512-t8I7HM1dw0SECitBYAqFOVHoBAHEQBTeKjIL9y9ImHzAVkdyPK4ifTgM4VJRDtTUY4r/u5Eqxs4XcGPHaoPkeQ==
|
||||||
|
dependencies:
|
||||||
|
"@wry/context" "^0.5.2"
|
||||||
|
|
||||||
optimize-css-assets-webpack-plugin@5.0.3:
|
optimize-css-assets-webpack-plugin@5.0.3:
|
||||||
version "5.0.3"
|
version "5.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz#e2f1d4d94ad8c0af8967ebd7cf138dcb1ef14572"
|
resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz#e2f1d4d94ad8c0af8967ebd7cf138dcb1ef14572"
|
||||||
@ -17236,7 +17265,7 @@ zen-observable-ts@^0.8.21:
|
|||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
zen-observable "^0.8.0"
|
zen-observable "^0.8.0"
|
||||||
|
|
||||||
zen-observable@^0.8.0:
|
zen-observable@^0.8.0, zen-observable@^0.8.14:
|
||||||
version "0.8.15"
|
version "0.8.15"
|
||||||
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
|
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
|
||||||
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
|
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
|
||||||
|
Loading…
Reference in New Issue
Block a user