Fix medium issues: user ID display, mirror toast, post-seal guidance
Fix #14 — User ID hash display: Add formatActor() to bundle-version-detail that truncates raw hex hashes to "User 209d1257..." instead of showing the full 32-char ID. Short IDs, emails, and names pass through unchanged. Fix #15 — Mirror generate-immediately silent failure: When domain creation succeeds but bundle generation fails, show a meaningful status message instead of silently swallowing the error: "Generation failed — the domain was created but the initial bundle could not be generated. You can retry from the mirror dashboard." Fix #19 — Wizard error handling: Already implemented — topology wizard sets wizard.error signal on all CRUD failures and displays error banner. No additional changes needed. Fix #21 — Post-seal guidance: After sealing a release (source=release-create query param), show a "What's next?" panel with links to: Promote to environment, Review approvals, Back to versions. Uses branded action buttons. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,7 @@ import {
|
||||
</article>
|
||||
<article>
|
||||
<h2>Created by</h2>
|
||||
<p>{{ versionDetailModel.createdBy }}</p>
|
||||
<p>{{ formatActor(versionDetailModel.createdBy) }}</p>
|
||||
</article>
|
||||
<article>
|
||||
<h2>Promotion readiness</h2>
|
||||
@@ -49,6 +49,17 @@ import {
|
||||
</article>
|
||||
</section>
|
||||
|
||||
@if (showPostSealGuide()) {
|
||||
<section class="bvd__post-seal" aria-label="Next steps">
|
||||
<h3>Release sealed successfully. What's next?</h3>
|
||||
<div class="bvd__post-seal-actions">
|
||||
<a [routerLink]="['/releases/promotions']" queryParamsHandling="merge" class="bvd__action-link">Promote to environment</a>
|
||||
<a [routerLink]="['/releases/approvals']" queryParamsHandling="merge" class="bvd__action-link">Review approvals</a>
|
||||
<a [routerLink]="['/releases/versions']" queryParamsHandling="merge" class="bvd__action-link">Back to versions</a>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
<div class="bvd__tabs" role="tablist">
|
||||
<button role="tab" [class.tab--active]="activeTab() === 'components'" (click)="setTab('components')">Components</button>
|
||||
<button role="tab" [class.tab--active]="activeTab() === 'validation'" (click)="setTab('validation')">Validation</button>
|
||||
@@ -207,6 +218,36 @@ import {
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
.bvd__post-seal {
|
||||
padding: 1rem 1.25rem;
|
||||
border: 1px solid var(--color-brand-primary, #6366f1);
|
||||
border-radius: 8px;
|
||||
background: var(--color-surface-secondary, #f8fafc);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.bvd__post-seal h3 {
|
||||
margin: 0 0 0.75rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.bvd__post-seal-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.bvd__action-link {
|
||||
padding: 0.45rem 1rem;
|
||||
border-radius: 6px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
background: var(--color-brand-primary, #6366f1);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.bvd__tabs {
|
||||
display: flex;
|
||||
border-bottom: 2px solid var(--color-border, #e5e7eb);
|
||||
@@ -366,6 +407,7 @@ export class BundleVersionDetailComponent implements OnInit {
|
||||
readonly versionId = signal('');
|
||||
readonly activeTab = signal<'components' | 'validation' | 'releases'>('components');
|
||||
readonly loading = signal(true);
|
||||
readonly showPostSealGuide = signal(false);
|
||||
readonly errorMessage = signal<string | null>(null);
|
||||
readonly versionDetail = signal<ReleaseControlBundleVersionDetailDto | null>(null);
|
||||
readonly materializing = signal(false);
|
||||
@@ -379,6 +421,12 @@ export class BundleVersionDetailComponent implements OnInit {
|
||||
this.route.snapshot.params['versionId'] ?? this.route.snapshot.params['version'] ?? ''
|
||||
);
|
||||
|
||||
// Show post-seal guidance when arriving from the release creation wizard
|
||||
const source = this.route.snapshot.queryParams['source'];
|
||||
if (source === 'release-create') {
|
||||
this.showPostSealGuide.set(true);
|
||||
}
|
||||
|
||||
if (!this.bundleId() || !this.versionId()) {
|
||||
this.loading.set(false);
|
||||
this.errorMessage.set('Bundle or version id is missing from route.');
|
||||
@@ -435,6 +483,16 @@ export class BundleVersionDetailComponent implements OnInit {
|
||||
return `${digest.slice(0, 20)}...`;
|
||||
}
|
||||
|
||||
formatActor(actorId: string): string {
|
||||
if (!actorId) return 'Unknown';
|
||||
// Short readable IDs or well-known names pass through
|
||||
if (actorId.length <= 20 || actorId.includes('@') || actorId.includes(' ')) {
|
||||
return actorId;
|
||||
}
|
||||
// Raw hex hashes get truncated with a user indicator
|
||||
return `User ${actorId.slice(0, 8)}...`;
|
||||
}
|
||||
|
||||
promotionReadiness(status: string): string {
|
||||
return status.toLowerCase() === 'published'
|
||||
? 'Ready after validation and materialization checks.'
|
||||
|
||||
@@ -1446,7 +1446,13 @@ export class MirrorDomainBuilderComponent implements OnInit {
|
||||
this.creating.set(false);
|
||||
},
|
||||
error: () => {
|
||||
// Domain was created but generate failed -- still show success
|
||||
// Domain was created but generate failed
|
||||
this.generateResult.set({
|
||||
domainId: domain.domainId,
|
||||
jobId: 'failed',
|
||||
status: 'Generation failed — the domain was created but the initial bundle could not be generated. You can retry from the mirror dashboard.',
|
||||
startedAt: new Date().toISOString(),
|
||||
});
|
||||
this.creating.set(false);
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user