mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-08 18:21:55 +00:00
copy(portal): normalize remaining workspace account language
This commit is contained in:
parent
776d281f87
commit
aaa008e48b
5 changed files with 55 additions and 55 deletions
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"source_hash": "76d42d67fcfa327e662a150fb9ae74fe5ebc1cc020771aa889191ffb6e2c9be0",
|
||||
"source_hash": "59170a8df52cfe51c3e646dd1968ca1e89f250a1d12286ed374dacab67128d3c",
|
||||
"build_inputs": [
|
||||
"package.json",
|
||||
"tsconfig.json",
|
||||
|
|
|
|||
40
internal/cloudcp/portal/dist/portal_app.js
vendored
40
internal/cloudcp/portal/dist/portal_app.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -33,13 +33,13 @@ function roleLabel(role: string): string {
|
|||
function roleCapabilityCopy(role: string): string {
|
||||
switch (normalizedTeamRole(role)) {
|
||||
case 'owner':
|
||||
return 'Full account control, including billing, team access, and hosted workspace control.';
|
||||
return 'Full account control, including billing, team access, and workspace control.';
|
||||
case 'admin':
|
||||
return 'Can manage hosted workspaces and billing for this account.';
|
||||
return 'Can manage workspaces and billing for this account.';
|
||||
case 'tech':
|
||||
return 'Can manage hosted workspaces without billing ownership.';
|
||||
return 'Can manage workspaces without billing ownership.';
|
||||
case 'read_only':
|
||||
return 'Can review hosted state without making control-plane changes.';
|
||||
return 'Can review workspace status without making control-plane changes.';
|
||||
case 'member':
|
||||
return 'Has access through the account roster.';
|
||||
default:
|
||||
|
|
@ -88,10 +88,10 @@ function workspaceGuidance(workspace: PortalWorkspaceSummary): string {
|
|||
return 'This workspace looks ready for normal use. Use the fleet table to open it, or suspend it here if you are intentionally taking it out of service.';
|
||||
}
|
||||
if (workspace.state === 'active' && workspace.health_status === 'checking') {
|
||||
return 'This workspace is active but still waiting on a completed health check. Review it before you treat the hosted posture as settled.';
|
||||
return 'This workspace is active but still waiting on a completed health check. Review it before you treat the account status as settled.';
|
||||
}
|
||||
if (workspace.health_status === 'unhealthy') {
|
||||
return 'This workspace needs review before it is treated as trustworthy. Use the management action only when you intend to suspend or remove it from the hosted fleet.';
|
||||
return 'This workspace needs review before it is treated as trustworthy. Use the management action only when you intend to suspend or remove it from the workspace list.';
|
||||
}
|
||||
if (workspace.state === 'suspended') {
|
||||
return 'This workspace is already suspended. The remaining lifecycle action here is deletion, so treat it as a deliberate irreversible step.';
|
||||
|
|
@ -369,7 +369,7 @@ export function renderTeamSection(accountID: string, entry: PortalAccountUIEntry
|
|||
}
|
||||
if (!entry.teamQuery.data.length) {
|
||||
if (rosterPanel) rosterPanel.classList.add('state-only');
|
||||
setContainerMessage(roster, 'No one added yet', 'Invite someone new when this hosted account needs shared access.', false);
|
||||
setContainerMessage(roster, 'No one added yet', 'Invite someone new when this account needs shared access.', false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ describe('shell view', function() {
|
|||
expect(html).toContain('Workspace summary');
|
||||
expect(html).toContain('Account scope');
|
||||
expect(html).toContain('Manage client workspaces, billing, and team access from one place.');
|
||||
expect(html).toContain('Hosted path');
|
||||
expect(html).toContain('Workspace path');
|
||||
expect(html).toContain('Commercial path');
|
||||
expect(html).toContain('Open workspaces');
|
||||
expect(html).toContain('Review team access');
|
||||
|
|
@ -192,7 +192,7 @@ describe('shell view', function() {
|
|||
expect(html).toContain('data-action="clear-workspace-selection"');
|
||||
expect(html).toContain('Team management');
|
||||
expect(html).toContain('Least privilege');
|
||||
expect(html).toContain('Hosted access');
|
||||
expect(html).toContain('Workspace access');
|
||||
expect(html).toContain('Invite someone new');
|
||||
expect(html).toContain('Access model');
|
||||
expect(html).toContain('Access review');
|
||||
|
|
@ -245,7 +245,7 @@ describe('shell view', function() {
|
|||
expect(html).toContain('Summary');
|
||||
expect(html).toContain('None');
|
||||
expect(html).toContain('Use these account tools for self-hosted licenses, billing, refunds, and privacy actions.');
|
||||
expect(html).toContain('Pick one commercial request and keep it separate from hosted workspaces and team changes.');
|
||||
expect(html).toContain('Pick one commercial request and keep it separate from workspace and team changes.');
|
||||
expect(html).toContain('Account services');
|
||||
expect(html).not.toContain('Self-hosted commercial services');
|
||||
});
|
||||
|
|
@ -317,8 +317,8 @@ describe('shell view', function() {
|
|||
expect(html).toContain('No active blockers');
|
||||
expect(html).toContain('Active workspaces are healthy while suspended workspaces stay parked until you resume them.');
|
||||
expect(html).toContain('Next step');
|
||||
expect(html).toContain('Active hosted workspaces look stable. Resume a suspended workspace only when you are ready to bring it back into regular use.');
|
||||
expect(html).toContain('Active hosted workspaces are healthy. Suspended workspaces stay parked until you resume them.');
|
||||
expect(html).toContain('Active workspaces look stable. Resume a suspended workspace only when you are ready to bring it back into regular use.');
|
||||
expect(html).toContain('Active workspaces are healthy. Suspended workspaces stay parked until you resume them.');
|
||||
expect(html).toContain('Suspended stays parked');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -200,13 +200,13 @@ function renderAttentionPanel(workspaces: PortalWorkspaceSummary[]): string {
|
|||
'<div class="account-panel-kicker">Attention</div>' +
|
||||
'<h4>' + escapeHTML(suspendedCount > 0 ? 'No active blockers' : 'Fleet is clear') + '</h4>' +
|
||||
'<p>' + escapeHTML(suspendedCount > 0
|
||||
? 'Active hosted workspaces are healthy. Suspended workspaces stay parked until you resume them.'
|
||||
: 'Every active hosted workspace currently reports a healthy status.'
|
||||
? 'Active workspaces are healthy. Suspended workspaces stay parked until you resume them.'
|
||||
: 'Every active workspace currently reports a healthy status.'
|
||||
) + '</p>' +
|
||||
'<div class="overview-stable-list">' +
|
||||
'<div class="overview-stable-item"><strong>Healthy now</strong><span>' + escapeHTML(suspendedCount > 0
|
||||
? 'Active hosted workspaces are clear for routine use.'
|
||||
: 'All active hosted workspaces are clear for routine use.'
|
||||
? 'Active workspaces are clear for routine use.'
|
||||
: 'All active workspaces are clear for routine use.'
|
||||
) + '</span></div>' +
|
||||
(suspendedCount > 0
|
||||
? '<div class="overview-stable-item"><strong>Suspended stays parked</strong><span>' + escapeHTML(String(suspendedCount) + ' workspace' + (suspendedCount === 1 ? ' is' : 's are') + ' suspended and intentionally out of day-to-day use.') + '</span></div>'
|
||||
|
|
@ -351,11 +351,11 @@ function renderShellNavigation(accounts: PortalAccountSummary[], supportEmail: s
|
|||
'<div class="portal-shell-nav-header">' +
|
||||
'<div class="portal-shell-nav-eyebrow">Pulse Account</div>' +
|
||||
'<div class="portal-shell-nav-title">Account center</div>' +
|
||||
'<div class="portal-shell-nav-support">' + (hosted ? 'Hosted workspaces, account access, and commercial services' : 'Commercial account services and support') + '</div>' +
|
||||
'<div class="portal-shell-nav-support">' + (hosted ? 'Workspaces, account access, and commercial services' : 'Commercial account services and support') + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="portal-shell-nav-group">' +
|
||||
shellSectionButton('overview', activeSection, '01', 'Overview', hosted ? 'Status, priorities, and next actions' : 'Account summary and access state', hosted ? String(totalWorkspaces) + ' total' : 'Summary') +
|
||||
shellSectionButton('workspaces', activeSection, '02', hosted ? 'Workspaces' : 'Hosted access', hosted ? 'Hosted workspaces and lifecycle actions' : 'No hosted workspaces are attached yet', hosted ? String(readyWorkspaces) + ' ready' : 'None') +
|
||||
shellSectionButton('workspaces', activeSection, '02', hosted ? 'Workspaces' : 'Workspace access', hosted ? 'Workspace access and lifecycle actions' : 'No workspaces are attached yet', hosted ? String(readyWorkspaces) + ' ready' : 'None') +
|
||||
shellSectionButton('team', activeSection, '03', 'Team', hosted ? 'Access and team roster' : 'Account membership', canManage ? 'Manage' : 'View') +
|
||||
shellSectionButton('services', activeSection, '04', 'Account services', 'Licenses, billing, refunds, and privacy', '4 tools') +
|
||||
shellSectionButton('support', activeSection, '05', 'Support', hosted ? 'Escalation and account support' : (supportEmail || 'Support contact'), supportEmail ? 'Email' : 'Help') +
|
||||
|
|
@ -450,10 +450,10 @@ function renderAccountOverviewSection(account: PortalAccountSummary): string {
|
|||
: 'Next step';
|
||||
var nextStepCopy = unhealthyCount > 0
|
||||
? 'One or more workspaces need review before you treat this account as healthy.'
|
||||
: checkingCount > 0
|
||||
? 'The fleet is mostly healthy, but there are still workspaces waiting on a completed health check.'
|
||||
: checkingCount > 0
|
||||
? 'The fleet is mostly healthy, but there are still workspaces waiting on a completed health check.'
|
||||
: suspendedCount > 0
|
||||
? 'Active hosted workspaces look stable. Resume a suspended workspace only when you are ready to bring it back into regular use.'
|
||||
? 'Active workspaces look stable. Resume a suspended workspace only when you are ready to bring it back into regular use.'
|
||||
: 'Everything looks stable. Move into Team or Account services only if you need to change access or billing.';
|
||||
var nextStepChecklist = unhealthyCount > 0
|
||||
? (
|
||||
|
|
@ -473,7 +473,7 @@ function renderAccountOverviewSection(account: PortalAccountSummary): string {
|
|||
)
|
||||
: (
|
||||
'<div class="overview-next-checklist">' +
|
||||
'<div class="overview-next-check"><strong>1. Open a workspace for the next operational task</strong><span>Move into Workspaces when you are ready to do hosted work.</span></div>' +
|
||||
'<div class="overview-next-check"><strong>1. Open a workspace for the next operational task</strong><span>Move into Workspaces when you are ready to do workspace work.</span></div>' +
|
||||
'<div class="overview-next-check"><strong>2. Change access in Team only</strong><span>Keep roster changes explicit instead of mixing them into routine workspace work.</span></div>' +
|
||||
'<div class="overview-next-check"><strong>3. Keep billing and privacy separate</strong><span>Licenses, refunds, privacy, and self-hosted billing stay in their own section.</span></div>' +
|
||||
'</div>'
|
||||
|
|
@ -485,7 +485,7 @@ function renderAccountOverviewSection(account: PortalAccountSummary): string {
|
|||
'</div>';
|
||||
var accountScopeCopy = account.kind === 'msp'
|
||||
? 'Manage client workspaces, billing, and team access from one place.'
|
||||
: 'Manage hosted workspaces, billing, and team access from one place.';
|
||||
: 'Manage workspaces, billing, and team access from one place.';
|
||||
var overviewBriefStrip =
|
||||
'<div class="account-overview-brief-strip">' +
|
||||
'<div class="account-overview-brief-point account-overview-brief-point-wide">' +
|
||||
|
|
@ -493,12 +493,12 @@ function renderAccountOverviewSection(account: PortalAccountSummary): string {
|
|||
'<span>' + escapeHTML(accountScopeCopy) + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="account-overview-brief-point">' +
|
||||
'<strong>Hosted path</strong>' +
|
||||
'<strong>Workspace path</strong>' +
|
||||
'<span>Use Workspaces for tenant access and lifecycle changes, and Team only when access needs to change.</span>' +
|
||||
'</div>' +
|
||||
'<div class="account-overview-brief-point">' +
|
||||
'<strong>Commercial path</strong>' +
|
||||
'<span>Keep licenses, refunds, privacy, and self-hosted billing in Account services instead of mixing them into hosted work.</span>' +
|
||||
'<span>Keep licenses, refunds, privacy, and self-hosted billing in Account services instead of mixing them into workspace work.</span>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
|
@ -512,7 +512,7 @@ function renderAccountOverviewSection(account: PortalAccountSummary): string {
|
|||
renderSectionContextChips([
|
||||
String(totalCount) + ' total',
|
||||
String(readyCount) + ' ready',
|
||||
suspendedCount > 0 ? String(suspendedCount) + ' suspended' : 'Active fleet',
|
||||
suspendedCount > 0 ? String(suspendedCount) + ' suspended' : 'All active',
|
||||
]) +
|
||||
renderOverviewMetricStrip(totalCount, readyCount, checkingCount, unhealthyCount, suspendedCount) +
|
||||
'</div>' +
|
||||
|
|
@ -759,10 +759,10 @@ function renderAccountTeamSection(account: PortalAccountSummary): string {
|
|||
'<p>Use the roster as a controlled access list, not a dumping ground for vague shared access.</p>' +
|
||||
'</div>' +
|
||||
'<div class="team-review-grid">' +
|
||||
'<div class="team-review-card">' +
|
||||
'<strong>Owners stay rare</strong>' +
|
||||
'<span>Reserve Owner for billing, team, and full hosted control. Default to Admin, Tech, or Read-only first.</span>' +
|
||||
'</div>' +
|
||||
'<div class="team-review-card">' +
|
||||
'<strong>Owners stay rare</strong>' +
|
||||
'<span>Reserve Owner for billing, team, and full account control. Default to Admin, Tech, or Read-only first.</span>' +
|
||||
'</div>' +
|
||||
'<div class="team-review-card">' +
|
||||
'<strong>Keep access narrow</strong>' +
|
||||
'<span>Use Tech for workspace control and Read-only for verification instead of handing out broader access.</span>' +
|
||||
|
|
@ -786,11 +786,11 @@ function renderAccountTeamSection(account: PortalAccountSummary): string {
|
|||
'<div>' +
|
||||
'<div class="account-panel-kicker">Team management</div>' +
|
||||
'<h3>Account access</h3>' +
|
||||
'<p>Owners govern billing and access. Admins and techs keep hosted work moving day to day.</p>' +
|
||||
'<p>Owners govern billing and access. Admins and techs keep workspace operations moving day to day.</p>' +
|
||||
renderSectionContextChips([
|
||||
account.can_manage ? 'Managed roster' : 'View only',
|
||||
'Least privilege',
|
||||
'Hosted access',
|
||||
'Workspace access',
|
||||
]) +
|
||||
'</div>' +
|
||||
'<button type="button" class="btn-secondary btn-compact" data-shell-action="activate-section" data-shell-section="workspaces">Close team view</button>' +
|
||||
|
|
@ -1010,7 +1010,7 @@ export function renderAuthenticatedPortalHTML(context: ShellViewContext): string
|
|||
'<div class="service-shell-sidebar-head">' +
|
||||
'<div class="account-panel-kicker">Service navigator</div>' +
|
||||
'<h3>Self-hosted tools</h3>' +
|
||||
'<p>Pick one commercial request and keep it separate from hosted workspaces and team changes.</p>' +
|
||||
'<p>Pick one commercial request and keep it separate from workspace and team changes.</p>' +
|
||||
'</div>' +
|
||||
'<div class="service-action-list">' +
|
||||
renderServiceActionRow('open-manage-service', 'Billing', 'Manage subscriptions', 'Billing', 'Open Stripe for self-hosted plan, invoice, and payment changes.', 'manage-service-panel', 'manage-inline-email', ['Plan changes', 'Invoices']) +
|
||||
|
|
@ -1119,7 +1119,7 @@ export function renderSignedOutPortalHTML(context: ShellViewContext): string {
|
|||
'<section class="intro-card">' +
|
||||
'<div class="account-panel-kicker">Pulse Account</div>' +
|
||||
'<h1>Sign in to Pulse Account</h1>' +
|
||||
'<p>Use one commercial email address to get into hosted workspaces, MSP access, billing, license recovery, refunds, and privacy actions.</p>' +
|
||||
'<p>Use one commercial email address to get into workspaces, MSP access, billing, license recovery, refunds, and privacy actions.</p>' +
|
||||
'</section>' +
|
||||
'<section class="service-section service-section-auth">' +
|
||||
'<div class="service-panel visible auth-panel">' +
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue