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
6 changes: 4 additions & 2 deletions src/api/InstatusApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,16 @@ export class InstatusApi {
if (!res.ok) {
throw new Error(`Failed to fetch incident: ${res.status}`);
}
return res.json();
const data: { incident: Incident } = await res.json();
return data.incident;
}

public async getMaintenance(id: string): Promise<Maintenance> {
const res = await fetch(new URL(`maintenances/${id}`, this.base));
if (!res.ok) {
throw new Error(`Failed to fetch maintenance: ${res.status}`);
}
return res.json();
const data: { maintenance: Maintenance } = await res.json();
return data.maintenance;
}
}
2 changes: 1 addition & 1 deletion src/components/AppHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class AppHeader extends Component {
public links: SiteLink[] = [];

public override render() {
const logoHref = this.home ? this.websiteUrl : "/";
const logoHref = this.home ? this.websiteUrl ?? "/" : "/";

return html`
<header
Expand Down
13 changes: 8 additions & 5 deletions src/components/AppRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { HomePage } from "./pages/HomePage";
import { Services } from "../models/Services";
import { Service } from "../models/Service";
import { ServiceGroup } from "../models/ServiceGroup";
import { NoticePage } from "./pages/NoticePage";

@customElement("app-root")
export class AppRoot extends Component {
Expand All @@ -27,9 +28,6 @@ export class AppRoot extends Component {
@state()
private page!: Page;

@state()
private home!: boolean;

private services!: Promise<Services>;

public constructor(api: InstatusApi) {
Expand Down Expand Up @@ -69,9 +67,14 @@ export class AppRoot extends Component {
let initial = true;
this.router
.on("/", () => {
this.home = true;
this.page = new HomePage(this.api, this.services);
})
.on("/incidents/:id", (match) => {
this.page = new NoticePage("incidents", match!.data!.id, this.api);
})
.on("/maintenance/:id", (match) => {
this.page = new NoticePage("maintenance", match!.data!.id, this.api);
})
.on("*", () => {
this.router.navigate("/");
})
Expand Down Expand Up @@ -101,7 +104,7 @@ export class AppRoot extends Component {
.logoAlt="${this.site.name.default}"
.websiteUrl="${this.site.websiteUrl}"
.links="${this.site.links.header}"
.home="${this.home}"
.home="${this.page instanceof HomePage}"
></app-header>
<div class="flex-1">
<main
Expand Down
24 changes: 13 additions & 11 deletions src/components/NoticeOverview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Maintenance } from "../models/Maintenance";
@customElement("notice-overview")
export class NoticeOverview extends Component {
@state()
private notice: Notice;
private readonly notice: Notice;

public constructor(notice: Notice) {
super();
Expand All @@ -24,13 +24,17 @@ export class NoticeOverview extends Component {
: new Time.DateTime(this.notice.ended);
const duration = new Time.Duration(this.notice.duration());

const nbsp = "\u00A0";

return html`
<div class="relative">
<div class="flex items-center justify-between mb-2">
<div>
<div class="flex flex-row-reverse items-center justify-end gap-3">
<a
href="/notices/${this.notice.id}"
href="/${this.notice instanceof Maintenance
? "maintenance"
: "incidents"}/${this.notice.id}"
class="text-lg font-medium text-white"
>
${this.notice.name}<span class="absolute inset-0"></span>
Expand Down Expand Up @@ -67,19 +71,17 @@ export class NoticeOverview extends Component {
? html`
<p class="text-sm leading-loose text-neutral-400">
Scheduled for
<time datetime="${start.toISOString()}">${start
.toString()}
</time>
&nbsp;–&nbsp;<time
<time datetime="${start.toISOString()}">${start.toString()
.replace(" ", nbsp)}</time>${nbsp}–${nbsp}<time
datetime="${end.toISOString()}"
>${end.getDay().is(start.getDay())
? end.toTimeString()
: end.toString()}
</time>
<span
: end.toString().replace(" ", nbsp)}</time>
<time
class="rounded-full bg-white/10 px-2 py-0.5 ring-1 ring-white/10 ring-inset"
><time datetime="${duration.toISOString()}">${duration
.toString()}</time></span>
datetime="${duration.toISOString()}"
>${duration
.toString()}</time>
</p>
`
: nothing}
Expand Down
10 changes: 8 additions & 2 deletions src/components/ServiceDayTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Notice } from "../models/Notice";
import { ServiceStatus } from "../models/ServiceStatus";
import { Time } from "../Time";
import { EnumMappings } from "../EnumMappings";
import { Maintenance } from "../models/Maintenance";

