mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-06-02 07:10:00 +00:00
Keep portal overview ready state honest
This commit is contained in:
parent
4c41103cf0
commit
59bf0c9cee
7 changed files with 89 additions and 7 deletions
|
|
@ -244,6 +244,11 @@ Core rules:
|
|||
not leak raw transport strings such as `Network error.` into `Access`,
|
||||
`Workspaces`, or `Billing`; each failure must stay on the task-specific
|
||||
action the user was trying to complete.
|
||||
36. `Overview` must keep `Ready` honest when no hosted workspace exists yet.
|
||||
Hosted accounts with zero workspaces may not tell the user to review
|
||||
current workspace state; they must say that nothing is ready yet and that
|
||||
the first hosted workspace still needs owner/admin creation before routine
|
||||
work can start.
|
||||
|
||||
## Screen Model
|
||||
|
||||
|
|
|
|||
|
|
@ -337,6 +337,10 @@ That same shared request/runtime boundary must also preserve task-specific
|
|||
failure copy on transport errors: portal job surfaces may not leak raw strings
|
||||
such as `Network error.`, and must instead surface the owned fallback for the
|
||||
exact action that failed.
|
||||
That same typed overview contract must also keep `Ready` honest when no hosted
|
||||
workspace exists yet: hosted accounts with zero workspaces may not route the
|
||||
user into current workspace review, and must instead render that nothing is
|
||||
ready until the first hosted workspace exists.
|
||||
plus a package-local `tsc --noEmit` gate, so future account-shell work should
|
||||
extend the typed source boundary instead of reviving opaque global runtime
|
||||
objects, document-wide render events, or untyped embedded asset edits.
|
||||
|
|
|
|||
|
|
@ -898,6 +898,10 @@ That same owned task surface must also keep failure copy on the user job
|
|||
instead of leaking raw transport wording: `Access`, `Workspaces`, and
|
||||
`Billing` failures must render the task-specific action that could not
|
||||
complete, not generic copy such as `Network error.`.
|
||||
That same owned `Overview` surface must also keep `Ready` honest when no
|
||||
hosted workspace exists yet: hosted accounts with zero workspaces may not tell
|
||||
the user to review current workspace state, and must instead say that nothing
|
||||
is ready yet until the first hosted workspace exists.
|
||||
That same canonical shell/runtime boundary now also owns the bootstrap truth
|
||||
for when self-hosted commercial history is relevant. Hosted-only accounts must
|
||||
not render self-hosted license, refund, privacy, or support-escalation copy
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"source_hash": "d515bbe22da7a6154237402934adaefe1e896687914a72d8bf36587689abf31a",
|
||||
"source_hash": "2b04882678dc1fd7fd9160747d190ba62581f1c44ab3a6632f04a0c55756b78f",
|
||||
"build_inputs": [
|
||||
"package.json",
|
||||
"tsconfig.json",
|
||||
|
|
|
|||
10
internal/cloudcp/portal/dist/portal_app.js
vendored
10
internal/cloudcp/portal/dist/portal_app.js
vendored
|
|
@ -2232,9 +2232,15 @@
|
|||
function renderOverviewReadyCard(accounts, entries, accountAPIBasePath) {
|
||||
var ready = readyOverviewEntries(entries);
|
||||
var includeAccountName = accounts.length > 1;
|
||||
var totalWorkspaces = countWorkspaces(accounts);
|
||||
var canManageHosted = accounts.some(function(account) {
|
||||
return account.can_manage;
|
||||
});
|
||||
if (!ready.length) {
|
||||
return '<article class="overview-task-card"><div class="account-panel-kicker">Ready</div><h4>' + escapeHTML(accounts.length > 0 ? "No workspace is ready yet" : "Billing tools are ready") + "</h4><p>" + escapeHTML(
|
||||
accounts.length > 0 ? "Use Workspaces to review current state before you start routine work." : "Use Billing for self-hosted subscriptions, licenses, refunds, and privacy requests."
|
||||
return '<article class="overview-task-card"><div class="account-panel-kicker">Ready</div><h4>' + escapeHTML(
|
||||
!accounts.length ? "Billing tools are ready" : totalWorkspaces > 0 ? "No workspace is ready yet" : "Nothing is ready yet"
|
||||
) + "</h4><p>" + escapeHTML(
|
||||
!accounts.length ? "Use Billing for self-hosted subscriptions, licenses, refunds, and privacy requests." : totalWorkspaces > 0 ? "Use Workspaces to review current state before you start routine work." : canManageHosted ? "The first hosted workspace still needs to be created before routine work can start." : "An owner or admin still needs to create the first hosted workspace before routine work can start."
|
||||
) + "</p></article>";
|
||||
}
|
||||
return '<article class="overview-task-card"><div class="account-panel-kicker">Ready</div><h4>Open and work</h4><p>These workspaces are active and healthy right now.</p><div class="overview-task-list">' + ready.slice(0, 3).map(function(entry) {
|
||||
|
|
|
|||
|
|
@ -478,6 +478,56 @@ describe('shell view', function() {
|
|||
expect(html).not.toContain('If this is an access change, go to Access. If it is a billing or license issue, go to Billing. Support is only for escalation.');
|
||||
});
|
||||
|
||||
it('keeps ready state honest for hosted view-only accounts with no workspace yet', function() {
|
||||
var html = renderAuthenticatedPortalHTML(
|
||||
createContext({
|
||||
bootstrap: createBootstrap({
|
||||
accounts: [
|
||||
{
|
||||
id: 'acct_view_empty',
|
||||
name: 'Empty Hosted Account',
|
||||
kind: 'cloud',
|
||||
kind_label: 'Cloud',
|
||||
role: 'read_only',
|
||||
can_manage: false,
|
||||
has_billing: true,
|
||||
workspaces: [],
|
||||
},
|
||||
],
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
expect(html).toContain('Nothing is ready yet');
|
||||
expect(html).toContain('An owner or admin still needs to create the first hosted workspace before routine work can start.');
|
||||
expect(html).not.toContain('Use Workspaces to review current state before you start routine work.');
|
||||
});
|
||||
|
||||
it('keeps ready state honest for managed hosted accounts with no workspace yet', function() {
|
||||
var html = renderAuthenticatedPortalHTML(
|
||||
createContext({
|
||||
bootstrap: createBootstrap({
|
||||
accounts: [
|
||||
{
|
||||
id: 'acct_manage_empty',
|
||||
name: 'Managed Empty Account',
|
||||
kind: 'msp',
|
||||
kind_label: 'MSP',
|
||||
role: 'owner',
|
||||
can_manage: true,
|
||||
has_billing: true,
|
||||
workspaces: [],
|
||||
},
|
||||
],
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
expect(html).toContain('Nothing is ready yet');
|
||||
expect(html).toContain('The first hosted workspace still needs to be created before routine work can start.');
|
||||
expect(html).not.toContain('Use Workspaces to review current state before you start routine work.');
|
||||
});
|
||||
|
||||
it('keeps next action on review surfaces for suspended hosted view-only accounts', function() {
|
||||
var html = renderAuthenticatedPortalHTML(
|
||||
createContext({
|
||||
|
|
|
|||
|
|
@ -678,14 +678,27 @@ function renderOverviewReadyCard(
|
|||
): string {
|
||||
var ready = readyOverviewEntries(entries);
|
||||
var includeAccountName = accounts.length > 1;
|
||||
var totalWorkspaces = countWorkspaces(accounts);
|
||||
var canManageHosted = accounts.some(function(account) {
|
||||
return account.can_manage;
|
||||
});
|
||||
if (!ready.length) {
|
||||
return (
|
||||
'<article class="overview-task-card">' +
|
||||
'<div class="account-panel-kicker">Ready</div>' +
|
||||
'<h4>' + escapeHTML(accounts.length > 0 ? 'No workspace is ready yet' : 'Billing tools are ready') + '</h4>' +
|
||||
'<p>' + escapeHTML(accounts.length > 0
|
||||
? 'Use Workspaces to review current state before you start routine work.'
|
||||
: 'Use Billing for self-hosted subscriptions, licenses, refunds, and privacy requests.'
|
||||
'<h4>' + escapeHTML(!accounts.length
|
||||
? 'Billing tools are ready'
|
||||
: totalWorkspaces > 0
|
||||
? 'No workspace is ready yet'
|
||||
: 'Nothing is ready yet'
|
||||
) + '</h4>' +
|
||||
'<p>' + escapeHTML(!accounts.length
|
||||
? 'Use Billing for self-hosted subscriptions, licenses, refunds, and privacy requests.'
|
||||
: totalWorkspaces > 0
|
||||
? 'Use Workspaces to review current state before you start routine work.'
|
||||
: canManageHosted
|
||||
? 'The first hosted workspace still needs to be created before routine work can start.'
|
||||
: 'An owner or admin still needs to create the first hosted workspace before routine work can start.'
|
||||
) + '</p>' +
|
||||
'</article>'
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue