diff --git a/Dockerfile b/Dockerfile index aac4558..a2ef629 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,9 +7,12 @@ RUN yarn build FROM golang:1.14.5-alpine as backend WORKDIR /usr/src/app +COPY go.mod go.mod +COPY go.sum go.sum +RUN go mod download COPY . . -COPY --from=frontend /usr/src/app/build . -RUN go run cmd/mage/main.go backend:genFrontend backend:build +COPY --from=frontend /usr/src/app/build ./frontend/build +RUN go run cmd/mage/main.go backend:genFrontend backend:genMigrations backend:build FROM alpine:latest WORKDIR /root/ diff --git a/cmd/citadel/main.go b/cmd/citadel/main.go index a263872..28af871 100644 --- a/cmd/citadel/main.go +++ b/cmd/citadel/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/jordanknott/project-citadel/api/internal/commands" + "github.com/jordanknott/project-citadel/internal/commands" _ "github.com/lib/pq" ) diff --git a/cmd/citadelctl/main.go b/cmd/citadelctl/main.go index 5f1e3b1..c8e187d 100644 --- a/cmd/citadelctl/main.go +++ b/cmd/citadelctl/main.go @@ -7,8 +7,8 @@ import ( "github.com/BurntSushi/toml" "github.com/jmoiron/sqlx" "github.com/jordan-wright/email" - "github.com/jordanknott/project-citadel/api/pg" - "github.com/jordanknott/project-citadel/api/router" + "github.com/jordanknott/project-citadel/pg" + "github.com/jordanknott/project-citadel/router" _ "github.com/lib/pq" "golang.org/x/crypto/bcrypt" "io/ioutil" diff --git a/cmd/worker/main.go b/cmd/worker/main.go index 034faa9..075f0dd 100644 --- a/cmd/worker/main.go +++ b/cmd/worker/main.go @@ -8,7 +8,7 @@ import ( "github.com/RichardKnop/machinery/v1/config" "github.com/google/uuid" "github.com/jmoiron/sqlx" - "github.com/jordanknott/project-citadel/api/pg" + "github.com/jordanknott/project-citadel/pg" _ "github.com/lib/pq" ) diff --git a/frontend/package.json b/frontend/package.json index 22d5891..04395ff 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,11 +11,6 @@ "@fortawesome/free-regular-svg-icons": "^5.12.1", "@fortawesome/free-solid-svg-icons": "^5.12.1", "@fortawesome/react-fontawesome": "^0.1.8", - "@storybook/addon-backgrounds": "^5.3.17", - "@storybook/addon-docs": "^5.3.17", - "@storybook/addon-knobs": "^5.3.17", - "@storybook/addon-storysource": "^5.3.17", - "@storybook/addon-viewport": "^5.3.17", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", @@ -34,9 +29,6 @@ "@types/react-router-dom": "^5.1.3", "@types/react-select": "^3.0.13", "@types/styled-components": "^5.0.0", - "@welldone-software/why-did-you-render": "^4.2.2", - "ag-grid-community": "^23.2.0", - "ag-grid-react": "^23.2.0", "apollo-cache-inmemory": "^1.6.5", "apollo-client": "^2.6.8", "apollo-link": "^1.2.13", @@ -103,6 +95,11 @@ "@graphql-codegen/typescript-react-apollo": "^1.13.2", "@storybook/addon-actions": "^5.3.13", "@storybook/addon-links": "^5.3.13", + "@storybook/addon-backgrounds": "^5.3.17", + "@storybook/addon-docs": "^5.3.17", + "@storybook/addon-knobs": "^5.3.17", + "@storybook/addon-storysource": "^5.3.17", + "@storybook/addon-viewport": "^5.3.17", "@storybook/addons": "^5.3.13", "@storybook/preset-create-react-app": "^1.5.2", "@storybook/react": "^5.3.13", diff --git a/frontend/src/shared/components/Admin/index.tsx b/frontend/src/shared/components/Admin/index.tsx index e70e1a3..1d3009d 100644 --- a/frontend/src/shared/components/Admin/index.tsx +++ b/frontend/src/shared/components/Admin/index.tsx @@ -6,12 +6,9 @@ import Select from 'shared/components/Select'; import { User, Plus, Lock, Pencil, Trash } from 'shared/icons'; import { usePopup, Popup } from 'shared/components/PopupMenu'; import { RoleCode, useUpdateUserRoleMutation } from 'shared/generated/graphql'; -import { AgGridReact } from 'ag-grid-react'; import Input from 'shared/components/Input'; import Member from 'shared/components/Member'; -import 'ag-grid-community/dist/styles/ag-grid.css'; -import 'ag-grid-community/dist/styles/ag-theme-material.css'; import Button from 'shared/components/Button'; export const RoleCheckmark = styled(Checkmark)` @@ -58,7 +55,7 @@ export const MiniProfileActionItem = styled.span<{ disabled?: boolean }>` position: relative; text-decoration: none; - ${props => + ${(props) => props.disabled ? css` user-select: none; @@ -78,7 +75,7 @@ export const Content = styled.div` export const CurrentPermission = styled.span` margin-left: 4px; - color: rgba(${props => props.theme.colors.text.secondary}, 0.4); + color: rgba(${(props) => props.theme.colors.text.secondary}, 0.4); `; export const Separator = styled.div` @@ -89,13 +86,13 @@ export const Separator = styled.div` export const WarningText = styled.span` display: flex; - color: rgba(${props => props.theme.colors.text.primary}, 0.4); + color: rgba(${(props) => props.theme.colors.text.primary}, 0.4); padding: 6px; `; export const DeleteDescription = styled.div` font-size: 14px; - color: rgba(${props => props.theme.colors.text.primary}); + color: rgba(${(props) => props.theme.colors.text.primary}); `; export const RemoveMemberButton = styled(Button)` @@ -162,8 +159,8 @@ const TeamRoleManagerPopup: React.FC = ({ {permissions - .filter(p => (user.role && user.role.code === 'owner') || p.code !== 'owner') - .map(perm => ( + .filter((p) => (user.role && user.role.code === 'owner') || p.code !== 'owner') + .map((perm) => ( = ({ Choose a new user to take over ownership of this user's teams & projects. setDeleteUser(v)} + onChange={(v) => setDeleteUser(v)} value={deleteUser} - options={users.map(u => ({ label: u.fullName, value: u.id }))} + options={users.map((u) => ({ label: u.fullName, value: u.id }))} /> )} @@ -242,7 +239,11 @@ const TeamRoleManagerPopup: React.FC = ({ Removing this user from the organzation will remove them from assigned tasks, projects, and teams. {`The user is the owner of ${user.owned.projects.length} projects & ${user.owned.teams.length} teams.`} - {}} value={null} options={users.map(u => ({ label: u.fullName, value: u.id }))} /> + {}} + value={null} + options={users.map((u) => ({ label: u.fullName, value: u.id }))} + /> { // onDeleteUser(); @@ -333,14 +334,14 @@ const MemberItemOption = styled(Button)` `; const MemberList = styled.div` - border-top: 1px solid rgba(${props => props.theme.colors.border}); + border-top: 1px solid rgba(${(props) => props.theme.colors.border}); `; const MemberListItem = styled.div` display: flex; flex-flow: row wrap; justify-content: space-between; - border-bottom: 1px solid rgba(${props => props.theme.colors.border}); + border-bottom: 1px solid rgba(${(props) => props.theme.colors.border}); min-height: 40px; padding: 12px 0 12px 40px; position: relative; @@ -364,11 +365,11 @@ const MemberProfile = styled(TaskAssignee)` `; const MemberItemName = styled.p` - color: rgba(${props => props.theme.colors.text.secondary}); + color: rgba(${(props) => props.theme.colors.text.secondary}); `; const MemberItemUsername = styled.p` - color: rgba(${props => props.theme.colors.text.primary}); + color: rgba(${(props) => props.theme.colors.text.primary}); `; const MemberListHeader = styled.div` @@ -377,12 +378,12 @@ const MemberListHeader = styled.div` `; const ListTitle = styled.h3` font-size: 18px; - color: rgba(${props => props.theme.colors.text.secondary}); + color: rgba(${(props) => props.theme.colors.text.secondary}); margin-bottom: 12px; `; const ListDesc = styled.span` font-size: 16px; - color: rgba(${props => props.theme.colors.text.primary}); + color: rgba(${(props) => props.theme.colors.text.primary}); `; const FilterSearch = styled(Input)` margin: 0; @@ -483,72 +484,13 @@ const ActionButtons = (params: any) => { {}}> - params.onDeleteUser($target, params.value)}> + params.onDeleteUser($target, params.value)}> ); }; -type ListTableProps = { - users: Array; - onDeleteUser: ($target: React.RefObject, userID: string) => void; -}; - -const ListTable: React.FC = ({ users, onDeleteUser }) => { - const data = { - defaultColDef: { - resizable: true, - sortable: true, - }, - columnDefs: [ - { - minWidth: 55, - width: 55, - headerCheckboxSelection: true, - checkboxSelection: true, - }, - { minWidth: 210, headerName: 'Username', editable: true, field: 'username' }, - { minWidth: 225, headerName: 'Email', field: 'email' }, - { minWidth: 200, headerName: 'Name', editable: true, field: 'fullName' }, - { minWidth: 200, headerName: 'Role', editable: true, field: 'roleName' }, - { - minWidth: 200, - headerName: 'Actions', - field: 'id', - cellRenderer: 'actionButtons', - cellRendererParams: { - onDeleteUser: (target: any, userID: any) => { - onDeleteUser(target, userID); - }, - }, - }, - ], - frameworkComponents: { - actionButtons: ActionButtons, - }, - }; - return ( - -
- ({ ...u, roleName: 'member' }))} - frameworkComponents={data.frameworkComponents} - onFirstDataRendered={params => { - params.api.sizeColumnsToFit(); - }} - onGridSizeChanged={params => { - params.api.sizeColumnsToFit(); - }} - /> -
-
- ); -}; - const Wrapper = styled.div` background: #eff2f7; display: flex; @@ -599,7 +541,7 @@ const TabNavItemButton = styled.button<{ active: boolean }>` width: 100%; position: relative; - color: ${props => (props.active ? 'rgba(115, 103, 240)' : '#c2c6dc')}; + color: ${(props) => (props.active ? 'rgba(115, 103, 240)' : '#c2c6dc')}; &:hover { color: rgba(115, 103, 240); } @@ -620,7 +562,7 @@ const TabNavLine = styled.span<{ top: number }>` width: 2px; height: 48px; transform: scaleX(1); - top: ${props => props.top}px; + top: ${(props) => props.top}px; background: linear-gradient(30deg, rgba(115, 103, 240), rgba(115, 103, 240)); box-shadow: 0 0 8px 0 rgba(115, 103, 240); @@ -734,7 +676,7 @@ const Admin: React.FC = ({ { + onClick={($target) => { onAddUser($target); }} > @@ -744,7 +686,7 @@ const Admin: React.FC = ({ - {users.map(member => { + {users.map((member) => { const projectTotal = member.owned.projects.length + member.member.projects.length; return ( @@ -757,7 +699,7 @@ const Admin: React.FC = ({ {`On ${projectTotal} projects`} { + onClick={($target) => { showPopup( $target, = ({ onUpdateUserPassword(user, password); }} canChangeRole={(member.role && member.role.code !== 'owner') ?? false} - onChangeRole={roleCode => { + onChangeRole={(roleCode) => { updateUserRole({ variables: { userID: member.id, roleCode } }); }} onDeleteUser={onDeleteUser} diff --git a/go.mod b/go.mod index 90d3ff4..2c040df 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/jordanknott/project-citadel/api +module github.com/jordanknott/project-citadel go 1.13 diff --git a/gqlgen.yml b/gqlgen.yml index e205281..cc89c0f 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -29,7 +29,7 @@ omit_slice_element_pointers: true # gqlgen will search for any type names in the schema in these go packages # if they match it will use them, otherwise it will generate them. autobind: - - "github.com/jordanknott/project-citadel/api/internal/db" + - "github.com/jordanknott/project-citadel/internal/db" # This section declares type mapping between the GraphQL and go type systems # @@ -38,10 +38,10 @@ autobind: # your liking models: ID: - model: github.com/jordanknott/project-citadel/api/internal/graph.UUID + model: github.com/jordanknott/project-citadel/internal/graph.UUID Int: model: - github.com/99designs/gqlgen/graphql.Int UUID: - model: github.com/jordanknott/project-citadel/api/internal/graph.UUID + model: github.com/jordanknott/project-citadel/internal/graph.UUID diff --git a/internal/commands/migrate.go b/internal/commands/migrate.go index 8edc590..3eff75b 100644 --- a/internal/commands/migrate.go +++ b/internal/commands/migrate.go @@ -9,8 +9,8 @@ import ( _ "github.com/golang-migrate/migrate/v4/source/file" "github.com/golang-migrate/migrate/v4/source/httpfs" "github.com/jmoiron/sqlx" - "github.com/jordanknott/project-citadel/api/internal/config" - "github.com/jordanknott/project-citadel/api/internal/migrations" + "github.com/jordanknott/project-citadel/internal/config" + "github.com/jordanknott/project-citadel/internal/migrations" log "github.com/sirupsen/logrus" ) diff --git a/internal/commands/web.go b/internal/commands/web.go index 76fcd74..e18d2e6 100644 --- a/internal/commands/web.go +++ b/internal/commands/web.go @@ -7,8 +7,8 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/jordanknott/project-citadel/api/internal/config" - "github.com/jordanknott/project-citadel/api/internal/route" + "github.com/jordanknott/project-citadel/internal/config" + "github.com/jordanknott/project-citadel/internal/route" log "github.com/sirupsen/logrus" ) diff --git a/internal/graph/generated.go b/internal/graph/generated.go index ef5c08e..29c10da 100644 --- a/internal/graph/generated.go +++ b/internal/graph/generated.go @@ -14,7 +14,7 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/introspection" "github.com/google/uuid" - "github.com/jordanknott/project-citadel/api/internal/db" + "github.com/jordanknott/project-citadel/internal/db" gqlparser "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" ) diff --git a/internal/graph/graph.go b/internal/graph/graph.go index 9b7dd87..12201ab 100644 --- a/internal/graph/graph.go +++ b/internal/graph/graph.go @@ -12,9 +12,9 @@ import ( "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/99designs/gqlgen/graphql/playground" "github.com/google/uuid" - "github.com/jordanknott/project-citadel/api/internal/auth" - "github.com/jordanknott/project-citadel/api/internal/config" - "github.com/jordanknott/project-citadel/api/internal/db" + "github.com/jordanknott/project-citadel/internal/auth" + "github.com/jordanknott/project-citadel/internal/config" + "github.com/jordanknott/project-citadel/internal/db" ) // NewHandler returns a new graphql endpoint handler. diff --git a/internal/graph/helpers.go b/internal/graph/helpers.go index d9daba5..2721fe9 100644 --- a/internal/graph/helpers.go +++ b/internal/graph/helpers.go @@ -4,7 +4,7 @@ import ( "context" "database/sql" - "github.com/jordanknott/project-citadel/api/internal/db" + "github.com/jordanknott/project-citadel/internal/db" ) func GetOwnedList(ctx context.Context, r db.Repository, user db.UserAccount) (*OwnedList, error) { diff --git a/internal/graph/models_gen.go b/internal/graph/models_gen.go index 3608723..c634b32 100644 --- a/internal/graph/models_gen.go +++ b/internal/graph/models_gen.go @@ -9,7 +9,7 @@ import ( "time" "github.com/google/uuid" - "github.com/jordanknott/project-citadel/api/internal/db" + "github.com/jordanknott/project-citadel/internal/db" ) type AddTaskLabelInput struct { diff --git a/internal/graph/resolver.go b/internal/graph/resolver.go index 1ec1ff8..3d5e173 100644 --- a/internal/graph/resolver.go +++ b/internal/graph/resolver.go @@ -5,8 +5,8 @@ package graph import ( "sync" - "github.com/jordanknott/project-citadel/api/internal/config" - "github.com/jordanknott/project-citadel/api/internal/db" + "github.com/jordanknott/project-citadel/internal/config" + "github.com/jordanknott/project-citadel/internal/db" ) type Resolver struct { diff --git a/internal/graph/schema.resolvers.go b/internal/graph/schema.resolvers.go index eedd8d1..d958f9f 100644 --- a/internal/graph/schema.resolvers.go +++ b/internal/graph/schema.resolvers.go @@ -11,7 +11,7 @@ import ( "time" "github.com/google/uuid" - "github.com/jordanknott/project-citadel/api/internal/db" + "github.com/jordanknott/project-citadel/internal/db" log "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/v2/gqlerror" "golang.org/x/crypto/bcrypt" diff --git a/internal/route/auth.go b/internal/route/auth.go index e85347e..e382fa7 100644 --- a/internal/route/auth.go +++ b/internal/route/auth.go @@ -8,8 +8,8 @@ import ( "github.com/go-chi/chi" "github.com/google/uuid" - "github.com/jordanknott/project-citadel/api/internal/auth" - "github.com/jordanknott/project-citadel/api/internal/db" + "github.com/jordanknott/project-citadel/internal/auth" + "github.com/jordanknott/project-citadel/internal/db" log "github.com/sirupsen/logrus" "golang.org/x/crypto/bcrypt" ) diff --git a/internal/route/avatar.go b/internal/route/avatar.go index b875ad4..376e31e 100644 --- a/internal/route/avatar.go +++ b/internal/route/avatar.go @@ -12,8 +12,8 @@ import ( "time" - "github.com/jordanknott/project-citadel/api/internal/db" - "github.com/jordanknott/project-citadel/api/internal/frontend" + "github.com/jordanknott/project-citadel/internal/db" + "github.com/jordanknott/project-citadel/internal/frontend" ) func (h *CitadelHandler) Frontend(w http.ResponseWriter, r *http.Request) { diff --git a/internal/route/middleware.go b/internal/route/middleware.go index 002603f..d658665 100644 --- a/internal/route/middleware.go +++ b/internal/route/middleware.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/google/uuid" - "github.com/jordanknott/project-citadel/api/internal/auth" + "github.com/jordanknott/project-citadel/internal/auth" log "github.com/sirupsen/logrus" ) diff --git a/internal/route/route.go b/internal/route/route.go index 7d1c774..47842da 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -10,11 +10,11 @@ import ( "github.com/jmoiron/sqlx" log "github.com/sirupsen/logrus" - "github.com/jordanknott/project-citadel/api/internal/config" - "github.com/jordanknott/project-citadel/api/internal/db" - "github.com/jordanknott/project-citadel/api/internal/frontend" - "github.com/jordanknott/project-citadel/api/internal/graph" - "github.com/jordanknott/project-citadel/api/internal/logger" + "github.com/jordanknott/project-citadel/internal/config" + "github.com/jordanknott/project-citadel/internal/db" + "github.com/jordanknott/project-citadel/internal/frontend" + "github.com/jordanknott/project-citadel/internal/graph" + "github.com/jordanknott/project-citadel/internal/logger" "os" "path/filepath" )