@customElement("service-day-tooltip")
export class ServiceDayTooltip extends Component {
Expand Down Expand Up @@ -85,7 +86,9 @@ export class ServiceDayTooltip extends Component {
>${style.label}</span>
</div>
<a
href="/notices/${n.id}"
href="/${n instanceof Maintenance
? "maintenance"
: "incidents"}/${n.id}"
class="font-medium text-white focus-visible:outline-none"
>
${n.name}
Expand All @@ -98,7 +101,10 @@ export class ServiceDayTooltip extends Component {
n.ended.getTime() > now.getTime()
? EnumMappings.NOTICE_STATUS_NAMES[n.status]
: html`
Resolved after <time datetime="${duration
${EnumMappings
.NOTICE_STATUS_NAMES[
n.status
]} after <time datetime="${duration
.toISOString()}">
${duration.toString()}
</time>
Expand Down
6 changes: 3 additions & 3 deletions src/components/UpdatesFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ export class UpdatesFeed extends Component {
html`
<li class="group/update flex">
<div class="relative group-only/update:hidden">
<div class="absolute h-full w-px bg-white/5 group-last/update:h-4"></div>
<div class="absolute h-full w-px bg-white/10 group-last/update:h-4"></div>
<div
class="relative mt-4 flex size-6 -translate-x-1/2 items-center justify-center bg-neutral-900 group-first/update:mt-0"
class="relative mt-4 flex size-6 -translate-x-1/2 items-center justify-center bg-neutral-950 group-first/update:mt-0 sm:bg-neutral-900"
>
<div class="size-1.5 rounded-full bg-white/5 ring-1 ring-white/10"></div>
<div class="size-1.5 rounded-full bg-white/10 ring-1 ring-white/15"></div>
</div>
</div>
<div class="py-4 group-first/update:pt-0 group-last/update:pb-0">
Expand Down
43 changes: 3 additions & 40 deletions src/components/pages/HomePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { Services } from "../../models/Services";
import { InstatusApi } from "../../api/InstatusApi";
import { Notice } from "../../models/Notice";
import { Incident } from "../../models/Incident";
import { Service } from "../../models/Service";
import { NoticeUpdate } from "../../models/NoticeUpdate";
import { Maintenance } from "../../models/Maintenance";
import { ActiveNotices } from "../ActiveNotices";

Expand Down Expand Up @@ -67,24 +65,7 @@ export class HomePage extends Page {
this.notices = [];

for (const i of incidents) {
const incident = new Incident(
i.id,
typeof i.name === "string" ? i.name : i.name.default,
i.components,
i.updates.map((u) =>
new NoticeUpdate(
u.id,
new Date(u.started),
Incident.parseStatus(u.status),
typeof u.message === "string" ? u.message : u.message.default,
)
),
Incident.parseStatus(i.status),
new Date(i.started),
i.resolved === null ? null : new Date(i.resolved),
Service.parseStatus(i.impact),
);

const incident = Incident.fromAPI(i);
this.notices.push(incident);

for (const affected of i.components) {
Expand All @@ -95,26 +76,7 @@ export class HomePage extends Page {
}

for (const m of maintenances) {
const maintenance = new Maintenance(
m.id,
typeof m.name === "string" ? m.name : m.name.default,
m.components,
m.updates.map((u) =>
new NoticeUpdate(
u.id,
new Date(u.started),
Maintenance.parseStatus(u.status),
typeof u.message === "string" ? u.message : u.message.default,
)
),
Maintenance.parseStatus(m.status),
new Date(m.start),
new Date(
m.resolved === null
? new Date(m.start).getTime() + (m.duration * 60000)
: m.resolved,
),
);
const maintenance = Maintenance.fromAPI(m);
this.notices.push(maintenance);

for (const affected of m.components) {
Expand All @@ -126,6 +88,7 @@ export class HomePage extends Page {
}

public override render() {
this.pageTitle(null);
return html`
${new ActiveNotices(this.notices ?? [])}
<div class="flex flex-col">
Expand Down
Loading