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
55 changes: 45 additions & 10 deletions apps/app/src/directory-settings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from "react";
import { type ReactNode, useState } from "react";

import { Button, Input } from "@ace/ui";
import type { Diagnostics } from "@ace/host/protocol";
Expand All @@ -9,6 +9,13 @@ import { Confirm, Group, Page, Problem, Row, Status, Value } from "./settings-la

const SETUP = "https://github.com/githubnext/ace/blob/main/docs/setup.md#team-directory";

/** What each service the directory can name offers, since an unnamed one leaves no trace elsewhere. */
const services = [
{ key: "hosted", label: "Hosted channels", offers: "Move to cloud in a channel's menu" },
{ key: "app", label: "Web app", offers: "Ace in a browser on other devices" },
{ key: "compute", label: "Cloud compute", offers: "Run in cloud for new channels" },
] as const;

const secrets = {
keychain: "Saved in Keychain",
environment: "From the environment",
Expand Down Expand Up @@ -55,6 +62,9 @@ export function TeamSettings({ active }: { active: boolean }) {
</>
)}
</Group>
{checked?.directory.url && checked.directory.synced && (
<TeamServices services={checked.directory.services} />
)}
{!checks.open
? <Status>Waiting for Ace Helper…</Status>
: !checked && !checks.error && <Status>Checking…</Status>}
Expand All @@ -63,6 +73,39 @@ export function TeamSettings({ active }: { active: boolean }) {
);
}

function Setup({ children }: { children: ReactNode }) {
return (
<a
href={SETUP}
target="_blank"
rel="noopener noreferrer"
className="rounded-sm underline outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/30"
>
{children}
</a>
);
}

/** Which services the joined directory names; whoever deployed it sets the rest up. */
function TeamServices({ services: named }: { services: Diagnostics["directory"]["services"] }) {
return (
<Group title="Team services">
{services.map(({ key, label, offers }) => (
<Row key={key} label={label} description={offers}>
<Value>{named[key] ? URL.parse(named[key])?.host || named[key] : "Not set up"}</Value>
</Row>
))}
{services.some(({ key }) => !named[key]) && (
<div className="py-3">
<Status>
Whoever deployed the directory can add the rest. <Setup>Set up team services</Setup>
</Status>
</div>
)}
</Group>
);
}

/** A time today, or a date and time when older, so a stale sync doesn't read as recent. */
function when(time: number) {
const date = new Date(time);
Expand Down Expand Up @@ -127,15 +170,7 @@ function TeamDirectory(
label="Directory"
description={directory.url || (
<>
Not joined.{" "}
<a
href={SETUP}
target="_blank"
rel="noopener noreferrer"
className="rounded-sm underline outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/30"
>
Set up a directory
</a>
Not joined. <Setup>Set up a directory</Setup>
</>
)}
footer={
Expand Down
3 changes: 2 additions & 1 deletion apps/host/src/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ export async function diagnostics(sync?: boolean): Promise<Diagnostics> {
Promise.all([git(), shell()]),
tailnet.diagnostics(),
]);
const { hosted, app, compute } = directory.read();
return {
tools,
tailscale: config.loopback ? { ...tailscale, loopback: true } : tailscale,
directory: { ...directory.status(), secret: await secret },
directory: { ...directory.status(), secret: await secret, services: { hosted, app, compute } },
shell: { ...environment },
};
}
2 changes: 2 additions & 0 deletions apps/host/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export type Diagnostics = {
error?: string;
failed?: number;
secret: CredentialStatus;
/** The team services the directory named in its last answer; an unnamed one is not set up. */
services: { hosted?: string; app?: string; compute?: string };
};
/** Whether the helper loaded the login shell's environment; `pending` while it retries. */
shell: { state: "adopted" | "pending" | "failed"; error?: string };
Expand Down
2 changes: 1 addition & 1 deletion docs/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ for s in channel directory; do (cd services/$s && bunx wrangler deploy && printf
```

Then name the other services in the directory, from `services/directory`, so every host that joins
picks them up:
picks them up. `Settings → Team → Team services` shows which ones a host's directory names:

- `HOSTED`: the channel service (`https://ace-channel.<your-subdomain>.workers.dev`), offered in a
channel's `Move to` menu.
Expand Down