Project settings say who created the project, by name
1 file+21−50/1 viewed
| 10 | 10 | import { Button, ErrorText, Field, Input, TimeAgo } from "../../components/ui"; | |
| 11 | 11 | import { RadioGroup, RadioOption } from "../../components/ui/radio-group"; | |
| 12 | 12 | import { DEPLOYS_CHOICES } from "../../lib/project-kind"; | |
| 13 | − | import { deployments, projects } from "../../lib/services.server"; | |
| 13 | + | import { deployments, identity, projects } from "../../lib/services.server"; | |
| 14 | 14 | import { assertSameOrigin, getViewer, requireUser, unwrap } from "../../lib/session.server"; | |
| 15 | 15 | import { requireCapability, requireInsider } from "../../lib/access.server"; | |
| 16 | 16 | ||
| 28 | 28 | deployments.settings({ workspace: params.owner, slug: params.repo }, viewer).catch(() => null), | |
| 29 | 29 | ]); | |
| 30 | 30 | const found = unwrap(project); | |
| 31 | − | // Who made it is kept as an id; name it only when it was the viewer. | |
| 32 | − | return { project: found, deploymentsOn: deploys?.ok ? deploys.value.enabled : null, mine: viewer?.id === found.createdBy }; | |
| 31 | + | // Who made it is kept as an id: named by identity, or left out if it cannot say. | |
| 32 | + | const names = await identity.usernames([found.createdBy]).catch(() => ({}) as Record<string, string>); | |
| 33 | + | return { | |
| 34 | + | project: found, | |
| 35 | + | deploymentsOn: deploys?.ok ? deploys.value.enabled : null, | |
| 36 | + | mine: viewer?.id === found.createdBy, | |
| 37 | + | creator: names[found.createdBy] ?? null, | |
| 38 | + | }; | |
| 33 | 39 | } | |
| 34 | 40 | ||
| 35 | 41 | export async function action({ request, params, context }: Route.ActionArgs) { | |
| 48 | 54 | } | |
| 49 | 55 | ||
| 50 | 56 | export default function ProjectSettings({ loaderData, actionData, params }: Route.ComponentProps) { | |
| 51 | − | const { project, deploymentsOn, mine } = loaderData; | |
| 57 | + | const { project, deploymentsOn, mine, creator } = loaderData; | |
| 52 | 58 | const [deploys, setDeploys] = useState<DeploysSetting>(project.deploys); | |
| 53 | 59 | // Not deploying while Deployments are on is refused: they are turned off first. | |
| 54 | 60 | const blocked = deploys === "no" && project.deploys !== "no" && deploymentsOn === true; | |
| 184 | 190 | </Button> | |
| 185 | 191 | {actionData && "saved" in actionData && <span className="text-sm text-accent">Saved.</span>} | |
| 186 | 192 | <span className="ml-auto text-xs text-faint"> | |
| 187 | − | Created {mine && "by you "} | |
| 193 | + | Created{" "} | |
| 194 | + | {mine ? ( | |
| 195 | + | "by you " | |
| 196 | + | ) : creator ? ( | |
| 197 | + | <> | |
| 198 | + | by{" "} | |
| 199 | + | <Link to={`/${creator}`} className="text-muted hover:text-fg"> | |
| 200 | + | {creator} | |
| 201 | + | </Link>{" "} | |
| 202 | + | </> | |
| 203 | + | ) : null} | |
| 188 | 204 | <TimeAgo at={project.createdAt} /> | |
| 189 | 205 | </span> | |
| 190 | 206 | </div> |