mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-18 14:55:22 +00:00
Translate the member page
This commit is contained in:
@@ -3208,5 +3208,48 @@
|
|||||||
"domainPickerWildcardCertWarning": "Wildcard resources may require additional configuration to work properly.",
|
"domainPickerWildcardCertWarning": "Wildcard resources may require additional configuration to work properly.",
|
||||||
"domainPickerWildcardCertWarningLink": "Learn more",
|
"domainPickerWildcardCertWarningLink": "Learn more",
|
||||||
"health": "Health",
|
"health": "Health",
|
||||||
"domainPendingErrorTitle": "Verification Issue"
|
"domainPendingErrorTitle": "Verification Issue",
|
||||||
|
"memberPortalTitle": "Resources",
|
||||||
|
"memberPortalDescription": "Resources you have access to in this organization",
|
||||||
|
"memberPortalSortBy": "Sort by...",
|
||||||
|
"memberPortalSortNameAsc": "Name A-Z",
|
||||||
|
"memberPortalSortNameDesc": "Name Z-A",
|
||||||
|
"memberPortalSortDomainAsc": "Domain A-Z",
|
||||||
|
"memberPortalSortDomainDesc": "Domain Z-A",
|
||||||
|
"memberPortalSortEnabledFirst": "Enabled First",
|
||||||
|
"memberPortalSortDisabledFirst": "Disabled First",
|
||||||
|
"memberPortalRefresh": "Refresh",
|
||||||
|
"memberPortalRefreshResources": "Refresh Resources",
|
||||||
|
"memberPortalFailedToLoad": "Failed to load resources",
|
||||||
|
"memberPortalFailedToLoadDescription": "Failed to load resources. Please check your connection and try again.",
|
||||||
|
"memberPortalUnableToLoad": "Unable to Load Resources",
|
||||||
|
"memberPortalTryAgain": "Try Again",
|
||||||
|
"memberPortalNoResourcesFound": "No Resources Found",
|
||||||
|
"memberPortalNoResourcesAvailable": "No Resources Available",
|
||||||
|
"memberPortalNoResourcesMatchSearch": "No resources match \"{query}\". Try adjusting your search terms or clearing the search to see all resources.",
|
||||||
|
"memberPortalNoResourcesAccess": "You don't have access to any resources yet. Contact your administrator to get access to resources you need.",
|
||||||
|
"memberPortalClearSearch": "Clear Search",
|
||||||
|
"memberPortalPublicResources": "Public Resources",
|
||||||
|
"memberPortalPublicResourcesDescription": "Web applications and services accessible via browser",
|
||||||
|
"memberPortalCopiedToClipboard": "Copied to clipboard",
|
||||||
|
"memberPortalCopiedUrlDescription": "Resource URL has been copied to your clipboard.",
|
||||||
|
"memberPortalOpenResource": "Open Resource",
|
||||||
|
"memberPortalPrivateResources": "Private Resources",
|
||||||
|
"memberPortalPrivateResourcesDescription": "Internal network resources accessible via client",
|
||||||
|
"memberPortalResourceDetails": "Resource Details",
|
||||||
|
"memberPortalMode": "Mode",
|
||||||
|
"memberPortalDestination": "Destination",
|
||||||
|
"memberPortalAlias": "Alias",
|
||||||
|
"memberPortalCopiedAliasDescription": "Resource alias has been copied to your clipboard.",
|
||||||
|
"memberPortalCopiedDestinationDescription": "Resource destination has been copied to your clipboard.",
|
||||||
|
"memberPortalRequiresClientConnection": "Requires Client Connection",
|
||||||
|
"memberPortalAuthMethods": "Authentication Methods",
|
||||||
|
"memberPortalSso": "Single Sign-On (SSO)",
|
||||||
|
"memberPortalPasswordProtected": "Password Protected",
|
||||||
|
"memberPortalPinCode": "PIN Code",
|
||||||
|
"memberPortalEmailWhitelist": "Email Whitelist",
|
||||||
|
"memberPortalResourceDisabled": "Resource Disabled",
|
||||||
|
"memberPortalShowingResources": "Showing {start}-{end} of {total} resources",
|
||||||
|
"memberPortalPrevious": "Previous",
|
||||||
|
"memberPortalNext": "Next"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ const ResourceFavicon = ({
|
|||||||
|
|
||||||
// Resource Info component
|
// Resource Info component
|
||||||
const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
||||||
|
const t = useTranslations();
|
||||||
const hasAuthMethods =
|
const hasAuthMethods =
|
||||||
resource.sso ||
|
resource.sso ||
|
||||||
resource.password ||
|
resource.password ||
|
||||||
@@ -141,7 +142,9 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
|||||||
{/* Site Information */}
|
{/* Site Information */}
|
||||||
{resource.siteName && (
|
{resource.siteName && (
|
||||||
<div>
|
<div>
|
||||||
<div className="text-xs font-medium mb-1.5">Site</div>
|
<div className="text-xs font-medium mb-1.5">
|
||||||
|
{t("site")}
|
||||||
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Combine className="h-4 w-4 text-foreground shrink-0" />
|
<Combine className="h-4 w-4 text-foreground shrink-0" />
|
||||||
<span className="text-sm">{resource.siteName}</span>
|
<span className="text-sm">{resource.siteName}</span>
|
||||||
@@ -157,7 +160,7 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="text-xs font-medium mb-1.5">
|
<div className="text-xs font-medium mb-1.5">
|
||||||
Authentication Methods
|
{t("memberPortalAuthMethods")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-1.5">
|
<div className="flex flex-col gap-1.5">
|
||||||
{resource.sso && (
|
{resource.sso && (
|
||||||
@@ -166,7 +169,7 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
|||||||
<Key className="h-3 w-3 text-blue-700 dark:text-blue-300" />
|
<Key className="h-3 w-3 text-blue-700 dark:text-blue-300" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm">
|
<span className="text-sm">
|
||||||
Single Sign-On (SSO)
|
{t("memberPortalSso")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -176,7 +179,7 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
|||||||
<KeyRound className="h-3 w-3 text-purple-700 dark:text-purple-300" />
|
<KeyRound className="h-3 w-3 text-purple-700 dark:text-purple-300" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm">
|
<span className="text-sm">
|
||||||
Password Protected
|
{t("memberPortalPasswordProtected")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -185,7 +188,9 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
|||||||
<div className="h-5 w-5 rounded-full flex items-center justify-center bg-emerald-50/50 dark:bg-emerald-950/50">
|
<div className="h-5 w-5 rounded-full flex items-center justify-center bg-emerald-50/50 dark:bg-emerald-950/50">
|
||||||
<Fingerprint className="h-3 w-3 text-emerald-700 dark:text-emerald-300" />
|
<Fingerprint className="h-3 w-3 text-emerald-700 dark:text-emerald-300" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm">PIN Code</span>
|
<span className="text-sm">
|
||||||
|
{t("memberPortalPinCode")}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{resource.whitelist && (
|
{resource.whitelist && (
|
||||||
@@ -193,7 +198,9 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
|||||||
<div className="h-5 w-5 rounded-full flex items-center justify-center bg-amber-50/50 dark:bg-amber-950/50">
|
<div className="h-5 w-5 rounded-full flex items-center justify-center bg-amber-50/50 dark:bg-amber-950/50">
|
||||||
<AtSign className="h-3 w-3 text-amber-700 dark:text-amber-300" />
|
<AtSign className="h-3 w-3 text-amber-700 dark:text-amber-300" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm">Email Whitelist</span>
|
<span className="text-sm">
|
||||||
|
{t("memberPortalEmailWhitelist")}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -208,7 +215,7 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<AlertCircle className="h-4 w-4 text-destructive shrink-0" />
|
<AlertCircle className="h-4 w-4 text-destructive shrink-0" />
|
||||||
<span className="text-sm text-destructive">
|
<span className="text-sm text-destructive">
|
||||||
Resource Disabled
|
{t("memberPortalResourceDisabled")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -233,6 +240,7 @@ const PaginationControls = ({
|
|||||||
totalItems: number;
|
totalItems: number;
|
||||||
itemsPerPage: number;
|
itemsPerPage: number;
|
||||||
}) => {
|
}) => {
|
||||||
|
const t = useTranslations();
|
||||||
const startItem = (currentPage - 1) * itemsPerPage + 1;
|
const startItem = (currentPage - 1) * itemsPerPage + 1;
|
||||||
const endItem = Math.min(currentPage * itemsPerPage, totalItems);
|
const endItem = Math.min(currentPage * itemsPerPage, totalItems);
|
||||||
|
|
||||||
@@ -241,7 +249,11 @@ const PaginationControls = ({
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col sm:flex-row items-center justify-between gap-4 mt-8">
|
<div className="flex flex-col sm:flex-row items-center justify-between gap-4 mt-8">
|
||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
Showing {startItem}-{endItem} of {totalItems} resources
|
{t("memberPortalShowingResources", {
|
||||||
|
start: startItem,
|
||||||
|
end: endItem,
|
||||||
|
total: totalItems
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -253,7 +265,7 @@ const PaginationControls = ({
|
|||||||
className="gap-1"
|
className="gap-1"
|
||||||
>
|
>
|
||||||
<ChevronLeft className="h-4 w-4" />
|
<ChevronLeft className="h-4 w-4" />
|
||||||
Previous
|
{t("memberPortalPrevious")}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
@@ -309,7 +321,7 @@ const PaginationControls = ({
|
|||||||
disabled={currentPage === totalPages}
|
disabled={currentPage === totalPages}
|
||||||
className="gap-1"
|
className="gap-1"
|
||||||
>
|
>
|
||||||
Next
|
{t("memberPortalNext")}
|
||||||
<ChevronRight className="h-4 w-4" />
|
<ChevronRight className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -389,13 +401,11 @@ export default function MemberResourcesPortal({
|
|||||||
response.data.data.siteResources || []
|
response.data.data.siteResources || []
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
setError("Failed to load resources");
|
setError(t("memberPortalFailedToLoad"));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error fetching user resources:", err);
|
console.error("Error fetching user resources:", err);
|
||||||
setError(
|
setError(t("memberPortalFailedToLoadDescription"));
|
||||||
"Failed to load resources. Please check your connection and try again."
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setRefreshing(false);
|
setRefreshing(false);
|
||||||
@@ -526,8 +536,8 @@ export default function MemberResourcesPortal({
|
|||||||
return (
|
return (
|
||||||
<div className="container mx-auto max-w-12xl">
|
<div className="container mx-auto max-w-12xl">
|
||||||
<SettingsSectionTitle
|
<SettingsSectionTitle
|
||||||
title="Resources"
|
title={t("memberPortalTitle")}
|
||||||
description="Resources you have access to in this organization"
|
description={t("memberPortalDescription")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Search and Sort Controls - Skeleton */}
|
{/* Search and Sort Controls - Skeleton */}
|
||||||
@@ -554,8 +564,8 @@ export default function MemberResourcesPortal({
|
|||||||
return (
|
return (
|
||||||
<div className="container mx-auto max-w-12xl">
|
<div className="container mx-auto max-w-12xl">
|
||||||
<SettingsSectionTitle
|
<SettingsSectionTitle
|
||||||
title="Resources"
|
title={t("memberPortalTitle")}
|
||||||
description="Resources you have access to in this organization"
|
description={t("memberPortalDescription")}
|
||||||
/>
|
/>
|
||||||
<Card>
|
<Card>
|
||||||
<CardContent className="flex flex-col items-center justify-center py-20 text-center">
|
<CardContent className="flex flex-col items-center justify-center py-20 text-center">
|
||||||
@@ -563,7 +573,7 @@ export default function MemberResourcesPortal({
|
|||||||
<AlertCircle className="h-16 w-16 text-destructive/60" />
|
<AlertCircle className="h-16 w-16 text-destructive/60" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-semibold text-foreground mb-3">
|
<h3 className="text-xl font-semibold text-foreground mb-3">
|
||||||
Unable to Load Resources
|
{t("memberPortalUnableToLoad")}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-muted-foreground max-w-lg text-base mb-6">
|
<p className="text-muted-foreground max-w-lg text-base mb-6">
|
||||||
{error}
|
{error}
|
||||||
@@ -574,7 +584,7 @@ export default function MemberResourcesPortal({
|
|||||||
className="gap-2"
|
className="gap-2"
|
||||||
>
|
>
|
||||||
<RefreshCw className="h-4 w-4" />
|
<RefreshCw className="h-4 w-4" />
|
||||||
Try Again
|
{t("memberPortalTryAgain")}
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -585,8 +595,8 @@ export default function MemberResourcesPortal({
|
|||||||
return (
|
return (
|
||||||
<div className="container mx-auto max-w-12xl">
|
<div className="container mx-auto max-w-12xl">
|
||||||
<SettingsSectionTitle
|
<SettingsSectionTitle
|
||||||
title="Resources"
|
title={t("memberPortalTitle")}
|
||||||
description="Resources you have access to in this organization"
|
description={t("memberPortalDescription")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Search and Sort Controls with Refresh */}
|
{/* Search and Sort Controls with Refresh */}
|
||||||
@@ -595,7 +605,7 @@ export default function MemberResourcesPortal({
|
|||||||
{/* Search */}
|
{/* Search */}
|
||||||
<div className="relative w-full sm:w-80">
|
<div className="relative w-full sm:w-80">
|
||||||
<Input
|
<Input
|
||||||
placeholder="Search resources..."
|
placeholder={t("resourcesSearch")}
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
className="w-full pl-8 bg-card"
|
className="w-full pl-8 bg-card"
|
||||||
@@ -607,26 +617,28 @@ export default function MemberResourcesPortal({
|
|||||||
<div className="w-full sm:w-36">
|
<div className="w-full sm:w-36">
|
||||||
<Select value={sortBy} onValueChange={setSortBy}>
|
<Select value={sortBy} onValueChange={setSortBy}>
|
||||||
<SelectTrigger className="bg-card">
|
<SelectTrigger className="bg-card">
|
||||||
<SelectValue placeholder="Sort by..." />
|
<SelectValue
|
||||||
|
placeholder={t("memberPortalSortBy")}
|
||||||
|
/>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="name-asc">
|
<SelectItem value="name-asc">
|
||||||
Name A-Z
|
{t("memberPortalSortNameAsc")}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="name-desc">
|
<SelectItem value="name-desc">
|
||||||
Name Z-A
|
{t("memberPortalSortNameDesc")}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="domain-asc">
|
<SelectItem value="domain-asc">
|
||||||
Domain A-Z
|
{t("memberPortalSortDomainAsc")}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="domain-desc">
|
<SelectItem value="domain-desc">
|
||||||
Domain Z-A
|
{t("memberPortalSortDomainDesc")}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="status-enabled">
|
<SelectItem value="status-enabled">
|
||||||
Enabled First
|
{t("memberPortalSortEnabledFirst")}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="status-disabled">
|
<SelectItem value="status-disabled">
|
||||||
Disabled First
|
{t("memberPortalSortDisabledFirst")}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
@@ -644,7 +656,7 @@ export default function MemberResourcesPortal({
|
|||||||
<RefreshCw
|
<RefreshCw
|
||||||
className={`h-4 w-4 ${refreshing ? "animate-spin" : ""}`}
|
className={`h-4 w-4 ${refreshing ? "animate-spin" : ""}`}
|
||||||
/>
|
/>
|
||||||
Refresh
|
{t("memberPortalRefresh")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -663,13 +675,15 @@ export default function MemberResourcesPortal({
|
|||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-semibold text-foreground mb-3">
|
<h3 className="text-2xl font-semibold text-foreground mb-3">
|
||||||
{searchQuery
|
{searchQuery
|
||||||
? "No Resources Found"
|
? t("memberPortalNoResourcesFound")
|
||||||
: "No Resources Available"}
|
: t("memberPortalNoResourcesAvailable")}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-muted-foreground max-w-lg text-base mb-6">
|
<p className="text-muted-foreground max-w-lg text-base mb-6">
|
||||||
{searchQuery
|
{searchQuery
|
||||||
? `No resources match "${searchQuery}". Try adjusting your search terms or clearing the search to see all resources.`
|
? t("memberPortalNoResourcesMatchSearch", {
|
||||||
: "You don't have access to any resources yet. Contact your administrator to get access to resources you need."}
|
query: searchQuery
|
||||||
|
})
|
||||||
|
: t("memberPortalNoResourcesAccess")}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-col sm:flex-row gap-3">
|
<div className="flex flex-col sm:flex-row gap-3">
|
||||||
{searchQuery ? (
|
{searchQuery ? (
|
||||||
@@ -678,7 +692,7 @@ export default function MemberResourcesPortal({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
className="gap-2"
|
className="gap-2"
|
||||||
>
|
>
|
||||||
Clear Search
|
{t("memberPortalClearSearch")}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
@@ -690,7 +704,7 @@ export default function MemberResourcesPortal({
|
|||||||
<RefreshCw
|
<RefreshCw
|
||||||
className={`h-4 w-4 ${refreshing ? "animate-spin" : ""}`}
|
className={`h-4 w-4 ${refreshing ? "animate-spin" : ""}`}
|
||||||
/>
|
/>
|
||||||
Refresh Resources
|
{t("memberPortalRefreshResources")}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -704,11 +718,12 @@ export default function MemberResourcesPortal({
|
|||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<h3 className="text-lg font-semibold text-foreground flex items-center gap-2">
|
<h3 className="text-lg font-semibold text-foreground flex items-center gap-2">
|
||||||
<Globe className="h-5 w-5" />
|
<Globe className="h-5 w-5" />
|
||||||
Public Resources
|
{t("memberPortalPublicResources")}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-muted-foreground mt-1">
|
<p className="text-sm text-muted-foreground mt-1">
|
||||||
Web applications and services accessible via
|
{t(
|
||||||
browser
|
"memberPortalPublicResourcesDescription"
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-5 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4 auto-cols-fr mb-8">
|
<div className="grid gap-5 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4 auto-cols-fr mb-8">
|
||||||
@@ -768,9 +783,12 @@ export default function MemberResourcesPortal({
|
|||||||
resource.domain
|
resource.domain
|
||||||
);
|
);
|
||||||
toast({
|
toast({
|
||||||
title: "Copied to clipboard",
|
title: t(
|
||||||
description:
|
"memberPortalCopiedToClipboard"
|
||||||
"Resource URL has been copied to your clipboard.",
|
),
|
||||||
|
description: t(
|
||||||
|
"memberPortalCopiedUrlDescription"
|
||||||
|
),
|
||||||
duration: 2000
|
duration: 2000
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -791,7 +809,7 @@ export default function MemberResourcesPortal({
|
|||||||
disabled={!resource.enabled}
|
disabled={!resource.enabled}
|
||||||
>
|
>
|
||||||
<ExternalLink className="h-3.5 w-3.5 mr-2" />
|
<ExternalLink className="h-3.5 w-3.5 mr-2" />
|
||||||
Open Resource
|
{t("memberPortalOpenResource")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -806,11 +824,12 @@ export default function MemberResourcesPortal({
|
|||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<h3 className="text-lg font-semibold text-foreground flex items-center gap-2">
|
<h3 className="text-lg font-semibold text-foreground flex items-center gap-2">
|
||||||
<Combine className="h-5 w-5" />
|
<Combine className="h-5 w-5" />
|
||||||
Private Resources
|
{t("memberPortalPrivateResources")}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-muted-foreground mt-1">
|
<p className="text-sm text-muted-foreground mt-1">
|
||||||
Internal network resources accessible via
|
{t(
|
||||||
client
|
"memberPortalPrivateResourcesDescription"
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-5 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4 auto-cols-fr mb-8">
|
<div className="grid gap-5 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4 auto-cols-fr mb-8">
|
||||||
@@ -843,11 +862,16 @@ export default function MemberResourcesPortal({
|
|||||||
<InfoPopup>
|
<InfoPopup>
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
<div className="text-xs font-medium mb-1.5">
|
<div className="text-xs font-medium mb-1.5">
|
||||||
Resource Details
|
{t(
|
||||||
|
"memberPortalResourceDetails"
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
Mode:
|
{t(
|
||||||
|
"memberPortalMode"
|
||||||
|
)}
|
||||||
|
:
|
||||||
</span>
|
</span>
|
||||||
<span className="ml-2 text-muted-foreground capitalize">
|
<span className="ml-2 text-muted-foreground capitalize">
|
||||||
{
|
{
|
||||||
@@ -858,7 +882,10 @@ export default function MemberResourcesPortal({
|
|||||||
{siteResource.protocol && (
|
{siteResource.protocol && (
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
Protocol:
|
{t(
|
||||||
|
"protocol"
|
||||||
|
)}
|
||||||
|
:
|
||||||
</span>
|
</span>
|
||||||
<span className="ml-2 text-muted-foreground uppercase">
|
<span className="ml-2 text-muted-foreground uppercase">
|
||||||
{
|
{
|
||||||
@@ -869,7 +896,10 @@ export default function MemberResourcesPortal({
|
|||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
Destination:
|
{t(
|
||||||
|
"memberPortalDestination"
|
||||||
|
)}
|
||||||
|
:
|
||||||
</span>
|
</span>
|
||||||
<span className="ml-2 text-muted-foreground">
|
<span className="ml-2 text-muted-foreground">
|
||||||
{
|
{
|
||||||
@@ -880,7 +910,10 @@ export default function MemberResourcesPortal({
|
|||||||
{siteResource.alias && (
|
{siteResource.alias && (
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
Alias:
|
{t(
|
||||||
|
"memberPortalAlias"
|
||||||
|
)}
|
||||||
|
:
|
||||||
</span>
|
</span>
|
||||||
<span className="ml-2 text-muted-foreground">
|
<span className="ml-2 text-muted-foreground">
|
||||||
{
|
{
|
||||||
@@ -891,14 +924,21 @@ export default function MemberResourcesPortal({
|
|||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<span className="font-medium">
|
<span className="font-medium">
|
||||||
Status:
|
{t(
|
||||||
|
"status"
|
||||||
|
)}
|
||||||
|
:
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`ml-2 ${siteResource.enabled ? "text-green-600" : "text-red-600"}`}
|
className={`ml-2 ${siteResource.enabled ? "text-green-600" : "text-red-600"}`}
|
||||||
>
|
>
|
||||||
{siteResource.enabled
|
{siteResource.enabled
|
||||||
? "Enabled"
|
? t(
|
||||||
: "Disabled"}
|
"enabled"
|
||||||
|
)
|
||||||
|
: t(
|
||||||
|
"disabled"
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -925,9 +965,13 @@ export default function MemberResourcesPortal({
|
|||||||
siteResource.alias!
|
siteResource.alias!
|
||||||
);
|
);
|
||||||
toast({
|
toast({
|
||||||
title: "Copied to clipboard",
|
title: t(
|
||||||
|
"memberPortalCopiedToClipboard"
|
||||||
|
),
|
||||||
description:
|
description:
|
||||||
"Resource alias has been copied to your clipboard.",
|
t(
|
||||||
|
"memberPortalCopiedAliasDescription"
|
||||||
|
),
|
||||||
duration: 2000
|
duration: 2000
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -959,9 +1003,13 @@ export default function MemberResourcesPortal({
|
|||||||
siteResource.destination
|
siteResource.destination
|
||||||
);
|
);
|
||||||
toast({
|
toast({
|
||||||
title: "Copied to clipboard",
|
title: t(
|
||||||
|
"memberPortalCopiedToClipboard"
|
||||||
|
),
|
||||||
description:
|
description:
|
||||||
"Resource destination has been copied to your clipboard.",
|
t(
|
||||||
|
"memberPortalCopiedDestinationDescription"
|
||||||
|
),
|
||||||
duration: 2000
|
duration: 2000
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -976,7 +1024,9 @@ export default function MemberResourcesPortal({
|
|||||||
<div className="p-6 pt-0 mt-auto">
|
<div className="p-6 pt-0 mt-auto">
|
||||||
<div className="flex items-center justify-center py-2 px-4 bg-muted/50 rounded text-sm text-muted-foreground">
|
<div className="flex items-center justify-center py-2 px-4 bg-muted/50 rounded text-sm text-muted-foreground">
|
||||||
<Combine className="h-3.5 w-3.5 mr-2" />
|
<Combine className="h-3.5 w-3.5 mr-2" />
|
||||||
Requires Client Connection
|
{t(
|
||||||
|
"memberPortalRequiresClientConnection"
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user