Files
ComfyUI_frontend/src/platform/cloud/subscription/components/SubscriptionPanel.vue
Simula_r 4771565486 Workspaces 4 members invites (#8245)
## Summary

  Add team workspace member management and invite system.

## Changes

- Add members panel with role management (owner/admin/member) and member
removal
- Add invite system with email invites, pending invite display, and
revoke functionality
   - Add invite URL loading for accepting invites
  - Add subscription panel updates for member management
  - Add i18n translations for member and invite features

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8245-Workspaces-4-members-invites-2f06d73d36508176b2caf852a1505c4a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-24 15:52:40 -08:00

106 lines
3.6 KiB
Vue

<template>
<TabPanel value="PlanCredits" class="subscription-container h-full">
<div class="flex h-full flex-col gap-6">
<div class="flex items-center gap-2">
<span class="text-2xl font-inter font-semibold leading-tight">
{{
isActiveSubscription
? $t('subscription.title')
: $t('subscription.titleUnsubscribed')
}}
</span>
<div class="pt-1">
<CloudBadge
reverse-order
background-color="var(--p-dialog-background)"
/>
</div>
</div>
<!-- Workspace mode: workspace-aware subscription content -->
<SubscriptionPanelContentWorkspace v-if="teamWorkspacesEnabled" />
<!-- Legacy mode: user-level subscription content -->
<SubscriptionPanelContentLegacy v-else />
<div
class="flex items-center justify-between border-t border-interface-stroke pt-3"
>
<div class="flex gap-2">
<Button
variant="muted-textonly"
class="text-xs text-text-secondary"
@click="handleLearnMoreClick"
>
<i class="pi pi-question-circle text-text-secondary text-xs" />
{{ $t('subscription.learnMore') }}
</Button>
<Button
variant="muted-textonly"
class="text-xs text-text-secondary"
@click="handleOpenPartnerNodesInfo"
>
<i class="pi pi-question-circle text-text-secondary text-xs" />
{{ $t('subscription.partnerNodesCredits') }}
</Button>
<Button
variant="muted-textonly"
class="text-xs text-text-secondary"
:loading="isLoadingSupport"
@click="handleMessageSupport"
>
<i class="pi pi-comment text-text-secondary text-xs" />
{{ $t('subscription.messageSupport') }}
</Button>
</div>
<Button
variant="muted-textonly"
class="text-xs text-text-secondary"
@click="handleInvoiceHistory"
>
{{ $t('subscription.invoiceHistory') }}
<i class="pi pi-external-link text-text-secondary text-xs" />
</Button>
</div>
</div>
</TabPanel>
</template>
<script setup lang="ts">
import TabPanel from 'primevue/tabpanel'
import { computed, defineAsyncComponent } from 'vue'
import CloudBadge from '@/components/topbar/CloudBadge.vue'
import Button from '@/components/ui/button/Button.vue'
import { useExternalLink } from '@/composables/useExternalLink'
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import SubscriptionPanelContentLegacy from '@/platform/cloud/subscription/components/SubscriptionPanelContentLegacy.vue'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
import { useSubscriptionActions } from '@/platform/cloud/subscription/composables/useSubscriptionActions'
import { isCloud } from '@/platform/distribution/types'
const SubscriptionPanelContentWorkspace = defineAsyncComponent(
() =>
import('@/platform/cloud/subscription/components/SubscriptionPanelContentWorkspace.vue')
)
const { flags } = useFeatureFlags()
const teamWorkspacesEnabled = computed(
() => isCloud && flags.teamWorkspacesEnabled
)
const { buildDocsUrl, docsPaths } = useExternalLink()
const { isActiveSubscription, handleInvoiceHistory } = useSubscription()
const { isLoadingSupport, handleMessageSupport, handleLearnMoreClick } =
useSubscriptionActions()
const handleOpenPartnerNodesInfo = () => {
window.open(
buildDocsUrl(docsPaths.partnerNodesPricing, { includeLocale: true }),
'_blank'
)
}
</script>