feat(workspaces): work(space) invader default logos (#2708)
* feat(workspaces): add default logo index * Added WorkspaceAvatar component * Added WorkspaceAvatar component * Fix issues * Fix Avatar --------- Co-authored-by: Mike Tasset <mike.tasset@gmail.com>
This commit is contained in:
@@ -68,7 +68,11 @@
|
||||
:active="isActive(item.to)"
|
||||
>
|
||||
<template #icon>
|
||||
<UserAvatar :logo="item.logo" size="sm" />
|
||||
<WorkspaceAvatar
|
||||
:logo="item.logo"
|
||||
:default-logo-index="item.defaultLogoIndex"
|
||||
size="sm"
|
||||
/>
|
||||
</template>
|
||||
</LayoutSidebarMenuGroupItem>
|
||||
</NuxtLink>
|
||||
@@ -172,7 +176,8 @@ const workspacesItems = computed(() =>
|
||||
label: workspace.name,
|
||||
id: workspace.id,
|
||||
to: workspaceRoute(workspace.id),
|
||||
logo: workspace.logo
|
||||
logo: workspace.logo,
|
||||
defaultLogoIndex: workspace.defaultLogoIndex
|
||||
}))
|
||||
: []
|
||||
)
|
||||
|
||||
@@ -52,7 +52,11 @@
|
||||
collapsible
|
||||
>
|
||||
<template #title-icon>
|
||||
<UserAvatar :logo="workspaceItem.logo" size="sm" />
|
||||
<WorkspaceAvatar
|
||||
:logo="workspaceItem.logo"
|
||||
:default-logo-index="workspaceItem.defaultLogoIndex"
|
||||
size="sm"
|
||||
/>
|
||||
</template>
|
||||
<LayoutSidebarMenuGroupItem
|
||||
v-for="(workspaceMenuItem, itemKey) in workspaceMenuItems"
|
||||
@@ -118,9 +122,9 @@ graphql(`
|
||||
workspaces {
|
||||
items {
|
||||
...SettingsWorkspacesGeneralEditAvatar_Workspace
|
||||
...WorkspaceAvatar_Workspace
|
||||
id
|
||||
name
|
||||
logo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
'text-foreground-on-primary flex shrink-0 items-center justify-center overflow-hidden rounded-full uppercase transition',
|
||||
sizeClasses
|
||||
]"
|
||||
>
|
||||
<div
|
||||
class="h-full w-full bg-cover bg-center bg-no-repeat"
|
||||
:style="{ backgroundImage: `url('${avatar}')` }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { graphql } from '~~/lib/common/generated/gql'
|
||||
import type { MaybeNullOrUndefined } from '@speckle/shared'
|
||||
import type { UserAvatarSize } from '@speckle/ui-components'
|
||||
import { useAvatarSizeClasses } from '@speckle/ui-components'
|
||||
import { useWorkspacesAvatar } from '~/lib/workspaces/composables/avatar'
|
||||
|
||||
graphql(`
|
||||
fragment WorkspaceAvatar_Workspace on Workspace {
|
||||
id
|
||||
logo
|
||||
defaultLogoIndex
|
||||
}
|
||||
`)
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
size?: UserAvatarSize
|
||||
logo?: MaybeNullOrUndefined<string>
|
||||
defaultLogoIndex: number
|
||||
}>(),
|
||||
{
|
||||
size: 'base'
|
||||
}
|
||||
)
|
||||
|
||||
const { sizeClasses } = useAvatarSizeClasses({ props: toRefs(props) })
|
||||
const { defaultAvatar } = useWorkspacesAvatar(props.defaultLogoIndex)
|
||||
|
||||
const avatar = computed(() => (props.logo ? props.logo : defaultAvatar.value))
|
||||
</script>
|
||||
@@ -1,9 +1,11 @@
|
||||
<template>
|
||||
<div class="flex flex-col sm:flex-row justify-between sm:items-center">
|
||||
<div class="flex gap-2 mb-3 mt-2">
|
||||
<div class="flex items-center">
|
||||
<UserAvatar :logo="workspaceInfo.logo" size="lg" />
|
||||
</div>
|
||||
<WorkspaceAvatar
|
||||
:logo="workspaceInfo.logo"
|
||||
:default-logo-index="workspaceInfo.defaultLogoIndex"
|
||||
size="sm"
|
||||
/>
|
||||
<div class="flex flex-col">
|
||||
<h1 class="text-heading-lg">{{ workspaceInfo.name }}</h1>
|
||||
<div class="text-body-xs text-foreground-2">
|
||||
@@ -46,6 +48,7 @@ import type { WorkspaceHeader_WorkspaceFragment } from '~~/lib/common/generated/
|
||||
|
||||
graphql(`
|
||||
fragment WorkspaceHeader_Workspace on Workspace {
|
||||
...WorkspaceAvatar_Workspace
|
||||
id
|
||||
role
|
||||
name
|
||||
|
||||
@@ -89,7 +89,7 @@ const documents = {
|
||||
"\n fragment ProjectsDashboardHeaderWorkspaces_User on User {\n ...WorkspaceInviteBanners_User\n }\n": types.ProjectsDashboardHeaderWorkspaces_UserFragmentDoc,
|
||||
"\n fragment ProjectsInviteBanner on PendingStreamCollaborator {\n id\n invitedBy {\n ...LimitedUserAvatar\n }\n projectId\n projectName\n token\n user {\n id\n }\n }\n": types.ProjectsInviteBannerFragmentDoc,
|
||||
"\n fragment ProjectsInviteBanners on User {\n projectInvites {\n ...ProjectsInviteBanner\n }\n }\n": types.ProjectsInviteBannersFragmentDoc,
|
||||
"\n fragment SettingsDialog_User on User {\n workspaces {\n items {\n ...SettingsWorkspacesGeneralEditAvatar_Workspace\n id\n name\n logo\n }\n }\n }\n": types.SettingsDialog_UserFragmentDoc,
|
||||
"\n fragment SettingsDialog_User on User {\n workspaces {\n items {\n ...SettingsWorkspacesGeneralEditAvatar_Workspace\n ...WorkspaceAvatar_Workspace\n id\n name\n }\n }\n }\n": types.SettingsDialog_UserFragmentDoc,
|
||||
"\n fragment SettingsServerProjects_ProjectCollection on ProjectCollection {\n totalCount\n items {\n ...SettingsSharedProjects_Project\n }\n }\n": types.SettingsServerProjects_ProjectCollectionFragmentDoc,
|
||||
"\n fragment SettingsSharedProjects_Project on Project {\n id\n name\n visibility\n createdAt\n updatedAt\n models {\n totalCount\n }\n versions {\n totalCount\n }\n team {\n id\n user {\n name\n id\n avatar\n }\n }\n }\n": types.SettingsSharedProjects_ProjectFragmentDoc,
|
||||
"\n fragment SettingsUserEmails_User on User {\n id\n emails {\n ...SettingsUserEmailCards_UserEmail\n }\n }\n": types.SettingsUserEmails_UserFragmentDoc,
|
||||
@@ -116,9 +116,10 @@ const documents = {
|
||||
"\n fragment ThreadCommentAttachment on Comment {\n text {\n attachments {\n id\n fileName\n fileType\n fileSize\n }\n }\n }\n": types.ThreadCommentAttachmentFragmentDoc,
|
||||
"\n fragment ViewerCommentsListItem on Comment {\n id\n rawText\n archived\n author {\n ...LimitedUserAvatar\n }\n createdAt\n viewedAt\n replies {\n totalCount\n cursor\n items {\n ...ViewerCommentsReplyItem\n }\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n resources {\n resourceId\n resourceType\n }\n }\n": types.ViewerCommentsListItemFragmentDoc,
|
||||
"\n fragment ViewerModelVersionCardItem on Version {\n id\n message\n referencedObject\n sourceApplication\n createdAt\n previewUrl\n authorUser {\n ...LimitedUserAvatar\n }\n }\n": types.ViewerModelVersionCardItemFragmentDoc,
|
||||
"\n fragment WorkspaceAvatar_Workspace on Workspace {\n id\n logo\n defaultLogoIndex\n }\n": types.WorkspaceAvatar_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceInviteDialog_Workspace on Workspace {\n id\n team {\n id\n user {\n id\n }\n }\n invitedTeam(filter: $invitesFilter) {\n title\n user {\n id\n }\n }\n }\n": types.WorkspaceInviteDialog_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceProjectList_ProjectCollection on ProjectCollection {\n totalCount\n items {\n ...ProjectDashboardItem\n }\n cursor\n }\n": types.WorkspaceProjectList_ProjectCollectionFragmentDoc,
|
||||
"\n fragment WorkspaceHeader_Workspace on Workspace {\n id\n role\n name\n logo\n description\n totalProjects: projects {\n totalCount\n }\n team {\n id\n user {\n id\n name\n ...LimitedUserAvatar\n }\n }\n ...WorkspaceInviteDialog_Workspace\n }\n": types.WorkspaceHeader_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceHeader_Workspace on Workspace {\n ...WorkspaceAvatar_Workspace\n id\n role\n name\n logo\n description\n totalProjects: projects {\n totalCount\n }\n team {\n id\n user {\n id\n name\n ...LimitedUserAvatar\n }\n }\n ...WorkspaceInviteDialog_Workspace\n }\n": types.WorkspaceHeader_WorkspaceFragmentDoc,
|
||||
"\n fragment WorkspaceInviteBanner_PendingWorkspaceCollaborator on PendingWorkspaceCollaborator {\n id\n invitedBy {\n id\n ...LimitedUserAvatar\n }\n workspaceId\n workspaceName\n token\n user {\n id\n }\n ...UseWorkspaceInviteManager_PendingWorkspaceCollaborator\n }\n": types.WorkspaceInviteBanner_PendingWorkspaceCollaboratorFragmentDoc,
|
||||
"\n fragment WorkspaceInviteBanners_User on User {\n workspaceInvites {\n ...WorkspaceInviteBanner_PendingWorkspaceCollaborator\n }\n }\n": types.WorkspaceInviteBanners_UserFragmentDoc,
|
||||
"\n fragment WorkspaceInviteBlock_PendingWorkspaceCollaborator on PendingWorkspaceCollaborator {\n id\n workspaceId\n workspaceName\n token\n user {\n id\n name\n ...LimitedUserAvatar\n }\n title\n email\n ...UseWorkspaceInviteManager_PendingWorkspaceCollaborator\n }\n": types.WorkspaceInviteBlock_PendingWorkspaceCollaboratorFragmentDoc,
|
||||
@@ -621,7 +622,7 @@ export function graphql(source: "\n fragment ProjectsInviteBanners on User {\n
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment SettingsDialog_User on User {\n workspaces {\n items {\n ...SettingsWorkspacesGeneralEditAvatar_Workspace\n id\n name\n logo\n }\n }\n }\n"): (typeof documents)["\n fragment SettingsDialog_User on User {\n workspaces {\n items {\n ...SettingsWorkspacesGeneralEditAvatar_Workspace\n id\n name\n logo\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment SettingsDialog_User on User {\n workspaces {\n items {\n ...SettingsWorkspacesGeneralEditAvatar_Workspace\n ...WorkspaceAvatar_Workspace\n id\n name\n }\n }\n }\n"): (typeof documents)["\n fragment SettingsDialog_User on User {\n workspaces {\n items {\n ...SettingsWorkspacesGeneralEditAvatar_Workspace\n ...WorkspaceAvatar_Workspace\n id\n name\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -726,6 +727,10 @@ export function graphql(source: "\n fragment ViewerCommentsListItem on Comment
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment ViewerModelVersionCardItem on Version {\n id\n message\n referencedObject\n sourceApplication\n createdAt\n previewUrl\n authorUser {\n ...LimitedUserAvatar\n }\n }\n"): (typeof documents)["\n fragment ViewerModelVersionCardItem on Version {\n id\n message\n referencedObject\n sourceApplication\n createdAt\n previewUrl\n authorUser {\n ...LimitedUserAvatar\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment WorkspaceAvatar_Workspace on Workspace {\n id\n logo\n defaultLogoIndex\n }\n"): (typeof documents)["\n fragment WorkspaceAvatar_Workspace on Workspace {\n id\n logo\n defaultLogoIndex\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -737,7 +742,7 @@ export function graphql(source: "\n fragment WorkspaceProjectList_ProjectCollec
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment WorkspaceHeader_Workspace on Workspace {\n id\n role\n name\n logo\n description\n totalProjects: projects {\n totalCount\n }\n team {\n id\n user {\n id\n name\n ...LimitedUserAvatar\n }\n }\n ...WorkspaceInviteDialog_Workspace\n }\n"): (typeof documents)["\n fragment WorkspaceHeader_Workspace on Workspace {\n id\n role\n name\n logo\n description\n totalProjects: projects {\n totalCount\n }\n team {\n id\n user {\n id\n name\n ...LimitedUserAvatar\n }\n }\n ...WorkspaceInviteDialog_Workspace\n }\n"];
|
||||
export function graphql(source: "\n fragment WorkspaceHeader_Workspace on Workspace {\n ...WorkspaceAvatar_Workspace\n id\n role\n name\n logo\n description\n totalProjects: projects {\n totalCount\n }\n team {\n id\n user {\n id\n name\n ...LimitedUserAvatar\n }\n }\n ...WorkspaceInviteDialog_Workspace\n }\n"): (typeof documents)["\n fragment WorkspaceHeader_Workspace on Workspace {\n ...WorkspaceAvatar_Workspace\n id\n role\n name\n logo\n description\n totalProjects: projects {\n totalCount\n }\n team {\n id\n user {\n id\n name\n ...LimitedUserAvatar\n }\n }\n ...WorkspaceInviteDialog_Workspace\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,13 @@
|
||||
export const useWorkspacesAvatar = (avatarIndex: number) => {
|
||||
const count = ref(4)
|
||||
|
||||
const defaultAvatar = computed(() => {
|
||||
const index = avatarIndex >= 0 && avatarIndex <= count.value ? avatarIndex : 0
|
||||
return `/images/workspace/avatars/avatar_${index}.svg`
|
||||
})
|
||||
|
||||
return {
|
||||
count,
|
||||
defaultAvatar
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 8H8V12H12V8Z" fill="#FBBF24"/>
|
||||
<path d="M12 12H8V18H12V12Z" fill="#FBBF24"/>
|
||||
<path d="M12 28H8V32H12V28Z" fill="#FBBF24"/>
|
||||
<path d="M18 22H12V28H18V22Z" fill="#FBBF24"/>
|
||||
<path d="M18 28H12V32H18V28Z" fill="#FBBF24"/>
|
||||
<path d="M22 12H18V18H22V12Z" fill="#FBBF24"/>
|
||||
<path d="M22 18H18V22H22V18Z" fill="#FBBF24"/>
|
||||
<path d="M22 22H18V28H22V22Z" fill="#FBBF24"/>
|
||||
<path d="M22 28H18V32H22V28Z" fill="#FBBF24"/>
|
||||
<path d="M32 8H28V12H32V8Z" fill="#FBBF24"/>
|
||||
<path d="M32 12H28V18H32V12Z" fill="#FBBF24"/>
|
||||
<path d="M32 28H28V32H32V28Z" fill="#FBBF24"/>
|
||||
<path d="M28 22H22V28H28V22Z" fill="#FBBF24"/>
|
||||
<path d="M28 28H22V32H28V28Z" fill="#FBBF24"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 754 B |
@@ -0,0 +1,13 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 8H8V14H12V8Z" fill="#1CBA80"/>
|
||||
<path d="M12 22H8V28H12V22Z" fill="#1CBA80"/>
|
||||
<path d="M12 28H8V32H12V28Z" fill="#1CBA80"/>
|
||||
<path d="M18 18H12V22H18V18Z" fill="#1CBA80"/>
|
||||
<path d="M22 8H18V14H22V8Z" fill="#1CBA80"/>
|
||||
<path d="M22 18H18V22H22V18Z" fill="#1CBA80"/>
|
||||
<path d="M24 26H16V32H24V26Z" fill="#1CBA80"/>
|
||||
<path d="M32 8H28V14H32V8Z" fill="#1CBA80"/>
|
||||
<path d="M32 22H28V28H32V22Z" fill="#1CBA80"/>
|
||||
<path d="M32 28H28V32H32V28Z" fill="#1CBA80"/>
|
||||
<path d="M28 18H22V22H28V18Z" fill="#1CBA80"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 611 B |
@@ -0,0 +1,8 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 8H8V14H12V8Z" fill="#4B40C9"/>
|
||||
<path d="M22 8H18V24H22V8Z" fill="#4B40C9"/>
|
||||
<path d="M26 24H14V28H26V24Z" fill="#4B40C9"/>
|
||||
<path d="M32 14H8V18H32V14Z" fill="#4B40C9"/>
|
||||
<path d="M32 28H8V32H32V28Z" fill="#4B40C9"/>
|
||||
<path d="M32 8H28V14H32V8Z" fill="#4B40C9"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 376 B |
@@ -0,0 +1,8 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 16H8V22H12V16Z" fill="#C45959"/>
|
||||
<path d="M26 28H14V34H26V28Z" fill="#C45959"/>
|
||||
<path d="M18 6H22V10H18V6Z" fill="#C45959"/>
|
||||
<path d="M18 18H22V22H18V18Z" fill="#C45959"/>
|
||||
<path d="M32 22H8V28H32V22Z" fill="#C45959"/>
|
||||
<path d="M32 16H28V22H32V16Z" fill="#C45959"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 381 B |
@@ -16,6 +16,7 @@ extend type Query {
|
||||
input WorkspaceCreateInput {
|
||||
name: String!
|
||||
description: String
|
||||
defaultLogoIndex: Int
|
||||
}
|
||||
|
||||
input WorkspaceUpdateInput {
|
||||
@@ -26,6 +27,7 @@ input WorkspaceUpdateInput {
|
||||
Logo image as base64-encoded string
|
||||
"""
|
||||
logo: String
|
||||
defaultLogoIndex: Int
|
||||
}
|
||||
|
||||
input WorkspaceRoleUpdateInput {
|
||||
@@ -162,6 +164,10 @@ type Workspace {
|
||||
"""
|
||||
logo: String
|
||||
"""
|
||||
Selected fallback when `logo` not set
|
||||
"""
|
||||
defaultLogoIndex: Int!
|
||||
"""
|
||||
Active user's role for this workspace. `null` if request is not authenticated, or the workspace is not explicitly shared with you.
|
||||
"""
|
||||
role: String
|
||||
|
||||
@@ -3820,6 +3820,8 @@ export type WebhookUpdateInput = {
|
||||
export type Workspace = {
|
||||
__typename?: 'Workspace';
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
/** Selected fallback when `logo` not set */
|
||||
defaultLogoIndex: Scalars['Int']['output'];
|
||||
description?: Maybe<Scalars['String']['output']>;
|
||||
id: Scalars['ID']['output'];
|
||||
/** Only available to workspace owners */
|
||||
@@ -3866,6 +3868,7 @@ export type WorkspaceCollection = {
|
||||
};
|
||||
|
||||
export type WorkspaceCreateInput = {
|
||||
defaultLogoIndex?: InputMaybe<Scalars['Int']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
name: Scalars['String']['input'];
|
||||
};
|
||||
@@ -4012,6 +4015,7 @@ export type WorkspaceTeamFilter = {
|
||||
};
|
||||
|
||||
export type WorkspaceUpdateInput = {
|
||||
defaultLogoIndex?: InputMaybe<Scalars['Int']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
id: Scalars['String']['input'];
|
||||
/** Logo image as base64-encoded string */
|
||||
@@ -5878,6 +5882,7 @@ export type WebhookEventCollectionResolvers<ContextType = GraphQLContext, Parent
|
||||
|
||||
export type WorkspaceResolvers<ContextType = GraphQLContext, ParentType extends ResolversParentTypes['Workspace'] = ResolversParentTypes['Workspace']> = {
|
||||
createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
|
||||
defaultLogoIndex?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
||||
description?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
|
||||
invitedTeam?: Resolver<Maybe<Array<ResolversTypes['PendingWorkspaceCollaborator']>>, ParentType, ContextType, Partial<WorkspaceInvitedTeamArgs>>;
|
||||
|
||||
@@ -3809,6 +3809,8 @@ export type WebhookUpdateInput = {
|
||||
export type Workspace = {
|
||||
__typename?: 'Workspace';
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
/** Selected fallback when `logo` not set */
|
||||
defaultLogoIndex: Scalars['Int']['output'];
|
||||
description?: Maybe<Scalars['String']['output']>;
|
||||
id: Scalars['ID']['output'];
|
||||
/** Only available to workspace owners */
|
||||
@@ -3855,6 +3857,7 @@ export type WorkspaceCollection = {
|
||||
};
|
||||
|
||||
export type WorkspaceCreateInput = {
|
||||
defaultLogoIndex?: InputMaybe<Scalars['Int']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
name: Scalars['String']['input'];
|
||||
};
|
||||
@@ -4001,6 +4004,7 @@ export type WorkspaceTeamFilter = {
|
||||
};
|
||||
|
||||
export type WorkspaceUpdateInput = {
|
||||
defaultLogoIndex?: InputMaybe<Scalars['Int']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
id: Scalars['String']['input'];
|
||||
/** Logo image as base64-encoded string */
|
||||
|
||||
@@ -10,6 +10,7 @@ const createFakeWorkspace = (): Workspace => {
|
||||
id: cryptoRandomString({ length: 10 }),
|
||||
description: cryptoRandomString({ length: 10 }),
|
||||
logo: null,
|
||||
defaultLogoIndex: 0,
|
||||
name: cryptoRandomString({ length: 10 }),
|
||||
updatedAt: new Date(),
|
||||
createdAt: new Date()
|
||||
|
||||
@@ -220,7 +220,7 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
},
|
||||
WorkspaceMutations: {
|
||||
create: async (_parent, args, context) => {
|
||||
const { name, description } = args.input
|
||||
const { name, description, defaultLogoIndex } = args.input
|
||||
|
||||
const createWorkspace = createWorkspaceFactory({
|
||||
upsertWorkspace: upsertWorkspaceFactory({ db }),
|
||||
@@ -233,7 +233,8 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
workspaceInput: {
|
||||
name,
|
||||
description: description || null,
|
||||
logo: null
|
||||
logo: null,
|
||||
defaultLogoIndex: defaultLogoIndex || 0
|
||||
},
|
||||
userResourceAccessLimits: context.resourceAccessRules
|
||||
})
|
||||
|
||||
@@ -6,7 +6,8 @@ export const Workspaces = buildTableHelper('workspaces', [
|
||||
'description',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'logo'
|
||||
'logo',
|
||||
'defaultLogoIndex'
|
||||
])
|
||||
|
||||
export const WorkspaceAcl = buildTableHelper('workspace_acl', [
|
||||
|
||||
@@ -92,7 +92,7 @@ export const upsertWorkspaceFactory =
|
||||
.workspaces(db)
|
||||
.insert(workspace)
|
||||
.onConflict('id')
|
||||
.merge(['description', 'logo', 'name', 'updatedAt'])
|
||||
.merge(['description', 'logo', 'defaultLogoIndex', 'name', 'updatedAt'])
|
||||
}
|
||||
|
||||
export const deleteWorkspaceFactory =
|
||||
|
||||
@@ -51,6 +51,7 @@ type WorkspaceCreateArgs = {
|
||||
name: string
|
||||
description: string | null
|
||||
logo: string | null
|
||||
defaultLogoIndex: number
|
||||
}
|
||||
userResourceAccessLimits: MaybeNullOrUndefined<TokenResourceIdentifier[]>
|
||||
}
|
||||
@@ -108,6 +109,7 @@ type WorkspaceUpdateArgs = {
|
||||
name?: string | null
|
||||
description?: string | null
|
||||
logo?: string | null
|
||||
defaultLogoIndex?: number | null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ export const createTestWorkspace = async (
|
||||
workspaceInput: {
|
||||
name: workspace.name,
|
||||
description: workspace.description || null,
|
||||
logo: workspace.logo || null
|
||||
logo: workspace.logo || null,
|
||||
defaultLogoIndex: 0
|
||||
},
|
||||
userResourceAccessLimits: null
|
||||
})
|
||||
|
||||
@@ -51,7 +51,8 @@ const createAndStoreTestWorkspace = async (): Promise<Workspace> => {
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
description: null,
|
||||
logo: null
|
||||
logo: null,
|
||||
defaultLogoIndex: 0
|
||||
}
|
||||
|
||||
await upsertWorkspace({ workspace })
|
||||
|
||||
@@ -61,7 +61,8 @@ const getCreateWorkspaceInput = () => {
|
||||
workspaceInput: {
|
||||
description: 'foobar',
|
||||
logo: null,
|
||||
name: cryptoRandomString({ length: 6 })
|
||||
name: cryptoRandomString({ length: 6 }),
|
||||
defaultLogoIndex: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export type Workspace = {
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
logo: string | null
|
||||
defaultLogoIndex: number
|
||||
}
|
||||
|
||||
export type WorkspaceWithOptionalRole = Workspace & { role?: WorkspaceRoles }
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { Knex } from 'knex'
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
await knex.schema.alterTable('workspaces', (table) => {
|
||||
table.integer('defaultLogoIndex').defaultTo(0).notNullable()
|
||||
})
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.alterTable('workspaces', (table) => {
|
||||
table.dropColumn('defaultLogoIndex')
|
||||
})
|
||||
}
|
||||
@@ -3810,6 +3810,8 @@ export type WebhookUpdateInput = {
|
||||
export type Workspace = {
|
||||
__typename?: 'Workspace';
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
/** Selected fallback when `logo` not set */
|
||||
defaultLogoIndex: Scalars['Int']['output'];
|
||||
description?: Maybe<Scalars['String']['output']>;
|
||||
id: Scalars['ID']['output'];
|
||||
/** Only available to workspace owners */
|
||||
@@ -3856,6 +3858,7 @@ export type WorkspaceCollection = {
|
||||
};
|
||||
|
||||
export type WorkspaceCreateInput = {
|
||||
defaultLogoIndex?: InputMaybe<Scalars['Int']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
name: Scalars['String']['input'];
|
||||
};
|
||||
@@ -4002,6 +4005,7 @@ export type WorkspaceTeamFilter = {
|
||||
};
|
||||
|
||||
export type WorkspaceUpdateInput = {
|
||||
defaultLogoIndex?: InputMaybe<Scalars['Int']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
id: Scalars['String']['input'];
|
||||
/** Logo image as base64-encoded string */
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
>
|
||||
<slot>
|
||||
<div
|
||||
v-if="user?.avatar || logo"
|
||||
v-if="user?.avatar"
|
||||
class="h-full w-full bg-cover bg-center bg-no-repeat"
|
||||
:style="{ backgroundImage: `url('${user ? user.avatar : logo}')` }"
|
||||
:style="{ backgroundImage: `url('${user.avatar}')` }"
|
||||
/>
|
||||
<div
|
||||
v-else-if="initials"
|
||||
@@ -41,7 +41,6 @@ const props = withDefaults(
|
||||
active?: boolean
|
||||
noBorder?: boolean
|
||||
noBg?: boolean
|
||||
logo?: MaybeNullOrUndefined<string>
|
||||
}>(),
|
||||
{
|
||||
size: 'base',
|
||||
|
||||
@@ -96,6 +96,8 @@ import type { AvatarUser, AvatarUserWithId } from '~~/src/composables/user/avata
|
||||
import { useDebouncedTextInput } from '~~/src/composables/form/textInput'
|
||||
|
||||
export { vKeyboardClickable } from '~~/src/directives/accessibility'
|
||||
export { useAvatarSizeClasses } from '~~/src/composables/user/avatar'
|
||||
export type { UserAvatarSize } from '~~/src/composables/user/avatar'
|
||||
|
||||
export {
|
||||
CommonLoadingIcon,
|
||||
|
||||
Reference in New Issue
Block a user