feat: global workspace selector (#2922)

Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
This commit is contained in:
Nivedin
2023-02-24 23:20:02 +05:30
committed by GitHub
parent 4ca6e9ec3a
commit 7e686a8882
35 changed files with 1130 additions and 808 deletions

View File

@@ -0,0 +1,94 @@
<template>
<div class="flex items-center -space-x-1">
<div
v-for="(member, index) in slicedTeamMembers"
:key="`member-${index}`"
class="inline-flex"
>
<ProfilePicture
v-if="member.user.photoURL"
v-tippy="{ theme: 'tooltip' }"
:url="member.user.photoURL"
:title="getUserName(member)"
:alt="getUserName(member)"
class="ring-primary ring-2"
@click="handleClick()"
/>
<ProfilePicture
v-else
v-tippy="{ theme: 'tooltip' }"
:title="getUserName(member)"
:initial="getUserName(member)"
class="ring-primary ring-2"
@click="handleClick()"
/>
</div>
<button
v-if="props.showCount && props.teamMembers.length > maxMembersSoftLimit"
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="remainingSlicedMembers"
class="z-10 inline-flex items-center justify-center w-5 h-5 rounded-full cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-primaryDark font- text-8px text-secondaryDark bg-dividerDark ring-2 ring-primary"
tabindex="0"
@click="handleClick()"
>
{{
teamMembers.length > 0
? `+${teamMembers.length - maxMembersSoftLimit}`
: ""
}}
</button>
</div>
</template>
<script setup lang="ts">
import { GetMyTeamsQuery, TeamMember } from "~/helpers/backend/graphql"
import { useI18n } from "@composables/i18n"
import { computed } from "vue"
const t = useI18n()
const props = defineProps<{
teamMembers: GetMyTeamsQuery["myTeams"][number]["teamMembers"]
showCount?: boolean
}>()
const emit = defineEmits<{
(e: "handle-click"): void
}>()
const getUserName = (member: TeamMember): string =>
member.user.displayName ||
member.user.email ||
t("profile.default_hopp_displayName")
const maxMembersSoftLimit = 4
const maxMembersHardLimit = 6
const slicedTeamMembers = computed(() => {
if (props.showCount && props.teamMembers.length > maxMembersSoftLimit) {
return props.teamMembers.slice(0, maxMembersSoftLimit)
} else {
return props.teamMembers
}
})
const remainingSlicedMembers = computed(
() =>
props.teamMembers
.slice(maxMembersSoftLimit)
.slice(0, maxMembersHardLimit)
.map((member) => getUserName(member))
.join(`,<br>`) +
(props.teamMembers.length - (maxMembersSoftLimit + maxMembersHardLimit) > 0
? `,<br>${t("team.more_members", {
count:
props.teamMembers.length -
(maxMembersSoftLimit + maxMembersHardLimit),
})}`
: ``)
)
const handleClick = () => {
emit("handle-click")
}
</script>

View File

@@ -27,31 +27,7 @@
>
{{ team.name || t("state.nothing_found") }}
</label>
<div class="flex mt-2 overflow-hidden -space-x-1">
<div
v-for="(member, index) in team.teamMembers"
:key="`member-${index}`"
v-tippy="{ theme: 'tooltip' }"
:title="
member.user.displayName ||
member.user.email ||
t('default_hopp_displayName')
"
class="inline-flex"
>
<ProfilePicture
v-if="member.user.photoURL"
:url="member.user.photoURL"
:alt="member.user.displayName"
class="ring-primary ring-2"
/>
<ProfilePicture
v-else
:initial="member.user.displayName || member.user.email"
class="ring-primary ring-2"
/>
</div>
</div>
<TeamsMemberStack :team-members="team.teamMembers" class="mt-4" />
</div>
</div>
<div v-if="!compact" class="flex items-end justify-between flex-shrink-0">
@@ -171,7 +147,7 @@
import { ref } from "vue"
import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/TaskEither"
import { TeamMemberRole } from "~/helpers/backend/graphql"
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
import {
deleteTeam as backendDeleteTeam,
leaveTeam,
@@ -189,18 +165,7 @@ import IconTrash2 from "~icons/lucide/trash-2"
const t = useI18n()
const props = defineProps<{
team: {
name: string
myRole: TeamMemberRole
ownersCount: number
teamMembers: Array<{
user: {
displayName: string
photoURL: string | null
email: string | null
}
}>
}
team: GetMyTeamsQuery["myTeams"][number]
teamID: string
compact: boolean
}>()