Skip to content
Open
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
101 changes: 101 additions & 0 deletions apps/app/src/components/organization-select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { DenOrgSummary } from "@/app/lib/den";
import { Field } from "@/components/ui/field";
import { Select, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectItem, SelectLabel } from "@/components/ui/select";
import { Building2, Check } from "lucide-react";
import { cn } from "@/lib/utils";

interface OrganizationSelectProps {
className?: string;
organizations: DenOrgSummary[];
value: DenOrgSummary | null;
onValueChange: (organization: DenOrgSummary | null) => void;
disabled?: boolean;
}

export function OrganizationSelect({ className, organizations, value, onValueChange, disabled }: OrganizationSelectProps) {
if (organizations.length === 0) {
return <EmptyOrganizationSelect className={className} />;
}

return (
<Field className={className}>
<Select
disabled={disabled}
value={value}
onValueChange={(nextValue) => {
if (nextValue) onValueChange(nextValue);
}}
>
<SelectTrigger className="h-18! w-full rounded-xl border-dls-border bg-dls-surface px-4 py-3 text-left hover:bg-dls-hover *:data-[slot=select-value]:min-w-0 *:data-[slot=select-value]:line-clamp-none">
<SelectValue>
{(item: DenOrgSummary | null) => (
<span className="flex min-w-0 flex-1 items-center gap-3">
<Building2 size={18} className="shrink-0 text-muted-foreground" />
<span className="min-w-0 flex-1">
<span className="block truncate text-sm font-medium text-foreground">
{item?.name ?? "Select organization"}
</span>
{item ? (
<span className="mt-0.5 block truncate text-xs text-muted-foreground">
{item.slug}
</span>
) : null}
</span>
{item ? <Check size={16} className="shrink-0 text-green-11" /> : null}
</span>
)}
</SelectValue>
</SelectTrigger>
<SelectContent alignItemWithTrigger={false}>
<SelectGroup>
<SelectLabel>Organizations</SelectLabel>
{organizations.map((organization) => (
<SelectItem
key={organization.id}
value={organization}
className={cn(
"rounded-xl border px-4 py-3 text-left last:mb-0 [&>span:first-child]:min-w-0 [&>span:first-child]:flex-1 [&>span:last-child]:end-4 [&>span:last-child_svg]:text-green-11 hover:[&>span:last-child_svg]:text-green-11",
)}
>
<span className="flex min-w-0 flex-1 items-center gap-3">
<Building2 size={18} className="size-4 shrink-0 text-muted-foreground" />
<span className="min-w-0 flex-1">
<span className="block truncate text-sm font-medium text-foreground">
{organization.name}
</span>
<span className="mt-0.5 block truncate text-xs text-muted-foreground">
{organization.slug}
</span>
</span>
</span>
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</Field>
);
}

interface EmptyOrganizationSelectProps {
className?: string;
}

export function EmptyOrganizationSelect({ className }: EmptyOrganizationSelectProps) {
return (
<Field className={className}>
<div className="flex h-18 w-full items-center gap-3 rounded-xl border border-dls-border bg-dls-surface px-4 py-3 text-left">
<Building2 size={18} className="shrink-0 text-muted-foreground" />
<span className="min-w-0 flex-1">
<span className="block truncate text-sm font-medium text-foreground">
No organizations
</span>
<span className="mt-0.5 block truncate text-xs text-muted-foreground">
Create an organization to get started
</span>
</span>
</div>
</Field>
);
}

7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/ca.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,13 @@ export default {
"den.cloud_workers_title": "Workers del núvol",
"den.create_account": "Crea un compte",
"den.credentials_ready_badge": "Credencial a punt",
"den.enter_code_hint": "Si el navegador no torna a OpenWork automàticament, introdueix el codi de verificació de la pàgina d'inici de sessió.",
"den.enter_code_label": "Codi de verificació",
"den.enter_code_placeholder": "Introdueix el codi de verificació",
"den.enter_code_submit": "Continua l'inici de sessió",
"den.enter_code_submitting": "S'està iniciant la sessió...",
"den.enter_code_title": "Introdueix el codi de verificació per iniciar la sessió",
"den.enter_code_trigger": "Introdueix el codi d'inici de sessió manualment",
"den.error_base_url": "Introdueix un URL del pla de control http:// o https:// Cloud vàlid.",
"den.error_choose_org": "Tria una organització abans d'obrir un worker.",
"den.error_load_orgs": "No s'han pogut carregar les organitzacions.",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ export default {
"den.cloud_workers_title": "Cloud workers",
"den.create_account": "Create account",
"den.credentials_ready_badge": "Credential ready",
"den.enter_code_hint": "If your browser doesn't bounce back into OpenWork automatically, enter the verification code from the sign-in page.",
"den.enter_code_label": "Verification code",
"den.enter_code_placeholder": "Enter verification code",
"den.enter_code_submit": "Continue sign-in",
"den.enter_code_submitting": "Signing in...",
"den.enter_code_title": "Enter the verification code to sign-in",
"den.enter_code_trigger": "Enter sign-in code manually",
"den.error_base_url": "Enter a valid http:// or https:// Cloud control plane URL.",
"den.error_choose_org": "Choose an org before opening a worker.",
"den.error_load_orgs": "Failed to load orgs.",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,13 @@ export default {
"den.cloud_workers_title": "Workers de Cloud",
"den.create_account": "Crear una cuenta",
"den.credentials_ready_badge": "Credencial lista",
"den.enter_code_hint": "Si tu navegador no vuelve automáticamente a OpenWork, introduce el código de verificación de la página de inicio de sesión.",
"den.enter_code_label": "Código de verificación",
"den.enter_code_placeholder": "Introduce el código de verificación",
"den.enter_code_submit": "Continuar inicio de sesión",
"den.enter_code_submitting": "Iniciando sesión...",
"den.enter_code_title": "Introduce el código de verificación para iniciar sesión",
"den.enter_code_trigger": "Introducir el código de inicio de sesión manualmente",
"den.error_base_url": "Introduce una URL válida del plano de control de Cloud con `http://` o `https://`.",
"den.error_choose_org": "Elige una organización antes de abrir un worker.",
"den.error_load_orgs": "No se pudieron cargar las organizaciones.",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,13 @@ export default {
"den.cloud_workers_title": "Workers cloud",
"den.create_account": "Créer un compte",
"den.credentials_ready_badge": "Identifiant prêt",
"den.enter_code_hint": "Si votre navigateur ne revient pas automatiquement dans OpenWork, saisissez le code de vérification de la page de connexion.",
"den.enter_code_label": "Code de vérification",
"den.enter_code_placeholder": "Saisir le code de vérification",
"den.enter_code_submit": "Continuer la connexion",
"den.enter_code_submitting": "Connexion...",
"den.enter_code_title": "Saisissez le code de vérification pour vous connecter",
"den.enter_code_trigger": "Saisir le code de connexion manuellement",
"den.error_base_url": "Entrez une URL de plan de contrôle Cloud valide en http:// ou https://.",
"den.error_choose_org": "Choisissez une organisation avant d'ouvrir un worker.",
"den.error_load_orgs": "Échec du chargement des organisations.",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,13 @@ export default {
"den.cloud_workers_title": "クラウドワーカー",
"den.create_account": "アカウントを作成",
"den.credentials_ready_badge": "認証情報準備完了",
"den.enter_code_hint": "ブラウザが自動的にOpenWorkに戻らない場合は、サインインページの認証コードを入力してください。",
"den.enter_code_label": "認証コード",
"den.enter_code_placeholder": "認証コードを入力",
"den.enter_code_submit": "サインインを続行",
"den.enter_code_submitting": "サインインしています…",
"den.enter_code_title": "サインインするには認証コードを入力してください",
"den.enter_code_trigger": "サインインコードを手動で入力",
"den.error_base_url": "有効なhttp://またはhttps://のCloudコントロールプレーンURLを入力してください。",
"den.error_choose_org": "ワーカーを開く前に組織を選択してください。",
"den.error_load_orgs": "組織の読み込みに失敗しました。",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ export default {
"den.cloud_workers_title": "Workers na nuvem",
"den.create_account": "Criar conta",
"den.credentials_ready_badge": "Credencial pronta",
"den.enter_code_hint": "Se o navegador não redirecionar de volta para o OpenWork automaticamente, insira o código de verificação da página de login.",
"den.enter_code_label": "Código de verificação",
"den.enter_code_placeholder": "Insira o código de verificação",
"den.enter_code_submit": "Continuar login",
"den.enter_code_submitting": "Entrando...",
"den.enter_code_title": "Insira o código de verificação para fazer login",
"den.enter_code_trigger": "Inserir código de login manualmente",
"den.error_base_url": "Digite uma URL de plano de controle Cloud válida com http:// ou https://.",
"den.error_choose_org": "Escolha uma organização antes de abrir um worker.",
"den.error_load_orgs": "Falha ao carregar organizações.",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,13 @@ export default {
"den.cloud_workers_title": "Cloud workers",
"den.create_account": "Создать аккаунт",
"den.credentials_ready_badge": "Учетные данные готовы",
"den.enter_code_hint": "Если браузер не возвращает вас в OpenWork автоматически, введите код подтверждения со страницы входа.",
"den.enter_code_label": "Код подтверждения",
"den.enter_code_placeholder": "Введите код подтверждения",
"den.enter_code_submit": "Продолжить вход",
"den.enter_code_submitting": "Выполняется вход...",
"den.enter_code_title": "Введите код подтверждения для входа",
"den.enter_code_trigger": "Ввести код входа вручную",
"den.error_base_url": "Введите допустимый Cloud control plane URL с http:// или https://.",
"den.error_choose_org": "Выберите организацию перед открытием воркера.",
"den.error_load_orgs": "Не удалось загрузить организации.",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/th.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ export default {
"den.cloud_workers_title": "Cloud workers",
"den.create_account": "สร้างบัญชี",
"den.credentials_ready_badge": "ข้อมูลรับรองพร้อม",
"den.enter_code_hint": "หากเบราว์เซอร์ไม่กลับมาที่ OpenWork โดยอัตโนมัติ ให้ป้อนรหัสยืนยันจากหน้าเข้าสู่ระบบ",
"den.enter_code_label": "รหัสยืนยัน",
"den.enter_code_placeholder": "ป้อนรหัสยืนยัน",
"den.enter_code_submit": "ดำเนินการเข้าสู่ระบบต่อ",
"den.enter_code_submitting": "กำลังเข้าสู่ระบบ...",
"den.enter_code_title": "ป้อนรหัสยืนยันเพื่อเข้าสู่ระบบ",
"den.enter_code_trigger": "ป้อนรหัสเข้าสู่ระบบด้วยตนเอง",
"den.error_base_url": "ใส่ URL ของ Cloud control plane ที่ถูกต้อง (http:// หรือ https://)",
"den.error_choose_org": "เลือกองค์กรก่อนเปิด worker",
"den.error_load_orgs": "โหลดองค์กรไม่สำเร็จ",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/vi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ export default {
"den.cloud_workers_title": "Worker Cloud",
"den.create_account": "Tạo tài khoản",
"den.credentials_ready_badge": "Thông tin xác thực sẵn sàng",
"den.enter_code_hint": "Nếu trình duyệt không tự quay lại OpenWork, hãy nhập mã xác minh từ trang đăng nhập.",
"den.enter_code_label": "Mã xác minh",
"den.enter_code_placeholder": "Nhập mã xác minh",
"den.enter_code_submit": "Tiếp tục đăng nhập",
"den.enter_code_submitting": "Đang đăng nhập...",
"den.enter_code_title": "Nhập mã xác minh để đăng nhập",
"den.enter_code_trigger": "Nhập mã đăng nhập thủ công",
"den.error_base_url": "Nhập URL Cloud control plane hợp lệ dạng http:// hoặc https://.",
"den.error_choose_org": "Chọn tổ chức trước khi mở worker.",
"den.error_load_orgs": "Tải tổ chức thất bại.",
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/i18n/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,13 @@ export default {
"den.cloud_workers_title": "云端工作区",
"den.create_account": "创建账户",
"den.credentials_ready_badge": "凭据就绪",
"den.enter_code_hint": "如果浏览器未自动跳回OpenWork,请输入登录页面上的验证码。",
"den.enter_code_label": "验证码",
"den.enter_code_placeholder": "输入验证码",
"den.enter_code_submit": "继续登录",
"den.enter_code_submitting": "正在登录…",
"den.enter_code_title": "输入验证码以登录",
"den.enter_code_trigger": "手动输入登录码",
"den.error_base_url": "请输入有效的http:// 或https:// Cloud控制平面URL。",
"den.error_choose_org": "请先选择组织再打开工作区。",
"den.error_load_orgs": "加载组织失败。",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"use memo";

import * as React from "react";

import type { useDenSession } from "./use-den-session";

export type CloudAccountSession = Pick<
ReturnType<typeof useDenSession>,
| "authBusy"
| "authError"
| "baseUrlDraft"
| "baseUrlError"
| "needsOrgSelection"
| "orgs"
| "orgsBusy"
| "orgsError"
| "sessionBusy"
| "summaryLabel"
| "summaryTone"
| "onActiveOrgChange"
| "onApplyBaseUrl"
| "onBaseUrlDraftChange"
| "onClearAuthError"
| "onOpenBrowserAuth"
| "onOpenControlPlane"
| "onRefreshOrgs"
| "onResetBaseUrl"
| "onSignOut"
| "onSubmitManualAuth"
>;

interface CloudAccountContextValue {
developerMode: boolean;
error: string | null;
isBusy: boolean;
session: CloudAccountSession;
}

const CloudAccountContext = React.createContext<CloudAccountContextValue | null>(null);

interface CloudAccountProviderProps {
children: React.ReactNode;
developerMode: boolean;
session: CloudAccountSession;
}

export function CloudAccountProvider({ children, developerMode, session }: CloudAccountProviderProps) {
const value = React.useMemo(
() => ({
developerMode,
error: session.baseUrlError ?? session.authError ?? session.orgsError,
isBusy: session.authBusy || session.sessionBusy,
session,
}),
[developerMode, session],
);

return <CloudAccountContext.Provider value={value}>{children}</CloudAccountContext.Provider>;
}

export function useCloudAccount() {
const context = React.useContext(CloudAccountContext);

if (!context) {
throw new Error("useCloudAccount must be used within a CloudAccountProvider");
}

return context;
}
Loading
Loading