Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"Antiforgery",
"Cronos",
"Npgsql",
"Prerender",
"prerendered",
"Sheddueller",
"Shouldly",
"Upserted",
Expand Down
1 change: 1 addition & 0 deletions samples/Sheddueller.SampleHost/LauncherPageRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public static string Render(string? statusMessage)
AppendActionCard(builder, "/launch/retry-then-succeed", "Retry then succeed", "Fails twice, then succeeds so retry history is visible.", "Enqueue job");
AppendActionCard(builder, "/launch/permanent-failure", "Permanent failure", "Fails terminally without retries.", "Enqueue job");
AppendActionCard(builder, "/launch/delayed", "Delayed job", "Queues a short delayed job to exercise delayed state and not-before time.", "Enqueue job");
AppendActionCard(builder, "/launch/many-tags", "Many tags", "Queues a tagged job with informational tags first and ceremonial tags later.", "Enqueue job");
AppendActionCard(builder, "/launch/blocking-batch", "Concurrency batch", "Sets a shared group limit to 1 and enqueues several long jobs.", "Enqueue batch");
AppendActionCard(builder, "/launch/idempotent", "Idempotent reprice", "Queues one reprice-listing-3 job behind a held group slot; click twice quickly to reuse the queued job.", "Enqueue job");
AppendActionCard(builder, "/launch/cancelable", "Cancelable delayed job", "Creates a delayed queued job that can be canceled from the dashboard.", "Enqueue job");
Expand Down
26 changes: 25 additions & 1 deletion samples/Sheddueller.SampleHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
options.HeartbeatInterval = TimeSpan.FromSeconds(5);
options.DefaultRetryPolicy = new RetryPolicy(3, RetryBackoffKind.Fixed, TimeSpan.FromSeconds(2));
}));
builder.Services.AddShedduellerDashboard(options => options.EventRetention = TimeSpan.FromDays(14));
builder.Services.AddShedduellerDashboard(options =>
{
options.EventRetention = TimeSpan.FromDays(14);
options.TagDisplayOrder = ["tenant", "listing", "domain", "workflow", "source", "demo"];
});

var app = builder.Build();

Expand Down Expand Up @@ -92,6 +96,26 @@
return RedirectWithMessage($"Queued delayed job {jobId:D} for {notBeforeUtc:O}.");
});

app.MapPost("/launch/many-tags", async (IJobEnqueuer enqueuer, CancellationToken cancellationToken) =>
{
var jobId = await enqueuer.EnqueueAsync<DemoJobService>(
(service, ct) => service.RunProgressAsync("many-tags-demo", Job.Context, ct),
new JobSubmission(
Priority: 15,
Tags:
[
new JobTag("tenant", "acme"),
new JobTag("listing", "villa-8842"),
new JobTag("domain", "pricing"),
new JobTag("workflow", "rate-refresh"),
new JobTag("source", "sample-host"),
new JobTag("demo", "many-tags"),
new JobTag("ceremony", "dashboard-overflow"),
]),
cancellationToken).ConfigureAwait(false);
return RedirectWithMessage($"Queued many-tags demo job {jobId:D}.");
});

app.MapPost("/launch/blocking-batch", async (
IConcurrencyGroupManager concurrencyGroupManager,
IJobEnqueuer enqueuer,
Expand Down
58 changes: 55 additions & 3 deletions src/Sheddueller.Dashboard/Components/ChipList.razor
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
}
else
{
@foreach (var value in Values)
@for (var i = 0; i < VisibleCount; i++)
{
var value = Values[i];
@if (HrefFactory is null)
{
<span class="@ChipClass" @key="value" title="@value">@value</span>
Expand All @@ -17,6 +18,27 @@
aria-label="@GetLinkAriaLabel(value)">@value</a>
}
}
@if (HiddenCount > 0)
{
<span class="@OverflowClass">
<button class="@OverflowTriggerClass" type="button" title="@Title" aria-label="@OverflowAriaLabel" aria-haspopup="true">@OverflowText</button>
<span class="@OverflowPanelClass" aria-label="@OverflowAriaLabel">
@for (var i = VisibleCount; i < Values.Count; i++)
{
var value = Values[i];
@if (HrefFactory is null)
{
<span class="@OverflowItemClass" @key="value" title="@value">@value</span>
}
else
{
<a class="@OverflowItemClass" @key="value" href="@HrefFactory(value)" title="@value"
aria-label="@GetLinkAriaLabel(value)">@value</a>
}
}
</span>
</span>
}
}
</div>

Expand All @@ -39,15 +61,45 @@
[Parameter]
public string? LinkAriaLabelPrefix { get; set; }

[Parameter]
public int MaxVisible { get; set; } = int.MaxValue;

[Parameter]
public string OverflowAriaLabelPrefix { get; set; } = "Additional values";

private int VisibleCount
=> Math.Clamp(this.MaxVisible, 0, this.Values.Count);

private int HiddenCount
=> this.Values.Count - this.VisibleCount;

private string ListClass
=> string.Concat(this.ClassPrefix, "-list");
=> string.Concat("sd-chip-list ", this.ClassPrefix, "-list");

private string ChipClass
=> this.ClassPrefix;
=> string.Concat("sd-chip ", this.ClassPrefix);

private string EmptyClass
=> string.Concat(this.ClassPrefix, "-empty");

private string OverflowClass
=> string.Concat("sd-chip-overflow ", this.ClassPrefix, "-overflow");

private string OverflowTriggerClass
=> string.Concat(this.ChipClass, " ", this.ClassPrefix, "--overflow sd-chip-overflow__summary");

private string OverflowPanelClass
=> string.Concat("sd-chip-overflow__panel ", this.ClassPrefix, "-overflow-panel");

private string OverflowItemClass
=> string.Concat("sd-chip-overflow__item ", this.ClassPrefix, "-overflow-item");

private string OverflowAriaLabel
=> string.Concat(this.OverflowAriaLabelPrefix, ": ", this.Title);

private string OverflowText
=> string.Create(CultureInfo.InvariantCulture, $"+{this.HiddenCount}");

private string? GetLinkAriaLabel(string value)
=> string.IsNullOrWhiteSpace(this.LinkAriaLabelPrefix)
? null
Expand Down
4 changes: 4 additions & 0 deletions src/Sheddueller.Dashboard/Components/DashboardApp.razor
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&amp;family=Space+Grotesk:wght@400;500;600;700&amp;display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/uplot@1.6.32/dist/uPlot.min.css" rel="stylesheet" />
<link href="_content/Sheddueller.Dashboard/vendor/prism/prism.css" rel="stylesheet" />
<link href="_content/Sheddueller.Dashboard/vendor/prism/prism-dark.css" rel="stylesheet" media="(prefers-color-scheme: dark)" />
</head>
<body>
<Routes @rendermode="DashboardRenderMode" />
<script src="https://cdn.jsdelivr.net/npm/uplot@1.6.32/dist/uPlot.iife.min.js"></script>
<script src="_content/Sheddueller.Dashboard/vendor/prism/prism.js" data-manual></script>
<script src="_content/Sheddueller.Dashboard/vendor/prism/sheddueller-prism.js"></script>
<script src="_content/Sheddueller.Dashboard/vendor/sheddueller-throughput-chart.js"></script>
<script src="_framework/blazor.web.js"></script>
</body>
</html>
Expand Down
73 changes: 73 additions & 0 deletions src/Sheddueller.Dashboard/Components/DashboardLayout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,79 @@
color: inherit;
}

