Compare commits
1 Commits
feat/colle
...
revamp/hea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dcfc684ef |
@@ -1,5 +0,0 @@
|
|||||||
-- AlterTable
|
|
||||||
ALTER TABLE "TeamCollection" ADD COLUMN "data" JSONB;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE "UserCollection" ADD COLUMN "data" JSONB;
|
|
||||||
@@ -43,7 +43,6 @@ model TeamInvitation {
|
|||||||
model TeamCollection {
|
model TeamCollection {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
parentID String?
|
parentID String?
|
||||||
data Json?
|
|
||||||
parent TeamCollection? @relation("TeamCollectionChildParent", fields: [parentID], references: [id])
|
parent TeamCollection? @relation("TeamCollectionChildParent", fields: [parentID], references: [id])
|
||||||
children TeamCollection[] @relation("TeamCollectionChildParent")
|
children TeamCollection[] @relation("TeamCollectionChildParent")
|
||||||
requests TeamRequest[]
|
requests TeamRequest[]
|
||||||
@@ -75,8 +74,7 @@ model Shortcode {
|
|||||||
creatorUid String?
|
creatorUid String?
|
||||||
User User? @relation(fields: [creatorUid], references: [uid])
|
User User? @relation(fields: [creatorUid], references: [uid])
|
||||||
createdOn DateTime @default(now())
|
createdOn DateTime @default(now())
|
||||||
updatedOn DateTime @default(now()) @updatedAt
|
updatedOn DateTime @updatedAt @default(now())
|
||||||
|
|
||||||
@@unique(fields: [id, creatorUid], name: "creator_uid_shortcode_unique")
|
@@unique(fields: [id, creatorUid], name: "creator_uid_shortcode_unique")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +195,6 @@ model UserCollection {
|
|||||||
userUid String
|
userUid String
|
||||||
user User @relation(fields: [userUid], references: [uid], onDelete: Cascade)
|
user User @relation(fields: [userUid], references: [uid], onDelete: Cascade)
|
||||||
title String
|
title String
|
||||||
data Json?
|
|
||||||
orderIndex Int
|
orderIndex Int
|
||||||
type ReqType
|
type ReqType
|
||||||
createdOn DateTime @default(now()) @db.Timestamp(3)
|
createdOn DateTime @default(now()) @db.Timestamp(3)
|
||||||
|
|||||||
@@ -254,13 +254,6 @@ export const TEAM_COLL_INVALID_JSON = 'team_coll/invalid_json';
|
|||||||
*/
|
*/
|
||||||
export const TEAM_NOT_OWNER = 'team_coll/team_not_owner' as const;
|
export const TEAM_NOT_OWNER = 'team_coll/team_not_owner' as const;
|
||||||
|
|
||||||
/**
|
|
||||||
* The Team Collection data is not valid
|
|
||||||
* (TeamCollectionService)
|
|
||||||
*/
|
|
||||||
export const TEAM_COLL_DATA_INVALID =
|
|
||||||
'team_coll/team_coll_data_invalid' as const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tried to perform an action on a request that doesn't accept their member role level
|
* Tried to perform an action on a request that doesn't accept their member role level
|
||||||
* (GqlRequestTeamMemberGuard)
|
* (GqlRequestTeamMemberGuard)
|
||||||
@@ -592,13 +585,6 @@ export const USER_COLL_REORDERING_FAILED =
|
|||||||
export const USER_COLL_SAME_NEXT_COLL =
|
export const USER_COLL_SAME_NEXT_COLL =
|
||||||
'user_coll/user_collection_and_next_user_collection_are_same' as const;
|
'user_coll/user_collection_and_next_user_collection_are_same' as const;
|
||||||
|
|
||||||
/**
|
|
||||||
* The User Collection data is not valid
|
|
||||||
* (UserCollectionService)
|
|
||||||
*/
|
|
||||||
export const USER_COLL_DATA_INVALID =
|
|
||||||
'user_coll/user_coll_data_invalid' as const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The User Collection does not belong to the logged-in user
|
* The User Collection does not belong to the logged-in user
|
||||||
* (UserCollectionService)
|
* (UserCollectionService)
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import {
|
|||||||
} from 'src/team-request/team-request.model';
|
} from 'src/team-request/team-request.model';
|
||||||
import { TeamInvitation } from 'src/team-invitation/team-invitation.model';
|
import { TeamInvitation } from 'src/team-invitation/team-invitation.model';
|
||||||
import { InvitedUser } from '../admin/invited-user.model';
|
import { InvitedUser } from '../admin/invited-user.model';
|
||||||
|
import { UserCollection } from '@prisma/client';
|
||||||
import {
|
import {
|
||||||
UserCollection,
|
|
||||||
UserCollectionRemovedData,
|
UserCollectionRemovedData,
|
||||||
UserCollectionReorderData,
|
UserCollectionReorderData,
|
||||||
} from 'src/user-collection/user-collections.model';
|
} from 'src/user-collection/user-collections.model';
|
||||||
|
|||||||
@@ -14,13 +14,6 @@ export class CreateRootTeamCollectionArgs {
|
|||||||
|
|
||||||
@Field({ name: 'title', description: 'Title of the new collection' })
|
@Field({ name: 'title', description: 'Title of the new collection' })
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
@Field({
|
|
||||||
name: 'data',
|
|
||||||
description: 'JSON string representing the collection data',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
data: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgsType()
|
@ArgsType()
|
||||||
@@ -33,13 +26,6 @@ export class CreateChildTeamCollectionArgs {
|
|||||||
|
|
||||||
@Field({ name: 'childTitle', description: 'Title of the new collection' })
|
@Field({ name: 'childTitle', description: 'Title of the new collection' })
|
||||||
childTitle: string;
|
childTitle: string;
|
||||||
|
|
||||||
@Field({
|
|
||||||
name: 'data',
|
|
||||||
description: 'JSON string representing the collection data',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
data: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgsType()
|
@ArgsType()
|
||||||
@@ -47,14 +33,12 @@ export class RenameTeamCollectionArgs {
|
|||||||
@Field(() => ID, {
|
@Field(() => ID, {
|
||||||
name: 'collectionID',
|
name: 'collectionID',
|
||||||
description: 'ID of the collection',
|
description: 'ID of the collection',
|
||||||
deprecationReason: 'Switch to updateTeamCollection mutation instead',
|
|
||||||
})
|
})
|
||||||
collectionID: string;
|
collectionID: string;
|
||||||
|
|
||||||
@Field({
|
@Field({
|
||||||
name: 'newTitle',
|
name: 'newTitle',
|
||||||
description: 'The updated title of the collection',
|
description: 'The updated title of the collection',
|
||||||
deprecationReason: 'Switch to updateTeamCollection mutation instead',
|
|
||||||
})
|
})
|
||||||
newTitle: string;
|
newTitle: string;
|
||||||
}
|
}
|
||||||
@@ -114,26 +98,3 @@ export class ReplaceTeamCollectionArgs {
|
|||||||
})
|
})
|
||||||
parentCollectionID?: string;
|
parentCollectionID?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgsType()
|
|
||||||
export class UpdateTeamCollectionArgs {
|
|
||||||
@Field(() => ID, {
|
|
||||||
name: 'collectionID',
|
|
||||||
description: 'ID of the collection',
|
|
||||||
})
|
|
||||||
collectionID: string;
|
|
||||||
|
|
||||||
@Field({
|
|
||||||
name: 'newTitle',
|
|
||||||
description: 'The updated title of the collection',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
newTitle: string;
|
|
||||||
|
|
||||||
@Field({
|
|
||||||
name: 'data',
|
|
||||||
description: 'JSON string representing the collection data',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
data: string;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,17 +12,12 @@ export class TeamCollection {
|
|||||||
})
|
})
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
@Field({
|
|
||||||
description: 'JSON string representing the collection data',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
data: string;
|
|
||||||
|
|
||||||
@Field(() => ID, {
|
@Field(() => ID, {
|
||||||
description: 'ID of the collection',
|
description: 'ID of the collection',
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
parentID: string;
|
parentID: string;
|
||||||
|
teamID: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import {
|
|||||||
MoveTeamCollectionArgs,
|
MoveTeamCollectionArgs,
|
||||||
RenameTeamCollectionArgs,
|
RenameTeamCollectionArgs,
|
||||||
ReplaceTeamCollectionArgs,
|
ReplaceTeamCollectionArgs,
|
||||||
UpdateTeamCollectionArgs,
|
|
||||||
UpdateTeamCollectionOrderArgs,
|
UpdateTeamCollectionOrderArgs,
|
||||||
} from './input-type.args';
|
} from './input-type.args';
|
||||||
import * as E from 'fp-ts/Either';
|
import * as E from 'fp-ts/Either';
|
||||||
@@ -142,14 +141,7 @@ export class TeamCollectionResolver {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (E.isLeft(teamCollections)) throwErr(teamCollections.left);
|
if (E.isLeft(teamCollections)) throwErr(teamCollections.left);
|
||||||
return <TeamCollection>{
|
return teamCollections.right;
|
||||||
id: teamCollections.right.id,
|
|
||||||
title: teamCollections.right.title,
|
|
||||||
parentID: teamCollections.right.parentID,
|
|
||||||
data: !teamCollections.right.data
|
|
||||||
? null
|
|
||||||
: JSON.stringify(teamCollections.right.data),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutations
|
// Mutations
|
||||||
@@ -163,7 +155,6 @@ export class TeamCollectionResolver {
|
|||||||
const teamCollection = await this.teamCollectionService.createCollection(
|
const teamCollection = await this.teamCollectionService.createCollection(
|
||||||
args.teamID,
|
args.teamID,
|
||||||
args.title,
|
args.title,
|
||||||
args.data,
|
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -239,7 +230,6 @@ export class TeamCollectionResolver {
|
|||||||
const teamCollection = await this.teamCollectionService.createCollection(
|
const teamCollection = await this.teamCollectionService.createCollection(
|
||||||
team.right.id,
|
team.right.id,
|
||||||
args.childTitle,
|
args.childTitle,
|
||||||
args.data,
|
|
||||||
args.collectionID,
|
args.collectionID,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -249,7 +239,6 @@ export class TeamCollectionResolver {
|
|||||||
|
|
||||||
@Mutation(() => TeamCollection, {
|
@Mutation(() => TeamCollection, {
|
||||||
description: 'Rename a collection',
|
description: 'Rename a collection',
|
||||||
deprecationReason: 'Switch to updateTeamCollection mutation instead',
|
|
||||||
})
|
})
|
||||||
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
||||||
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
||||||
@@ -314,23 +303,6 @@ export class TeamCollectionResolver {
|
|||||||
return request.right;
|
return request.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => TeamCollection, {
|
|
||||||
description: 'Update Team Collection details',
|
|
||||||
})
|
|
||||||
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
|
||||||
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
||||||
async updateTeamCollection(@Args() args: UpdateTeamCollectionArgs) {
|
|
||||||
const updatedTeamCollection =
|
|
||||||
await this.teamCollectionService.updateTeamCollection(
|
|
||||||
args.collectionID,
|
|
||||||
args.data,
|
|
||||||
args.newTitle,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (E.isLeft(updatedTeamCollection)) throwErr(updatedTeamCollection.left);
|
|
||||||
return updatedTeamCollection.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subscriptions
|
// Subscriptions
|
||||||
|
|
||||||
@Subscription(() => TeamCollection, {
|
@Subscription(() => TeamCollection, {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Team, TeamCollection as DBTeamCollection } from '@prisma/client';
|
import { Team, TeamCollection as DBTeamCollection } from '@prisma/client';
|
||||||
import { mockDeep, mockReset } from 'jest-mock-extended';
|
import { mockDeep, mockReset } from 'jest-mock-extended';
|
||||||
import {
|
import {
|
||||||
TEAM_COLL_DATA_INVALID,
|
|
||||||
TEAM_COLL_DEST_SAME,
|
TEAM_COLL_DEST_SAME,
|
||||||
TEAM_COLL_INVALID_JSON,
|
TEAM_COLL_INVALID_JSON,
|
||||||
TEAM_COLL_IS_PARENT_COLL,
|
TEAM_COLL_IS_PARENT_COLL,
|
||||||
@@ -18,7 +17,6 @@ import { PrismaService } from 'src/prisma/prisma.service';
|
|||||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||||
import { AuthUser } from 'src/types/AuthUser';
|
import { AuthUser } from 'src/types/AuthUser';
|
||||||
import { TeamCollectionService } from './team-collection.service';
|
import { TeamCollectionService } from './team-collection.service';
|
||||||
import { TeamCollection } from './team-collection.model';
|
|
||||||
|
|
||||||
const mockPrisma = mockDeep<PrismaService>();
|
const mockPrisma = mockDeep<PrismaService>();
|
||||||
const mockPubSub = mockDeep<PubSubService>();
|
const mockPubSub = mockDeep<PubSubService>();
|
||||||
@@ -53,60 +51,35 @@ const rootTeamCollection: DBTeamCollection = {
|
|||||||
id: '123',
|
id: '123',
|
||||||
orderIndex: 1,
|
orderIndex: 1,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
data: {},
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
const rootTeamCollectionsCasted: TeamCollection = {
|
|
||||||
id: rootTeamCollection.id,
|
|
||||||
title: rootTeamCollection.title,
|
|
||||||
parentID: rootTeamCollection.parentID,
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
};
|
|
||||||
|
|
||||||
const rootTeamCollection_2: DBTeamCollection = {
|
const rootTeamCollection_2: DBTeamCollection = {
|
||||||
id: 'erv',
|
id: 'erv',
|
||||||
orderIndex: 2,
|
orderIndex: 2,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
data: {},
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
const rootTeamCollection_2Casted: TeamCollection = {
|
|
||||||
id: 'erv',
|
|
||||||
parentID: null,
|
|
||||||
data: JSON.stringify(rootTeamCollection_2.data),
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
};
|
|
||||||
|
|
||||||
const childTeamCollection: DBTeamCollection = {
|
const childTeamCollection: DBTeamCollection = {
|
||||||
id: 'rfe',
|
id: 'rfe',
|
||||||
orderIndex: 1,
|
orderIndex: 1,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
data: {},
|
|
||||||
title: 'Child Collection 1',
|
title: 'Child Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
const childTeamCollectionCasted: TeamCollection = {
|
|
||||||
id: 'rfe',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
data: JSON.stringify(childTeamCollection.data),
|
|
||||||
title: 'Child Collection 1',
|
|
||||||
};
|
|
||||||
|
|
||||||
const childTeamCollection_2: DBTeamCollection = {
|
const childTeamCollection_2: DBTeamCollection = {
|
||||||
id: 'bgdz',
|
id: 'bgdz',
|
||||||
orderIndex: 1,
|
orderIndex: 1,
|
||||||
data: {},
|
|
||||||
parentID: rootTeamCollection_2.id,
|
parentID: rootTeamCollection_2.id,
|
||||||
title: 'Child Collection 1',
|
title: 'Child Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
@@ -114,20 +87,11 @@ const childTeamCollection_2: DBTeamCollection = {
|
|||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
const childTeamCollection_2Casted: TeamCollection = {
|
|
||||||
id: 'bgdz',
|
|
||||||
data: JSON.stringify(childTeamCollection_2.data),
|
|
||||||
parentID: rootTeamCollection_2.id,
|
|
||||||
title: 'Child Collection 1',
|
|
||||||
};
|
|
||||||
|
|
||||||
const rootTeamCollectionList: DBTeamCollection[] = [
|
const rootTeamCollectionList: DBTeamCollection[] = [
|
||||||
{
|
{
|
||||||
id: 'fdv',
|
id: 'fdv',
|
||||||
orderIndex: 1,
|
orderIndex: 1,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
data: {},
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -138,8 +102,6 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
orderIndex: 2,
|
orderIndex: 2,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
data: {},
|
|
||||||
|
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
@@ -149,8 +111,6 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
orderIndex: 3,
|
orderIndex: 3,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
data: {},
|
|
||||||
|
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
@@ -159,8 +119,6 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
id: 'bre3',
|
id: 'bre3',
|
||||||
orderIndex: 4,
|
orderIndex: 4,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
data: {},
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -171,8 +129,6 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
orderIndex: 5,
|
orderIndex: 5,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
data: {},
|
|
||||||
|
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
@@ -183,8 +139,6 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
parentID: null,
|
parentID: null,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
data: {},
|
|
||||||
|
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
},
|
},
|
||||||
@@ -194,8 +148,6 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
parentID: null,
|
parentID: null,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
data: {},
|
|
||||||
|
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
},
|
},
|
||||||
@@ -204,7 +156,6 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
orderIndex: 8,
|
orderIndex: 8,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
data: {},
|
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
@@ -214,7 +165,6 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
orderIndex: 9,
|
orderIndex: 9,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
data: {},
|
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
@@ -225,83 +175,17 @@ const rootTeamCollectionList: DBTeamCollection[] = [
|
|||||||
parentID: null,
|
parentID: null,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
data: {},
|
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const rootTeamCollectionListCasted: TeamCollection[] = [
|
|
||||||
{
|
|
||||||
id: 'fdv',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'fbbg',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'fgbfg',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'bre3',
|
|
||||||
parentID: null,
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'hghgf',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '123',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '54tyh',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '234re',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '34rtg',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '45tgh',
|
|
||||||
parentID: null,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify(rootTeamCollection.data),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const childTeamCollectionList: DBTeamCollection[] = [
|
const childTeamCollectionList: DBTeamCollection[] = [
|
||||||
{
|
{
|
||||||
id: '123',
|
id: '123',
|
||||||
orderIndex: 1,
|
orderIndex: 1,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
data: {},
|
|
||||||
|
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
@@ -311,8 +195,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
orderIndex: 2,
|
orderIndex: 2,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
data: {},
|
|
||||||
|
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
@@ -322,8 +204,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
orderIndex: 3,
|
orderIndex: 3,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
data: {},
|
|
||||||
|
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
updatedOn: currentTime,
|
updatedOn: currentTime,
|
||||||
@@ -332,8 +212,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
id: '567',
|
id: '567',
|
||||||
orderIndex: 4,
|
orderIndex: 4,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
data: {},
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -343,8 +221,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
id: '123',
|
id: '123',
|
||||||
orderIndex: 5,
|
orderIndex: 5,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
data: {},
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -354,8 +230,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
id: '678',
|
id: '678',
|
||||||
orderIndex: 6,
|
orderIndex: 6,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
data: {},
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -365,8 +239,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
id: '789',
|
id: '789',
|
||||||
orderIndex: 7,
|
orderIndex: 7,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
data: {},
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -376,8 +248,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
id: '890',
|
id: '890',
|
||||||
orderIndex: 8,
|
orderIndex: 8,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
data: {},
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -387,7 +257,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
id: '012',
|
id: '012',
|
||||||
orderIndex: 9,
|
orderIndex: 9,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
data: {},
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -397,8 +266,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
id: '0bhu',
|
id: '0bhu',
|
||||||
orderIndex: 10,
|
orderIndex: 10,
|
||||||
parentID: rootTeamCollection.id,
|
parentID: rootTeamCollection.id,
|
||||||
data: {},
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
title: 'Root Collection 1',
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
createdOn: currentTime,
|
createdOn: currentTime,
|
||||||
@@ -406,75 +273,6 @@ const childTeamCollectionList: DBTeamCollection[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const childTeamCollectionListCasted: TeamCollection[] = [
|
|
||||||
{
|
|
||||||
id: '123',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '345',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '456',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '567',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '123',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '678',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '789',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '890',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '012',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '0bhu',
|
|
||||||
parentID: rootTeamCollection.id,
|
|
||||||
data: JSON.stringify({}),
|
|
||||||
|
|
||||||
title: 'Root Collection 1',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockReset(mockPrisma);
|
mockReset(mockPrisma);
|
||||||
mockPubSub.publish.mockClear();
|
mockPubSub.publish.mockClear();
|
||||||
@@ -513,7 +311,7 @@ describe('getParentOfCollection', () => {
|
|||||||
const result = await teamCollectionService.getParentOfCollection(
|
const result = await teamCollectionService.getParentOfCollection(
|
||||||
childTeamCollection.id,
|
childTeamCollection.id,
|
||||||
);
|
);
|
||||||
expect(result).toEqual(rootTeamCollectionsCasted);
|
expect(result).toEqual(rootTeamCollection);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return null successfully for a root collection with valid collectionID', async () => {
|
test('should return null successfully for a root collection with valid collectionID', async () => {
|
||||||
@@ -549,7 +347,7 @@ describe('getChildrenOfCollection', () => {
|
|||||||
null,
|
null,
|
||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
expect(result).toEqual(childTeamCollectionListCasted);
|
expect(result).toEqual(childTeamCollectionList);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return a list of 3 child collections successfully with cursor being equal to the 7th item in the list', async () => {
|
test('should return a list of 3 child collections successfully with cursor being equal to the 7th item in the list', async () => {
|
||||||
@@ -565,9 +363,9 @@ describe('getChildrenOfCollection', () => {
|
|||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
{ ...childTeamCollectionListCasted[7] },
|
{ ...childTeamCollectionList[7] },
|
||||||
{ ...childTeamCollectionListCasted[8] },
|
{ ...childTeamCollectionList[8] },
|
||||||
{ ...childTeamCollectionListCasted[9] },
|
{ ...childTeamCollectionList[9] },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -594,7 +392,7 @@ describe('getTeamRootCollections', () => {
|
|||||||
null,
|
null,
|
||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
expect(result).toEqual(rootTeamCollectionListCasted);
|
expect(result).toEqual(rootTeamCollectionList);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return a list of 3 root collections successfully with cursor being equal to the 7th item in the list', async () => {
|
test('should return a list of 3 root collections successfully with cursor being equal to the 7th item in the list', async () => {
|
||||||
@@ -610,9 +408,9 @@ describe('getTeamRootCollections', () => {
|
|||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
{ ...rootTeamCollectionListCasted[7] },
|
{ ...rootTeamCollectionList[7] },
|
||||||
{ ...rootTeamCollectionListCasted[8] },
|
{ ...rootTeamCollectionList[8] },
|
||||||
{ ...rootTeamCollectionListCasted[9] },
|
{ ...rootTeamCollectionList[9] },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -666,7 +464,6 @@ describe('createCollection', () => {
|
|||||||
const result = await teamCollectionService.createCollection(
|
const result = await teamCollectionService.createCollection(
|
||||||
rootTeamCollection.teamID,
|
rootTeamCollection.teamID,
|
||||||
'ab',
|
'ab',
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
rootTeamCollection.id,
|
rootTeamCollection.id,
|
||||||
);
|
);
|
||||||
expect(result).toEqualLeft(TEAM_COLL_SHORT_TITLE);
|
expect(result).toEqualLeft(TEAM_COLL_SHORT_TITLE);
|
||||||
@@ -681,27 +478,11 @@ describe('createCollection', () => {
|
|||||||
const result = await teamCollectionService.createCollection(
|
const result = await teamCollectionService.createCollection(
|
||||||
rootTeamCollection.teamID,
|
rootTeamCollection.teamID,
|
||||||
'abcd',
|
'abcd',
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
rootTeamCollection.id,
|
rootTeamCollection.id,
|
||||||
);
|
);
|
||||||
expect(result).toEqualLeft(TEAM_NOT_OWNER);
|
expect(result).toEqualLeft(TEAM_NOT_OWNER);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should throw TEAM_COLL_DATA_INVALID when parent TeamCollection does not belong to the team', async () => {
|
|
||||||
// isOwnerCheck
|
|
||||||
mockPrisma.teamCollection.findFirstOrThrow.mockResolvedValueOnce(
|
|
||||||
rootTeamCollection,
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await teamCollectionService.createCollection(
|
|
||||||
rootTeamCollection.teamID,
|
|
||||||
'abcd',
|
|
||||||
'{',
|
|
||||||
rootTeamCollection.id,
|
|
||||||
);
|
|
||||||
expect(result).toEqualLeft(TEAM_COLL_DATA_INVALID);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should successfully create a new root TeamCollection with valid inputs', async () => {
|
test('should successfully create a new root TeamCollection with valid inputs', async () => {
|
||||||
// isOwnerCheck
|
// isOwnerCheck
|
||||||
mockPrisma.teamCollection.findFirstOrThrow.mockResolvedValueOnce(
|
mockPrisma.teamCollection.findFirstOrThrow.mockResolvedValueOnce(
|
||||||
@@ -715,10 +496,9 @@ describe('createCollection', () => {
|
|||||||
const result = await teamCollectionService.createCollection(
|
const result = await teamCollectionService.createCollection(
|
||||||
rootTeamCollection.teamID,
|
rootTeamCollection.teamID,
|
||||||
'abcdefg',
|
'abcdefg',
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
rootTeamCollection.id,
|
rootTeamCollection.id,
|
||||||
);
|
);
|
||||||
expect(result).toEqualRight(rootTeamCollectionsCasted);
|
expect(result).toEqualRight(rootTeamCollection);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should successfully create a new child TeamCollection with valid inputs', async () => {
|
test('should successfully create a new child TeamCollection with valid inputs', async () => {
|
||||||
@@ -734,10 +514,9 @@ describe('createCollection', () => {
|
|||||||
const result = await teamCollectionService.createCollection(
|
const result = await teamCollectionService.createCollection(
|
||||||
childTeamCollection.teamID,
|
childTeamCollection.teamID,
|
||||||
childTeamCollection.title,
|
childTeamCollection.title,
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
rootTeamCollection.id,
|
rootTeamCollection.id,
|
||||||
);
|
);
|
||||||
expect(result).toEqualRight(childTeamCollectionCasted);
|
expect(result).toEqualRight(childTeamCollection);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should send pubsub message to "team_coll/<teamID>/coll_added" if child TeamCollection is created successfully', async () => {
|
test('should send pubsub message to "team_coll/<teamID>/coll_added" if child TeamCollection is created successfully', async () => {
|
||||||
@@ -753,13 +532,11 @@ describe('createCollection', () => {
|
|||||||
const result = await teamCollectionService.createCollection(
|
const result = await teamCollectionService.createCollection(
|
||||||
childTeamCollection.teamID,
|
childTeamCollection.teamID,
|
||||||
childTeamCollection.title,
|
childTeamCollection.title,
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
|
|
||||||
rootTeamCollection.id,
|
rootTeamCollection.id,
|
||||||
);
|
);
|
||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${childTeamCollection.teamID}/coll_added`,
|
`team_coll/${childTeamCollection.teamID}/coll_added`,
|
||||||
childTeamCollectionCasted,
|
childTeamCollection,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -776,13 +553,11 @@ describe('createCollection', () => {
|
|||||||
const result = await teamCollectionService.createCollection(
|
const result = await teamCollectionService.createCollection(
|
||||||
rootTeamCollection.teamID,
|
rootTeamCollection.teamID,
|
||||||
'abcdefg',
|
'abcdefg',
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
|
|
||||||
rootTeamCollection.id,
|
rootTeamCollection.id,
|
||||||
);
|
);
|
||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${rootTeamCollection.teamID}/coll_added`,
|
`team_coll/${rootTeamCollection.teamID}/coll_added`,
|
||||||
rootTeamCollectionsCasted,
|
rootTeamCollection,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -812,7 +587,7 @@ describe('renameCollection', () => {
|
|||||||
'NewTitle',
|
'NewTitle',
|
||||||
);
|
);
|
||||||
expect(result).toEqualRight({
|
expect(result).toEqualRight({
|
||||||
...rootTeamCollectionsCasted,
|
...rootTeamCollection,
|
||||||
title: 'NewTitle',
|
title: 'NewTitle',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -850,7 +625,7 @@ describe('renameCollection', () => {
|
|||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${rootTeamCollection.teamID}/coll_updated`,
|
`team_coll/${rootTeamCollection.teamID}/coll_updated`,
|
||||||
{
|
{
|
||||||
...rootTeamCollectionsCasted,
|
...rootTeamCollection,
|
||||||
title: 'NewTitle',
|
title: 'NewTitle',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -1057,8 +832,9 @@ describe('moveCollection', () => {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
expect(result).toEqualRight({
|
expect(result).toEqualRight({
|
||||||
...childTeamCollectionCasted,
|
...childTeamCollection,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
|
orderIndex: 2,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1114,8 +890,9 @@ describe('moveCollection', () => {
|
|||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${childTeamCollection.teamID}/coll_moved`,
|
`team_coll/${childTeamCollection.teamID}/coll_moved`,
|
||||||
{
|
{
|
||||||
...childTeamCollectionCasted,
|
...childTeamCollection,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
|
orderIndex: 2,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -1154,8 +931,9 @@ describe('moveCollection', () => {
|
|||||||
childTeamCollection_2.id,
|
childTeamCollection_2.id,
|
||||||
);
|
);
|
||||||
expect(result).toEqualRight({
|
expect(result).toEqualRight({
|
||||||
...rootTeamCollectionsCasted,
|
...rootTeamCollection,
|
||||||
parentID: childTeamCollection_2Casted.id,
|
parentID: childTeamCollection_2.id,
|
||||||
|
orderIndex: 1,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1195,8 +973,9 @@ describe('moveCollection', () => {
|
|||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${childTeamCollection_2.teamID}/coll_moved`,
|
`team_coll/${childTeamCollection_2.teamID}/coll_moved`,
|
||||||
{
|
{
|
||||||
...rootTeamCollectionsCasted,
|
...rootTeamCollection,
|
||||||
parentID: childTeamCollection_2Casted.id,
|
parentID: childTeamCollection_2.id,
|
||||||
|
orderIndex: 1,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -1235,8 +1014,9 @@ describe('moveCollection', () => {
|
|||||||
childTeamCollection_2.id,
|
childTeamCollection_2.id,
|
||||||
);
|
);
|
||||||
expect(result).toEqualRight({
|
expect(result).toEqualRight({
|
||||||
...childTeamCollectionCasted,
|
...childTeamCollection,
|
||||||
parentID: childTeamCollection_2Casted.id,
|
parentID: childTeamCollection_2.id,
|
||||||
|
orderIndex: 1,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1276,8 +1056,9 @@ describe('moveCollection', () => {
|
|||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${childTeamCollection.teamID}/coll_moved`,
|
`team_coll/${childTeamCollection.teamID}/coll_moved`,
|
||||||
{
|
{
|
||||||
...childTeamCollectionCasted,
|
...childTeamCollection,
|
||||||
parentID: childTeamCollection_2Casted.id,
|
parentID: childTeamCollection_2.id,
|
||||||
|
orderIndex: 1,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -1373,7 +1154,7 @@ describe('updateCollectionOrder', () => {
|
|||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${childTeamCollectionList[4].teamID}/coll_order_updated`,
|
`team_coll/${childTeamCollectionList[4].teamID}/coll_order_updated`,
|
||||||
{
|
{
|
||||||
collection: rootTeamCollectionListCasted[4],
|
collection: rootTeamCollectionList[4],
|
||||||
nextCollection: null,
|
nextCollection: null,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -1454,8 +1235,8 @@ describe('updateCollectionOrder', () => {
|
|||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${childTeamCollectionList[2].teamID}/coll_order_updated`,
|
`team_coll/${childTeamCollectionList[2].teamID}/coll_order_updated`,
|
||||||
{
|
{
|
||||||
collection: childTeamCollectionListCasted[4],
|
collection: childTeamCollectionList[4],
|
||||||
nextCollection: childTeamCollectionListCasted[2],
|
nextCollection: childTeamCollectionList[2],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -1521,7 +1302,7 @@ describe('importCollectionsFromJSON', () => {
|
|||||||
);
|
);
|
||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${rootTeamCollection.teamID}/coll_added`,
|
`team_coll/${rootTeamCollection.teamID}/coll_added`,
|
||||||
rootTeamCollectionsCasted,
|
rootTeamCollection,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1640,7 +1421,7 @@ describe('replaceCollectionsWithJSON', () => {
|
|||||||
);
|
);
|
||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
||||||
`team_coll/${rootTeamCollection.teamID}/coll_added`,
|
`team_coll/${rootTeamCollection.teamID}/coll_added`,
|
||||||
rootTeamCollectionsCasted,
|
rootTeamCollection,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1677,64 +1458,4 @@ describe('totalCollectionsInTeam', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('updateTeamCollection', () => {
|
|
||||||
test('should throw TEAM_COLL_SHORT_TITLE if title is invalid', async () => {
|
|
||||||
const result = await teamCollectionService.updateTeamCollection(
|
|
||||||
rootTeamCollection.id,
|
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
'de',
|
|
||||||
);
|
|
||||||
expect(result).toEqualLeft(TEAM_COLL_SHORT_TITLE);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should throw TEAM_COLL_DATA_INVALID is collection data is invalid', async () => {
|
|
||||||
const result = await teamCollectionService.updateTeamCollection(
|
|
||||||
rootTeamCollection.id,
|
|
||||||
'{',
|
|
||||||
rootTeamCollection.title,
|
|
||||||
);
|
|
||||||
expect(result).toEqualLeft(TEAM_COLL_DATA_INVALID);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should throw TEAM_COLL_NOT_FOUND is collectionID is invalid', async () => {
|
|
||||||
mockPrisma.teamCollection.update.mockRejectedValueOnce('RecordNotFound');
|
|
||||||
|
|
||||||
const result = await teamCollectionService.updateTeamCollection(
|
|
||||||
'invalid_id',
|
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
rootTeamCollection.title,
|
|
||||||
);
|
|
||||||
expect(result).toEqualLeft(TEAM_COLL_NOT_FOUND);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should successfully update a collection', async () => {
|
|
||||||
mockPrisma.teamCollection.update.mockResolvedValueOnce(rootTeamCollection);
|
|
||||||
|
|
||||||
const result = await teamCollectionService.updateTeamCollection(
|
|
||||||
rootTeamCollection.id,
|
|
||||||
JSON.stringify({ foo: 'bar' }),
|
|
||||||
'new_title',
|
|
||||||
);
|
|
||||||
expect(result).toEqualRight({
|
|
||||||
data: JSON.stringify({ foo: 'bar' }),
|
|
||||||
title: 'new_title',
|
|
||||||
...rootTeamCollectionsCasted,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should send pubsub message to "team_coll/<teamID>/coll_updated" if TeamCollection is updated successfully', async () => {
|
|
||||||
mockPrisma.teamCollection.update.mockResolvedValueOnce(rootTeamCollection);
|
|
||||||
|
|
||||||
const result = await teamCollectionService.updateTeamCollection(
|
|
||||||
rootTeamCollection.id,
|
|
||||||
JSON.stringify(rootTeamCollection.data),
|
|
||||||
rootTeamCollection.title,
|
|
||||||
);
|
|
||||||
expect(mockPubSub.publish).toHaveBeenCalledWith(
|
|
||||||
`team_coll/${rootTeamCollection.teamID}/coll_updated`,
|
|
||||||
rootTeamCollectionsCasted,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//ToDo: write test cases for exportCollectionsToJSON
|
//ToDo: write test cases for exportCollectionsToJSON
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
TEAM_COLL_IS_PARENT_COLL,
|
TEAM_COLL_IS_PARENT_COLL,
|
||||||
TEAM_COL_SAME_NEXT_COLL,
|
TEAM_COL_SAME_NEXT_COLL,
|
||||||
TEAM_COL_REORDERING_FAILED,
|
TEAM_COL_REORDERING_FAILED,
|
||||||
TEAM_COLL_DATA_INVALID,
|
|
||||||
} from '../errors';
|
} from '../errors';
|
||||||
import { PubSubService } from '../pubsub/pubsub.service';
|
import { PubSubService } from '../pubsub/pubsub.service';
|
||||||
import { isValidLength } from 'src/utils';
|
import { isValidLength } from 'src/utils';
|
||||||
@@ -70,7 +69,6 @@ export class TeamCollectionService {
|
|||||||
this.generatePrismaQueryObjForFBCollFolder(f, teamID, index + 1),
|
this.generatePrismaQueryObjForFBCollFolder(f, teamID, index + 1),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
data: folder.data ?? undefined,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +118,6 @@ export class TeamCollectionService {
|
|||||||
name: collection.right.title,
|
name: collection.right.title,
|
||||||
folders: childrenCollectionObjects,
|
folders: childrenCollectionObjects,
|
||||||
requests: requests.map((x) => x.request),
|
requests: requests.map((x) => x.request),
|
||||||
data: JSON.stringify(collection.right.data),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return E.right(result);
|
return E.right(result);
|
||||||
@@ -201,11 +198,8 @@ export class TeamCollectionService {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
teamCollections.forEach((collection) =>
|
teamCollections.forEach((x) =>
|
||||||
this.pubsub.publish(
|
this.pubsub.publish(`team_coll/${destTeamID}/coll_added`, x),
|
||||||
`team_coll/${destTeamID}/coll_added`,
|
|
||||||
this.cast(collection),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return E.right(true);
|
return E.right(true);
|
||||||
@@ -274,11 +268,8 @@ export class TeamCollectionService {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
teamCollections.forEach((collections) =>
|
teamCollections.forEach((x) =>
|
||||||
this.pubsub.publish(
|
this.pubsub.publish(`team_coll/${destTeamID}/coll_added`, x),
|
||||||
`team_coll/${destTeamID}/coll_added`,
|
|
||||||
this.cast(collections),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return E.right(true);
|
return E.right(true);
|
||||||
@@ -286,17 +277,11 @@ export class TeamCollectionService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Typecast a database TeamCollection to a TeamCollection model
|
* Typecast a database TeamCollection to a TeamCollection model
|
||||||
*
|
|
||||||
* @param teamCollection database TeamCollection
|
* @param teamCollection database TeamCollection
|
||||||
* @returns TeamCollection model
|
* @returns TeamCollection model
|
||||||
*/
|
*/
|
||||||
private cast(teamCollection: DBTeamCollection): TeamCollection {
|
private cast(teamCollection: DBTeamCollection): TeamCollection {
|
||||||
return <TeamCollection>{
|
return <TeamCollection>{ ...teamCollection };
|
||||||
id: teamCollection.id,
|
|
||||||
title: teamCollection.title,
|
|
||||||
parentID: teamCollection.parentID,
|
|
||||||
data: !teamCollection.data ? null : JSON.stringify(teamCollection.data),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -339,7 +324,7 @@ export class TeamCollectionService {
|
|||||||
});
|
});
|
||||||
if (!teamCollection) return null;
|
if (!teamCollection) return null;
|
||||||
|
|
||||||
return !teamCollection.parent ? null : this.cast(teamCollection.parent);
|
return teamCollection.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -350,12 +335,12 @@ export class TeamCollectionService {
|
|||||||
* @param take Number of items we want returned
|
* @param take Number of items we want returned
|
||||||
* @returns A list of child collections
|
* @returns A list of child collections
|
||||||
*/
|
*/
|
||||||
async getChildrenOfCollection(
|
getChildrenOfCollection(
|
||||||
collectionID: string,
|
collectionID: string,
|
||||||
cursor: string | null,
|
cursor: string | null,
|
||||||
take: number,
|
take: number,
|
||||||
) {
|
) {
|
||||||
const res = await this.prisma.teamCollection.findMany({
|
return this.prisma.teamCollection.findMany({
|
||||||
where: {
|
where: {
|
||||||
parentID: collectionID,
|
parentID: collectionID,
|
||||||
},
|
},
|
||||||
@@ -366,12 +351,6 @@ export class TeamCollectionService {
|
|||||||
skip: cursor ? 1 : 0,
|
skip: cursor ? 1 : 0,
|
||||||
cursor: cursor ? { id: cursor } : undefined,
|
cursor: cursor ? { id: cursor } : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const childCollections = res.map((teamCollection) =>
|
|
||||||
this.cast(teamCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return childCollections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -387,7 +366,7 @@ export class TeamCollectionService {
|
|||||||
cursor: string | null,
|
cursor: string | null,
|
||||||
take: number,
|
take: number,
|
||||||
) {
|
) {
|
||||||
const res = await this.prisma.teamCollection.findMany({
|
return this.prisma.teamCollection.findMany({
|
||||||
where: {
|
where: {
|
||||||
teamID,
|
teamID,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
@@ -399,12 +378,6 @@ export class TeamCollectionService {
|
|||||||
skip: cursor ? 1 : 0,
|
skip: cursor ? 1 : 0,
|
||||||
cursor: cursor ? { id: cursor } : undefined,
|
cursor: cursor ? { id: cursor } : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const teamCollections = res.map((teamCollection) =>
|
|
||||||
this.cast(teamCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return teamCollections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -497,7 +470,6 @@ export class TeamCollectionService {
|
|||||||
async createCollection(
|
async createCollection(
|
||||||
teamID: string,
|
teamID: string,
|
||||||
title: string,
|
title: string,
|
||||||
data: string | null = null,
|
|
||||||
parentTeamCollectionID: string | null,
|
parentTeamCollectionID: string | null,
|
||||||
) {
|
) {
|
||||||
const isTitleValid = isValidLength(title, this.TITLE_LENGTH);
|
const isTitleValid = isValidLength(title, this.TITLE_LENGTH);
|
||||||
@@ -509,13 +481,6 @@ export class TeamCollectionService {
|
|||||||
if (O.isNone(isOwner)) return E.left(TEAM_NOT_OWNER);
|
if (O.isNone(isOwner)) return E.left(TEAM_NOT_OWNER);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data === '') return E.left(TEAM_COLL_DATA_INVALID);
|
|
||||||
if (data) {
|
|
||||||
const jsonReq = stringToJson(data);
|
|
||||||
if (E.isLeft(jsonReq)) return E.left(TEAM_COLL_DATA_INVALID);
|
|
||||||
data = jsonReq.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isParent = parentTeamCollectionID
|
const isParent = parentTeamCollectionID
|
||||||
? {
|
? {
|
||||||
connect: {
|
connect: {
|
||||||
@@ -533,23 +498,18 @@ export class TeamCollectionService {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
parent: isParent,
|
parent: isParent,
|
||||||
data: data ?? undefined,
|
|
||||||
orderIndex: !parentTeamCollectionID
|
orderIndex: !parentTeamCollectionID
|
||||||
? (await this.getRootCollectionsCount(teamID)) + 1
|
? (await this.getRootCollectionsCount(teamID)) + 1
|
||||||
: (await this.getChildCollectionsCount(parentTeamCollectionID)) + 1,
|
: (await this.getChildCollectionsCount(parentTeamCollectionID)) + 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.pubsub.publish(
|
this.pubsub.publish(`team_coll/${teamID}/coll_added`, teamCollection);
|
||||||
`team_coll/${teamID}/coll_added`,
|
|
||||||
this.cast(teamCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return E.right(this.cast(teamCollection));
|
return E.right(this.cast(teamCollection));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use updateTeamCollection method instead
|
|
||||||
* Update the title of a TeamCollection
|
* Update the title of a TeamCollection
|
||||||
*
|
*
|
||||||
* @param collectionID The Collection ID
|
* @param collectionID The Collection ID
|
||||||
@@ -572,10 +532,10 @@ export class TeamCollectionService {
|
|||||||
|
|
||||||
this.pubsub.publish(
|
this.pubsub.publish(
|
||||||
`team_coll/${updatedTeamCollection.teamID}/coll_updated`,
|
`team_coll/${updatedTeamCollection.teamID}/coll_updated`,
|
||||||
this.cast(updatedTeamCollection),
|
updatedTeamCollection,
|
||||||
);
|
);
|
||||||
|
|
||||||
return E.right(this.cast(updatedTeamCollection));
|
return E.right(updatedTeamCollection);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return E.left(TEAM_COLL_NOT_FOUND);
|
return E.left(TEAM_COLL_NOT_FOUND);
|
||||||
}
|
}
|
||||||
@@ -734,8 +694,8 @@ export class TeamCollectionService {
|
|||||||
* @returns An Option of boolean, is parent or not
|
* @returns An Option of boolean, is parent or not
|
||||||
*/
|
*/
|
||||||
private async isParent(
|
private async isParent(
|
||||||
collection: DBTeamCollection,
|
collection: TeamCollection,
|
||||||
destCollection: DBTeamCollection,
|
destCollection: TeamCollection,
|
||||||
): Promise<O.Option<boolean>> {
|
): Promise<O.Option<boolean>> {
|
||||||
//* Recursively check if collection is a parent by going up the tree of child-parent collections until we reach a root collection i.e parentID === null
|
//* Recursively check if collection is a parent by going up the tree of child-parent collections until we reach a root collection i.e parentID === null
|
||||||
//* Valid condition, isParent returns false
|
//* Valid condition, isParent returns false
|
||||||
@@ -1011,49 +971,4 @@ export class TeamCollectionService {
|
|||||||
const teamCollectionsCount = this.prisma.teamCollection.count();
|
const teamCollectionsCount = this.prisma.teamCollection.count();
|
||||||
return teamCollectionsCount;
|
return teamCollectionsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update Team Collection details
|
|
||||||
*
|
|
||||||
* @param collectionID Collection ID
|
|
||||||
* @param collectionData new header data in a JSONified string form
|
|
||||||
* @param newTitle New title of the collection
|
|
||||||
* @returns Updated TeamCollection
|
|
||||||
*/
|
|
||||||
async updateTeamCollection(
|
|
||||||
collectionID: string,
|
|
||||||
collectionData: string = null,
|
|
||||||
newTitle: string = null,
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
if (newTitle != null) {
|
|
||||||
const isTitleValid = isValidLength(newTitle, this.TITLE_LENGTH);
|
|
||||||
if (!isTitleValid) return E.left(TEAM_COLL_SHORT_TITLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collectionData === '') return E.left(TEAM_COLL_DATA_INVALID);
|
|
||||||
if (collectionData) {
|
|
||||||
const jsonReq = stringToJson(collectionData);
|
|
||||||
if (E.isLeft(jsonReq)) return E.left(TEAM_COLL_DATA_INVALID);
|
|
||||||
collectionData = jsonReq.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedTeamCollection = await this.prisma.teamCollection.update({
|
|
||||||
where: { id: collectionID },
|
|
||||||
data: {
|
|
||||||
data: collectionData ?? undefined,
|
|
||||||
title: newTitle ?? undefined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.pubsub.publish(
|
|
||||||
`team_coll/${updatedTeamCollection.teamID}/coll_updated`,
|
|
||||||
this.cast(updatedTeamCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return E.right(this.cast(updatedTeamCollection));
|
|
||||||
} catch (e) {
|
|
||||||
return E.left(TEAM_COLL_NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ const teamCollection: DbTeamCollection = {
|
|||||||
id: 'team-coll-1',
|
id: 'team-coll-1',
|
||||||
parentID: null,
|
parentID: null,
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
data: {},
|
|
||||||
title: 'Team Collection 1',
|
title: 'Team Collection 1',
|
||||||
orderIndex: 1,
|
orderIndex: 1,
|
||||||
createdOn: new Date(),
|
createdOn: new Date(),
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// This interface defines how data will be received from the app when we are importing Hoppscotch collections
|
|
||||||
export interface CollectionFolder {
|
export interface CollectionFolder {
|
||||||
id?: string;
|
id?: string;
|
||||||
folders: CollectionFolder[];
|
folders: CollectionFolder[];
|
||||||
requests: any[];
|
requests: any[];
|
||||||
name: string;
|
name: string;
|
||||||
data?: string;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,6 @@ import { PaginationArgs } from 'src/types/input-types.args';
|
|||||||
export class CreateRootUserCollectionArgs {
|
export class CreateRootUserCollectionArgs {
|
||||||
@Field({ name: 'title', description: 'Title of the new user collection' })
|
@Field({ name: 'title', description: 'Title of the new user collection' })
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
@Field({
|
|
||||||
name: 'data',
|
|
||||||
description: 'JSON string representing the collection data',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
data: string;
|
|
||||||
}
|
}
|
||||||
@ArgsType()
|
@ArgsType()
|
||||||
export class CreateChildUserCollectionArgs {
|
export class CreateChildUserCollectionArgs {
|
||||||
@@ -24,13 +17,6 @@ export class CreateChildUserCollectionArgs {
|
|||||||
description: 'ID of the parent to the new user collection',
|
description: 'ID of the parent to the new user collection',
|
||||||
})
|
})
|
||||||
parentUserCollectionID: string;
|
parentUserCollectionID: string;
|
||||||
|
|
||||||
@Field({
|
|
||||||
name: 'data',
|
|
||||||
description: 'JSON string representing the collection data',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
data: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgsType()
|
@ArgsType()
|
||||||
@@ -109,26 +95,3 @@ export class ImportUserCollectionsFromJSONArgs {
|
|||||||
})
|
})
|
||||||
parentCollectionID?: string;
|
parentCollectionID?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgsType()
|
|
||||||
export class UpdateUserCollectionsArgs {
|
|
||||||
@Field(() => ID, {
|
|
||||||
name: 'userCollectionID',
|
|
||||||
description: 'ID of the user collection',
|
|
||||||
})
|
|
||||||
userCollectionID: string;
|
|
||||||
|
|
||||||
@Field({
|
|
||||||
name: 'newTitle',
|
|
||||||
description: 'The updated title of the user collection',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
newTitle: string;
|
|
||||||
|
|
||||||
@Field({
|
|
||||||
name: 'data',
|
|
||||||
description: 'JSON string representing the collection data',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
data: string;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import {
|
|||||||
MoveUserCollectionArgs,
|
MoveUserCollectionArgs,
|
||||||
RenameUserCollectionsArgs,
|
RenameUserCollectionsArgs,
|
||||||
UpdateUserCollectionArgs,
|
UpdateUserCollectionArgs,
|
||||||
UpdateUserCollectionsArgs,
|
|
||||||
} from './input-type.args';
|
} from './input-type.args';
|
||||||
import { ReqType } from 'src/types/RequestTypes';
|
import { ReqType } from 'src/types/RequestTypes';
|
||||||
import * as E from 'fp-ts/Either';
|
import * as E from 'fp-ts/Either';
|
||||||
@@ -143,13 +142,7 @@ export class UserCollectionResolver {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (E.isLeft(userCollection)) throwErr(userCollection.left);
|
if (E.isLeft(userCollection)) throwErr(userCollection.left);
|
||||||
return <UserCollection>{
|
return userCollection.right;
|
||||||
...userCollection.right,
|
|
||||||
userID: userCollection.right.userUid,
|
|
||||||
data: !userCollection.right.data
|
|
||||||
? null
|
|
||||||
: JSON.stringify(userCollection.right.data),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => UserCollectionExportJSONData, {
|
@Query(() => UserCollectionExportJSONData, {
|
||||||
@@ -198,7 +191,6 @@ export class UserCollectionResolver {
|
|||||||
await this.userCollectionService.createUserCollection(
|
await this.userCollectionService.createUserCollection(
|
||||||
user,
|
user,
|
||||||
args.title,
|
args.title,
|
||||||
args.data,
|
|
||||||
null,
|
null,
|
||||||
ReqType.REST,
|
ReqType.REST,
|
||||||
);
|
);
|
||||||
@@ -220,7 +212,6 @@ export class UserCollectionResolver {
|
|||||||
await this.userCollectionService.createUserCollection(
|
await this.userCollectionService.createUserCollection(
|
||||||
user,
|
user,
|
||||||
args.title,
|
args.title,
|
||||||
args.data,
|
|
||||||
null,
|
null,
|
||||||
ReqType.GQL,
|
ReqType.GQL,
|
||||||
);
|
);
|
||||||
@@ -241,7 +232,6 @@ export class UserCollectionResolver {
|
|||||||
await this.userCollectionService.createUserCollection(
|
await this.userCollectionService.createUserCollection(
|
||||||
user,
|
user,
|
||||||
args.title,
|
args.title,
|
||||||
args.data,
|
|
||||||
args.parentUserCollectionID,
|
args.parentUserCollectionID,
|
||||||
ReqType.GQL,
|
ReqType.GQL,
|
||||||
);
|
);
|
||||||
@@ -262,7 +252,6 @@ export class UserCollectionResolver {
|
|||||||
await this.userCollectionService.createUserCollection(
|
await this.userCollectionService.createUserCollection(
|
||||||
user,
|
user,
|
||||||
args.title,
|
args.title,
|
||||||
args.data,
|
|
||||||
args.parentUserCollectionID,
|
args.parentUserCollectionID,
|
||||||
ReqType.REST,
|
ReqType.REST,
|
||||||
);
|
);
|
||||||
@@ -370,26 +359,6 @@ export class UserCollectionResolver {
|
|||||||
return importedCollection.right;
|
return importedCollection.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => UserCollection, {
|
|
||||||
description: 'Update a UserCollection',
|
|
||||||
})
|
|
||||||
@UseGuards(GqlAuthGuard)
|
|
||||||
async updateUserCollection(
|
|
||||||
@GqlUser() user: AuthUser,
|
|
||||||
@Args() args: UpdateUserCollectionsArgs,
|
|
||||||
) {
|
|
||||||
const updatedUserCollection =
|
|
||||||
await this.userCollectionService.updateUserCollection(
|
|
||||||
args.newTitle,
|
|
||||||
args.data,
|
|
||||||
args.userCollectionID,
|
|
||||||
user.uid,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (E.isLeft(updatedUserCollection)) throwErr(updatedUserCollection.left);
|
|
||||||
return updatedUserCollection.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subscriptions
|
// Subscriptions
|
||||||
@Subscription(() => UserCollection, {
|
@Subscription(() => UserCollection, {
|
||||||
description: 'Listen for User Collection Creation',
|
description: 'Listen for User Collection Creation',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,6 @@ import {
|
|||||||
USER_NOT_FOUND,
|
USER_NOT_FOUND,
|
||||||
USER_NOT_OWNER,
|
USER_NOT_OWNER,
|
||||||
USER_COLL_INVALID_JSON,
|
USER_COLL_INVALID_JSON,
|
||||||
USER_COLL_DATA_INVALID,
|
|
||||||
} from 'src/errors';
|
} from 'src/errors';
|
||||||
import { PrismaService } from 'src/prisma/prisma.service';
|
import { PrismaService } from 'src/prisma/prisma.service';
|
||||||
import { AuthUser } from 'src/types/AuthUser';
|
import { AuthUser } from 'src/types/AuthUser';
|
||||||
@@ -44,12 +43,8 @@ export class UserCollectionService {
|
|||||||
*/
|
*/
|
||||||
private cast(collection: UserCollection) {
|
private cast(collection: UserCollection) {
|
||||||
return <UserCollectionModel>{
|
return <UserCollectionModel>{
|
||||||
id: collection.id,
|
...collection,
|
||||||
title: collection.title,
|
|
||||||
type: collection.type,
|
|
||||||
parentID: collection.parentID,
|
|
||||||
userID: collection.userUid,
|
userID: collection.userUid,
|
||||||
data: !collection.data ? null : JSON.stringify(collection.data),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +146,7 @@ export class UserCollectionService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return !parent ? null : this.cast(parent);
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,7 +164,7 @@ export class UserCollectionService {
|
|||||||
take: number,
|
take: number,
|
||||||
type: ReqType,
|
type: ReqType,
|
||||||
) {
|
) {
|
||||||
const res = await this.prisma.userCollection.findMany({
|
return this.prisma.userCollection.findMany({
|
||||||
where: {
|
where: {
|
||||||
parentID: collectionID,
|
parentID: collectionID,
|
||||||
type: type,
|
type: type,
|
||||||
@@ -181,12 +176,6 @@ export class UserCollectionService {
|
|||||||
skip: cursor ? 1 : 0,
|
skip: cursor ? 1 : 0,
|
||||||
cursor: cursor ? { id: cursor } : undefined,
|
cursor: cursor ? { id: cursor } : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const childCollections = res.map((childCollection) =>
|
|
||||||
this.cast(childCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return childCollections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,20 +211,12 @@ export class UserCollectionService {
|
|||||||
async createUserCollection(
|
async createUserCollection(
|
||||||
user: AuthUser,
|
user: AuthUser,
|
||||||
title: string,
|
title: string,
|
||||||
data: string | null = null,
|
|
||||||
parentUserCollectionID: string | null,
|
parentUserCollectionID: string | null,
|
||||||
type: ReqType,
|
type: ReqType,
|
||||||
) {
|
) {
|
||||||
const isTitleValid = isValidLength(title, this.TITLE_LENGTH);
|
const isTitleValid = isValidLength(title, this.TITLE_LENGTH);
|
||||||
if (!isTitleValid) return E.left(USER_COLL_SHORT_TITLE);
|
if (!isTitleValid) return E.left(USER_COLL_SHORT_TITLE);
|
||||||
|
|
||||||
if (data === '') return E.left(USER_COLL_DATA_INVALID);
|
|
||||||
if (data) {
|
|
||||||
const jsonReq = stringToJson(data);
|
|
||||||
if (E.isLeft(jsonReq)) return E.left(USER_COLL_DATA_INVALID);
|
|
||||||
data = jsonReq.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If creating a child collection
|
// If creating a child collection
|
||||||
if (parentUserCollectionID !== null) {
|
if (parentUserCollectionID !== null) {
|
||||||
const parentCollection = await this.getUserCollection(
|
const parentCollection = await this.getUserCollection(
|
||||||
@@ -270,19 +251,15 @@ export class UserCollectionService {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
parent: isParent,
|
parent: isParent,
|
||||||
data: data ?? undefined,
|
|
||||||
orderIndex: !parentUserCollectionID
|
orderIndex: !parentUserCollectionID
|
||||||
? (await this.getRootCollectionsCount(user.uid)) + 1
|
? (await this.getRootCollectionsCount(user.uid)) + 1
|
||||||
: (await this.getChildCollectionsCount(parentUserCollectionID)) + 1,
|
: (await this.getChildCollectionsCount(parentUserCollectionID)) + 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.pubsub.publish(
|
await this.pubsub.publish(`user_coll/${user.uid}/created`, userCollection);
|
||||||
`user_coll/${user.uid}/created`,
|
|
||||||
this.cast(userCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return E.right(this.cast(userCollection));
|
return E.right(userCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -299,7 +276,7 @@ export class UserCollectionService {
|
|||||||
take: number,
|
take: number,
|
||||||
type: ReqType,
|
type: ReqType,
|
||||||
) {
|
) {
|
||||||
const res = await this.prisma.userCollection.findMany({
|
return this.prisma.userCollection.findMany({
|
||||||
where: {
|
where: {
|
||||||
userUid: user.uid,
|
userUid: user.uid,
|
||||||
parentID: null,
|
parentID: null,
|
||||||
@@ -312,12 +289,6 @@ export class UserCollectionService {
|
|||||||
skip: cursor ? 1 : 0,
|
skip: cursor ? 1 : 0,
|
||||||
cursor: cursor ? { id: cursor } : undefined,
|
cursor: cursor ? { id: cursor } : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const userCollections = res.map((childCollection) =>
|
|
||||||
this.cast(childCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return userCollections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -336,7 +307,7 @@ export class UserCollectionService {
|
|||||||
take: number,
|
take: number,
|
||||||
type: ReqType,
|
type: ReqType,
|
||||||
) {
|
) {
|
||||||
const res = await this.prisma.userCollection.findMany({
|
return this.prisma.userCollection.findMany({
|
||||||
where: {
|
where: {
|
||||||
userUid: user.uid,
|
userUid: user.uid,
|
||||||
parentID: userCollectionID,
|
parentID: userCollectionID,
|
||||||
@@ -346,16 +317,9 @@ export class UserCollectionService {
|
|||||||
skip: cursor ? 1 : 0,
|
skip: cursor ? 1 : 0,
|
||||||
cursor: cursor ? { id: cursor } : undefined,
|
cursor: cursor ? { id: cursor } : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const childCollections = res.map((childCollection) =>
|
|
||||||
this.cast(childCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return childCollections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use updateUserCollection method instead
|
|
||||||
* Update the title of a UserCollection
|
* Update the title of a UserCollection
|
||||||
*
|
*
|
||||||
* @param newTitle The new title of collection
|
* @param newTitle The new title of collection
|
||||||
@@ -387,10 +351,10 @@ export class UserCollectionService {
|
|||||||
|
|
||||||
this.pubsub.publish(
|
this.pubsub.publish(
|
||||||
`user_coll/${updatedUserCollection.userUid}/updated`,
|
`user_coll/${updatedUserCollection.userUid}/updated`,
|
||||||
this.cast(updatedUserCollection),
|
updatedUserCollection,
|
||||||
);
|
);
|
||||||
|
|
||||||
return E.right(this.cast(updatedUserCollection));
|
return E.right(updatedUserCollection);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return E.left(USER_COLL_NOT_FOUND);
|
return E.left(USER_COLL_NOT_FOUND);
|
||||||
}
|
}
|
||||||
@@ -627,10 +591,10 @@ export class UserCollectionService {
|
|||||||
|
|
||||||
this.pubsub.publish(
|
this.pubsub.publish(
|
||||||
`user_coll/${collection.right.userUid}/moved`,
|
`user_coll/${collection.right.userUid}/moved`,
|
||||||
this.cast(updatedCollection.right),
|
updatedCollection.right,
|
||||||
);
|
);
|
||||||
|
|
||||||
return E.right(this.cast(updatedCollection.right));
|
return E.right(updatedCollection.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
// destCollectionID != null i.e move into another collection
|
// destCollectionID != null i.e move into another collection
|
||||||
@@ -678,10 +642,10 @@ export class UserCollectionService {
|
|||||||
|
|
||||||
this.pubsub.publish(
|
this.pubsub.publish(
|
||||||
`user_coll/${collection.right.userUid}/moved`,
|
`user_coll/${collection.right.userUid}/moved`,
|
||||||
this.cast(updatedCollection.right),
|
updatedCollection.right,
|
||||||
);
|
);
|
||||||
|
|
||||||
return E.right(this.cast(updatedCollection.right));
|
return E.right(updatedCollection.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -882,7 +846,6 @@ export class UserCollectionService {
|
|||||||
...(x.request as Record<string, unknown>), // type casting x.request of type Prisma.JSONValue to an object to enable spread
|
...(x.request as Record<string, unknown>), // type casting x.request of type Prisma.JSONValue to an object to enable spread
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
data: JSON.stringify(collection.right.data),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return E.right(result);
|
return E.right(result);
|
||||||
@@ -955,7 +918,6 @@ export class UserCollectionService {
|
|||||||
...(x.request as Record<string, unknown>), // type casting x.request of type Prisma.JSONValue to an object to enable spread
|
...(x.request as Record<string, unknown>), // type casting x.request of type Prisma.JSONValue to an object to enable spread
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
data: JSON.stringify(parentCollection.right.data),
|
|
||||||
}),
|
}),
|
||||||
collectionType: parentCollection.right.type,
|
collectionType: parentCollection.right.type,
|
||||||
});
|
});
|
||||||
@@ -1009,7 +971,6 @@ export class UserCollectionService {
|
|||||||
this.generatePrismaQueryObj(f, userID, index + 1, reqType),
|
this.generatePrismaQueryObj(f, userID, index + 1, reqType),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
data: folder.data ?? undefined,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1079,63 +1040,10 @@ export class UserCollectionService {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
userCollections.forEach((collection) =>
|
userCollections.forEach((x) =>
|
||||||
this.pubsub.publish(`user_coll/${userID}/created`, this.cast(collection)),
|
this.pubsub.publish(`user_coll/${userID}/created`, x),
|
||||||
);
|
);
|
||||||
|
|
||||||
return E.right(true);
|
return E.right(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a UserCollection
|
|
||||||
*
|
|
||||||
* @param newTitle The new title of collection
|
|
||||||
* @param userCollectionID The Collection Id
|
|
||||||
* @param userID The User UID
|
|
||||||
* @returns An Either of the updated UserCollection
|
|
||||||
*/
|
|
||||||
async updateUserCollection(
|
|
||||||
newTitle: string = null,
|
|
||||||
collectionData: string | null = null,
|
|
||||||
userCollectionID: string,
|
|
||||||
userID: string,
|
|
||||||
) {
|
|
||||||
if (collectionData === '') return E.left(USER_COLL_DATA_INVALID);
|
|
||||||
|
|
||||||
if (collectionData) {
|
|
||||||
const jsonReq = stringToJson(collectionData);
|
|
||||||
if (E.isLeft(jsonReq)) return E.left(USER_COLL_DATA_INVALID);
|
|
||||||
collectionData = jsonReq.right;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newTitle != null) {
|
|
||||||
const isTitleValid = isValidLength(newTitle, this.TITLE_LENGTH);
|
|
||||||
if (!isTitleValid) return E.left(USER_COLL_SHORT_TITLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see is the collection belongs to the user
|
|
||||||
const isOwner = await this.isOwnerCheck(userCollectionID, userID);
|
|
||||||
if (O.isNone(isOwner)) return E.left(USER_NOT_OWNER);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const updatedUserCollection = await this.prisma.userCollection.update({
|
|
||||||
where: {
|
|
||||||
id: userCollectionID,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
data: collectionData ?? undefined,
|
|
||||||
title: newTitle ?? undefined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.pubsub.publish(
|
|
||||||
`user_coll/${updatedUserCollection.userUid}/updated`,
|
|
||||||
this.cast(updatedUserCollection),
|
|
||||||
);
|
|
||||||
|
|
||||||
return E.right(this.cast(updatedUserCollection));
|
|
||||||
} catch (error) {
|
|
||||||
return E.left(USER_COLL_NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,6 @@ export class UserCollection {
|
|||||||
})
|
})
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
@Field({
|
|
||||||
description: 'JSON string representing the collection data',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
data: string;
|
|
||||||
|
|
||||||
@Field(() => ReqType, {
|
@Field(() => ReqType, {
|
||||||
description: 'Type of the user collection',
|
description: 'Type of the user collection',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -332,9 +332,13 @@
|
|||||||
"url": "URL"
|
"url": "URL"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"install_pwa": "Install app",
|
"install_pwa": "Add to Home Screen",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
"save_workspace": "Save My Workspace"
|
"save_workspace": "Save My Workspace",
|
||||||
|
"download_app": "Download app",
|
||||||
|
"menu": "Menu",
|
||||||
|
"go_back": "Go back",
|
||||||
|
"go_forward": "Go forward"
|
||||||
},
|
},
|
||||||
"helpers": {
|
"helpers": {
|
||||||
"authorization": "The authorization header will be automatically generated when you send the request.",
|
"authorization": "The authorization header will be automatically generated when you send the request.",
|
||||||
|
|||||||
@@ -2,25 +2,49 @@
|
|||||||
<div>
|
<div>
|
||||||
<header
|
<header
|
||||||
ref="headerRef"
|
ref="headerRef"
|
||||||
class="flex flex-1 flex-shrink-0 items-center justify-between space-x-2 overflow-x-auto overflow-y-hidden px-2 py-2"
|
class="grid grid-cols-5 grid-rows-1 gap-2 overflow-x-auto overflow-y-hidden p-2"
|
||||||
@mousedown.prevent="platform.ui?.appHeader?.onHeaderAreaClick?.()"
|
@mousedown.prevent="platform.ui?.appHeader?.onHeaderAreaClick?.()"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="inline-flex flex-1 items-center justify-start space-x-2"
|
class="col-span-2 flex items-center justify-between space-x-2"
|
||||||
:style="{
|
:style="{
|
||||||
paddingTop: platform.ui?.appHeader?.paddingTop?.value,
|
paddingTop: platform.ui?.appHeader?.paddingTop?.value,
|
||||||
paddingLeft: platform.ui?.appHeader?.paddingLeft?.value,
|
paddingLeft: platform.ui?.appHeader?.paddingLeft?.value,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<HoppButtonSecondary
|
<div class="flex">
|
||||||
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
<HoppButtonSecondary
|
||||||
:label="t('app.name')"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
to="/"
|
:title="t('header.menu')"
|
||||||
/>
|
:icon="IconMenu"
|
||||||
|
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
|
/>
|
||||||
|
<HoppButtonSecondary
|
||||||
|
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
|
:label="t('app.name')"
|
||||||
|
to="/"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<HoppButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('header.go_back')"
|
||||||
|
:icon="IconArrowLeft"
|
||||||
|
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
|
@click="router.back()"
|
||||||
|
/>
|
||||||
|
<HoppButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('header.go_forward')"
|
||||||
|
:icon="IconArrowRight"
|
||||||
|
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
|
@click="router.forward()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-flex flex-1 items-center justify-center space-x-2">
|
<div class="col-span-1 flex items-center justify-between space-x-2">
|
||||||
<button
|
<button
|
||||||
class="flex max-w-[15rem] flex-1 cursor-text items-center justify-between self-stretch rounded border border-dividerDark bg-primaryDark px-2 py-1 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
|
class="flex h-full flex-1 cursor-text items-center justify-between rounded border border-dividerDark bg-primaryDark px-2 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
|
||||||
@click="invokeAction('modals.search.toggle')"
|
@click="invokeAction('modals.search.toggle')"
|
||||||
>
|
>
|
||||||
<span class="inline-flex flex-1 items-center">
|
<span class="inline-flex flex-1 items-center">
|
||||||
@@ -32,189 +56,221 @@
|
|||||||
<kbd class="shortcut-key">K</kbd>
|
<kbd class="shortcut-key">K</kbd>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<HoppButtonSecondary
|
|
||||||
v-if="showInstallButton"
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('header.install_pwa')"
|
|
||||||
:icon="IconDownload"
|
|
||||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
|
||||||
@click="installPWA()"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
|
||||||
:title="`${
|
|
||||||
mdAndLarger ? t('support.title') : t('app.options')
|
|
||||||
} <kbd>?</kbd>`"
|
|
||||||
:icon="IconLifeBuoy"
|
|
||||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
|
||||||
@click="invokeAction('modals.support.toggle')"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-flex flex-1 items-center justify-end space-x-2">
|
<div class="col-span-2 flex items-center justify-between space-x-2">
|
||||||
<div
|
<div class="flex">
|
||||||
v-if="currentUser === null"
|
|
||||||
class="inline-flex items-center space-x-2"
|
|
||||||
>
|
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
:icon="IconUploadCloud"
|
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
||||||
:label="t('header.save_workspace')"
|
:title="`${
|
||||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 hidden border border-green-600/25 bg-green-500/[.15] !text-green-500 hover:border-green-800/50 hover:bg-green-400/10 focus-visible:border-green-800/50 focus-visible:bg-green-400/10 md:flex"
|
mdAndLarger ? t('support.title') : t('app.options')
|
||||||
@click="invokeAction('modals.login.toggle')"
|
} <kbd>?</kbd>`"
|
||||||
|
:icon="IconLifeBuoy"
|
||||||
|
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
|
@click="invokeAction('modals.support.toggle')"
|
||||||
/>
|
/>
|
||||||
<HoppButtonPrimary
|
<span>
|
||||||
:label="t('header.login')"
|
|
||||||
@click="invokeAction('modals.login.toggle')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-else class="inline-flex items-center space-x-2">
|
|
||||||
<TeamsMemberStack
|
|
||||||
v-if="
|
|
||||||
workspace.type === 'team' &&
|
|
||||||
selectedTeam &&
|
|
||||||
selectedTeam.teamMembers.length > 1
|
|
||||||
"
|
|
||||||
:team-members="selectedTeam.teamMembers"
|
|
||||||
show-count
|
|
||||||
class="mx-2"
|
|
||||||
@handle-click="handleTeamEdit()"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="flex divide-x divide-green-600/25 rounded border border-green-600/25 bg-green-500/[.15] focus-within:divide-green-800/50 focus-within:border-green-800/50 focus-within:bg-green-400/10 hover:divide-green-800/50 hover:border-green-800/50 hover:bg-green-400/10"
|
|
||||||
>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('team.invite_tooltip')"
|
|
||||||
:icon="IconUserPlus"
|
|
||||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
|
|
||||||
@click="handleInvite()"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-if="
|
|
||||||
workspace.type === 'team' &&
|
|
||||||
selectedTeam &&
|
|
||||||
selectedTeam?.myRole === 'OWNER'
|
|
||||||
"
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('team.edit')"
|
|
||||||
:icon="IconSettings"
|
|
||||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
|
|
||||||
@click="handleTeamEdit()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<tippy
|
|
||||||
interactive
|
|
||||||
trigger="click"
|
|
||||||
theme="popover"
|
|
||||||
:on-shown="() => accountActions.focus()"
|
|
||||||
>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('workspace.change')"
|
|
||||||
:label="mdAndLarger ? workspaceName : ``"
|
|
||||||
:icon="workspace.type === 'personal' ? IconUser : IconUsers"
|
|
||||||
class="select-wrapper !focus-visible:text-blue-600 !hover:text-blue-600 rounded border border-blue-600/25 bg-blue-500/[.15] py-[0.4375rem] pr-8 !text-blue-500 hover:border-blue-800/50 hover:bg-blue-400/10 focus-visible:border-blue-800/50 focus-visible:bg-blue-400/10"
|
|
||||||
/>
|
|
||||||
<template #content="{ hide }">
|
|
||||||
<div
|
|
||||||
ref="accountActions"
|
|
||||||
class="flex flex-col focus:outline-none"
|
|
||||||
tabindex="0"
|
|
||||||
@keyup.escape="hide()"
|
|
||||||
@click="hide()"
|
|
||||||
>
|
|
||||||
<WorkspaceSelector />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</tippy>
|
|
||||||
<span class="px-2">
|
|
||||||
<tippy
|
<tippy
|
||||||
interactive
|
interactive
|
||||||
trigger="click"
|
trigger="click"
|
||||||
theme="popover"
|
theme="popover"
|
||||||
:on-shown="() => tippyActions.focus()"
|
:on-shown="() => downloadActions.focus()"
|
||||||
>
|
>
|
||||||
<HoppSmartPicture
|
<HoppButtonSecondary
|
||||||
v-if="currentUser.photoURL"
|
|
||||||
v-tippy="{
|
|
||||||
theme: 'tooltip',
|
|
||||||
}"
|
|
||||||
:url="currentUser.photoURL"
|
|
||||||
:alt="
|
|
||||||
currentUser.displayName ||
|
|
||||||
t('profile.default_hopp_displayname')
|
|
||||||
"
|
|
||||||
:title="
|
|
||||||
currentUser.displayName ||
|
|
||||||
currentUser.email ||
|
|
||||||
t('profile.default_hopp_displayname')
|
|
||||||
"
|
|
||||||
indicator
|
|
||||||
:indicator-styles="
|
|
||||||
network.isOnline ? 'bg-green-500' : 'bg-red-500'
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<HoppSmartPicture
|
|
||||||
v-else
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="
|
:title="t('header.download_app')"
|
||||||
currentUser.displayName ||
|
:icon="IconDownload"
|
||||||
currentUser.email ||
|
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
t('profile.default_hopp_displayname')
|
|
||||||
"
|
|
||||||
:initial="currentUser.displayName || currentUser.email"
|
|
||||||
indicator
|
|
||||||
:indicator-styles="
|
|
||||||
network.isOnline ? 'bg-green-500' : 'bg-red-500'
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
<template #content="{ hide }">
|
<template #content="{ hide }">
|
||||||
<div
|
<div
|
||||||
ref="tippyActions"
|
ref="downloadActions"
|
||||||
class="flex flex-col focus:outline-none"
|
class="flex flex-col focus:outline-none"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@keyup.p="profile.$el.click()"
|
|
||||||
@keyup.s="settings.$el.click()"
|
|
||||||
@keyup.l="logout.$el.click()"
|
|
||||||
@keyup.escape="hide()"
|
@keyup.escape="hide()"
|
||||||
|
@click="hide()"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col px-2 text-tiny">
|
|
||||||
<span class="inline-flex truncate font-semibold">
|
|
||||||
{{
|
|
||||||
currentUser.displayName ||
|
|
||||||
t("profile.default_hopp_displayname")
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
<span class="inline-flex truncate text-secondaryLight">
|
|
||||||
{{ currentUser.email }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
<HoppSmartItem
|
<HoppSmartItem
|
||||||
ref="profile"
|
:label="t('header.download_app')"
|
||||||
to="/profile"
|
:icon="IconDownload"
|
||||||
:icon="IconUser"
|
|
||||||
:label="t('navigation.profile')"
|
|
||||||
:shortcut="['P']"
|
|
||||||
@click="hide()"
|
|
||||||
/>
|
/>
|
||||||
<HoppSmartItem
|
<HoppSmartItem
|
||||||
ref="settings"
|
v-if="showInstallButton"
|
||||||
to="/settings"
|
:label="t('header.install_pwa')"
|
||||||
:icon="IconSettings"
|
:icon="IconPlusSquare"
|
||||||
:label="t('navigation.settings')"
|
@click="installPWA()"
|
||||||
:shortcut="['S']"
|
|
||||||
@click="hide()"
|
|
||||||
/>
|
|
||||||
<FirebaseLogout
|
|
||||||
ref="logout"
|
|
||||||
:shortcut="['L']"
|
|
||||||
@confirm-logout="hide()"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</tippy>
|
</tippy>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<div
|
||||||
|
v-if="currentUser === null"
|
||||||
|
class="inline-flex items-center space-x-2"
|
||||||
|
>
|
||||||
|
<HoppButtonSecondary
|
||||||
|
:icon="IconUploadCloud"
|
||||||
|
:label="t('header.save_workspace')"
|
||||||
|
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 hidden h-8 border border-emerald-600/25 bg-emerald-500/10 !text-emerald-500 hover:border-emerald-600/20 hover:bg-emerald-600/20 focus-visible:border-emerald-600/20 focus-visible:bg-emerald-600/20 md:flex"
|
||||||
|
@click="invokeAction('modals.login.toggle')"
|
||||||
|
/>
|
||||||
|
<HoppButtonPrimary
|
||||||
|
:label="t('header.login')"
|
||||||
|
class="h-8"
|
||||||
|
@click="invokeAction('modals.login.toggle')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else class="inline-flex items-center space-x-2">
|
||||||
|
<TeamsMemberStack
|
||||||
|
v-if="
|
||||||
|
workspace.type === 'team' &&
|
||||||
|
selectedTeam &&
|
||||||
|
selectedTeam.teamMembers.length > 1
|
||||||
|
"
|
||||||
|
:team-members="selectedTeam.teamMembers"
|
||||||
|
show-count
|
||||||
|
class="mx-2"
|
||||||
|
@handle-click="handleTeamEdit()"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="flex h-8 divide-x divide-emerald-600/25 rounded border border-emerald-600/25 bg-emerald-500/10 focus-within:divide-emerald-600/20 focus-within:border-emerald-600/20 focus-within:bg-emerald-600/20 hover:divide-emerald-600/20 hover:border-emerald-600/20 hover:bg-emerald-600/20"
|
||||||
|
>
|
||||||
|
<HoppButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('team.invite_tooltip')"
|
||||||
|
:icon="IconUserPlus"
|
||||||
|
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 !text-emerald-500"
|
||||||
|
@click="handleInvite()"
|
||||||
|
/>
|
||||||
|
<HoppButtonSecondary
|
||||||
|
v-if="
|
||||||
|
workspace.type === 'team' &&
|
||||||
|
selectedTeam &&
|
||||||
|
selectedTeam?.myRole === 'OWNER'
|
||||||
|
"
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('team.edit')"
|
||||||
|
:icon="IconSettings"
|
||||||
|
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 !text-emerald-500"
|
||||||
|
@click="handleTeamEdit()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<tippy
|
||||||
|
interactive
|
||||||
|
trigger="click"
|
||||||
|
theme="popover"
|
||||||
|
:on-shown="() => accountActions.focus()"
|
||||||
|
>
|
||||||
|
<HoppButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('workspace.change')"
|
||||||
|
:label="mdAndLarger ? workspaceName : ``"
|
||||||
|
:icon="workspace.type === 'personal' ? IconUser : IconUsers"
|
||||||
|
class="select-wrapper !focus-visible:text-blue-600 !hover:text-blue-600 h-8 rounded border border-blue-600/25 bg-blue-500/10 pr-8 !text-blue-500 hover:border-blue-600/20 hover:bg-blue-600/20 focus-visible:border-blue-600/20 focus-visible:bg-blue-600/20"
|
||||||
|
/>
|
||||||
|
<template #content="{ hide }">
|
||||||
|
<div
|
||||||
|
ref="accountActions"
|
||||||
|
class="flex flex-col focus:outline-none"
|
||||||
|
tabindex="0"
|
||||||
|
@keyup.escape="hide()"
|
||||||
|
@click="hide()"
|
||||||
|
>
|
||||||
|
<WorkspaceSelector />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</tippy>
|
||||||
|
<span class="px-2">
|
||||||
|
<tippy
|
||||||
|
interactive
|
||||||
|
trigger="click"
|
||||||
|
theme="popover"
|
||||||
|
:on-shown="() => tippyActions.focus()"
|
||||||
|
>
|
||||||
|
<HoppSmartPicture
|
||||||
|
v-if="currentUser.photoURL"
|
||||||
|
v-tippy="{
|
||||||
|
theme: 'tooltip',
|
||||||
|
}"
|
||||||
|
:url="currentUser.photoURL"
|
||||||
|
:alt="
|
||||||
|
currentUser.displayName ||
|
||||||
|
t('profile.default_hopp_displayname')
|
||||||
|
"
|
||||||
|
:title="
|
||||||
|
currentUser.displayName ||
|
||||||
|
currentUser.email ||
|
||||||
|
t('profile.default_hopp_displayname')
|
||||||
|
"
|
||||||
|
indicator
|
||||||
|
:indicator-styles="
|
||||||
|
network.isOnline ? 'bg-emerald-500' : 'bg-red-500'
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<HoppSmartPicture
|
||||||
|
v-else
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="
|
||||||
|
currentUser.displayName ||
|
||||||
|
currentUser.email ||
|
||||||
|
t('profile.default_hopp_displayname')
|
||||||
|
"
|
||||||
|
:initial="currentUser.displayName || currentUser.email"
|
||||||
|
indicator
|
||||||
|
:indicator-styles="
|
||||||
|
network.isOnline ? 'bg-emerald-500' : 'bg-red-500'
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<template #content="{ hide }">
|
||||||
|
<div
|
||||||
|
ref="tippyActions"
|
||||||
|
class="flex flex-col focus:outline-none"
|
||||||
|
tabindex="0"
|
||||||
|
@keyup.p="profile.$el.click()"
|
||||||
|
@keyup.s="settings.$el.click()"
|
||||||
|
@keyup.l="logout.$el.click()"
|
||||||
|
@keyup.escape="hide()"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col px-2 text-tiny">
|
||||||
|
<span class="inline-flex truncate font-semibold">
|
||||||
|
{{
|
||||||
|
currentUser.displayName ||
|
||||||
|
t("profile.default_hopp_displayname")
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
<span class="inline-flex truncate text-secondaryLight">
|
||||||
|
{{ currentUser.email }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<HoppSmartItem
|
||||||
|
ref="profile"
|
||||||
|
to="/profile"
|
||||||
|
:icon="IconUser"
|
||||||
|
:label="t('navigation.profile')"
|
||||||
|
:shortcut="['P']"
|
||||||
|
@click="hide()"
|
||||||
|
/>
|
||||||
|
<HoppSmartItem
|
||||||
|
ref="settings"
|
||||||
|
to="/settings"
|
||||||
|
:icon="IconSettings"
|
||||||
|
:label="t('navigation.settings')"
|
||||||
|
:shortcut="['S']"
|
||||||
|
@click="hide()"
|
||||||
|
/>
|
||||||
|
<FirebaseLogout
|
||||||
|
ref="logout"
|
||||||
|
:shortcut="['L']"
|
||||||
|
@confirm-logout="hide()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</tippy>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<AppBanner v-if="bannerContent" :banner="bannerContent" />
|
<AppBanner v-if="bannerContent" :banner="bannerContent" />
|
||||||
@@ -233,7 +289,6 @@
|
|||||||
@invite-team="inviteTeam(editingTeamName, editingTeamID)"
|
@invite-team="inviteTeam(editingTeamName, editingTeamID)"
|
||||||
@refetch-teams="refetchTeams"
|
@refetch-teams="refetchTeams"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HoppSmartConfirmModal
|
<HoppSmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="t('confirm.remove_team')"
|
:title="t('confirm.remove_team')"
|
||||||
@@ -263,6 +318,10 @@ import IconUploadCloud from "~icons/lucide/upload-cloud"
|
|||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
import IconUserPlus from "~icons/lucide/user-plus"
|
import IconUserPlus from "~icons/lucide/user-plus"
|
||||||
import IconUsers from "~icons/lucide/users"
|
import IconUsers from "~icons/lucide/users"
|
||||||
|
import IconPlusSquare from "~icons/lucide/plus-square"
|
||||||
|
import IconArrowLeft from "~icons/lucide/arrow-left"
|
||||||
|
import IconArrowRight from "~icons/lucide/arrow-right"
|
||||||
|
import IconMenu from "~icons/lucide/align-left"
|
||||||
import { pipe } from "fp-ts/function"
|
import { pipe } from "fp-ts/function"
|
||||||
import * as TE from "fp-ts/TaskEither"
|
import * as TE from "fp-ts/TaskEither"
|
||||||
import { deleteTeam as backendDeleteTeam } from "~/helpers/backend/mutations/Team"
|
import { deleteTeam as backendDeleteTeam } from "~/helpers/backend/mutations/Team"
|
||||||
@@ -271,9 +330,11 @@ import {
|
|||||||
BannerContent,
|
BannerContent,
|
||||||
BANNER_PRIORITY_HIGH,
|
BANNER_PRIORITY_HIGH,
|
||||||
} from "~/services/banner.service"
|
} from "~/services/banner.service"
|
||||||
|
import { useRouter } from "vue-router"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Once the PWA code is initialized, this holds a method
|
* Once the PWA code is initialized, this holds a method
|
||||||
@@ -445,6 +506,7 @@ const profile = ref<any | null>(null)
|
|||||||
const settings = ref<any | null>(null)
|
const settings = ref<any | null>(null)
|
||||||
const logout = ref<any | null>(null)
|
const logout = ref<any | null>(null)
|
||||||
const accountActions = ref<any | null>(null)
|
const accountActions = ref<any | null>(null)
|
||||||
|
const downloadActions = ref<any | null>(null)
|
||||||
|
|
||||||
defineActionHandler("modals.team.edit", handleTeamEdit)
|
defineActionHandler("modals.team.edit", handleTeamEdit)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user