happyDomain/web/src/lib/components/Header.svelte
Pierre-Olivier Mercier f7a16df8d9 Add frontend /whois page for domain RDAP/WHOIS information
Implements a new /whois/[[domain]] route displaying registrar,
creation/expiration dates, nameservers and RDAP status codes
retrieved from the /api/domaininfo/{domain} endpoint. Includes
translations for en, fr, de, es, zh and hi, and a header menu
entry between DNS resolver and Domain Checkers.
2026-03-17 15:50:30 +07:00

204 lines
7.5 KiB
Svelte

<!--
This file is part of the happyDomain (R) project.
Copyright (c) 2022-2024 happyDomain
Authors: Pierre-Olivier Mercier, et al.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at <contact@happydomain.org>.
For AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<script lang="ts">
import { page } from "$app/state";
import type { ClassValue } from "svelte/elements";
import {
Button,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownToggle,
Icon,
Navbar,
NavbarBrand,
Nav,
} from "@sveltestrap/sveltestrap";
import { logout as APILogout } from "$lib/api/user";
import HelpButton from "$lib/components/Help.svelte";
import Logo from "$lib/components/Logo.svelte";
import { appConfig, navigate } from "$lib/stores/config";
import { userSession, refreshUserSession } from "$lib/stores/usersession";
import { toasts } from "$lib/stores/toasts";
import { t, locales, locale } from "$lib/translations";
interface Props {
class?: ClassValue;
sw_state: { triedUpdate: boolean; hasUpdate: boolean };
}
let { class: className, sw_state }: Props = $props();
function logout() {
APILogout().then(
() => {
refreshUserSession().then(
() => {},
() => {
navigate("/login");
},
);
},
(error) => {
toasts.addErrorToast({
title: $t("errors.logout"),
message: error,
timeout: 20000,
});
},
);
}
</script>
<Navbar
class="{className} {$userSession.id ? 'p-0' : ''}"
style="z-index: 100"
container
expand="xs"
light
>
<NavbarBrand
href="/"
style="padding: 0; margin: -.5rem 1rem -.5rem 0;"
target={$userSession.id ? undefined : "_self"}
>
<Logo />
</NavbarBrand>
<Nav class="ms-auto align-items-center" navbar>
<HelpButton
size={$userSession.id ? "sm" : undefined}
class={$userSession.id ? "my-2" : "mx-1"}
/>
{#if $userSession.id}
<Dropdown nav inNavbar>
<DropdownToggle nav caret>
<Button color="dark" size="sm">
<Icon name="person" />
{#if $userSession.email !== "_no_auth"}
<span class="d-inline d-sm-none">
{$userSession.email.split("@")[0]}
</span>
{/if}
<span class="d-none d-sm-inline">
{#if $userSession.email !== "_no_auth"}
{$userSession.email}
{:else}
{$t("menu.quick-menu")}
{/if}
</span>
</Button>
</DropdownToggle>
<DropdownMenu end>
<DropdownItem
active={page.route && page.route.id == "/domains"}
href="/domains/"
>
{$t("menu.my-domains")}
</DropdownItem>
<DropdownItem
active={page.route && page.route.id == "/providers"}
href="/providers/"
>
{$t("menu.my-providers")}
</DropdownItem>
<DropdownItem divider />
<DropdownItem
active={page.route && page.route.id == "/providers/features"}
href="/providers/features"
>
{$t("menu.provider-features")}
</DropdownItem>
<DropdownItem
active={page.route && page.route.id == "/resolver/[[domain]]"}
href="/resolver"
>
{$t("menu.dns-resolver")}
</DropdownItem>
<DropdownItem
active={page.route && page.route.id == "/whois/[[domain]]"}
href="/whois"
>
{$t("menu.whois")}
</DropdownItem>
<DropdownItem
active={page.route &&
(page.route.id == "/checkers" ||
page.route.id?.startsWith("/checkers/"))}
href="/checkers"
>
{$t("menu.checkers")}
</DropdownItem>
<DropdownItem divider />
<DropdownItem active={page.route && page.route.id == "/me"} href="/me">
{$t("menu.my-account")}
</DropdownItem>
{#if $userSession.email !== "_no_auth"}
<DropdownItem divider />
<DropdownItem on:click={logout}>
{$t("menu.logout")}
</DropdownItem>
{/if}
</DropdownMenu>
</Dropdown>
{:else}
<Button class="mx-1" color="info" href="/resolver">
<Icon name="list" aria-hidden="true" />
<span class="d-none d-sm-inline">{$t("menu.dns-resolver")}</span>
</Button>
{#if !$appConfig.disable_registration}
<Button
class="d-none d-md-inline-block mx-1"
outline={!page.route || page.route.id != "/register"}
color="dark"
href="/register"
>
<Icon name="person-plus-fill" aria-hidden="true" />
{$t("menu.signup")}
</Button>
{/if}
<Button
class="d-none d-md-inline-block mx-1"
outline={!page.route || page.route.id != "/login"}
color="primary"
href="/login"
>
<Icon name="person-check-fill" aria-hidden="true" />
{$t("menu.signin")}
</Button>
<Dropdown nav inNavbar>
<DropdownToggle nav caret>{$locale}</DropdownToggle>
<DropdownMenu end>
{#each $locales as lang}
<DropdownItem active={$locale == lang} on:click={() => ($locale = lang)}>
{$t(`locales.${lang}`)}
</DropdownItem>
{/each}
</DropdownMenu>
</Dropdown>
{/if}
</Nav>
</Navbar>