.sd-chip-list {
position: relative;
overflow: visible;
}

.sd-chip-list .sd-chip {
max-width: 180px;
flex: 0 0 auto;
}

.sd-chip-overflow {
position: relative;
display: inline-flex;
flex: 0 0 auto;
}

.sd-chip-overflow__summary {
display: inline-flex;
min-width: 30px;
max-width: none;
appearance: none;
align-items: center;
justify-content: center;
cursor: pointer;
font: inherit;
}

.sd-chip-overflow:hover .sd-chip-overflow__summary,
.sd-chip-overflow:focus-within .sd-chip-overflow__summary {
border-color: var(--sd-primary);
color: var(--sd-primary);
}

.sd-chip-overflow__panel {
position: absolute;
top: 100%;
right: 0;
z-index: 30;
display: none;
min-width: 220px;
max-width: min(420px, 70vw);
gap: 2px;
border: 1px solid var(--sd-outline-variant);
border-radius: 4px;
background: var(--sd-surface-lowest);
box-shadow: 0 12px 28px rgb(0 0 0 / 30%);
padding: 10px 6px 6px;
white-space: normal;
}

.sd-chip-overflow:hover .sd-chip-overflow__panel,
.sd-chip-overflow:focus-within .sd-chip-overflow__panel {
display: grid;
}

.sd-chip-overflow__item {
display: block;
overflow-wrap: anywhere;
border-radius: 2px;
color: var(--sd-on-surface);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 11px;
line-height: 16px;
padding: 4px 6px;
text-decoration: none;
white-space: normal;
}

a.sd-chip-overflow__item:hover {
background: var(--sd-surface-low);
color: var(--sd-primary);
}

button,
input,
select {
Expand Down
19 changes: 16 additions & 3 deletions src/Sheddueller.Dashboard/Components/Pages/JobDetail.razor
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@
</div>
<span class="job-detail-mono job-detail-muted">@DashboardFormat.Utc(GetStartedAt(_detail))</span>
</div>
<div class="job-detail-timestamp-pair">
<div>
<span>Run Time:</span>
<strong class="job-detail-inline-duration">@DashboardFormat.RunTime(_detail)</strong>
</div>
<span class="job-detail-mono job-detail-muted">@DashboardFormat.Utc(DashboardFormat.TerminalTimestamp(job))</span>
</div>
</div>

<div class="job-detail-summary-block job-detail-summary-block--ruled">
Expand Down Expand Up @@ -195,9 +202,8 @@

<div class="job-detail-chip-section">
<span class="job-detail-label">Tags</span>
<ChipList ClassPrefix="job-detail-chip" Values="DashboardFormat.Tags(job.Tags)"
Title="@DashboardFormat.TagsTitle(job.Tags)" HrefFactory="TagFilterHref"
LinkAriaLabelPrefix="Filter jobs by tag" />
<TagChipList ClassPrefix="job-detail-chip" Tags="job.Tags" HrefFactory="TagFilterHref"
LinkAriaLabelPrefix="Filter jobs by tag" />
</div>

<div class="job-detail-chip-section">
Expand Down Expand Up @@ -622,6 +628,7 @@
.job-detail-metadata-item strong,
.job-detail-chip,
.job-detail-invocation-call,
.job-detail-inline-duration,
.job-detail-parameter pre,
.job-detail-progress-percent,
.job-detail-log-table,
Expand Down Expand Up @@ -1028,18 +1035,24 @@
margin: 0;
border: 1px solid var(--sd-outline-variant);
border-radius: 2px;
background: var(--sd-surface-container);
box-shadow: none;
color: var(--sd-on-surface);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 13px;
line-height: 20px;
padding: 10px;
text-shadow: none;
white-space: pre-wrap;
overflow-wrap: anywhere;
}

pre.job-detail-invocation-call[class*="language-"] > code[class*="language-"] {
display: block;
background: transparent;
color: inherit;
font: inherit;
text-shadow: none;
white-space: inherit;
overflow-wrap: inherit;
}
Expand Down
Loading