feat: add public projects
This commit is contained in:
@ -122,12 +122,12 @@ func (q *Queries) DeleteProjectMember(ctx context.Context, arg DeleteProjectMemb
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllProjects = `-- name: GetAllProjects :many
|
||||
SELECT project_id, team_id, created_at, name FROM project
|
||||
const getAllProjectsForTeam = `-- name: GetAllProjectsForTeam :many
|
||||
SELECT project_id, team_id, created_at, name FROM project WHERE team_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllProjects(ctx context.Context) ([]Project, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllProjects)
|
||||
func (q *Queries) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllProjectsForTeam, teamID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -154,12 +154,12 @@ func (q *Queries) GetAllProjects(ctx context.Context) ([]Project, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllProjectsForTeam = `-- name: GetAllProjectsForTeam :many
|
||||
SELECT project_id, team_id, created_at, name FROM project WHERE team_id = $1
|
||||
const getAllTeamProjects = `-- name: GetAllTeamProjects :many
|
||||
SELECT project_id, team_id, created_at, name FROM project WHERE team_id IS NOT null
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllProjectsForTeam, teamID)
|
||||
func (q *Queries) GetAllTeamProjects(ctx context.Context) ([]Project, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllTeamProjects)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -49,10 +49,10 @@ type Querier interface {
|
||||
DeleteUserAccountByID(ctx context.Context, userID uuid.UUID) error
|
||||
GetAllNotificationsForUserID(ctx context.Context, notifierID uuid.UUID) ([]Notification, error)
|
||||
GetAllOrganizations(ctx context.Context) ([]Organization, error)
|
||||
GetAllProjects(ctx context.Context) ([]Project, error)
|
||||
GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error)
|
||||
GetAllTaskGroups(ctx context.Context) ([]TaskGroup, error)
|
||||
GetAllTasks(ctx context.Context) ([]Task, error)
|
||||
GetAllTeamProjects(ctx context.Context) ([]Project, error)
|
||||
GetAllTeams(ctx context.Context) ([]Team, error)
|
||||
GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||
GetAllVisibleProjectsForUserID(ctx context.Context, userID uuid.UUID) ([]Project, error)
|
||||
@ -61,6 +61,7 @@ type Querier interface {
|
||||
GetEntityIDForNotificationID(ctx context.Context, notificationID uuid.UUID) (uuid.UUID, error)
|
||||
GetLabelColorByID(ctx context.Context, labelColorID uuid.UUID) (LabelColor, error)
|
||||
GetLabelColors(ctx context.Context) ([]LabelColor, error)
|
||||
GetMemberData(ctx context.Context) ([]GetMemberDataRow, error)
|
||||
GetMemberProjectIDsForUserID(ctx context.Context, userID uuid.UUID) ([]uuid.UUID, error)
|
||||
GetMemberTeamIDsForUserID(ctx context.Context, userID uuid.UUID) ([]uuid.UUID, error)
|
||||
GetNotificationForNotificationID(ctx context.Context, notificationID uuid.UUID) (GetNotificationForNotificationIDRow, error)
|
||||
|
@ -15,6 +15,9 @@ INSERT INTO user_account(full_name, initials, email, username, created_at, passw
|
||||
UPDATE user_account SET profile_avatar_url = $2 WHERE user_id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetMemberData :many
|
||||
SELECT username, email, user_id FROM user_account;
|
||||
|
||||
-- name: UpdateUserAccountInfo :one
|
||||
UPDATE user_account SET bio = $2, full_name = $3, initials = $4, email = $5
|
||||
WHERE user_id = $1 RETURNING *;
|
||||
|
@ -101,6 +101,39 @@ func (q *Queries) GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getMemberData = `-- name: GetMemberData :many
|
||||
SELECT username, email, user_id FROM user_account
|
||||
`
|
||||
|
||||
type GetMemberDataRow struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetMemberData(ctx context.Context) ([]GetMemberDataRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getMemberData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetMemberDataRow
|
||||
for rows.Next() {
|
||||
var i GetMemberDataRow
|
||||
if err := rows.Scan(&i.Username, &i.Email, &i.UserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getRoleForUserID = `-- name: GetRoleForUserID :one
|
||||
SELECT username, role.code, role.name FROM user_account
|
||||
INNER JOIN role ON role.code = user_account.role_code
|
||||
|
@ -160,6 +160,15 @@ type ComplexityRoot struct {
|
||||
Teams func(childComplexity int) int
|
||||
}
|
||||
|
||||
MemberSearchResult struct {
|
||||
Confirmed func(childComplexity int) int
|
||||
FullName func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
Joined func(childComplexity int) int
|
||||
Similarity func(childComplexity int) int
|
||||
Username func(childComplexity int) int
|
||||
}
|
||||
|
||||
Mutation struct {
|
||||
AddTaskLabel func(childComplexity int, input *AddTaskLabelInput) int
|
||||
AssignTask func(childComplexity int, input *AssignTaskInput) int
|
||||
@ -289,6 +298,7 @@ type ComplexityRoot struct {
|
||||
Notifications func(childComplexity int) int
|
||||
Organizations func(childComplexity int) int
|
||||
Projects func(childComplexity int, input *ProjectsFilter) int
|
||||
SearchMembers func(childComplexity int, input MemberSearchFilter) int
|
||||
TaskGroups func(childComplexity int) int
|
||||
Teams func(childComplexity int) int
|
||||
Users func(childComplexity int) int
|
||||
@ -528,6 +538,7 @@ type QueryResolver interface {
|
||||
TaskGroups(ctx context.Context) ([]db.TaskGroup, error)
|
||||
Me(ctx context.Context) (*MePayload, error)
|
||||
Notifications(ctx context.Context) ([]db.Notification, error)
|
||||
SearchMembers(ctx context.Context, input MemberSearchFilter) ([]MemberSearchResult, error)
|
||||
}
|
||||
type RefreshTokenResolver interface {
|
||||
ID(ctx context.Context, obj *db.RefreshToken) (uuid.UUID, error)
|
||||
@ -917,6 +928,48 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.MemberList.Teams(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.confirmed":
|
||||
if e.complexity.MemberSearchResult.Confirmed == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.Confirmed(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.fullName":
|
||||
if e.complexity.MemberSearchResult.FullName == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.FullName(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.id":
|
||||
if e.complexity.MemberSearchResult.ID == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.ID(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.joined":
|
||||
if e.complexity.MemberSearchResult.Joined == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.Joined(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.similarity":
|
||||
if e.complexity.MemberSearchResult.Similarity == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.Similarity(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.username":
|
||||
if e.complexity.MemberSearchResult.Username == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.Username(childComplexity), true
|
||||
|
||||
case "Mutation.addTaskLabel":
|
||||
if e.complexity.Mutation.AddTaskLabel == nil {
|
||||
break
|
||||
@ -1862,6 +1915,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Query.Projects(childComplexity, args["input"].(*ProjectsFilter)), true
|
||||
|
||||
case "Query.searchMembers":
|
||||
if e.complexity.Query.SearchMembers == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Query_searchMembers_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Query.SearchMembers(childComplexity, args["input"].(MemberSearchFilter)), true
|
||||
|
||||
case "Query.taskGroups":
|
||||
if e.complexity.Query.TaskGroups == nil {
|
||||
break
|
||||
@ -3208,6 +3273,24 @@ extend type Mutation {
|
||||
UpdateUserInfoPayload! @hasRole(roles: [ADMIN], level: ORG, type: ORG)
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
searchMembers(input: MemberSearchFilter!): [MemberSearchResult!]!
|
||||
}
|
||||
|
||||
input MemberSearchFilter {
|
||||
SearchFilter: String!
|
||||
projectID: UUID
|
||||
}
|
||||
|
||||
type MemberSearchResult {
|
||||
id: UUID!
|
||||
similarity: Int!
|
||||
username: String!
|
||||
fullName: String!
|
||||
confirmed: Boolean!
|
||||
joined: Boolean!
|
||||
}
|
||||
|
||||
type UpdateUserInfoPayload {
|
||||
user: UserAccount!
|
||||
}
|
||||
@ -4101,6 +4184,20 @@ func (ec *executionContext) field_Query_projects_args(ctx context.Context, rawAr
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Query_searchMembers_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 MemberSearchFilter
|
||||
if tmp, ok := rawArgs["input"]; ok {
|
||||
arg0, err = ec.unmarshalNMemberSearchFilter2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberSearchFilter(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args["input"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
@ -5701,6 +5798,210 @@ func (ec *executionContext) _MemberList_projects(ctx context.Context, field grap
|
||||
return ec.marshalNProject2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐProjectᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_id(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.ID, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(uuid.UUID)
|
||||
fc.Result = res
|
||||
return ec.marshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_similarity(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Similarity, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(int)
|
||||
fc.Result = res
|
||||
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_username(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Username, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_fullName(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.FullName, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_confirmed(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Confirmed, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_joined(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Joined, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_createProject(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -10978,6 +11279,47 @@ func (ec *executionContext) _Query_notifications(ctx context.Context, field grap
|
||||
return ec.marshalNNotification2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐNotificationᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_searchMembers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Query",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: true,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Query_searchMembers_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
fc.Args = args
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Query().SearchMembers(rctx, args["input"].(MemberSearchFilter))
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]MemberSearchResult)
|
||||
fc.Result = res
|
||||
return ec.marshalNMemberSearchResult2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberSearchResultᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -15144,6 +15486,30 @@ func (ec *executionContext) unmarshalInputLogoutUser(ctx context.Context, obj in
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputMemberSearchFilter(ctx context.Context, obj interface{}) (MemberSearchFilter, error) {
|
||||
var it MemberSearchFilter
|
||||
var asMap = obj.(map[string]interface{})
|
||||
|
||||
for k, v := range asMap {
|
||||
switch k {
|
||||
case "SearchFilter":
|
||||
var err error
|
||||
it.SearchFilter, err = ec.unmarshalNString2string(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "projectID":
|
||||
var err error
|
||||
it.ProjectID, err = ec.unmarshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputNewProject(ctx context.Context, obj interface{}) (NewProject, error) {
|
||||
var it NewProject
|
||||
var asMap = obj.(map[string]interface{})
|
||||
@ -16675,6 +17041,58 @@ func (ec *executionContext) _MemberList(ctx context.Context, sel ast.SelectionSe
|
||||
return out
|
||||
}
|
||||
|
||||
var memberSearchResultImplementors = []string{"MemberSearchResult"}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult(ctx context.Context, sel ast.SelectionSet, obj *MemberSearchResult) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, memberSearchResultImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("MemberSearchResult")
|
||||
case "id":
|
||||
out.Values[i] = ec._MemberSearchResult_id(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "similarity":
|
||||
out.Values[i] = ec._MemberSearchResult_similarity(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "username":
|
||||
out.Values[i] = ec._MemberSearchResult_username(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "fullName":
|
||||
out.Values[i] = ec._MemberSearchResult_fullName(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "confirmed":
|
||||
out.Values[i] = ec._MemberSearchResult_confirmed(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "joined":
|
||||
out.Values[i] = ec._MemberSearchResult_joined(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var mutationImplementors = []string{"Mutation"}
|
||||
|
||||
func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {
|
||||
@ -17645,6 +18063,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "searchMembers":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Query_searchMembers(ctx, field)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "__type":
|
||||
out.Values[i] = ec._Query___type(ctx, field)
|
||||
case "__schema":
|
||||
@ -19452,6 +19884,51 @@ func (ec *executionContext) marshalNMemberList2ᚖgithubᚗcomᚋjordanknottᚋt
|
||||
return ec._MemberList(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNMemberSearchFilter2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberSearchFilter(ctx context.Context, v interface{}) (MemberSearchFilter, error) {
|
||||
return ec.unmarshalInputMemberSearchFilter(ctx, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNMemberSearchResult2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberSearchResult(ctx context.Context, sel ast.SelectionSet, v MemberSearchResult) graphql.Marshaler {
|
||||
return ec._MemberSearchResult(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNMemberSearchResult2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberSearchResultᚄ(ctx context.Context, sel ast.SelectionSet, v []MemberSearchResult) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
if !isLen1 {
|
||||
wg.Add(len(v))
|
||||
}
|
||||
for i := range v {
|
||||
i := i
|
||||
fc := &graphql.FieldContext{
|
||||
Index: &i,
|
||||
Result: &v[i],
|
||||
}
|
||||
ctx := graphql.WithFieldContext(ctx, fc)
|
||||
f := func(i int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.marshalNMemberSearchResult2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberSearchResult(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNNewProject2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐNewProject(ctx context.Context, v interface{}) (NewProject, error) {
|
||||
return ec.unmarshalInputNewProject(ctx, v)
|
||||
}
|
||||
|
@ -212,6 +212,20 @@ type MemberList struct {
|
||||
Projects []db.Project `json:"projects"`
|
||||
}
|
||||
|
||||
type MemberSearchFilter struct {
|
||||
SearchFilter string `json:"SearchFilter"`
|
||||
ProjectID *uuid.UUID `json:"projectID"`
|
||||
}
|
||||
|
||||
type MemberSearchResult struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Similarity int `json:"similarity"`
|
||||
Username string `json:"username"`
|
||||
FullName string `json:"fullName"`
|
||||
Confirmed bool `json:"confirmed"`
|
||||
Joined bool `json:"joined"`
|
||||
}
|
||||
|
||||
type NewProject struct {
|
||||
TeamID *uuid.UUID `json:"teamID"`
|
||||
Name string `json:"name"`
|
||||
|
@ -734,6 +734,24 @@ extend type Mutation {
|
||||
UpdateUserInfoPayload! @hasRole(roles: [ADMIN], level: ORG, type: ORG)
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
searchMembers(input: MemberSearchFilter!): [MemberSearchResult!]!
|
||||
}
|
||||
|
||||
input MemberSearchFilter {
|
||||
SearchFilter: String!
|
||||
projectID: UUID
|
||||
}
|
||||
|
||||
type MemberSearchResult {
|
||||
id: UUID!
|
||||
similarity: Int!
|
||||
username: String!
|
||||
fullName: String!
|
||||
confirmed: Boolean!
|
||||
joined: Boolean!
|
||||
}
|
||||
|
||||
type UpdateUserInfoPayload {
|
||||
user: UserAccount!
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/jordanknott/taskcafe/internal/auth"
|
||||
"github.com/jordanknott/taskcafe/internal/db"
|
||||
"github.com/lithammer/fuzzysearch/fuzzy"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@ -1193,6 +1194,41 @@ func (r *queryResolver) Notifications(ctx context.Context) ([]db.Notification, e
|
||||
return notifications, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) SearchMembers(ctx context.Context, input MemberSearchFilter) ([]MemberSearchResult, error) {
|
||||
availableMembers, err := r.Repository.GetMemberData(ctx)
|
||||
if err != nil {
|
||||
return []MemberSearchResult{}, err
|
||||
}
|
||||
|
||||
sortList := []string{}
|
||||
masterList := map[string]uuid.UUID{}
|
||||
for _, member := range availableMembers {
|
||||
sortList = append(sortList, member.Username)
|
||||
sortList = append(sortList, member.Email)
|
||||
masterList[member.Username] = member.UserID
|
||||
masterList[member.Email] = member.UserID
|
||||
}
|
||||
rankedList := fuzzy.RankFind(input.SearchFilter, sortList)
|
||||
results := []MemberSearchResult{}
|
||||
memberList := map[uuid.UUID]bool{}
|
||||
for _, rank := range rankedList {
|
||||
if _, ok := memberList[masterList[rank.Target]]; !ok {
|
||||
log.WithFields(log.Fields{"source": rank.Source, "target": rank.Target}).Info("searching")
|
||||
userID := masterList[rank.Target]
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, userID)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
continue
|
||||
}
|
||||
return []MemberSearchResult{}, err
|
||||
}
|
||||
results = append(results, MemberSearchResult{FullName: user.FullName, Username: user.Username, Joined: false, Confirmed: false, Similarity: rank.Distance, ID: user.UserID})
|
||||
memberList[masterList[rank.Target]] = true
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (r *refreshTokenResolver) ID(ctx context.Context, obj *db.RefreshToken) (uuid.UUID, error) {
|
||||
return obj.TokenID, nil
|
||||
}
|
||||
|
@ -15,6 +15,24 @@ extend type Mutation {
|
||||
UpdateUserInfoPayload! @hasRole(roles: [ADMIN], level: ORG, type: ORG)
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
searchMembers(input: MemberSearchFilter!): [MemberSearchResult!]!
|
||||
}
|
||||
|
||||
input MemberSearchFilter {
|
||||
SearchFilter: String!
|
||||
projectID: UUID
|
||||
}
|
||||
|
||||
type MemberSearchResult {
|
||||
id: UUID!
|
||||
similarity: Int!
|
||||
username: String!
|
||||
fullName: String!
|
||||
confirmed: Boolean!
|
||||
joined: Boolean!
|
||||
}
|
||||
|
||||
type UpdateUserInfoPayload {
|
||||
user: UserAccount!
|
||||
}
|
||||
|
Reference in New Issue
Block a user