mirror of
https://github.com/GMWalletApp/epusdt.git
synced 2026-07-07 10:16:15 +00:00
Compare commits
9 Commits
v1.0.8
..
33b39e9771
| Author | SHA1 | Date | |
|---|---|---|---|
| 33b39e9771 | |||
| 642ea0ebe2 | |||
| 3621a02414 | |||
| 5e4dcfb539 | |||
| 1cdb1edd86 | |||
| 7d09adff20 | |||
| 15de0e6940 | |||
| 73aef80499 | |||
| 2dc538c0e1 |
+8
-1
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="./README.en.md">English</a> |
|
<a href="./README.en.md">English</a> |
|
||||||
<a href="./README.zh-CN.md">简体中文</a>
|
<a href="./README.md">简体中文</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -88,17 +88,24 @@ Quick-start links:
|
|||||||
|
|
||||||
| Guide | Description |
|
| Guide | Description |
|
||||||
|-------|-------------|
|
|-------|-------------|
|
||||||
|
| [Repo-local: epctl installer](wiki/EPCTL.en.md) | Linux binary install, upgrade, status inspection, and Docker validation |
|
||||||
| [Docker Deployment](https://epusdt.com/guide/installation/docker) | Recommended one-command setup |
|
| [Docker Deployment](https://epusdt.com/guide/installation/docker) | Recommended one-command setup |
|
||||||
| [aaPanel Deployment](https://epusdt.com/guide/installation/aapanel) | Great for aaPanel users |
|
| [aaPanel Deployment](https://epusdt.com/guide/installation/aapanel) | Great for aaPanel users |
|
||||||
| [Manual Deployment](https://epusdt.com/guide/installation/manual.html) | Full manual control |
|
| [Manual Deployment](https://epusdt.com/guide/installation/manual.html) | Full manual control |
|
||||||
| [Developer API Docs](https://epusdt.com) | Integration reference |
|
| [Developer API Docs](https://epusdt.com) | Integration reference |
|
||||||
|
|
||||||
|
The repository also ships these top-level scripts:
|
||||||
|
|
||||||
|
- [`./epctl`](./epctl) for Linux binary install, upgrade, config inspection, service status, logs, and initial password retrieval
|
||||||
|
- [`./epctl-docker-test.sh`](./epctl-docker-test.sh) for real Ubuntu + systemd installation validation inside local Docker
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Epusdt
|
Epusdt
|
||||||
|
├── epctl Linux binary installation and operations script
|
||||||
├── src/ Core project source code
|
├── src/ Core project source code
|
||||||
└── wiki/ Documentation assets and knowledge base
|
└── wiki/ Documentation assets and knowledge base
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -94,17 +94,24 @@ Epusdt 已完成第三方安全审计。
|
|||||||
|
|
||||||
| 教程 | 说明 |
|
| 教程 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
|
| [仓库内:epctl 安装脚本](wiki/EPCTL.md) | Linux 二进制安装、升级、状态查看与 Docker 验收脚本 |
|
||||||
| [Docker 部署](https://epusdt.com/guide/installation/docker) | 推荐方式,一键启动 |
|
| [Docker 部署](https://epusdt.com/guide/installation/docker) | 推荐方式,一键启动 |
|
||||||
| [宝塔面板部署](https://epusdt.com/guide/installation/aapanel) | 适合宝塔用户 |
|
| [宝塔面板部署](https://epusdt.com/guide/installation/aapanel) | 适合宝塔用户 |
|
||||||
| [手动部署](https://epusdt.com/guide/installation/manual.html) | 完全手动控制 |
|
| [手动部署](https://epusdt.com/guide/installation/manual.html) | 完全手动控制 |
|
||||||
| [开发者 API 文档](https://epusdt.com/zh/guide/integration/gmpay.html) | 接口集成指南 |
|
| [开发者 API 文档](https://epusdt.com/zh/guide/integration/gmpay.html) | 接口集成指南 |
|
||||||
|
|
||||||
|
仓库内还提供顶层脚本:
|
||||||
|
|
||||||
|
- [`./epctl`](./epctl) 用于 Linux 二进制安装、升级、查看配置、状态和初始化密码
|
||||||
|
- [`./epctl-docker-test.sh`](./epctl-docker-test.sh) 用于在本机 Docker 里跑 Ubuntu + systemd 的真实安装验收
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 项目结构
|
## 项目结构
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Epusdt
|
Epusdt
|
||||||
|
├── epctl Linux 二进制安装与运维脚本
|
||||||
├── src/ 项目核心代码
|
├── src/ 项目核心代码
|
||||||
└── wiki/ 文档与知识库
|
└── wiki/ 文档与知识库
|
||||||
```
|
```
|
||||||
|
|||||||
Executable
+379
@@ -0,0 +1,379 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
readonly IMAGE_TAG="epctl-ubuntu-systemd-test:$(date +%s)-$$"
|
||||||
|
readonly CONTAINER_NAME="epctl-systemd-test-$$"
|
||||||
|
readonly BASE_IMAGE="ubuntu:24.04"
|
||||||
|
|
||||||
|
ACTIVE_LANG=""
|
||||||
|
POSITIONAL_ARGS=()
|
||||||
|
|
||||||
|
detect_default_language() {
|
||||||
|
local raw normalized
|
||||||
|
|
||||||
|
raw="${EPCTL_LANG:-}"
|
||||||
|
if [[ -z "${raw}" ]]; then
|
||||||
|
printf 'zh\n'
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
normalized="${raw,,}"
|
||||||
|
case "${normalized}" in
|
||||||
|
zh|zh-*|zh_*|cn|chs|cht|中文)
|
||||||
|
printf 'zh\n'
|
||||||
|
;;
|
||||||
|
en|en-*|en_*|english)
|
||||||
|
printf 'en\n'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf '%s\n' "${raw}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
set_language() {
|
||||||
|
local requested normalized fallback_lang
|
||||||
|
|
||||||
|
requested="${1:-$(detect_default_language)}"
|
||||||
|
normalized="${requested,,}"
|
||||||
|
fallback_lang="${ACTIVE_LANG:-$(detect_default_language)}"
|
||||||
|
case "${normalized}" in
|
||||||
|
zh|zh-*|zh_*|cn|chs|cht|中文)
|
||||||
|
ACTIVE_LANG="zh"
|
||||||
|
;;
|
||||||
|
en|en-*|en_*|english)
|
||||||
|
ACTIVE_LANG="en"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ACTIVE_LANG="${fallback_lang}"
|
||||||
|
die "$(trf unsupported_language "${requested}")"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
export EPCTL_LANG="${ACTIVE_LANG}"
|
||||||
|
}
|
||||||
|
|
||||||
|
trf() {
|
||||||
|
local key="$1"
|
||||||
|
shift || true
|
||||||
|
local template
|
||||||
|
|
||||||
|
case "${ACTIVE_LANG}:${key}" in
|
||||||
|
en:usage) template='Usage:' ;;
|
||||||
|
zh:usage) template='用法:' ;;
|
||||||
|
en:example) template='Example:' ;;
|
||||||
|
zh:example) template='示例:' ;;
|
||||||
|
en:missing_dependency) template='missing dependency: %s' ;;
|
||||||
|
zh:missing_dependency) template='缺少依赖:%s' ;;
|
||||||
|
en:arg_requires_value) template='%s requires a value' ;;
|
||||||
|
zh:arg_requires_value) template='%s 需要一个参数值' ;;
|
||||||
|
en:unsupported_language) template='unsupported language: %s' ;;
|
||||||
|
zh:unsupported_language) template='不支持的语言:%s' ;;
|
||||||
|
en:unsupported_arch) template='unsupported architecture: %s' ;;
|
||||||
|
zh:unsupported_arch) template='不支持的架构:%s' ;;
|
||||||
|
en:test_failed_collecting) template='test failed; collecting container diagnostics' ;;
|
||||||
|
zh:test_failed_collecting) template='测试失败,正在收集容器诊断信息' ;;
|
||||||
|
en:install_tag_invalid) template='install tag must be a real GitHub release tag such as v1.0.6' ;;
|
||||||
|
zh:install_tag_invalid) template='安装 tag 必须是真实的 GitHub release tag,例如 v1.0.6' ;;
|
||||||
|
en:upgrade_tag_invalid) template='upgrade tag must be a real GitHub release tag such as v1.0.6' ;;
|
||||||
|
zh:upgrade_tag_invalid) template='升级 tag 必须是真实的 GitHub release tag,例如 v1.0.6' ;;
|
||||||
|
en:base_image) template='base image: %s' ;;
|
||||||
|
zh:base_image) template='基础镜像:%s' ;;
|
||||||
|
en:building_image) template='building the Ubuntu systemd test image' ;;
|
||||||
|
zh:building_image) template='正在构建 Ubuntu systemd 测试镜像' ;;
|
||||||
|
en:starting_container) template='starting the test container' ;;
|
||||||
|
zh:starting_container) template='正在启动测试容器' ;;
|
||||||
|
en:systemd_not_ready) template='systemd did not become ready inside the container' ;;
|
||||||
|
zh:systemd_not_ready) template='容器内的 systemd 未能及时就绪' ;;
|
||||||
|
en:self_installing) template='installing epctl into PATH' ;;
|
||||||
|
zh:self_installing) template='正在将 epctl 安装到 PATH' ;;
|
||||||
|
en:downloading_release) template='downloading release %s' ;;
|
||||||
|
zh:downloading_release) template='正在下载 release %s' ;;
|
||||||
|
en:installing_release) template='installing epusdt from release %s' ;;
|
||||||
|
zh:installing_release) template='正在从 release %s 安装 epusdt' ;;
|
||||||
|
en:waiting_assets) template='waiting for epusdt to start and release www assets' ;;
|
||||||
|
zh:waiting_assets) template='正在等待 epusdt 启动并释放 www 静态文件' ;;
|
||||||
|
en:upgrading_release) template='upgrading epusdt from %s to %s' ;;
|
||||||
|
zh:upgrading_release) template='正在将 epusdt 从 %s 升级到 %s' ;;
|
||||||
|
en:checking_init_password) template='checking init-password behavior' ;;
|
||||||
|
zh:checking_init_password) template='正在检查 init-password 行为' ;;
|
||||||
|
en:expected_second_failure) template='expected init-password to fail after the password was changed' ;;
|
||||||
|
zh:expected_second_failure) template='密码修改后,init-password 本应失败,但它却成功了' ;;
|
||||||
|
en:verification_succeeded) template='docker verification succeeded for install=%s%s' ;;
|
||||||
|
zh:verification_succeeded) template='Docker 验证通过,install=%s%s' ;;
|
||||||
|
*)
|
||||||
|
template="missing translation: ${key}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf -- "${template}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
printf '[epctl-docker-test] %s\n' "$*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf '[epctl-docker-test] error: %s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
if [[ "${ACTIVE_LANG}" == "zh" ]]; then
|
||||||
|
cat <<'EOF'
|
||||||
|
用法:
|
||||||
|
./epctl-docker-test.sh [--lang zh|en] <install-tag> [upgrade-tag]
|
||||||
|
|
||||||
|
示例:
|
||||||
|
./epctl-docker-test.sh v1.0.6
|
||||||
|
./epctl-docker-test.sh --lang zh v1.0.6 v1.0.8
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage:
|
||||||
|
./epctl-docker-test.sh [--lang zh|en] <install-tag> [upgrade-tag]
|
||||||
|
|
||||||
|
Example:
|
||||||
|
./epctl-docker-test.sh v1.0.6
|
||||||
|
./epctl-docker-test.sh --lang en v1.0.6 v1.0.8
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_global_options() {
|
||||||
|
POSITIONAL_ARGS=()
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--lang)
|
||||||
|
[[ $# -ge 2 ]] || die "$(trf arg_requires_value "--lang")"
|
||||||
|
set_language "$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--lang=*)
|
||||||
|
set_language "${1#*=}"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
POSITIONAL_ARGS+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
require_command() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || die "$(trf missing_dependency "$1")"
|
||||||
|
}
|
||||||
|
|
||||||
|
map_arch() {
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64|amd64)
|
||||||
|
printf 'amd64\n'
|
||||||
|
;;
|
||||||
|
aarch64|arm64)
|
||||||
|
printf 'arm64\n'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "$(trf unsupported_arch "$(uname -m)")"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
docker_bash() {
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
local exit_code="$?"
|
||||||
|
if [[ "${exit_code}" -ne 0 ]]; then
|
||||||
|
log "$(trf test_failed_collecting)"
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc 'systemctl status epusdt --no-pager || true' || true
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc 'journalctl -u epusdt --no-pager -n 100 || true' || true
|
||||||
|
fi
|
||||||
|
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 || true
|
||||||
|
docker rmi -f "${IMAGE_TAG}" >/dev/null 2>&1 || true
|
||||||
|
rm -rf "${TMPDIR_PATH:-}"
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_systemd() {
|
||||||
|
local attempt
|
||||||
|
for attempt in $(seq 1 30); do
|
||||||
|
if docker exec "${CONTAINER_NAME}" bash -lc 'systemctl show --property=Version --value >/dev/null 2>&1'; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
set_language ""
|
||||||
|
parse_global_options "$@"
|
||||||
|
|
||||||
|
INSTALL_TAG="${POSITIONAL_ARGS[0]:-}"
|
||||||
|
UPGRADE_TAG="${POSITIONAL_ARGS[1]:-}"
|
||||||
|
[[ -n "${INSTALL_TAG}" ]] || {
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
[[ "${INSTALL_TAG}" == v* ]] || die "$(trf install_tag_invalid)"
|
||||||
|
if [[ -n "${UPGRADE_TAG}" && "${UPGRADE_TAG}" != v* ]]; then
|
||||||
|
die "$(trf upgrade_tag_invalid)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
require_command docker
|
||||||
|
require_command curl
|
||||||
|
|
||||||
|
ASSET_ARCH="$(map_arch)"
|
||||||
|
ASSET_URL="https://github.com/GMWalletApp/epusdt/releases/download/${INSTALL_TAG}/epusdt-${INSTALL_TAG#v}-linux-${ASSET_ARCH}.tar.gz"
|
||||||
|
SUMS_URL="https://github.com/GMWalletApp/epusdt/releases/download/${INSTALL_TAG}/SHA256SUMS"
|
||||||
|
|
||||||
|
curl --fail --silent --show-error --head "${ASSET_URL}" >/dev/null
|
||||||
|
curl --fail --silent --show-error --head "${SUMS_URL}" >/dev/null
|
||||||
|
if [[ -n "${UPGRADE_TAG}" ]]; then
|
||||||
|
curl --fail --silent --show-error --head "https://github.com/GMWalletApp/epusdt/releases/download/${UPGRADE_TAG}/epusdt-${UPGRADE_TAG#v}-linux-${ASSET_ARCH}.tar.gz" >/dev/null
|
||||||
|
curl --fail --silent --show-error --head "https://github.com/GMWalletApp/epusdt/releases/download/${UPGRADE_TAG}/SHA256SUMS" >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMPDIR_PATH="$(mktemp -d)"
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
cat > "${TMPDIR_PATH}/Dockerfile" <<EOF
|
||||||
|
FROM ${BASE_IMAGE}
|
||||||
|
|
||||||
|
ENV container=docker
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
jq \
|
||||||
|
sudo \
|
||||||
|
systemd \
|
||||||
|
systemd-sysv \
|
||||||
|
tar \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& useradd -m -s /bin/bash tester \
|
||||||
|
&& echo 'tester ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/tester \
|
||||||
|
&& chmod 0440 /etc/sudoers.d/tester
|
||||||
|
|
||||||
|
STOPSIGNAL SIGRTMIN+3
|
||||||
|
|
||||||
|
CMD ["/sbin/init"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log "$(trf base_image "${BASE_IMAGE}")"
|
||||||
|
log "$(trf building_image)"
|
||||||
|
docker build -t "${IMAGE_TAG}" "${TMPDIR_PATH}" >/dev/null
|
||||||
|
|
||||||
|
log "$(trf starting_container)"
|
||||||
|
docker run -d \
|
||||||
|
--name "${CONTAINER_NAME}" \
|
||||||
|
--privileged \
|
||||||
|
--cgroupns=host \
|
||||||
|
-e container=docker \
|
||||||
|
--tmpfs /run \
|
||||||
|
--tmpfs /run/lock \
|
||||||
|
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
|
||||||
|
-v "${SCRIPT_DIR}:/work" \
|
||||||
|
-w /work \
|
||||||
|
"${IMAGE_TAG}" \
|
||||||
|
/sbin/init >/dev/null
|
||||||
|
|
||||||
|
wait_for_systemd || die "$(trf systemd_not_ready)"
|
||||||
|
|
||||||
|
log "$(trf self_installing)"
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc "su - tester -c 'cd /work && ./epctl self-install'"
|
||||||
|
docker_bash '[[ -x /usr/local/bin/epctl ]]'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc 'su - tester -c "EPCTL_NO_COLOR=1 epctl help | grep -q \"^用法:\""'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc 'su - tester -c "EPCTL_NO_COLOR=1 epctl --lang zh help | grep -q \"^用法:\""'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc 'su - tester -c "EPCTL_NO_COLOR=1 epctl --lang en help | grep -q \"^Usage:\""'
|
||||||
|
|
||||||
|
log "$(trf downloading_release "${INSTALL_TAG}")"
|
||||||
|
docker exec "${CONTAINER_NAME}" env TAG="${INSTALL_TAG}" bash -lc 'su - tester -c "epctl download --tag ${TAG}"'
|
||||||
|
|
||||||
|
log "$(trf installing_release "${INSTALL_TAG}")"
|
||||||
|
docker exec "${CONTAINER_NAME}" env TAG="${INSTALL_TAG}" bash -lc 'su - tester -c "epctl install --tag ${TAG} --app-uri http://127.0.0.1:8000"'
|
||||||
|
|
||||||
|
log "$(trf waiting_assets)"
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc '
|
||||||
|
for _ in $(seq 1 30); do
|
||||||
|
if systemctl is-active --quiet epusdt && [[ -f /opt/epusdt/www/index.html ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
systemctl status epusdt --no-pager || true
|
||||||
|
journalctl -u epusdt --no-pager -n 100 || true
|
||||||
|
exit 1
|
||||||
|
'
|
||||||
|
|
||||||
|
docker_bash '[[ -x /opt/epusdt/epusdt ]]'
|
||||||
|
docker_bash '[[ -f /opt/epusdt/.env ]]'
|
||||||
|
docker_bash 'systemctl is-active --quiet epusdt'
|
||||||
|
docker_bash '[[ -f /opt/epusdt/www/index.html ]]'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc 'su - tester -c "epctl show-config | grep -q \"^install=false$\""'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc 'su - tester -c "EPCTL_NO_COLOR=1 epctl --lang zh show-config | grep -q \"^install=false$\""'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc '
|
||||||
|
su - tester -c "epctl status >/tmp/epctl-status.out 2>/tmp/epctl-status.err"
|
||||||
|
! grep -q "systemd-journal" /tmp/epctl-status.err
|
||||||
|
'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc '
|
||||||
|
su - tester -c "epctl logs --lines 50 >/tmp/epctl-logs.out 2>/tmp/epctl-logs.err"
|
||||||
|
! grep -q "systemd-journal" /tmp/epctl-logs.err
|
||||||
|
'
|
||||||
|
|
||||||
|
if [[ -n "${UPGRADE_TAG}" ]]; then
|
||||||
|
log "$(trf upgrading_release "${INSTALL_TAG}" "${UPGRADE_TAG}")"
|
||||||
|
docker exec "${CONTAINER_NAME}" env TAG="${UPGRADE_TAG}" bash -lc 'su - tester -c "epctl upgrade --tag ${TAG}"'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc '
|
||||||
|
for _ in $(seq 1 30); do
|
||||||
|
if systemctl is-active --quiet epusdt && [[ -f /opt/epusdt/www/index.html ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
systemctl status epusdt --no-pager || true
|
||||||
|
journalctl -u epusdt --no-pager -n 100 || true
|
||||||
|
exit 1
|
||||||
|
'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc 'su - tester -c "epctl show-config | grep -q \"^install=false$\""'
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc '
|
||||||
|
su - tester -c "epctl status >/tmp/epctl-status-upgrade.out 2>/tmp/epctl-status-upgrade.err"
|
||||||
|
! grep -q "systemd-journal" /tmp/epctl-status-upgrade.err
|
||||||
|
'
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "$(trf checking_init_password)"
|
||||||
|
docker exec "${CONTAINER_NAME}" bash -lc '
|
||||||
|
response="$(su - tester -c "epctl init-password")"
|
||||||
|
password="$(printf "%s\n" "${response}" | jq -r ".data.password")"
|
||||||
|
printf "%s\n" "${response}" | jq -e ".status_code == 200 and (.data.password | type == \"string\" and length > 0)" >/dev/null
|
||||||
|
|
||||||
|
login_payload="$(jq -nc --arg username admin --arg password "${password}" "{username:\$username,password:\$password}")"
|
||||||
|
token="$(curl --fail --silent --show-error \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "${login_payload}" \
|
||||||
|
http://127.0.0.1:8000/admin/api/v1/auth/login | jq -r ".data.token")"
|
||||||
|
[[ -n "${token}" && "${token}" != "null" ]]
|
||||||
|
|
||||||
|
change_payload="$(jq -nc --arg old_password "${password}" --arg new_password "new-pass-789" "{old_password:\$old_password,new_password:\$new_password}")"
|
||||||
|
curl --fail --silent --show-error \
|
||||||
|
-H "Authorization: Bearer ${token}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "${change_payload}" \
|
||||||
|
http://127.0.0.1:8000/admin/api/v1/auth/password | jq -e ".status_code == 200" >/dev/null
|
||||||
|
|
||||||
|
failure_output="$(mktemp)"
|
||||||
|
if su - tester -c "epctl init-password" >"${failure_output}" 2>&1; then
|
||||||
|
cat "${failure_output}" >&2
|
||||||
|
rm -f "${failure_output}"
|
||||||
|
echo "'"$(trf expected_second_failure)"'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
grep -Eq "\"status_code\"[[:space:]]*:[[:space:]]*10040" "${failure_output}"
|
||||||
|
rm -f "${failure_output}"
|
||||||
|
'
|
||||||
|
|
||||||
|
log "$(trf verification_succeeded "${INSTALL_TAG}" "${UPGRADE_TAG:+ upgrade=${UPGRADE_TAG}}")"
|
||||||
@@ -55,8 +55,6 @@ func InitApp() {
|
|||||||
color.Yellow.Println("║ Default admin account created. Save these credentials now. ║")
|
color.Yellow.Println("║ Default admin account created. Save these credentials now. ║")
|
||||||
color.Yellow.Printf("║ Username: %-54s║\n", "admin")
|
color.Yellow.Printf("║ Username: %-54s║\n", "admin")
|
||||||
color.Yellow.Printf("║ Password: %-54s║\n", initialPassword)
|
color.Yellow.Printf("║ Password: %-54s║\n", initialPassword)
|
||||||
color.Yellow.Println("║ The one-time password API remains available until first fetch. ║")
|
|
||||||
color.Yellow.Println("║ GET /admin/api/v1/auth/init-password (one-time) ║")
|
|
||||||
color.Yellow.Println("╚════════════════════════════════════════════════════════════════════════╝")
|
color.Yellow.Println("╚════════════════════════════════════════════════════════════════════════╝")
|
||||||
}
|
}
|
||||||
if _, err := appjwt.EnsureSecret(); err != nil {
|
if _, err := appjwt.EnsureSecret(); err != nil {
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/GMWalletApp/epusdt/model/data"
|
"github.com/GMWalletApp/epusdt/model/data"
|
||||||
"github.com/GMWalletApp/epusdt/model/mdb"
|
"github.com/GMWalletApp/epusdt/model/mdb"
|
||||||
"github.com/GMWalletApp/epusdt/util/constant"
|
"github.com/GMWalletApp/epusdt/util/constant"
|
||||||
@@ -35,12 +33,6 @@ type MeResponse struct {
|
|||||||
PasswordIsDefault bool `json:"password_is_default" example:"true"`
|
PasswordIsDefault bool `json:"password_is_default" example:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitialPasswordResponse is returned by the one-time initial password API.
|
|
||||||
type InitialPasswordResponse struct {
|
|
||||||
Username string `json:"username" example:"admin"`
|
|
||||||
Password string `json:"password" example:"a1b2c3d4e5f6"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Login verifies credentials, stamps last_login_at, returns a signed JWT.
|
// Login verifies credentials, stamps last_login_at, returns a signed JWT.
|
||||||
// @Summary Admin login
|
// @Summary Admin login
|
||||||
// @Description Verify credentials and return a signed JWT token
|
// @Description Verify credentials and return a signed JWT token
|
||||||
@@ -84,28 +76,6 @@ func (c *BaseAdminController) Login(ctx echo.Context) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInitialPassword returns the one-time initial admin password.
|
|
||||||
// @Summary Get initial admin password (one-time)
|
|
||||||
// @Description Returns the initial random admin password once, then invalidates it.
|
|
||||||
// @Tags Admin Auth
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200 {object} response.ApiResponse{data=admin.InitialPasswordResponse}
|
|
||||||
// @Failure 400 {object} response.ApiResponse
|
|
||||||
// @Router /admin/api/v1/auth/init-password [get]
|
|
||||||
func (c *BaseAdminController) GetInitialPassword(ctx echo.Context) error {
|
|
||||||
password, err := data.ConsumeInitialAdminPassword()
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, data.ErrInitAdminPasswordAlreadyFetched) || errors.Is(err, data.ErrInitAdminPasswordUnavailable) {
|
|
||||||
return c.FailJson(ctx, constant.InitialAdminPasswordErr)
|
|
||||||
}
|
|
||||||
return c.FailJson(ctx, err)
|
|
||||||
}
|
|
||||||
return c.SucJson(ctx, InitialPasswordResponse{
|
|
||||||
Username: "admin",
|
|
||||||
Password: password,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInitialPasswordHash returns the initial-password fingerprint so the
|
// GetInitialPasswordHash returns the initial-password fingerprint so the
|
||||||
// frontend can warn until the password is changed.
|
// frontend can warn until the password is changed.
|
||||||
// @Summary Get initial admin password hash
|
// @Summary Get initial admin password hash
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ import (
|
|||||||
// rate.okx_c2c_enabled (bool) — use OKX C2C rate feed
|
// rate.okx_c2c_enabled (bool) — use OKX C2C rate feed
|
||||||
//
|
//
|
||||||
// - group=epay:
|
// - group=epay:
|
||||||
// epay.default_token (string) — default token for EPAY submit.php, e.g. "usdt"; empty allows status=4 placeholders when request token/network are also absent
|
// epay.default_token (string) — default token for EPAY submit.php, e.g. "usdt"; ignored when a supported type=token.network selector is supplied; empty allows status=4 placeholders when request token/network are also absent
|
||||||
// epay.default_currency (string) — default fiat currency for EPAY submit.php, e.g. "cny"; empty falls back to cny
|
// epay.default_currency (string) — default fiat currency for EPAY submit.php, e.g. "cny"; still applies when a supported type selector is supplied; empty falls back to cny
|
||||||
// epay.default_network (string) — default network for EPAY submit.php, e.g. "tron" or "ton"; empty allows status=4 placeholders when request token/network are also absent
|
// epay.default_network (string) — default network for EPAY submit.php, e.g. "tron" or "ton"; ignored when a supported type=token.network selector is supplied; empty allows status=4 placeholders when request token/network are also absent
|
||||||
//
|
//
|
||||||
// - group=okpay:
|
// - group=okpay:
|
||||||
// okpay.enabled (bool) — enable OkPay as a switch-network payment option
|
// okpay.enabled (bool) — enable OkPay as a switch-network payment option
|
||||||
@@ -95,7 +95,7 @@ func (c *BaseAdminController) ListSettings(ctx echo.Context) error {
|
|||||||
// @Summary Upsert settings
|
// @Summary Upsert settings
|
||||||
// @Description Batch insert/update settings. Returns per-key status; failed items include error_code for frontend i18n.
|
// @Description Batch insert/update settings. Returns per-key status; failed items include error_code for frontend i18n.
|
||||||
// @Description Supported groups: brand, rate, system, epay, okpay.
|
// @Description Supported groups: brand, rate, system, epay, okpay.
|
||||||
// @Description epay group keys: epay.default_token (e.g. "usdt" or "ton", empty allows status=4 placeholders), epay.default_currency (e.g. "cny", empty falls back to cny), epay.default_network (e.g. "tron" or "ton", empty allows status=4 placeholders).
|
// @Description epay group keys: epay.default_token (e.g. "usdt" or "ton", ignored when a supported type=token.network selector is supplied, empty allows status=4 placeholders), epay.default_currency (e.g. "cny", still applies when a supported type selector is supplied, empty falls back to cny), epay.default_network (e.g. "tron" or "ton", ignored when a supported type=token.network selector is supplied, empty allows status=4 placeholders).
|
||||||
// @Description okpay group keys: okpay.enabled, okpay.shop_id, okpay.shop_token, okpay.api_url, okpay.callback_url, okpay.return_url, okpay.timeout_seconds, okpay.allow_tokens.
|
// @Description okpay group keys: okpay.enabled, okpay.shop_id, okpay.shop_token, okpay.api_url, okpay.callback_url, okpay.return_url, okpay.timeout_seconds, okpay.allow_tokens.
|
||||||
// @Description rate group keys: rate.forced_rate_list (JSON map, e.g. {"cny":{"usdt":0.14635,"ton":0.5}}; base/coin keys are normalized to lowercase), rate.api_url, rate.adjust_percent, rate.okx_c2c_enabled.
|
// @Description rate group keys: rate.forced_rate_list (JSON map, e.g. {"cny":{"usdt":0.14635,"ton":0.5}}; base/coin keys are normalized to lowercase), rate.api_url, rate.adjust_percent, rate.okx_c2c_enabled.
|
||||||
// @Description brand group keys: brand.checkout_name, brand.logo_url, brand.site_title, brand.success_copy, brand.support_url, brand.background_color, brand.background_image_url. Legacy aliases brand.site_name, brand.page_title and brand.pay_success_text are also supported.
|
// @Description brand group keys: brand.checkout_name, brand.logo_url, brand.site_title, brand.success_copy, brand.support_url, brand.background_color, brand.background_image_url. Legacy aliases brand.site_name, brand.page_title and brand.pay_success_text are also supported.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package comm
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/GMWalletApp/epusdt/middleware"
|
"github.com/GMWalletApp/epusdt/middleware"
|
||||||
"github.com/GMWalletApp/epusdt/model/mdb"
|
"github.com/GMWalletApp/epusdt/model/mdb"
|
||||||
@@ -13,6 +14,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const EPayTypeContextKey = "epay_type"
|
||||||
|
|
||||||
// apiKeyFromContext returns the api_keys row stamped by CheckApiSign.
|
// apiKeyFromContext returns the api_keys row stamped by CheckApiSign.
|
||||||
// Returns nil when the middleware didn't run (should not happen on authed routes).
|
// Returns nil when the middleware didn't run (should not happen on authed routes).
|
||||||
func apiKeyFromContext(ctx echo.Context) *mdb.ApiKey {
|
func apiKeyFromContext(ctx echo.Context) *mdb.ApiKey {
|
||||||
@@ -101,7 +104,10 @@ func (c *BaseCommController) SwitchNetwork(ctx echo.Context) (err error) {
|
|||||||
// POST (form) per the legacy EPAY protocol; swagger documents POST as
|
// POST (form) per the legacy EPAY protocol; swagger documents POST as
|
||||||
// the canonical form — the GET variant is identical save the transport.
|
// the canonical form — the GET variant is identical save the transport.
|
||||||
// @Summary Create transaction and redirect (EPAY compat)
|
// @Summary Create transaction and redirect (EPAY compat)
|
||||||
// @Description Legacy EPAY-style endpoint. Accepts GET (querystring) and POST (form). On success, 302 redirects to /pay/checkout-counter/{trade_id}. Signature uses MD5 of sorted params + secret_key of the api_keys row matching the submitted pid. Optional request token/network/currency override database defaults and must be included in the EPay signature when sent. The server injects internal payment_type=Epay after EPay signature verification; merchants do not send GMPay payment_type to this endpoint.
|
// @Description Legacy EPAY-style endpoint. Accepts GET (querystring) and POST (form). On success, 302 redirects to /pay/checkout-counter/{trade_id}. Signature uses MD5 of sorted params + secret_key of the api_keys row matching the submitted pid.
|
||||||
|
// @Description After signature verification, type accepts only either alipay or a supported type=token.network selector (for example usdt.tron). Token/network resolution is: supported selector first; otherwise request token/network; otherwise epay.default_token / epay.default_network. If token and network are still both empty, the order is created as status=4 placeholder. Supplying only one of token/network remains invalid.
|
||||||
|
// @Description Currency resolution is unchanged: request currency -> epay.default_currency -> cny. Supported type selectors bypass only token/network defaults, not currency fallback.
|
||||||
|
// @Description Success return/notify reuse the stored request type. On this branch that means either alipay or a supported token.network selector; when the request omitted type, outbound fallback remains alipay. The server injects internal payment_type=Epay after EPay signature verification; merchants do not send GMPay payment_type to this endpoint.
|
||||||
// @Tags Payment
|
// @Tags Payment
|
||||||
// @Accept x-www-form-urlencoded
|
// @Accept x-www-form-urlencoded
|
||||||
// @Produce html
|
// @Produce html
|
||||||
@@ -111,7 +117,7 @@ func (c *BaseCommController) SwitchNetwork(ctx echo.Context) (err error) {
|
|||||||
// @Param notify_url query string false "Callback URL (GET query)"
|
// @Param notify_url query string false "Callback URL (GET query)"
|
||||||
// @Param return_url query string false "Redirect URL after payment (GET query)"
|
// @Param return_url query string false "Redirect URL after payment (GET query)"
|
||||||
// @Param name query string false "Order name (GET query)"
|
// @Param name query string false "Order name (GET query)"
|
||||||
// @Param type query string false "Payment type (e.g. alipay, GET query)"
|
// @Param type query string false "Either alipay or a supported token.network selector such as usdt.tron (GET query)"
|
||||||
// @Param sign query string false "MD5 signature (GET query)"
|
// @Param sign query string false "MD5 signature (GET query)"
|
||||||
// @Param sign_type query string false "Signature type (MD5, GET query)"
|
// @Param sign_type query string false "Signature type (MD5, GET query)"
|
||||||
// @Param pid formData integer true "API key PID"
|
// @Param pid formData integer true "API key PID"
|
||||||
@@ -120,7 +126,7 @@ func (c *BaseCommController) SwitchNetwork(ctx echo.Context) (err error) {
|
|||||||
// @Param notify_url formData string true "Callback URL"
|
// @Param notify_url formData string true "Callback URL"
|
||||||
// @Param return_url formData string false "Redirect URL after payment"
|
// @Param return_url formData string false "Redirect URL after payment"
|
||||||
// @Param name formData string false "Order name"
|
// @Param name formData string false "Order name"
|
||||||
// @Param type formData string false "Payment type (e.g. alipay)"
|
// @Param type formData string false "Either alipay or a supported token.network selector such as usdt.tron"
|
||||||
// @Param sign formData string true "MD5 signature"
|
// @Param sign formData string true "MD5 signature"
|
||||||
// @Param sign_type formData string false "Signature type (MD5)"
|
// @Param sign_type formData string false "Signature type (MD5)"
|
||||||
// @Success 302 "Redirect to checkout counter"
|
// @Success 302 "Redirect to checkout counter"
|
||||||
@@ -133,6 +139,9 @@ func (c *BaseCommController) CreateTransactionAndRedirect(ctx echo.Context) (err
|
|||||||
log.Sugar.Errorf("bind request error: %v", err)
|
log.Sugar.Errorf("bind request error: %v", err)
|
||||||
return c.FailJson(ctx, constant.ParamsMarshalErr)
|
return c.FailJson(ctx, constant.ParamsMarshalErr)
|
||||||
}
|
}
|
||||||
|
if raw, ok := ctx.Get(EPayTypeContextKey).(string); ok {
|
||||||
|
req.EpayType = strings.TrimSpace(raw)
|
||||||
|
}
|
||||||
if err = c.ValidateStruct(ctx, req); err != nil {
|
if err = c.ValidateStruct(ctx, req); err != nil {
|
||||||
log.Sugar.Errorf("validate request error: %v", err)
|
log.Sugar.Errorf("validate request error: %v", err)
|
||||||
return c.FailJson(ctx, err)
|
return c.FailJson(ctx, err)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
// CheckoutCounter 收银台
|
// CheckoutCounter 收银台
|
||||||
// @Summary Checkout counter page
|
// @Summary Checkout counter page
|
||||||
// @Description Return checkout initialization data when the order exists. This endpoint only confirms order existence and returns base order data; call /pay/check-status/{trade_id} for the current order status (1=waiting payment, 2=paid, 3=expired, 4=waiting token/network selection).
|
// @Description Return checkout initialization data when the order exists. This endpoint only confirms order existence and returns base order data; call /pay/check-status/{trade_id} for the current order status (1=waiting payment, 2=paid, 3=expired, 4=waiting token/network selection).
|
||||||
// @Description When status=4, actual_amount is 0 and token/network/receive_address are empty; this state is produced by GMPay placeholders or EPay submit.php when no token/network request values or database defaults exist. The cashier should guide the payer to choose an on-chain token/network or OkPay and then call /pay/switch-network.
|
// @Description When status=4, actual_amount is 0 and token/network/receive_address are empty; this state is produced by GMPay placeholders or EPay submit.php when no token/network request values or defaults resolve to a concrete payment asset. The cashier should guide the payer to choose an on-chain token/network or OkPay and then call /pay/switch-network.
|
||||||
// @Description For EPay orders with a merchant return_url, the response redirect_url is rewritten to the internal /pay/return/{trade_id} hop; the database still stores the merchant's raw return_url.
|
// @Description For EPay orders with a merchant return_url, the response redirect_url is rewritten to the internal /pay/return/{trade_id} hop; the database still stores the merchant's raw return_url.
|
||||||
// @Tags Payment
|
// @Tags Payment
|
||||||
// @Produce json
|
// @Produce json
|
||||||
@@ -36,6 +36,7 @@ func (c *BaseCommController) CheckoutCounter(ctx echo.Context) (err error) {
|
|||||||
// Non-EPay or not-yet-paid orders are sent back to the checkout counter.
|
// Non-EPay or not-yet-paid orders are sent back to the checkout counter.
|
||||||
// @Summary Return to merchant (EPAY compat)
|
// @Summary Return to merchant (EPAY compat)
|
||||||
// @Description Browser-facing success return hop for EPay orders. Paid EPay orders are redirected to the merchant return_url with signed legacy EPay query params. Orders that are not EPay or not yet paid are redirected back to the checkout counter.
|
// @Description Browser-facing success return hop for EPay orders. Paid EPay orders are redirected to the merchant return_url with signed legacy EPay query params. Orders that are not EPay or not yet paid are redirected back to the checkout counter.
|
||||||
|
// @Description The signed query params reuse the stored request type. On this branch that means either alipay or a supported token.network selector; if the original request omitted type, type=alipay is returned for compatibility.
|
||||||
// @Description This route also returns explicit business errors when the merchant return_url is missing, the order API key is unavailable, or EPay signature construction fails.
|
// @Description This route also returns explicit business errors when the merchant return_url is missing, the order API key is unavailable, or EPay signature construction fails.
|
||||||
// @Tags Payment
|
// @Tags Payment
|
||||||
// @Produce html
|
// @Produce html
|
||||||
|
|||||||
+144
-32
@@ -3,23 +3,25 @@
|
|||||||
// When the .env config file is absent (or has install=true) the HTTP start
|
// When the .env config file is absent (or has install=true) the HTTP start
|
||||||
// command calls RunInstallServer, which listens on the same address the main
|
// command calls RunInstallServer, which listens on the same address the main
|
||||||
// server will eventually use (default :8000) and mounts two JSON endpoints
|
// server will eventually use (default :8000) and mounts two JSON endpoints
|
||||||
// under /install consumed by the frontend install UI:
|
// consumed by the frontend install UI:
|
||||||
//
|
//
|
||||||
// GET /install/defaults — default field values for the form
|
// GET /api/install/defaults — default field values for the form
|
||||||
// POST /install — validate + write .env, then shut down
|
// POST /api/install — validate + initialize install state, then shut down
|
||||||
//
|
//
|
||||||
// The HTTP listen address is submitted as two separate fields (http_bind_addr
|
// The HTTP listen address is submitted as two separate fields (http_bind_addr
|
||||||
// and http_bind_port) and combined internally as "ADDR:PORT" before writing
|
// and http_bind_port) and combined internally as "ADDR:PORT" before writing
|
||||||
// the http_listen key in .env. This makes the form easier for users who only
|
// the http_listen key in .env. This makes the form easier for users who only
|
||||||
// want to change the port without touching the bind address.
|
// want to change the port without touching the bind address.
|
||||||
//
|
//
|
||||||
// Once the .env is written the install server stops and normal bootstrap
|
// Once install state is initialized and the .env is finalized with
|
||||||
// proceeds on the same port without a restart.
|
// install=false, the install server stops and normal bootstrap proceeds on the
|
||||||
|
// same port without a restart.
|
||||||
package install
|
package install
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -28,10 +30,15 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/GMWalletApp/epusdt/config"
|
||||||
|
"github.com/GMWalletApp/epusdt/model/dao"
|
||||||
|
"github.com/GMWalletApp/epusdt/model/data"
|
||||||
luluHttp "github.com/GMWalletApp/epusdt/util/http"
|
luluHttp "github.com/GMWalletApp/epusdt/util/http"
|
||||||
|
appLog "github.com/GMWalletApp/epusdt/util/log"
|
||||||
"github.com/gookit/color"
|
"github.com/gookit/color"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultInstallAddr is the listen address used by the install API.
|
// DefaultInstallAddr is the listen address used by the install API.
|
||||||
@@ -59,6 +66,14 @@ type InstallRequest struct {
|
|||||||
OrderNoticeMaxRetry int `json:"order_notice_max_retry" form:"order_notice_max_retry" example:"1"`
|
OrderNoticeMaxRetry int `json:"order_notice_max_retry" form:"order_notice_max_retry" example:"1"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InstallSubmitResponse is returned when the install request succeeds.
|
||||||
|
type InstallSubmitResponse struct {
|
||||||
|
// Completion message for the install request.
|
||||||
|
Message string `json:"message" example:"install complete, starting server…"`
|
||||||
|
// Initial admin password, returned only while the plaintext is still available.
|
||||||
|
InitPassword string `json:"init_password,omitempty" example:"a1b2c3d4e5f6"`
|
||||||
|
}
|
||||||
|
|
||||||
// InstallDefaults returns sensible default values for the install form.
|
// InstallDefaults returns sensible default values for the install form.
|
||||||
func InstallDefaults() InstallRequest {
|
func InstallDefaults() InstallRequest {
|
||||||
return InstallRequest{
|
return InstallRequest{
|
||||||
@@ -149,28 +164,20 @@ func (h *installHandler) GetDefaults(c echo.Context) error {
|
|||||||
return c.JSON(http.StatusOK, InstallDefaults())
|
return c.JSON(http.StatusOK, InstallDefaults())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit validates the install payload, writes the .env file, and signals
|
// Submit validates the install payload, writes the .env file, initializes the
|
||||||
// the install server to shut down so the main bootstrap can proceed.
|
// minimum DB/admin state, and signals the install server to shut down so the
|
||||||
|
// main bootstrap can proceed.
|
||||||
// http_bind_addr and http_bind_port are combined as "ADDR:PORT" to produce
|
// http_bind_addr and http_bind_port are combined as "ADDR:PORT" to produce
|
||||||
// the http_listen config key (e.g. 0.0.0.0:8000).
|
// the http_listen config key (e.g. 0.0.0.0:8000).
|
||||||
//
|
//
|
||||||
// @Summary Install — submit configuration
|
// @Summary Install — submit configuration
|
||||||
// @Description Validates the submitted configuration and writes the .env file.
|
// @Description Validates the submitted configuration, writes install=true, performs the minimum DB setup needed to ensure the default admin exists, optionally returns init_password, then rewrites install=false before shutting down the install server.
|
||||||
//
|
// @Description http_bind_addr + http_bind_port are joined internally as "ADDR:PORT" for http_listen. app_uri is required; other fields fall back to GET /api/install/defaults.
|
||||||
// http_bind_addr + http_bind_port are joined internally as "ADDR:PORT" for
|
|
||||||
// the http_listen config key (defaults: 127.0.0.1 and 8000 respectively).
|
|
||||||
// http_bind_port must be in the range 1–65535 if provided.
|
|
||||||
// app_uri is required. All other fields are optional and fall back to
|
|
||||||
// the defaults returned by GET /api/install/defaults.
|
|
||||||
// Sets install=false in the written .env, then shuts down the install
|
|
||||||
// server so that normal application bootstrap starts on the same port.
|
|
||||||
// After installation completes this route is no longer served.
|
|
||||||
//
|
|
||||||
// @Tags Install
|
// @Tags Install
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param body body InstallRequest true "Install configuration"
|
// @Param body body InstallRequest true "Install configuration"
|
||||||
// @Success 200 {object} map[string]string "message"
|
// @Success 200 {object} InstallSubmitResponse
|
||||||
// @Failure 400 {object} map[string]string "error"
|
// @Failure 400 {object} map[string]string "error"
|
||||||
// @Failure 500 {object} map[string]string "error"
|
// @Failure 500 {object} map[string]string "error"
|
||||||
// @Router /api/install [post]
|
// @Router /api/install [post]
|
||||||
@@ -210,16 +217,26 @@ func (h *installHandler) Submit(c echo.Context) error {
|
|||||||
req.OrderNoticeMaxRetry = d.OrderNoticeMaxRetry
|
req.OrderNoticeMaxRetry = d.OrderNoticeMaxRetry
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := writeEnvFile(h.envFilePath, req); err != nil {
|
if err := writeEnvFile(h.envFilePath, req, true); err != nil {
|
||||||
|
return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": err.Error()})
|
||||||
|
}
|
||||||
|
initPassword, err := initializeInstallState(h.envFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": err.Error()})
|
||||||
|
}
|
||||||
|
if err := writeEnvFile(h.envFilePath, req, false); err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": err.Error()})
|
return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": err.Error()})
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() { close(h.done) }()
|
go func() { close(h.done) }()
|
||||||
return c.JSON(http.StatusOK, map[string]interface{}{"message": "install complete, starting server…"})
|
return c.JSON(http.StatusOK, InstallSubmitResponse{
|
||||||
|
Message: "install complete, starting server…",
|
||||||
|
InitPassword: initPassword,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunInstallServer starts the install REST API on listenAddr (default :8000)
|
// RunInstallServer starts the install UI and REST API on listenAddr
|
||||||
// under the /install path and blocks until the .env file has been written.
|
// (default :8000), then blocks until installation has been finalized.
|
||||||
// The caller should then proceed with normal app initialisation (bootstrap.InitApp).
|
// The caller should then proceed with normal app initialisation (bootstrap.InitApp).
|
||||||
func RunInstallServer(listenAddr, envFilePath string) {
|
func RunInstallServer(listenAddr, envFilePath string) {
|
||||||
if listenAddr == "" {
|
if listenAddr == "" {
|
||||||
@@ -264,13 +281,18 @@ var formControlledKeys = map[string]bool{
|
|||||||
"install": true,
|
"install": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeEnvFile renders and writes a minimal .env file.
|
type envTemplateData struct {
|
||||||
|
*InstallRequest
|
||||||
|
InstallValue string
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeEnvFile renders and atomically writes a minimal .env file.
|
||||||
// If the file already exists, values for keys that are NOT controlled by the
|
// If the file already exists, values for keys that are NOT controlled by the
|
||||||
// install form are preserved from the existing file so that operator-specific
|
// install form are preserved from the existing file so that operator-specific
|
||||||
// settings (tg_bot_token, db_type, etc.) survive a re-install.
|
// settings (tg_bot_token, db_type, etc.) survive a re-install.
|
||||||
// Keys that the form controls (app_uri, http_listen, …) always use the
|
// Keys that the form controls (app_uri, http_listen, …) always use the
|
||||||
// submitted values.
|
// submitted values.
|
||||||
func writeEnvFile(path string, r *InstallRequest) error {
|
func writeEnvFile(path string, r *InstallRequest, installEnabled bool) error {
|
||||||
// Collect existing non-empty key→value pairs for non-form keys.
|
// Collect existing non-empty key→value pairs for non-form keys.
|
||||||
existingValues := map[string]string{}
|
existingValues := map[string]string{}
|
||||||
if data, err := os.ReadFile(path); err == nil {
|
if data, err := os.ReadFile(path); err == nil {
|
||||||
@@ -295,7 +317,14 @@ func writeEnvFile(path string, r *InstallRequest) error {
|
|||||||
|
|
||||||
// Render the template into a buffer first.
|
// Render the template into a buffer first.
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if err := envTemplate.Execute(&buf, r); err != nil {
|
renderData := envTemplateData{
|
||||||
|
InstallRequest: r,
|
||||||
|
InstallValue: "false",
|
||||||
|
}
|
||||||
|
if installEnabled {
|
||||||
|
renderData.InstallValue = "true"
|
||||||
|
}
|
||||||
|
if err := envTemplate.Execute(&buf, renderData); err != nil {
|
||||||
return fmt.Errorf("render env template: %w", err)
|
return fmt.Errorf("render env template: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,13 +344,96 @@ func writeEnvFile(path string, r *InstallRequest) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600)
|
f, err := os.CreateTemp(filepath.Dir(path), ".env.tmp.*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("open config file: %w", err)
|
return fmt.Errorf("open temp config file: %w", err)
|
||||||
|
}
|
||||||
|
tempPath := f.Name()
|
||||||
|
defer func() {
|
||||||
|
_ = os.Remove(tempPath)
|
||||||
|
}()
|
||||||
|
if _, err = fmt.Fprint(f, strings.Join(lines, "\n")); err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = os.Rename(tempPath, path); err != nil {
|
||||||
|
return fmt.Errorf("replace config file: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initializeInstallState(envFilePath string) (string, error) {
|
||||||
|
if err := initInstallConfig(envFilePath); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err := initInstallDatabases(); err != nil {
|
||||||
|
closeInstallDatabases()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer closeInstallDatabases()
|
||||||
|
|
||||||
|
password, created, err := data.EnsureDefaultAdmin()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if created {
|
||||||
|
password = strings.TrimSpace(password)
|
||||||
|
if password == "" {
|
||||||
|
return "", errors.New("default admin created without initial password")
|
||||||
|
}
|
||||||
|
return password, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
password, err = data.GetInitialAdminPassword()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, data.ErrInitAdminPasswordUnavailable) || errors.Is(err, data.ErrInitAdminPasswordAlreadyFetched) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(password), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initInstallConfig(envFilePath string) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if recovered := recover(); recovered != nil {
|
||||||
|
err = fmt.Errorf("init config: %v", recovered)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
config.SetConfigPath(envFilePath)
|
||||||
|
config.Init()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initInstallDatabases() error {
|
||||||
|
if appLog.Sugar == nil {
|
||||||
|
appLog.Sugar = zap.NewNop().Sugar()
|
||||||
|
}
|
||||||
|
if err := dao.DBInit(); err != nil {
|
||||||
|
return fmt.Errorf("init store db: %w", err)
|
||||||
|
}
|
||||||
|
if err := dao.RuntimeInit(); err != nil {
|
||||||
|
return fmt.Errorf("init runtime db: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func closeInstallDatabases() {
|
||||||
|
if dao.RuntimeDB != nil {
|
||||||
|
if db, err := dao.RuntimeDB.DB(); err == nil {
|
||||||
|
_ = db.Close()
|
||||||
|
}
|
||||||
|
dao.RuntimeDB = nil
|
||||||
|
}
|
||||||
|
if dao.Mdb != nil {
|
||||||
|
if db, err := dao.Mdb.DB(); err == nil {
|
||||||
|
_ = db.Close()
|
||||||
|
}
|
||||||
|
dao.Mdb = nil
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
_, err = fmt.Fprint(f, strings.Join(lines, "\n"))
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var envTemplate = template.Must(template.New("env").Parse(`app_name={{.AppName}}
|
var envTemplate = template.Must(template.New("env").Parse(`app_name={{.AppName}}
|
||||||
@@ -360,5 +472,5 @@ order_notice_max_retry={{.OrderNoticeMaxRetry}}
|
|||||||
api_rate_url=
|
api_rate_url=
|
||||||
|
|
||||||
# Set to true to re-run the install wizard on next startup.
|
# Set to true to re-run the install wizard on next startup.
|
||||||
install=false
|
install={{.InstallValue}}
|
||||||
`))
|
`))
|
||||||
|
|||||||
+192
-31
@@ -10,9 +10,89 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/GMWalletApp/epusdt/config"
|
||||||
|
"github.com/GMWalletApp/epusdt/model/dao"
|
||||||
|
"github.com/GMWalletApp/epusdt/model/data"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func resetInstallTestState(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
closeInstallDatabases()
|
||||||
|
dao.ResetMdbTableInitForTest()
|
||||||
|
config.SetConfigPath("")
|
||||||
|
viper.Reset()
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
closeInstallDatabases()
|
||||||
|
dao.ResetMdbTableInitForTest()
|
||||||
|
config.SetConfigPath("")
|
||||||
|
viper.Reset()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInstallTestAPI(envPath string) (*echo.Echo, *installHandler) {
|
||||||
|
h := &installHandler{envFilePath: envPath, done: make(chan struct{})}
|
||||||
|
e := echo.New()
|
||||||
|
e.POST("/install", h.Submit)
|
||||||
|
return e, h
|
||||||
|
}
|
||||||
|
|
||||||
|
func submitInstallRequest(t *testing.T, e *echo.Echo, payload string) *httptest.ResponseRecorder {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/install", strings.NewReader(payload))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
e.ServeHTTP(rec, req)
|
||||||
|
return rec
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]interface{} {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var body map[string]interface{}
|
||||||
|
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
|
||||||
|
t.Fatalf("decode body: %v", err)
|
||||||
|
}
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertDoneClosed(t *testing.T, done <-chan struct{}) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-time.After(500 * time.Millisecond):
|
||||||
|
t.Fatal("handler did not close done channel within timeout")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func changeInstalledAdminPassword(t *testing.T, envPath, newPassword string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
if err := initInstallConfig(envPath); err != nil {
|
||||||
|
t.Fatalf("reopen install config: %v", err)
|
||||||
|
}
|
||||||
|
if err := initInstallDatabases(); err != nil {
|
||||||
|
t.Fatalf("reopen install databases: %v", err)
|
||||||
|
}
|
||||||
|
defer closeInstallDatabases()
|
||||||
|
|
||||||
|
user, err := data.GetAdminUserByUsername("admin")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("load admin user: %v", err)
|
||||||
|
}
|
||||||
|
if user.ID == 0 {
|
||||||
|
t.Fatal("expected seeded admin user")
|
||||||
|
}
|
||||||
|
if err := data.UpdateAdminUserPassword(uint64(user.ID), newPassword); err != nil {
|
||||||
|
t.Fatalf("change admin password: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestInstallDefaults(t *testing.T) {
|
func TestInstallDefaults(t *testing.T) {
|
||||||
d := InstallDefaults()
|
d := InstallDefaults()
|
||||||
if d.AppName != "epusdt" {
|
if d.AppName != "epusdt" {
|
||||||
@@ -43,7 +123,7 @@ func TestWriteEnvFile(t *testing.T) {
|
|||||||
OrderExpirationTime: 15,
|
OrderExpirationTime: 15,
|
||||||
OrderNoticeMaxRetry: 3,
|
OrderNoticeMaxRetry: 3,
|
||||||
}
|
}
|
||||||
if err := writeEnvFile(path, req); err != nil {
|
if err := writeEnvFile(path, req, false); err != nil {
|
||||||
t.Fatalf("writeEnvFile: %v", err)
|
t.Fatalf("writeEnvFile: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,29 +224,30 @@ func TestInstallServerServesSPAOnInstallRoute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstallAPISubmit(t *testing.T) {
|
func TestInstallAPISubmitReturnsInitialPassword(t *testing.T) {
|
||||||
|
resetInstallTestState(t)
|
||||||
|
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
envPath := filepath.Join(dir, ".env")
|
envPath := filepath.Join(dir, ".env")
|
||||||
|
|
||||||
h := &installHandler{envFilePath: envPath, done: make(chan struct{})}
|
e, h := newInstallTestAPI(envPath)
|
||||||
e := echo.New()
|
|
||||||
e.POST("/install", h.Submit)
|
|
||||||
|
|
||||||
payload := `{"app_name":"testapp","app_uri":"http://10.0.0.1:8000","http_bind_addr":"0.0.0.0","http_bind_port":8000,"order_expiration_time":10,"order_notice_max_retry":1}`
|
payload := `{"app_name":"testapp","app_uri":"http://10.0.0.1:8000","http_bind_addr":"0.0.0.0","http_bind_port":8000,"order_expiration_time":10,"order_notice_max_retry":1}`
|
||||||
req := httptest.NewRequest(http.MethodPost, "/install", strings.NewReader(payload))
|
rec := submitInstallRequest(t, e, payload)
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
e.ServeHTTP(rec, req)
|
|
||||||
|
|
||||||
if rec.Code != http.StatusOK {
|
if rec.Code != http.StatusOK {
|
||||||
t.Fatalf("status = %d, want 200; body: %s", rec.Code, rec.Body.String())
|
t.Fatalf("status = %d, want 200; body: %s", rec.Code, rec.Body.String())
|
||||||
}
|
}
|
||||||
// done channel should be closed after successful submit
|
body := decodeBody(t, rec)
|
||||||
select {
|
if got, _ := body["message"].(string); got == "" {
|
||||||
case <-h.done:
|
t.Fatalf("expected success message, got body=%v", body)
|
||||||
case <-time.After(500 * time.Millisecond):
|
|
||||||
t.Fatal("handler did not close done channel within timeout")
|
|
||||||
}
|
}
|
||||||
|
initPassword, _ := body["init_password"].(string)
|
||||||
|
if strings.TrimSpace(initPassword) == "" {
|
||||||
|
t.Fatalf("expected non-empty init_password, got body=%v", body)
|
||||||
|
}
|
||||||
|
assertDoneClosed(t, h.done)
|
||||||
|
|
||||||
data, err := os.ReadFile(envPath)
|
data, err := os.ReadFile(envPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("env file not written: %v", err)
|
t.Fatalf("env file not written: %v", err)
|
||||||
@@ -178,20 +259,107 @@ func TestInstallAPISubmit(t *testing.T) {
|
|||||||
if !strings.Contains(content, "http_listen=0.0.0.0:8000") {
|
if !strings.Contains(content, "http_listen=0.0.0.0:8000") {
|
||||||
t.Errorf("env file missing http_listen; content:\n%s", content)
|
t.Errorf("env file missing http_listen; content:\n%s", content)
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(content, "install=false") {
|
||||||
|
t.Errorf("env file missing install=false; content:\n%s", content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstallAPISubmitRepeatInstallReturnsSamePasswordWhilePlaintextExists(t *testing.T) {
|
||||||
|
resetInstallTestState(t)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
envPath := filepath.Join(dir, ".env")
|
||||||
|
payload := `{"app_name":"testapp","app_uri":"http://10.0.0.1:8000","http_bind_addr":"0.0.0.0","http_bind_port":8000,"order_expiration_time":10,"order_notice_max_retry":1}`
|
||||||
|
|
||||||
|
e1, h1 := newInstallTestAPI(envPath)
|
||||||
|
rec1 := submitInstallRequest(t, e1, payload)
|
||||||
|
if rec1.Code != http.StatusOK {
|
||||||
|
t.Fatalf("first install status = %d, want 200; body: %s", rec1.Code, rec1.Body.String())
|
||||||
|
}
|
||||||
|
body1 := decodeBody(t, rec1)
|
||||||
|
password1, _ := body1["init_password"].(string)
|
||||||
|
if strings.TrimSpace(password1) == "" {
|
||||||
|
t.Fatalf("expected first init_password, got body=%v", body1)
|
||||||
|
}
|
||||||
|
assertDoneClosed(t, h1.done)
|
||||||
|
|
||||||
|
e2, h2 := newInstallTestAPI(envPath)
|
||||||
|
rec2 := submitInstallRequest(t, e2, payload)
|
||||||
|
if rec2.Code != http.StatusOK {
|
||||||
|
t.Fatalf("second install status = %d, want 200; body: %s", rec2.Code, rec2.Body.String())
|
||||||
|
}
|
||||||
|
body2 := decodeBody(t, rec2)
|
||||||
|
password2, _ := body2["init_password"].(string)
|
||||||
|
if password2 != password1 {
|
||||||
|
t.Fatalf("expected repeat install to return same init_password %q, got %q", password1, password2)
|
||||||
|
}
|
||||||
|
assertDoneClosed(t, h2.done)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstallAPISubmitRepeatInstallOmitsPasswordAfterPasswordChange(t *testing.T) {
|
||||||
|
resetInstallTestState(t)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
envPath := filepath.Join(dir, ".env")
|
||||||
|
payload := `{"app_name":"testapp","app_uri":"http://10.0.0.1:8000","http_bind_addr":"0.0.0.0","http_bind_port":8000,"order_expiration_time":10,"order_notice_max_retry":1}`
|
||||||
|
|
||||||
|
e1, h1 := newInstallTestAPI(envPath)
|
||||||
|
rec1 := submitInstallRequest(t, e1, payload)
|
||||||
|
if rec1.Code != http.StatusOK {
|
||||||
|
t.Fatalf("first install status = %d, want 200; body: %s", rec1.Code, rec1.Body.String())
|
||||||
|
}
|
||||||
|
assertDoneClosed(t, h1.done)
|
||||||
|
|
||||||
|
changeInstalledAdminPassword(t, envPath, "new-password-456")
|
||||||
|
|
||||||
|
e2, h2 := newInstallTestAPI(envPath)
|
||||||
|
rec2 := submitInstallRequest(t, e2, payload)
|
||||||
|
if rec2.Code != http.StatusOK {
|
||||||
|
t.Fatalf("repeat install status = %d, want 200; body: %s", rec2.Code, rec2.Body.String())
|
||||||
|
}
|
||||||
|
body2 := decodeBody(t, rec2)
|
||||||
|
if got, ok := body2["init_password"]; ok {
|
||||||
|
t.Fatalf("expected init_password to be omitted after password change, got %v", got)
|
||||||
|
}
|
||||||
|
if got, _ := body2["message"].(string); got == "" {
|
||||||
|
t.Fatalf("expected success message, got body=%v", body2)
|
||||||
|
}
|
||||||
|
assertDoneClosed(t, h2.done)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstallAPISubmitInitFailureKeepsInstallMode(t *testing.T) {
|
||||||
|
resetInstallTestState(t)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
envPath := filepath.Join(dir, ".env")
|
||||||
|
|
||||||
|
e, h := newInstallTestAPI(envPath)
|
||||||
|
payload := `{"app_name":"testapp","app_uri":"http://10.0.0.1:8000","http_bind_addr":"0.0.0.0","http_bind_port":8000,"runtime_root_path":"/dev/null/runtime","order_expiration_time":10,"order_notice_max_retry":1}`
|
||||||
|
rec := submitInstallRequest(t, e, payload)
|
||||||
|
if rec.Code != http.StatusInternalServerError {
|
||||||
|
t.Fatalf("status = %d, want 500; body: %s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-h.done:
|
||||||
|
t.Fatal("handler should not close done channel on init failure")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
}
|
||||||
|
contentBytes, err := os.ReadFile(envPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("read env after init failure: %v", err)
|
||||||
|
}
|
||||||
|
content := string(contentBytes)
|
||||||
|
if !strings.Contains(content, "install=true") {
|
||||||
|
t.Fatalf("expected env to keep install=true after failure; content:\n%s", content)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstallAPISubmitMissingURI(t *testing.T) {
|
func TestInstallAPISubmitMissingURI(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
envPath := filepath.Join(dir, ".env")
|
envPath := filepath.Join(dir, ".env")
|
||||||
|
|
||||||
h := &installHandler{envFilePath: envPath, done: make(chan struct{})}
|
e, _ := newInstallTestAPI(envPath)
|
||||||
e := echo.New()
|
rec := submitInstallRequest(t, e, `{"app_name":"x"}`)
|
||||||
e.POST("/install", h.Submit)
|
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodPost, "/install", strings.NewReader(`{"app_name":"x"}`))
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
e.ServeHTTP(rec, req)
|
|
||||||
|
|
||||||
if rec.Code != http.StatusBadRequest {
|
if rec.Code != http.StatusBadRequest {
|
||||||
t.Fatalf("status = %d, want 400", rec.Code)
|
t.Fatalf("status = %d, want 400", rec.Code)
|
||||||
@@ -205,15 +373,8 @@ func TestInstallAPISubmitInvalidPort(t *testing.T) {
|
|||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
envPath := filepath.Join(dir, ".env")
|
envPath := filepath.Join(dir, ".env")
|
||||||
|
|
||||||
h := &installHandler{envFilePath: envPath, done: make(chan struct{})}
|
e, _ := newInstallTestAPI(envPath)
|
||||||
e := echo.New()
|
rec := submitInstallRequest(t, e, `{"app_uri":"http://example.com","http_bind_port":99999}`)
|
||||||
e.POST("/install", h.Submit)
|
|
||||||
|
|
||||||
payload := `{"app_uri":"http://example.com","http_bind_port":99999}`
|
|
||||||
req := httptest.NewRequest(http.MethodPost, "/install", strings.NewReader(payload))
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
e.ServeHTTP(rec, req)
|
|
||||||
|
|
||||||
if rec.Code != http.StatusBadRequest {
|
if rec.Code != http.StatusBadRequest {
|
||||||
t.Fatalf("status = %d, want 400; body: %s", rec.Code, rec.Body.String())
|
t.Fatalf("status = %d, want 400; body: %s", rec.Code, rec.Body.String())
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ const (
|
|||||||
func CheckAdminJWT() echo.MiddlewareFunc {
|
func CheckAdminJWT() echo.MiddlewareFunc {
|
||||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
return func(ctx echo.Context) error {
|
return func(ctx echo.Context) error {
|
||||||
|
if ctx.Path() == "" {
|
||||||
|
return next(ctx)
|
||||||
|
}
|
||||||
token, err := adminTokenFromAuthorization(ctx.Request().Header.Get("Authorization"))
|
token, err := adminTokenFromAuthorization(ctx.Request().Header.Get("Authorization"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -14,6 +14,12 @@ import (
|
|||||||
|
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
|
|
||||||
|
// ResetMdbTableInitForTest resets the install/startup migration guard so tests
|
||||||
|
// can exercise fresh temporary databases in the same process.
|
||||||
|
func ResetMdbTableInitForTest() {
|
||||||
|
once = sync.Once{}
|
||||||
|
}
|
||||||
|
|
||||||
// MdbTableInit performs AutoMigrate for all primary DB tables and seeds
|
// MdbTableInit performs AutoMigrate for all primary DB tables and seeds
|
||||||
// the minimum static rows: chains, chain tokens, default settings, and
|
// the minimum static rows: chains, chain tokens, default settings, and
|
||||||
// a Telegram notification channel migrated from legacy settings keys.
|
// a Telegram notification channel migrated from legacy settings keys.
|
||||||
|
|||||||
@@ -40,39 +40,47 @@ type InitialAdminPasswordHashInfo struct {
|
|||||||
// can print it to the console. Idempotent — subsequent calls return
|
// can print it to the console. Idempotent — subsequent calls return
|
||||||
// ("", false, nil).
|
// ("", false, nil).
|
||||||
func EnsureDefaultAdmin() (password string, created bool, err error) {
|
func EnsureDefaultAdmin() (password string, created bool, err error) {
|
||||||
if err := purgeDeletedInitialAdminPasswordPlain(); err != nil {
|
if err := dao.Mdb.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if err := purgeDeletedInitialAdminPasswordPlainTx(tx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var count int64
|
||||||
|
if err := tx.Model(&mdb.AdminUser{}).Count(&count).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
password = randomAdminPassword()
|
||||||
|
hash, err := HashPassword(password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
user := &mdb.AdminUser{
|
||||||
|
Username: defaultAdminUsername,
|
||||||
|
PasswordHash: hash,
|
||||||
|
Status: mdb.AdminUserStatusEnable,
|
||||||
|
}
|
||||||
|
if err := tx.Create(user).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := initAdminPasswordStateTx(tx, password); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
created = true
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
return "", false, err
|
return "", false, err
|
||||||
}
|
}
|
||||||
var count int64
|
if created {
|
||||||
if err := dao.Mdb.Model(&mdb.AdminUser{}).Count(&count).Error; err != nil {
|
cacheInitialAdminPasswordState(password)
|
||||||
return "", false, err
|
|
||||||
}
|
}
|
||||||
if count > 0 {
|
return password, created, nil
|
||||||
return "", false, nil
|
|
||||||
}
|
|
||||||
password = randomAdminPassword()
|
|
||||||
hash, err := HashPassword(password)
|
|
||||||
if err != nil {
|
|
||||||
return "", false, err
|
|
||||||
}
|
|
||||||
user := &mdb.AdminUser{
|
|
||||||
Username: defaultAdminUsername,
|
|
||||||
PasswordHash: hash,
|
|
||||||
Status: mdb.AdminUserStatusEnable,
|
|
||||||
}
|
|
||||||
if err := dao.Mdb.Create(user).Error; err != nil {
|
|
||||||
return "", false, err
|
|
||||||
}
|
|
||||||
if err := initAdminPasswordState(password); err != nil {
|
|
||||||
// Account was already created; surface both for visibility while
|
|
||||||
// preserving created=true and password for emergency fallback.
|
|
||||||
return password, true, err
|
|
||||||
}
|
|
||||||
return password, true, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func purgeDeletedInitialAdminPasswordPlain() error {
|
func purgeDeletedInitialAdminPasswordPlainTx(tx *gorm.DB) error {
|
||||||
return dao.Mdb.Unscoped().
|
return tx.Unscoped().
|
||||||
Where("`key` = ? AND deleted_at IS NOT NULL", mdb.SettingKeyInitAdminPasswordPlain).
|
Where("`key` = ? AND deleted_at IS NOT NULL", mdb.SettingKeyInitAdminPasswordPlain).
|
||||||
Delete(&mdb.Setting{}).Error
|
Delete(&mdb.Setting{}).Error
|
||||||
}
|
}
|
||||||
@@ -91,12 +99,20 @@ func HashInitialAdminPassword(plain string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initAdminPasswordState(plain string) error {
|
func initAdminPasswordState(plain string) error {
|
||||||
|
if err := initAdminPasswordStateTx(dao.Mdb, plain); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cacheInitialAdminPasswordState(plain)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initAdminPasswordStateTx(tx *gorm.DB, plain string) error {
|
||||||
hash := HashInitialAdminPassword(plain)
|
hash := HashInitialAdminPassword(plain)
|
||||||
settings := []mdb.Setting{
|
settings := []mdb.Setting{
|
||||||
{
|
{
|
||||||
Group: mdb.SettingGroupSystem, Key: mdb.SettingKeyInitAdminPasswordPlain,
|
Group: mdb.SettingGroupSystem, Key: mdb.SettingKeyInitAdminPasswordPlain,
|
||||||
Value: plain, Type: mdb.SettingTypeString,
|
Value: plain, Type: mdb.SettingTypeString,
|
||||||
Description: "One-time readable initial admin password",
|
Description: "Readable initial admin password until password change",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Group: mdb.SettingGroupSystem, Key: mdb.SettingKeyInitAdminPasswordHash,
|
Group: mdb.SettingGroupSystem, Key: mdb.SettingKeyInitAdminPasswordHash,
|
||||||
@@ -106,7 +122,7 @@ func initAdminPasswordState(plain string) error {
|
|||||||
{
|
{
|
||||||
Group: mdb.SettingGroupSystem, Key: mdb.SettingKeyInitAdminPasswordFetched,
|
Group: mdb.SettingGroupSystem, Key: mdb.SettingKeyInitAdminPasswordFetched,
|
||||||
Value: "false", Type: mdb.SettingTypeBool,
|
Value: "false", Type: mdb.SettingTypeBool,
|
||||||
Description: "Whether initial admin password has been fetched",
|
Description: "Whether initial admin password plaintext has been cleared",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Group: mdb.SettingGroupSystem, Key: mdb.SettingKeyInitAdminPasswordChanged,
|
Group: mdb.SettingGroupSystem, Key: mdb.SettingKeyInitAdminPasswordChanged,
|
||||||
@@ -115,18 +131,21 @@ func initAdminPasswordState(plain string) error {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, row := range settings {
|
for _, row := range settings {
|
||||||
if err := upsertSettingRow(dao.Mdb, row); err != nil {
|
if err := upsertSettingRow(tx, row); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Keep in-process cache coherent for the current process.
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cacheInitialAdminPasswordState(plain string) {
|
||||||
|
hash := HashInitialAdminPassword(plain)
|
||||||
settingsCacheMu.Lock()
|
settingsCacheMu.Lock()
|
||||||
settingsCache[mdb.SettingKeyInitAdminPasswordPlain] = plain
|
settingsCache[mdb.SettingKeyInitAdminPasswordPlain] = plain
|
||||||
settingsCache[mdb.SettingKeyInitAdminPasswordHash] = hash
|
settingsCache[mdb.SettingKeyInitAdminPasswordHash] = hash
|
||||||
settingsCache[mdb.SettingKeyInitAdminPasswordFetched] = "false"
|
settingsCache[mdb.SettingKeyInitAdminPasswordFetched] = "false"
|
||||||
settingsCache[mdb.SettingKeyInitAdminPasswordChanged] = "false"
|
settingsCache[mdb.SettingKeyInitAdminPasswordChanged] = "false"
|
||||||
settingsCacheMu.Unlock()
|
settingsCacheMu.Unlock()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func upsertSettingRow(tx *gorm.DB, row mdb.Setting) error {
|
func upsertSettingRow(tx *gorm.DB, row mdb.Setting) error {
|
||||||
@@ -138,56 +157,51 @@ func upsertSettingRow(tx *gorm.DB, row mdb.Setting) error {
|
|||||||
}).Create(&row).Error
|
}).Create(&row).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConsumeInitialAdminPassword returns the one-time initial admin password.
|
// GetInitialAdminPassword returns the initial admin password plaintext while
|
||||||
// After a successful read, the plaintext is deleted and cannot be fetched
|
// it is still available. The plaintext remains readable until the admin
|
||||||
// again.
|
// password is changed, after which the stored plaintext is deleted.
|
||||||
func ConsumeInitialAdminPassword() (string, error) {
|
func GetInitialAdminPassword() (string, error) {
|
||||||
var password string
|
row := new(mdb.Setting)
|
||||||
err := dao.Mdb.Transaction(func(tx *gorm.DB) error {
|
if err := dao.Mdb.Model(&mdb.Setting{}).
|
||||||
row := new(mdb.Setting)
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
||||||
if err := tx.Model(&mdb.Setting{}).
|
Limit(1).
|
||||||
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
Find(row).Error; err != nil {
|
||||||
Limit(1).
|
|
||||||
Find(row).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if row.ID == 0 || row.Value == "" {
|
|
||||||
var fetched mdb.Setting
|
|
||||||
if err := tx.Model(&mdb.Setting{}).
|
|
||||||
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordFetched).
|
|
||||||
Limit(1).
|
|
||||||
Find(&fetched).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if strings.EqualFold(strings.TrimSpace(fetched.Value), "true") {
|
|
||||||
return ErrInitAdminPasswordAlreadyFetched
|
|
||||||
}
|
|
||||||
return ErrInitAdminPasswordUnavailable
|
|
||||||
}
|
|
||||||
password = row.Value
|
|
||||||
res := tx.Unscoped().Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).Delete(&mdb.Setting{})
|
|
||||||
if res.Error != nil {
|
|
||||||
return res.Error
|
|
||||||
}
|
|
||||||
if res.RowsAffected == 0 {
|
|
||||||
return ErrInitAdminPasswordAlreadyFetched
|
|
||||||
}
|
|
||||||
return upsertSettingRow(tx, mdb.Setting{
|
|
||||||
Group: mdb.SettingGroupSystem,
|
|
||||||
Key: mdb.SettingKeyInitAdminPasswordFetched,
|
|
||||||
Value: "true",
|
|
||||||
Type: mdb.SettingTypeBool,
|
|
||||||
Description: "Whether initial admin password has been fetched",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
settingsCacheMu.Lock()
|
if row.ID != 0 && row.Value != "" {
|
||||||
delete(settingsCache, mdb.SettingKeyInitAdminPasswordPlain)
|
return row.Value, nil
|
||||||
settingsCache[mdb.SettingKeyInitAdminPasswordFetched] = "true"
|
}
|
||||||
settingsCacheMu.Unlock()
|
|
||||||
return password, nil
|
var fetched mdb.Setting
|
||||||
|
if err := dao.Mdb.Model(&mdb.Setting{}).
|
||||||
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordFetched).
|
||||||
|
Limit(1).
|
||||||
|
Find(&fetched).Error; err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if strings.EqualFold(strings.TrimSpace(fetched.Value), "true") {
|
||||||
|
return "", ErrInitAdminPasswordAlreadyFetched
|
||||||
|
}
|
||||||
|
return "", ErrInitAdminPasswordUnavailable
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearInitialAdminPasswordPlain(tx *gorm.DB) error {
|
||||||
|
res := tx.Unscoped().
|
||||||
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
||||||
|
Delete(&mdb.Setting{})
|
||||||
|
if res.Error != nil {
|
||||||
|
return res.Error
|
||||||
|
}
|
||||||
|
if err := upsertSettingRow(tx, mdb.Setting{
|
||||||
|
Group: mdb.SettingGroupSystem,
|
||||||
|
Key: mdb.SettingKeyInitAdminPasswordFetched,
|
||||||
|
Value: "true",
|
||||||
|
Type: mdb.SettingTypeBool,
|
||||||
|
Description: "Whether initial admin password plaintext has been cleared",
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInitialAdminPasswordHashInfo returns the initial-password fingerprint
|
// GetInitialAdminPasswordHashInfo returns the initial-password fingerprint
|
||||||
@@ -250,12 +264,15 @@ func GetAdminUserByID(id uint64) (*mdb.AdminUser, error) {
|
|||||||
return u, err
|
return u, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateAdminUserPassword rehashes and persists a new password.
|
// UpdateAdminUserPassword rehashes and persists a new password. When the
|
||||||
|
// change succeeds, the stored initial-password plaintext is deleted so it can
|
||||||
|
// no longer be returned by the install flow.
|
||||||
func UpdateAdminUserPassword(id uint64, newPlain string) error {
|
func UpdateAdminUserPassword(id uint64, newPlain string) error {
|
||||||
hash, err := HashPassword(newPlain)
|
hash, err := HashPassword(newPlain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
clearedPlaintext := false
|
||||||
changedCacheValue := ""
|
changedCacheValue := ""
|
||||||
err = dao.Mdb.Transaction(func(tx *gorm.DB) error {
|
err = dao.Mdb.Transaction(func(tx *gorm.DB) error {
|
||||||
if err := tx.Model(&mdb.AdminUser{}).
|
if err := tx.Model(&mdb.AdminUser{}).
|
||||||
@@ -264,8 +281,18 @@ func UpdateAdminUserPassword(id uint64, newPlain string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var plainRow mdb.Setting
|
||||||
|
if err := tx.Model(&mdb.Setting{}).
|
||||||
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
||||||
|
Limit(1).
|
||||||
|
Find(&plainRow).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hasPlaintext := plainRow.ID != 0 && strings.TrimSpace(plainRow.Value) != ""
|
||||||
|
|
||||||
// Old installs may not have initial-password metadata; skip in
|
// Old installs may not have initial-password metadata; skip in
|
||||||
// that case to keep password updates backward compatible.
|
// that case to keep password_changed backward compatible, but still
|
||||||
|
// clear any leftover plaintext if it exists.
|
||||||
var initHashRow mdb.Setting
|
var initHashRow mdb.Setting
|
||||||
if err := tx.Model(&mdb.Setting{}).
|
if err := tx.Model(&mdb.Setting{}).
|
||||||
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordHash).
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordHash).
|
||||||
@@ -275,6 +302,12 @@ func UpdateAdminUserPassword(id uint64, newPlain string) error {
|
|||||||
}
|
}
|
||||||
initHash := strings.TrimSpace(initHashRow.Value)
|
initHash := strings.TrimSpace(initHashRow.Value)
|
||||||
if initHash == "" {
|
if initHash == "" {
|
||||||
|
if hasPlaintext {
|
||||||
|
if err := clearInitialAdminPasswordPlain(tx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clearedPlaintext = true
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,15 +326,25 @@ func UpdateAdminUserPassword(id uint64, newPlain string) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := clearInitialAdminPasswordPlain(tx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clearedPlaintext = true
|
||||||
changedCacheValue = changedValue
|
changedCacheValue = changedValue
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if changedCacheValue != "" {
|
if clearedPlaintext || changedCacheValue != "" {
|
||||||
settingsCacheMu.Lock()
|
settingsCacheMu.Lock()
|
||||||
settingsCache[mdb.SettingKeyInitAdminPasswordChanged] = changedCacheValue
|
if clearedPlaintext {
|
||||||
|
delete(settingsCache, mdb.SettingKeyInitAdminPasswordPlain)
|
||||||
|
settingsCache[mdb.SettingKeyInitAdminPasswordFetched] = "true"
|
||||||
|
}
|
||||||
|
if changedCacheValue != "" {
|
||||||
|
settingsCache[mdb.SettingKeyInitAdminPasswordChanged] = changedCacheValue
|
||||||
|
}
|
||||||
settingsCacheMu.Unlock()
|
settingsCacheMu.Unlock()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func TestUpsertSettingRowRestoresSoftDeletedSetting(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConsumeInitialAdminPasswordHardDeletesPlaintext(t *testing.T) {
|
func TestGetInitialAdminPasswordKeepsPlaintext(t *testing.T) {
|
||||||
cleanup := testutil.SetupTestDatabases(t)
|
cleanup := testutil.SetupTestDatabases(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
@@ -51,14 +51,58 @@ func TestConsumeInitialAdminPasswordHardDeletesPlaintext(t *testing.T) {
|
|||||||
t.Fatalf("seed initial password state: %v", err)
|
t.Fatalf("seed initial password state: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
got, err := ConsumeInitialAdminPassword()
|
got, err := GetInitialAdminPassword()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("consume initial password: %v", err)
|
t.Fatalf("get initial password: %v", err)
|
||||||
}
|
}
|
||||||
if got != password {
|
if got != password {
|
||||||
t.Fatalf("password = %q, want %q", got, password)
|
t.Fatalf("password = %q, want %q", got, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
if err := dao.Mdb.Unscoped().
|
||||||
|
Model(&mdb.Setting{}).
|
||||||
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
||||||
|
Count(&count).Error; err != nil {
|
||||||
|
t.Fatalf("count plaintext setting: %v", err)
|
||||||
|
}
|
||||||
|
if count != 1 {
|
||||||
|
t.Fatalf("plaintext setting rows after read = %d, want 1", count)
|
||||||
|
}
|
||||||
|
if GetSettingBool(mdb.SettingKeyInitAdminPasswordFetched, false) {
|
||||||
|
t.Fatal("expected fetched flag to stay false before password change")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateAdminUserPasswordHardDeletesInitialPasswordPlaintext(t *testing.T) {
|
||||||
|
cleanup := testutil.SetupTestDatabases(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
const (
|
||||||
|
oldPassword = "init-pass-plain"
|
||||||
|
newPassword = "new-password-123"
|
||||||
|
)
|
||||||
|
if err := initAdminPasswordState(oldPassword); err != nil {
|
||||||
|
t.Fatalf("seed initial password state: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err := HashPassword(oldPassword)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("hash password: %v", err)
|
||||||
|
}
|
||||||
|
user := &mdb.AdminUser{
|
||||||
|
Username: defaultAdminUsername,
|
||||||
|
PasswordHash: hash,
|
||||||
|
Status: mdb.AdminUserStatusEnable,
|
||||||
|
}
|
||||||
|
if err := dao.Mdb.Create(user).Error; err != nil {
|
||||||
|
t.Fatalf("seed admin user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := UpdateAdminUserPassword(uint64(user.ID), newPassword); err != nil {
|
||||||
|
t.Fatalf("update admin password: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
var count int64
|
var count int64
|
||||||
if err := dao.Mdb.Unscoped().
|
if err := dao.Mdb.Unscoped().
|
||||||
Model(&mdb.Setting{}).
|
Model(&mdb.Setting{}).
|
||||||
@@ -67,10 +111,59 @@ func TestConsumeInitialAdminPasswordHardDeletesPlaintext(t *testing.T) {
|
|||||||
t.Fatalf("count plaintext setting: %v", err)
|
t.Fatalf("count plaintext setting: %v", err)
|
||||||
}
|
}
|
||||||
if count != 0 {
|
if count != 0 {
|
||||||
t.Fatalf("plaintext setting rows after consume = %d, want 0", count)
|
t.Fatalf("plaintext setting rows after password change = %d, want 0", count)
|
||||||
}
|
}
|
||||||
if !GetSettingBool(mdb.SettingKeyInitAdminPasswordFetched, false) {
|
if !GetSettingBool(mdb.SettingKeyInitAdminPasswordFetched, false) {
|
||||||
t.Fatal("expected fetched flag to be true")
|
t.Fatal("expected fetched flag to be true after password change")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateAdminUserPasswordHardDeletesPlaintextWithoutHashMetadata(t *testing.T) {
|
||||||
|
cleanup := testutil.SetupTestDatabases(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
const (
|
||||||
|
oldPassword = "legacy-init-pass"
|
||||||
|
newPassword = "new-password-456"
|
||||||
|
)
|
||||||
|
if err := upsertSettingRow(dao.Mdb, mdb.Setting{
|
||||||
|
Group: mdb.SettingGroupSystem,
|
||||||
|
Key: mdb.SettingKeyInitAdminPasswordPlain,
|
||||||
|
Value: oldPassword,
|
||||||
|
Type: mdb.SettingTypeString,
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatalf("seed plaintext setting: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err := HashPassword(oldPassword)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("hash password: %v", err)
|
||||||
|
}
|
||||||
|
user := &mdb.AdminUser{
|
||||||
|
Username: defaultAdminUsername,
|
||||||
|
PasswordHash: hash,
|
||||||
|
Status: mdb.AdminUserStatusEnable,
|
||||||
|
}
|
||||||
|
if err := dao.Mdb.Create(user).Error; err != nil {
|
||||||
|
t.Fatalf("seed admin user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := UpdateAdminUserPassword(uint64(user.ID), newPassword); err != nil {
|
||||||
|
t.Fatalf("update admin password: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
if err := dao.Mdb.Unscoped().
|
||||||
|
Model(&mdb.Setting{}).
|
||||||
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
||||||
|
Count(&count).Error; err != nil {
|
||||||
|
t.Fatalf("count plaintext setting: %v", err)
|
||||||
|
}
|
||||||
|
if count != 0 {
|
||||||
|
t.Fatalf("plaintext setting rows after password change = %d, want 0", count)
|
||||||
|
}
|
||||||
|
if !GetSettingBool(mdb.SettingKeyInitAdminPasswordFetched, false) {
|
||||||
|
t.Fatal("expected fetched flag to be true after clearing plaintext")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,3 +213,55 @@ func TestEnsureDefaultAdminPurgesLegacySoftDeletedPlaintext(t *testing.T) {
|
|||||||
t.Fatalf("legacy plaintext rows after ensure = %d, want 0", count)
|
t.Fatalf("legacy plaintext rows after ensure = %d, want 0", count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEnsureDefaultAdminRollsBackWhenInitialPasswordStateFails(t *testing.T) {
|
||||||
|
cleanup := testutil.SetupTestDatabases(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
if err := dao.Mdb.Exec(`
|
||||||
|
CREATE TRIGGER fail_initial_password_state
|
||||||
|
BEFORE INSERT ON settings
|
||||||
|
WHEN NEW.key = 'system.init_admin_password_plain'
|
||||||
|
BEGIN
|
||||||
|
SELECT RAISE(FAIL, 'forced initial password state failure');
|
||||||
|
END;
|
||||||
|
`).Error; err != nil {
|
||||||
|
t.Fatalf("create failure trigger: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
password, created, err := EnsureDefaultAdmin()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected EnsureDefaultAdmin to fail")
|
||||||
|
}
|
||||||
|
if created || password != "" {
|
||||||
|
t.Fatalf("created=%v password=%q, want no created admin on failure", created, password)
|
||||||
|
}
|
||||||
|
|
||||||
|
var adminCount int64
|
||||||
|
if err := dao.Mdb.Model(&mdb.AdminUser{}).Count(&adminCount).Error; err != nil {
|
||||||
|
t.Fatalf("count admin users after failure: %v", err)
|
||||||
|
}
|
||||||
|
if adminCount != 0 {
|
||||||
|
t.Fatalf("admin users after failed initial password state = %d, want 0", adminCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dao.Mdb.Exec(`DROP TRIGGER fail_initial_password_state`).Error; err != nil {
|
||||||
|
t.Fatalf("drop failure trigger: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
password, created, err = EnsureDefaultAdmin()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("retry EnsureDefaultAdmin: %v", err)
|
||||||
|
}
|
||||||
|
if !created || password == "" {
|
||||||
|
t.Fatalf("retry created=%v password=%q, want new admin with password", created, password)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := GetInitialAdminPassword()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("get initial password after retry: %v", err)
|
||||||
|
}
|
||||||
|
if got != password {
|
||||||
|
t.Fatalf("initial password after retry = %q, want %q", got, password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ type Orders struct {
|
|||||||
NotifyUrl string `gorm:"column:notify_url" json:"notify_url" example:"https://example.com/notify"`
|
NotifyUrl string `gorm:"column:notify_url" json:"notify_url" example:"https://example.com/notify"`
|
||||||
RedirectUrl string `gorm:"column:redirect_url" json:"redirect_url" example:"https://example.com/success"`
|
RedirectUrl string `gorm:"column:redirect_url" json:"redirect_url" example:"https://example.com/success"`
|
||||||
Name string `gorm:"column:name" json:"name" example:"VIP月卡"`
|
Name string `gorm:"column:name" json:"name" example:"VIP月卡"`
|
||||||
|
EpayType string `gorm:"column:epay_type;size:64;default:''" json:"-"`
|
||||||
CallbackNum int `gorm:"column:callback_num;default:0" json:"callback_num" example:"0"`
|
CallbackNum int `gorm:"column:callback_num;default:0" json:"callback_num" example:"0"`
|
||||||
// 回调确认状态 1=回调成功 2=未回调/回调失败
|
// 回调确认状态 1=回调成功 2=未回调/回调失败
|
||||||
CallBackConfirm int `gorm:"column:callback_confirm;default:2" json:"callback_confirm" enums:"1,2" example:"2"`
|
CallBackConfirm int `gorm:"column:callback_confirm;default:2" json:"callback_confirm" enums:"1,2" example:"2"`
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ type CreateTransactionRequest struct {
|
|||||||
// empty or any other value is stored as "Gmpay" and uses GMPay JSON.
|
// empty or any other value is stored as "Gmpay" and uses GMPay JSON.
|
||||||
// It is optional for GMPay, but must be included in the signature when sent.
|
// It is optional for GMPay, but must be included in the signature when sent.
|
||||||
PaymentType string `json:"payment_type" form:"payment_type" example:"Epay"`
|
PaymentType string `json:"payment_type" form:"payment_type" example:"Epay"`
|
||||||
|
EpayType string `json:"-" form:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r CreateTransactionRequest) Translates() map[string]string {
|
func (r CreateTransactionRequest) Translates() map[string]string {
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ type NetworkTokenSupport struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type EpayPublicConfig struct {
|
type EpayPublicConfig struct {
|
||||||
DefaultToken string `json:"default_token" example:""` // EPay default token; empty means submit.php can create a status=4 placeholder when request token/network are also absent.
|
DefaultToken string `json:"default_token" example:""` // EPay default token; ignored when a supported type=token.network selector is supplied. Empty means submit.php can create a status=4 placeholder when request token/network are also absent.
|
||||||
DefaultCurrency string `json:"default_currency" example:"cny"` // EPay default fiat currency; falls back to cny when unset.
|
DefaultCurrency string `json:"default_currency" example:"cny"` // EPay default fiat currency; still applies when a supported type selector is supplied and falls back to cny when unset.
|
||||||
DefaultNetwork string `json:"default_network" example:""` // EPay default network; empty means submit.php can create a status=4 placeholder when request token/network are also absent.
|
DefaultNetwork string `json:"default_network" example:""` // EPay default network; ignored when a supported type=token.network selector is supplied. Empty means submit.php can create a status=4 placeholder when request token/network are also absent.
|
||||||
}
|
}
|
||||||
|
|
||||||
type SitePublicConfig struct {
|
type SitePublicConfig struct {
|
||||||
|
|||||||
@@ -71,6 +71,16 @@ func ResolveOrderApiKey(order *mdb.Orders) (*mdb.ApiKey, error) {
|
|||||||
return row, nil
|
return row, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func epayResultType(order *mdb.Orders) string {
|
||||||
|
if order == nil {
|
||||||
|
return "alipay"
|
||||||
|
}
|
||||||
|
if epayType := strings.TrimSpace(order.EpayType); epayType != "" {
|
||||||
|
return epayType
|
||||||
|
}
|
||||||
|
return "alipay"
|
||||||
|
}
|
||||||
|
|
||||||
func BuildEPayResultParams(order *mdb.Orders, apiKeyRow *mdb.ApiKey) (map[string]string, error) {
|
func BuildEPayResultParams(order *mdb.Orders, apiKeyRow *mdb.ApiKey) (map[string]string, error) {
|
||||||
if order == nil || apiKeyRow == nil {
|
if order == nil || apiKeyRow == nil {
|
||||||
return nil, constant.EPayReturnSignatureErr
|
return nil, constant.EPayReturnSignatureErr
|
||||||
@@ -85,7 +95,7 @@ func BuildEPayResultParams(order *mdb.Orders, apiKeyRow *mdb.ApiKey) (map[string
|
|||||||
PID: pidInt,
|
PID: pidInt,
|
||||||
TradeNo: order.TradeId,
|
TradeNo: order.TradeId,
|
||||||
OutTradeNo: order.OrderId,
|
OutTradeNo: order.OrderId,
|
||||||
Type: "alipay",
|
Type: epayResultType(order),
|
||||||
Name: order.Name,
|
Name: order.Name,
|
||||||
Money: fmt.Sprintf("%.4f", order.Amount),
|
Money: fmt.Sprintf("%.4f", order.Amount),
|
||||||
TradeStatus: "TRADE_SUCCESS",
|
TradeStatus: "TRADE_SUCCESS",
|
||||||
|
|||||||
@@ -40,12 +40,13 @@ func TestBuildPublicRedirectURLRewritesOnlyEpayOrders(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildEPayResultParamsMatchesLegacyFields(t *testing.T) {
|
func TestBuildEPayResultParamsUsesOriginalType(t *testing.T) {
|
||||||
params, err := BuildEPayResultParams(&mdb.Orders{
|
params, err := BuildEPayResultParams(&mdb.Orders{
|
||||||
TradeId: "trade_epay_params",
|
TradeId: "trade_epay_params",
|
||||||
OrderId: "order_epay_params",
|
OrderId: "order_epay_params",
|
||||||
Name: "VIP",
|
Name: "VIP",
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
|
EpayType: "usdt.tron",
|
||||||
}, &mdb.ApiKey{
|
}, &mdb.ApiKey{
|
||||||
Pid: "1001",
|
Pid: "1001",
|
||||||
SecretKey: "epay-secret",
|
SecretKey: "epay-secret",
|
||||||
@@ -58,7 +59,7 @@ func TestBuildEPayResultParamsMatchesLegacyFields(t *testing.T) {
|
|||||||
"pid": "1001",
|
"pid": "1001",
|
||||||
"trade_no": "trade_epay_params",
|
"trade_no": "trade_epay_params",
|
||||||
"out_trade_no": "order_epay_params",
|
"out_trade_no": "order_epay_params",
|
||||||
"type": "alipay",
|
"type": "usdt.tron",
|
||||||
"name": "VIP",
|
"name": "VIP",
|
||||||
"money": "1.0000",
|
"money": "1.0000",
|
||||||
"trade_status": "TRADE_SUCCESS",
|
"trade_status": "TRADE_SUCCESS",
|
||||||
@@ -88,6 +89,24 @@ func TestBuildEPayResultParamsMatchesLegacyFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildEPayResultParamsFallsBackToAlipayWhenTypeMissing(t *testing.T) {
|
||||||
|
params, err := BuildEPayResultParams(&mdb.Orders{
|
||||||
|
TradeId: "trade_epay_fallback",
|
||||||
|
OrderId: "order_epay_fallback",
|
||||||
|
Name: "VIP",
|
||||||
|
Amount: 1,
|
||||||
|
}, &mdb.ApiKey{
|
||||||
|
Pid: "1001",
|
||||||
|
SecretKey: "epay-secret",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("BuildEPayResultParams(): %v", err)
|
||||||
|
}
|
||||||
|
if got := params["type"]; got != "alipay" {
|
||||||
|
t.Fatalf("type = %q, want alipay", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuildEPayResultParamsRejectsNonNumericPid(t *testing.T) {
|
func TestBuildEPayResultParamsRejectsNonNumericPid(t *testing.T) {
|
||||||
_, err := BuildEPayResultParams(&mdb.Orders{
|
_, err := BuildEPayResultParams(&mdb.Orders{
|
||||||
TradeId: "trade_bad_pid",
|
TradeId: "trade_bad_pid",
|
||||||
|
|||||||
@@ -116,6 +116,10 @@ func CreateTransaction(req *request.CreateTransactionRequest, apiKey *mdb.ApiKey
|
|||||||
if strings.EqualFold(req.PaymentType, mdb.PaymentTypeEpay) {
|
if strings.EqualFold(req.PaymentType, mdb.PaymentTypeEpay) {
|
||||||
paymentType = mdb.PaymentTypeEpay
|
paymentType = mdb.PaymentTypeEpay
|
||||||
}
|
}
|
||||||
|
epayType := ""
|
||||||
|
if paymentType == mdb.PaymentTypeEpay {
|
||||||
|
epayType = strings.TrimSpace(req.EpayType)
|
||||||
|
}
|
||||||
|
|
||||||
gCreateTransactionLock.Lock()
|
gCreateTransactionLock.Lock()
|
||||||
defer gCreateTransactionLock.Unlock()
|
defer gCreateTransactionLock.Unlock()
|
||||||
@@ -146,6 +150,7 @@ func CreateTransaction(req *request.CreateTransactionRequest, apiKey *mdb.ApiKey
|
|||||||
NotifyUrl: notifyURL,
|
NotifyUrl: notifyURL,
|
||||||
RedirectUrl: req.RedirectUrl,
|
RedirectUrl: req.RedirectUrl,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
|
EpayType: epayType,
|
||||||
PaymentType: paymentType,
|
PaymentType: paymentType,
|
||||||
PayProvider: mdb.PaymentProviderOnChain,
|
PayProvider: mdb.PaymentProviderOnChain,
|
||||||
ApiKeyID: apiKeyID(apiKey),
|
ApiKeyID: apiKeyID(apiKey),
|
||||||
@@ -205,6 +210,7 @@ func CreateTransaction(req *request.CreateTransactionRequest, apiKey *mdb.ApiKey
|
|||||||
NotifyUrl: notifyURL,
|
NotifyUrl: notifyURL,
|
||||||
RedirectUrl: req.RedirectUrl,
|
RedirectUrl: req.RedirectUrl,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
|
EpayType: epayType,
|
||||||
PaymentType: paymentType,
|
PaymentType: paymentType,
|
||||||
PayProvider: mdb.PaymentProviderOnChain,
|
PayProvider: mdb.PaymentProviderOnChain,
|
||||||
ApiKeyID: apiKeyID(apiKey),
|
ApiKeyID: apiKeyID(apiKey),
|
||||||
@@ -637,6 +643,7 @@ func SwitchNetwork(req *request.SwitchNetworkRequest) (*response.CheckoutCounter
|
|||||||
NotifyUrl: "",
|
NotifyUrl: "",
|
||||||
RedirectUrl: parent.RedirectUrl,
|
RedirectUrl: parent.RedirectUrl,
|
||||||
Name: parent.Name,
|
Name: parent.Name,
|
||||||
|
EpayType: parent.EpayType,
|
||||||
CallBackConfirm: mdb.CallBackConfirmOk, // don't trigger callback on sub-order
|
CallBackConfirm: mdb.CallBackConfirmOk, // don't trigger callback on sub-order
|
||||||
PaymentType: parent.PaymentType,
|
PaymentType: parent.PaymentType,
|
||||||
PayProvider: mdb.PaymentProviderOnChain,
|
PayProvider: mdb.PaymentProviderOnChain,
|
||||||
@@ -916,6 +923,7 @@ func switchToOkPay(parent *mdb.Orders, token string) (*response.CheckoutCounterR
|
|||||||
NotifyUrl: "",
|
NotifyUrl: "",
|
||||||
RedirectUrl: parent.RedirectUrl,
|
RedirectUrl: parent.RedirectUrl,
|
||||||
Name: parent.Name,
|
Name: parent.Name,
|
||||||
|
EpayType: parent.EpayType,
|
||||||
CallBackConfirm: mdb.CallBackConfirmOk,
|
CallBackConfirm: mdb.CallBackConfirmOk,
|
||||||
PaymentType: parent.PaymentType,
|
PaymentType: parent.PaymentType,
|
||||||
PayProvider: mdb.PaymentProviderOkPay,
|
PayProvider: mdb.PaymentProviderOkPay,
|
||||||
|
|||||||
+74
-2
@@ -573,6 +573,7 @@ func TestSendOrderCallbackEpayUsesApiKeySecretByPid(t *testing.T) {
|
|||||||
Status: mdb.StatusPaySuccess,
|
Status: mdb.StatusPaySuccess,
|
||||||
NotifyUrl: server.URL,
|
NotifyUrl: server.URL,
|
||||||
BlockTransactionId: "block_epay_sign",
|
BlockTransactionId: "block_epay_sign",
|
||||||
|
EpayType: "usdt.tron",
|
||||||
PaymentType: "epay",
|
PaymentType: "epay",
|
||||||
ApiKeyID: key.ID,
|
ApiKeyID: key.ID,
|
||||||
}
|
}
|
||||||
@@ -587,8 +588,8 @@ func TestSendOrderCallbackEpayUsesApiKeySecretByPid(t *testing.T) {
|
|||||||
if formPayload["sign_type"] != "MD5" {
|
if formPayload["sign_type"] != "MD5" {
|
||||||
t.Fatalf("sign_type = %q, want MD5", formPayload["sign_type"])
|
t.Fatalf("sign_type = %q, want MD5", formPayload["sign_type"])
|
||||||
}
|
}
|
||||||
if formPayload["type"] != "alipay" {
|
if formPayload["type"] != "usdt.tron" {
|
||||||
t.Fatalf("type = %q, want alipay", formPayload["type"])
|
t.Fatalf("type = %q, want usdt.tron", formPayload["type"])
|
||||||
}
|
}
|
||||||
if formPayload["trade_status"] != "TRADE_SUCCESS" {
|
if formPayload["trade_status"] != "TRADE_SUCCESS" {
|
||||||
t.Fatalf("trade_status = %q, want TRADE_SUCCESS", formPayload["trade_status"])
|
t.Fatalf("trade_status = %q, want TRADE_SUCCESS", formPayload["trade_status"])
|
||||||
@@ -629,6 +630,77 @@ func TestSendOrderCallbackEpayUsesApiKeySecretByPid(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSendOrderCallbackEpayPreservesStoredAlipayType(t *testing.T) {
|
||||||
|
cleanup := testutil.SetupTestDatabases(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
key := &mdb.ApiKey{
|
||||||
|
Name: "epay-key-stored-type",
|
||||||
|
Pid: "9201",
|
||||||
|
SecretKey: "epay-secret-9201",
|
||||||
|
Status: mdb.ApiKeyStatusEnable,
|
||||||
|
}
|
||||||
|
if err := dao.Mdb.Create(key).Error; err != nil {
|
||||||
|
t.Fatalf("create epay api key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
formPayload := map[string]string{}
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for k, v := range r.Form {
|
||||||
|
if len(v) > 0 {
|
||||||
|
formPayload[k] = v[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, _ = io.WriteString(w, "ok")
|
||||||
|
}))
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
order := &mdb.Orders{
|
||||||
|
TradeId: "trade_epay_type_case_alipay",
|
||||||
|
OrderId: "order_epay_type_case_alipay",
|
||||||
|
Amount: 1,
|
||||||
|
Currency: "CNY",
|
||||||
|
ActualAmount: 1,
|
||||||
|
ReceiveAddress: "wallet_epay_type_case",
|
||||||
|
Token: "USDT",
|
||||||
|
Name: "VIP",
|
||||||
|
Status: mdb.StatusPaySuccess,
|
||||||
|
NotifyUrl: server.URL,
|
||||||
|
BlockTransactionId: "block_epay_type_case_alipay",
|
||||||
|
EpayType: "alipay",
|
||||||
|
PaymentType: "epay",
|
||||||
|
ApiKeyID: key.ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sendOrderCallback(order); err != nil {
|
||||||
|
t.Fatalf("send epay callback: %v", err)
|
||||||
|
}
|
||||||
|
if got := formPayload["type"]; got != "alipay" {
|
||||||
|
t.Fatalf("type = %q, want alipay", got)
|
||||||
|
}
|
||||||
|
|
||||||
|
signParams := map[string]interface{}{
|
||||||
|
"pid": formPayload["pid"],
|
||||||
|
"trade_no": formPayload["trade_no"],
|
||||||
|
"out_trade_no": formPayload["out_trade_no"],
|
||||||
|
"type": formPayload["type"],
|
||||||
|
"name": formPayload["name"],
|
||||||
|
"money": formPayload["money"],
|
||||||
|
"trade_status": formPayload["trade_status"],
|
||||||
|
}
|
||||||
|
calcSig, err := sign.Get(signParams, key.SecretKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("calc epay signature: %v", err)
|
||||||
|
}
|
||||||
|
if got := formPayload["sign"]; got != calcSig {
|
||||||
|
t.Fatalf("sign = %q, want %q", got, calcSig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDispatchPendingCallbacksEpayAcceptsSuccessAck(t *testing.T) {
|
func TestDispatchPendingCallbacksEpayAcceptsSuccessAck(t *testing.T) {
|
||||||
cleanup := testutil.SetupTestDatabases(t)
|
cleanup := testutil.SetupTestDatabases(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|||||||
@@ -290,9 +290,9 @@ func TestAdminChangePassword(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestAdminInitPasswordFlow verifies the one-time initial password endpoint
|
// TestAdminInitialPasswordMetadataFlow verifies that the public plaintext route
|
||||||
// and hash-based "password changed" detection flow.
|
// is gone while the hash-based default-password detection flow still works.
|
||||||
func TestAdminInitPasswordFlow(t *testing.T) {
|
func TestAdminInitialPasswordMetadataFlow(t *testing.T) {
|
||||||
e := setupTestEnv(t)
|
e := setupTestEnv(t)
|
||||||
const initPassword = "init-pass-123456"
|
const initPassword = "init-pass-123456"
|
||||||
|
|
||||||
@@ -320,14 +320,11 @@ func TestAdminInitPasswordFlow(t *testing.T) {
|
|||||||
t.Fatalf("expected password_changed=false before change, got true")
|
t.Fatalf("expected password_changed=false before change, got true")
|
||||||
}
|
}
|
||||||
|
|
||||||
recFetch := doGet(e, "/admin/api/v1/auth/init-password")
|
token := adminLogin(t, e, testAdminUsername, initPassword)
|
||||||
respFetch := assertOK(t, recFetch)
|
|
||||||
fetchData, _ := respFetch["data"].(map[string]interface{})
|
recFetch := doGetAdmin(e, "/admin/api/v1/auth/init-password", token)
|
||||||
if fetchData["username"] != testAdminUsername {
|
if recFetch.Code != http.StatusNotFound {
|
||||||
t.Fatalf("expected username=%s, got %v", testAdminUsername, fetchData["username"])
|
t.Fatalf("expected removed init-password route to return 404, got %d body=%s", recFetch.Code, recFetch.Body.String())
|
||||||
}
|
|
||||||
if fetchData["password"] != initPassword {
|
|
||||||
t.Fatalf("expected initial password %s, got %v", initPassword, fetchData["password"])
|
|
||||||
}
|
}
|
||||||
var plaintextRows int64
|
var plaintextRows int64
|
||||||
if err := dao.Mdb.Unscoped().
|
if err := dao.Mdb.Unscoped().
|
||||||
@@ -336,27 +333,10 @@ func TestAdminInitPasswordFlow(t *testing.T) {
|
|||||||
Count(&plaintextRows).Error; err != nil {
|
Count(&plaintextRows).Error; err != nil {
|
||||||
t.Fatalf("count init password plaintext rows: %v", err)
|
t.Fatalf("count init password plaintext rows: %v", err)
|
||||||
}
|
}
|
||||||
if plaintextRows != 0 {
|
if plaintextRows != 1 {
|
||||||
t.Fatalf("expected init password plaintext to be hard-deleted, got %d rows", plaintextRows)
|
t.Fatalf("expected init password plaintext to remain available, got %d rows", plaintextRows)
|
||||||
}
|
}
|
||||||
|
|
||||||
recFetch2 := doGet(e, "/admin/api/v1/auth/init-password")
|
|
||||||
if recFetch2.Code != http.StatusBadRequest {
|
|
||||||
t.Fatalf("second fetch should fail with 400, got %d body=%s", recFetch2.Code, recFetch2.Body.String())
|
|
||||||
}
|
|
||||||
var respFetch2 map[string]interface{}
|
|
||||||
if err := json.Unmarshal(recFetch2.Body.Bytes(), &respFetch2); err != nil {
|
|
||||||
t.Fatalf("unmarshal second fetch response: %v", err)
|
|
||||||
}
|
|
||||||
if got := int(respFetch2["status_code"].(float64)); got != 10040 {
|
|
||||||
t.Fatalf("second fetch status_code = %d, want 10040; response=%v", got, respFetch2)
|
|
||||||
}
|
|
||||||
if got, _ := respFetch2["message"].(string); got != constant.Errno[10040] {
|
|
||||||
t.Fatalf("second fetch message = %q, want %q; response=%v", got, constant.Errno[10040], respFetch2)
|
|
||||||
}
|
|
||||||
|
|
||||||
token := adminLogin(t, e, testAdminUsername, initPassword)
|
|
||||||
|
|
||||||
recMe1 := doGetAdmin(e, "/admin/api/v1/auth/me", token)
|
recMe1 := doGetAdmin(e, "/admin/api/v1/auth/me", token)
|
||||||
respMe1 := assertOK(t, recMe1)
|
respMe1 := assertOK(t, recMe1)
|
||||||
meData1, _ := respMe1["data"].(map[string]interface{})
|
meData1, _ := respMe1["data"].(map[string]interface{})
|
||||||
@@ -376,6 +356,15 @@ func TestAdminInitPasswordFlow(t *testing.T) {
|
|||||||
if got, _ := hashData2["password_changed"].(bool); !got {
|
if got, _ := hashData2["password_changed"].(bool); !got {
|
||||||
t.Fatalf("expected password_changed=true after change, got %v", got)
|
t.Fatalf("expected password_changed=true after change, got %v", got)
|
||||||
}
|
}
|
||||||
|
if err := dao.Mdb.Unscoped().
|
||||||
|
Model(&mdb.Setting{}).
|
||||||
|
Where("`key` = ?", mdb.SettingKeyInitAdminPasswordPlain).
|
||||||
|
Count(&plaintextRows).Error; err != nil {
|
||||||
|
t.Fatalf("count init password plaintext rows after change: %v", err)
|
||||||
|
}
|
||||||
|
if plaintextRows != 0 {
|
||||||
|
t.Fatalf("expected init password plaintext to be hard-deleted after change, got %d rows", plaintextRows)
|
||||||
|
}
|
||||||
|
|
||||||
recMe2 := doGetAdmin(e, "/admin/api/v1/auth/me", token)
|
recMe2 := doGetAdmin(e, "/admin/api/v1/auth/me", token)
|
||||||
respMe2 := assertOK(t, recMe2)
|
respMe2 := assertOK(t, recMe2)
|
||||||
|
|||||||
+50
-6
@@ -15,12 +15,43 @@ import (
|
|||||||
"github.com/GMWalletApp/epusdt/middleware"
|
"github.com/GMWalletApp/epusdt/middleware"
|
||||||
"github.com/GMWalletApp/epusdt/model/data"
|
"github.com/GMWalletApp/epusdt/model/data"
|
||||||
"github.com/GMWalletApp/epusdt/model/mdb"
|
"github.com/GMWalletApp/epusdt/model/mdb"
|
||||||
|
"github.com/GMWalletApp/epusdt/model/service"
|
||||||
"github.com/GMWalletApp/epusdt/util/constant"
|
"github.com/GMWalletApp/epusdt/util/constant"
|
||||||
"github.com/GMWalletApp/epusdt/util/sign"
|
"github.com/GMWalletApp/epusdt/util/sign"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
echoMiddleware "github.com/labstack/echo/v4/middleware"
|
echoMiddleware "github.com/labstack/echo/v4/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// resolveEPayTypeSelector only claims the type as a selector when it maps to a
|
||||||
|
// currently supported payment asset. Non-selector values are handled by the
|
||||||
|
// caller, which now only accepts empty type or alipay before falling back to
|
||||||
|
// request token/network/default resolution.
|
||||||
|
func resolveEPayTypeSelector(rawType string) (string, string, bool, error) {
|
||||||
|
rawType = strings.TrimSpace(rawType)
|
||||||
|
if rawType == "" || strings.Count(rawType, ".") != 1 {
|
||||||
|
return "", "", false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.SplitN(rawType, ".", 2)
|
||||||
|
token := strings.TrimSpace(parts[0])
|
||||||
|
network := strings.ToLower(strings.TrimSpace(parts[1]))
|
||||||
|
if token == "" || network == "" {
|
||||||
|
return "", "", false, nil
|
||||||
|
}
|
||||||
|
if !data.IsChainEnabled(network) {
|
||||||
|
return "", "", false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenRow, err := data.GetEnabledChainTokenBySymbol(network, token)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", false, err
|
||||||
|
}
|
||||||
|
if tokenRow == nil || tokenRow.ID == 0 || !service.ChainTokenReadyForPayment(*tokenRow) {
|
||||||
|
return "", "", false, nil
|
||||||
|
}
|
||||||
|
return token, network, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterRoute 路由注册
|
// RegisterRoute 路由注册
|
||||||
func RegisterRoute(e *echo.Echo) {
|
func RegisterRoute(e *echo.Echo) {
|
||||||
e.POST("/", func(c echo.Context) error {
|
e.POST("/", func(c echo.Context) error {
|
||||||
@@ -130,16 +161,29 @@ func RegisterRoute(e *echo.Echo) {
|
|||||||
|
|
||||||
money := getString(params, "money")
|
money := getString(params, "money")
|
||||||
name := getString(params, "name")
|
name := getString(params, "name")
|
||||||
|
epayType := strings.TrimSpace(getString(params, "type"))
|
||||||
notifyURL := getString(params, "notify_url")
|
notifyURL := getString(params, "notify_url")
|
||||||
outTradeNo := getString(params, "out_trade_no")
|
outTradeNo := getString(params, "out_trade_no")
|
||||||
returnURL := getString(params, "return_url")
|
returnURL := getString(params, "return_url")
|
||||||
token := strings.TrimSpace(getString(params, "token"))
|
selectorToken, selectorNetwork, selectorMatched, err := resolveEPayTypeSelector(epayType)
|
||||||
if token == "" {
|
if err != nil {
|
||||||
token = data.GetSettingString(mdb.SettingKeyEpayDefaultToken, "")
|
return comm.Ctrl.FailJson(ctx, constant.SystemErr)
|
||||||
}
|
}
|
||||||
|
if epayType != "" && !selectorMatched && !strings.EqualFold(epayType, "alipay") {
|
||||||
|
return comm.Ctrl.FailJson(ctx, constant.ParamsMarshalErr)
|
||||||
|
}
|
||||||
|
token := strings.TrimSpace(getString(params, "token"))
|
||||||
network := strings.TrimSpace(getString(params, "network"))
|
network := strings.TrimSpace(getString(params, "network"))
|
||||||
if network == "" {
|
if selectorMatched {
|
||||||
network = data.GetSettingString(mdb.SettingKeyEpayDefaultNetwork, "")
|
token = selectorToken
|
||||||
|
network = selectorNetwork
|
||||||
|
} else {
|
||||||
|
if token == "" {
|
||||||
|
token = data.GetSettingString(mdb.SettingKeyEpayDefaultToken, "")
|
||||||
|
}
|
||||||
|
if network == "" {
|
||||||
|
network = data.GetSettingString(mdb.SettingKeyEpayDefaultNetwork, "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
currency := strings.TrimSpace(getString(params, "currency"))
|
currency := strings.TrimSpace(getString(params, "currency"))
|
||||||
if currency == "" {
|
if currency == "" {
|
||||||
@@ -168,6 +212,7 @@ func RegisterRoute(e *echo.Echo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Set("request_body", body)
|
ctx.Set("request_body", body)
|
||||||
|
ctx.Set(comm.EPayTypeContextKey, epayType)
|
||||||
ctx.Set(middleware.ApiKeyIDKey, apiKeyRow.ID)
|
ctx.Set(middleware.ApiKeyIDKey, apiKeyRow.ID)
|
||||||
ctx.Set(middleware.ApiKeyRowKey, apiKeyRow)
|
ctx.Set(middleware.ApiKeyRowKey, apiKeyRow)
|
||||||
|
|
||||||
@@ -218,7 +263,6 @@ func registerAdminRoutes(e *echo.Echo) {
|
|||||||
|
|
||||||
// Public (no JWT)
|
// Public (no JWT)
|
||||||
adminV1.POST("/auth/login", admin.Ctrl.Login)
|
adminV1.POST("/auth/login", admin.Ctrl.Login)
|
||||||
adminV1.GET("/auth/init-password", admin.Ctrl.GetInitialPassword)
|
|
||||||
adminV1.GET("/auth/init-password-hash", admin.Ctrl.GetInitialPasswordHash)
|
adminV1.GET("/auth/init-password-hash", admin.Ctrl.GetInitialPasswordHash)
|
||||||
|
|
||||||
// Authenticated
|
// Authenticated
|
||||||
|
|||||||
@@ -1272,6 +1272,9 @@ func TestEpaySubmitPhpGetCompatible(t *testing.T) {
|
|||||||
if order.PaymentType != mdb.PaymentTypeEpay {
|
if order.PaymentType != mdb.PaymentTypeEpay {
|
||||||
t.Fatalf("epay payment_type = %q, want %q", order.PaymentType, mdb.PaymentTypeEpay)
|
t.Fatalf("epay payment_type = %q, want %q", order.PaymentType, mdb.PaymentTypeEpay)
|
||||||
}
|
}
|
||||||
|
if order.EpayType != "alipay" {
|
||||||
|
t.Fatalf("epay_type = %q, want alipay", order.EpayType)
|
||||||
|
}
|
||||||
checkoutData := getCheckoutCounterRespData(t, e, tradeID)
|
checkoutData := getCheckoutCounterRespData(t, e, tradeID)
|
||||||
if checkoutData["payment_type"] != "epay" {
|
if checkoutData["payment_type"] != "epay" {
|
||||||
t.Fatalf("epay checkout payment_type = %v, want epay", checkoutData["payment_type"])
|
t.Fatalf("epay checkout payment_type = %v, want epay", checkoutData["payment_type"])
|
||||||
@@ -1327,6 +1330,100 @@ func TestEpaySubmitPhpRequestTokenNetworkOverrideDefaults(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEpaySubmitPhpTypeSelectorOverridesRequestAndDefaults(t *testing.T) {
|
||||||
|
e := setupTestEnv(t)
|
||||||
|
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultToken, "usdc", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_token: %v", err)
|
||||||
|
}
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultNetwork, "solana", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_network: %v", err)
|
||||||
|
}
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultCurrency, "", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("clear epay.default_currency: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
values := signEpayValues(url.Values{
|
||||||
|
"pid": {"1"},
|
||||||
|
"name": {"epay-type-selector-001"},
|
||||||
|
"type": {"usdt.tron"},
|
||||||
|
"money": {"1.00"},
|
||||||
|
"out_trade_no": {"epay-type-selector-001"},
|
||||||
|
"notify_url": {"https://93.184.216.34/notify"},
|
||||||
|
"return_url": {"http://localhost/return"},
|
||||||
|
"token": {"usdc"},
|
||||||
|
"network": {"solana"},
|
||||||
|
})
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/payments/epay/v1/order/create-transaction/submit.php?"+values.Encode(), nil)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
e.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusFound {
|
||||||
|
t.Fatalf("expected 302, got %d body=%s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
tradeID := strings.TrimPrefix(rec.Header().Get("Location"), "/pay/checkout-counter/")
|
||||||
|
order, err := data.GetOrderInfoByTradeId(tradeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("reload epay selector order: %v", err)
|
||||||
|
}
|
||||||
|
if order.Token != "USDT" || order.Network != mdb.NetworkTron || order.ReceiveAddress != "TTestTronAddress001" {
|
||||||
|
t.Fatalf("selector order fields = token %q network %q address %q", order.Token, order.Network, order.ReceiveAddress)
|
||||||
|
}
|
||||||
|
if order.Currency != "CNY" {
|
||||||
|
t.Fatalf("currency = %q, want CNY", order.Currency)
|
||||||
|
}
|
||||||
|
if order.EpayType != "usdt.tron" {
|
||||||
|
t.Fatalf("epay_type = %q, want usdt.tron", order.EpayType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEpaySubmitPhpTypeSelectorUsesDefaultCurrencyWhenMissing(t *testing.T) {
|
||||||
|
e := setupTestEnv(t)
|
||||||
|
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultToken, "usdc", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_token: %v", err)
|
||||||
|
}
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultNetwork, "solana", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_network: %v", err)
|
||||||
|
}
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultCurrency, "usd", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_currency: %v", err)
|
||||||
|
}
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupRate, "rate.forced_rate_list", `{"cny":{"usdt":0.14285714285714285},"usd":{"usdt":1}}`, mdb.SettingTypeJSON); err != nil {
|
||||||
|
t.Fatalf("seed rate.forced_rate_list for usd: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
values := signEpayValues(url.Values{
|
||||||
|
"pid": {"1"},
|
||||||
|
"name": {"epay-type-default-cur-001"},
|
||||||
|
"type": {"usdt.tron"},
|
||||||
|
"money": {"1.00"},
|
||||||
|
"out_trade_no": {"epay-type-default-cur-001"},
|
||||||
|
"notify_url": {"https://93.184.216.34/notify"},
|
||||||
|
"return_url": {"http://localhost/return"},
|
||||||
|
"token": {"usdc"},
|
||||||
|
"network": {"solana"},
|
||||||
|
})
|
||||||
|
|
||||||
|
rec := doFormPost(e, "/payments/epay/v1/order/create-transaction/submit.php", values)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusFound {
|
||||||
|
t.Fatalf("expected 302, got %d body=%s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
tradeID := strings.TrimPrefix(rec.Header().Get("Location"), "/pay/checkout-counter/")
|
||||||
|
order, err := data.GetOrderInfoByTradeId(tradeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("reload epay selector order: %v", err)
|
||||||
|
}
|
||||||
|
if order.Token != "USDT" || order.Network != mdb.NetworkTron || order.ReceiveAddress != "TTestTronAddress001" {
|
||||||
|
t.Fatalf("selector order fields = token %q network %q address %q", order.Token, order.Network, order.ReceiveAddress)
|
||||||
|
}
|
||||||
|
if order.Currency != "USD" {
|
||||||
|
t.Fatalf("currency = %q, want USD", order.Currency)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestEpaySubmitPhpWithoutTokenNetworkDefaultsCreatesPlaceholder(t *testing.T) {
|
func TestEpaySubmitPhpWithoutTokenNetworkDefaultsCreatesPlaceholder(t *testing.T) {
|
||||||
e := setupTestEnv(t)
|
e := setupTestEnv(t)
|
||||||
|
|
||||||
@@ -1365,12 +1462,120 @@ func TestEpaySubmitPhpWithoutTokenNetworkDefaultsCreatesPlaceholder(t *testing.T
|
|||||||
if order.PaymentType != mdb.PaymentTypeEpay {
|
if order.PaymentType != mdb.PaymentTypeEpay {
|
||||||
t.Fatalf("payment_type = %q, want %q", order.PaymentType, mdb.PaymentTypeEpay)
|
t.Fatalf("payment_type = %q, want %q", order.PaymentType, mdb.PaymentTypeEpay)
|
||||||
}
|
}
|
||||||
|
if order.EpayType != "alipay" {
|
||||||
|
t.Fatalf("epay_type = %q, want alipay", order.EpayType)
|
||||||
|
}
|
||||||
checkoutData := getCheckoutCounterRespData(t, e, tradeID)
|
checkoutData := getCheckoutCounterRespData(t, e, tradeID)
|
||||||
if checkoutData["payment_type"] != "epay" || int(checkoutData["status"].(float64)) != mdb.StatusWaitSelect {
|
if checkoutData["payment_type"] != "epay" || int(checkoutData["status"].(float64)) != mdb.StatusWaitSelect {
|
||||||
t.Fatalf("checkout placeholder data = %#v", checkoutData)
|
t.Fatalf("checkout placeholder data = %#v", checkoutData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEpaySubmitPhpWithoutTypeKeepsCurrentBehavior(t *testing.T) {
|
||||||
|
e := setupTestEnv(t)
|
||||||
|
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultToken, "usdt", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_token: %v", err)
|
||||||
|
}
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultNetwork, "tron", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_network: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
values := signEpayValues(url.Values{
|
||||||
|
"pid": {"1"},
|
||||||
|
"name": {"epay-empty-type-001"},
|
||||||
|
"money": {"1.00"},
|
||||||
|
"out_trade_no": {"epay-empty-type-001"},
|
||||||
|
"notify_url": {"https://93.184.216.34/notify"},
|
||||||
|
"return_url": {"http://localhost/return"},
|
||||||
|
})
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/payments/epay/v1/order/create-transaction/submit.php?"+values.Encode(), nil)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
e.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusFound {
|
||||||
|
t.Fatalf("expected 302, got %d body=%s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
tradeID := strings.TrimPrefix(rec.Header().Get("Location"), "/pay/checkout-counter/")
|
||||||
|
order, err := data.GetOrderInfoByTradeId(tradeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("reload epay empty-type order: %v", err)
|
||||||
|
}
|
||||||
|
if order.Token != "USDT" || order.Network != mdb.NetworkTron || order.ReceiveAddress != "TTestTronAddress001" {
|
||||||
|
t.Fatalf("empty-type order fields = token %q network %q address %q", order.Token, order.Network, order.ReceiveAddress)
|
||||||
|
}
|
||||||
|
if order.EpayType != "" {
|
||||||
|
t.Fatalf("epay_type = %q, want empty", order.EpayType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEpaySubmitPhpRejectsNonSelectorType(t *testing.T) {
|
||||||
|
e := setupTestEnv(t)
|
||||||
|
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultToken, "usdt", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_token: %v", err)
|
||||||
|
}
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultNetwork, "tron", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_network: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
values := signEpayValues(url.Values{
|
||||||
|
"pid": {"1"},
|
||||||
|
"name": {"epay-non-selector-001"},
|
||||||
|
"type": {"usdt-tron"},
|
||||||
|
"money": {"1.00"},
|
||||||
|
"out_trade_no": {"epay-non-selector-001"},
|
||||||
|
"notify_url": {"https://93.184.216.34/notify"},
|
||||||
|
"return_url": {"http://localhost/return"},
|
||||||
|
})
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/payments/epay/v1/order/create-transaction/submit.php?"+values.Encode(), nil)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
e.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusBadRequest {
|
||||||
|
t.Fatalf("expected 400, got %d body=%s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
resp := parseResp(t, rec)
|
||||||
|
if got := int(resp["status_code"].(float64)); got != 10009 {
|
||||||
|
t.Fatalf("status_code = %d, want 10009", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEpaySubmitPhpRejectsUnsupportedSelectorType(t *testing.T) {
|
||||||
|
e := setupTestEnv(t)
|
||||||
|
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultToken, "usdt", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_token: %v", err)
|
||||||
|
}
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultNetwork, "tron", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_network: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
values := signEpayValues(url.Values{
|
||||||
|
"pid": {"1"},
|
||||||
|
"name": {"epay-unsupported-selector-001"},
|
||||||
|
"type": {"usdc.tron"},
|
||||||
|
"money": {"1.00"},
|
||||||
|
"out_trade_no": {"epay-unsupported-selector-001"},
|
||||||
|
"notify_url": {"https://93.184.216.34/notify"},
|
||||||
|
"return_url": {"http://localhost/return"},
|
||||||
|
})
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/payments/epay/v1/order/create-transaction/submit.php?"+values.Encode(), nil)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
e.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusBadRequest {
|
||||||
|
t.Fatalf("expected 400, got %d body=%s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
resp := parseResp(t, rec)
|
||||||
|
if got := int(resp["status_code"].(float64)); got != 10009 {
|
||||||
|
t.Fatalf("status_code = %d, want 10009", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestEpaySubmitPhpRejectsPartialResolvedTokenNetwork(t *testing.T) {
|
func TestEpaySubmitPhpRejectsPartialResolvedTokenNetwork(t *testing.T) {
|
||||||
e := setupTestEnv(t)
|
e := setupTestEnv(t)
|
||||||
|
|
||||||
@@ -1428,6 +1633,40 @@ func TestEpaySubmitPhpPostFormCompatible(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEpaySubmitPhpTypeSelectorPostFormCompatible(t *testing.T) {
|
||||||
|
e := setupTestEnv(t)
|
||||||
|
|
||||||
|
if err := data.SetSetting(mdb.SettingGroupEpay, mdb.SettingKeyEpayDefaultNetwork, "solana", mdb.SettingTypeString); err != nil {
|
||||||
|
t.Fatalf("seed epay.default_network: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
values := signEpayValues(url.Values{
|
||||||
|
"pid": {"1"},
|
||||||
|
"name": {"epay-post-selector-001"},
|
||||||
|
"type": {"usdt.tron"},
|
||||||
|
"money": {"1.00"},
|
||||||
|
"out_trade_no": {"epay-post-selector-001"},
|
||||||
|
"notify_url": {"https://93.184.216.34/notify"},
|
||||||
|
"return_url": {"http://localhost/return"},
|
||||||
|
})
|
||||||
|
|
||||||
|
rec := doFormPost(e, "/payments/epay/v1/order/create-transaction/submit.php", values)
|
||||||
|
if rec.Code != http.StatusFound {
|
||||||
|
t.Fatalf("expected 302, got %d body=%s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
tradeID := strings.TrimPrefix(rec.Header().Get("Location"), "/pay/checkout-counter/")
|
||||||
|
order, err := data.GetOrderInfoByTradeId(tradeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("reload epay post selector order: %v", err)
|
||||||
|
}
|
||||||
|
if order.Token != "USDT" || order.Network != mdb.NetworkTron || order.ReceiveAddress != "TTestTronAddress001" {
|
||||||
|
t.Fatalf("post selector order fields = token %q network %q address %q", order.Token, order.Network, order.ReceiveAddress)
|
||||||
|
}
|
||||||
|
if order.EpayType != "usdt.tron" {
|
||||||
|
t.Fatalf("epay_type = %q, want usdt.tron", order.EpayType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestCheckStatus_NotFound verifies that /pay/check-status/:trade_id returns a
|
// TestCheckStatus_NotFound verifies that /pay/check-status/:trade_id returns a
|
||||||
// graceful JSON error (not 500) when the trade_id doesn't exist.
|
// graceful JSON error (not 500) when the trade_id doesn't exist.
|
||||||
func TestCheckStatus_NotFound(t *testing.T) {
|
func TestCheckStatus_NotFound(t *testing.T) {
|
||||||
@@ -1656,6 +1895,33 @@ func TestPayReturn_PaidEpayRedirectsToMerchantWithSignedParams(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPayReturn_PaidEpayRedirectsWithOriginalType(t *testing.T) {
|
||||||
|
e := setupTestEnv(t)
|
||||||
|
tradeID := mustCreateEPayOrder(t, e, "epay-return-type-001", "https://merchant.example/return", url.Values{
|
||||||
|
"type": {"usdt.tron"},
|
||||||
|
})
|
||||||
|
if err := dao.Mdb.Model(&mdb.Orders{}).
|
||||||
|
Where("trade_id = ?", tradeID).
|
||||||
|
Update("status", mdb.StatusPaySuccess).Error; err != nil {
|
||||||
|
t.Fatalf("mark order paid: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/pay/return/"+tradeID, nil)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
e.ServeHTTP(rec, req)
|
||||||
|
if rec.Code != http.StatusFound {
|
||||||
|
t.Fatalf("expected 302, got %d: %s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
targetURL, err := url.Parse(rec.Header().Get("Location"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parse redirect location: %v", err)
|
||||||
|
}
|
||||||
|
if got := targetURL.Query().Get("type"); got != "usdt.tron" {
|
||||||
|
t.Fatalf("type = %q, want usdt.tron", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPayReturn_UnpaidEpayRedirectsBackToCheckout(t *testing.T) {
|
func TestPayReturn_UnpaidEpayRedirectsBackToCheckout(t *testing.T) {
|
||||||
e := setupTestEnv(t)
|
e := setupTestEnv(t)
|
||||||
tradeID := mustCreateEPayOrder(t, e, "epay-return-unpaid-001", "https://merchant.example/return", url.Values{
|
tradeID := mustCreateEPayOrder(t, e, "epay-return-unpaid-001", "https://merchant.example/return", url.Values{
|
||||||
@@ -2501,6 +2767,9 @@ func TestSwitchNetwork_EpayPlaceholderCompletesChainInPlace(t *testing.T) {
|
|||||||
if parent.Status != mdb.StatusWaitPay || parent.PaymentType != mdb.PaymentTypeEpay || parent.Network != mdb.NetworkTron || parent.Token != "USDT" || parent.ReceiveAddress == "" {
|
if parent.Status != mdb.StatusWaitPay || parent.PaymentType != mdb.PaymentTypeEpay || parent.Network != mdb.NetworkTron || parent.Token != "USDT" || parent.ReceiveAddress == "" {
|
||||||
t.Fatalf("parent fields = status %d payment_type %q network %q token %q address %q", parent.Status, parent.PaymentType, parent.Network, parent.Token, parent.ReceiveAddress)
|
t.Fatalf("parent fields = status %d payment_type %q network %q token %q address %q", parent.Status, parent.PaymentType, parent.Network, parent.Token, parent.ReceiveAddress)
|
||||||
}
|
}
|
||||||
|
if parent.EpayType != "alipay" {
|
||||||
|
t.Fatalf("parent epay_type = %q, want alipay", parent.EpayType)
|
||||||
|
}
|
||||||
if parent.RedirectUrl != "http://localhost/return" {
|
if parent.RedirectUrl != "http://localhost/return" {
|
||||||
t.Fatalf("stored redirect_url = %q, want merchant raw return_url", parent.RedirectUrl)
|
t.Fatalf("stored redirect_url = %q, want merchant raw return_url", parent.RedirectUrl)
|
||||||
}
|
}
|
||||||
@@ -2616,6 +2885,47 @@ func TestSwitchNetwork_OkPayFromEpayWaitSelectPlaceholder(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSwitchNetwork_EpayChildInheritsOriginalType(t *testing.T) {
|
||||||
|
e := setupTestEnv(t)
|
||||||
|
tradeID := mustCreateEPayOrder(t, e, "epay-switch-child-type-001", "http://localhost/return", url.Values{
|
||||||
|
"type": {"usdt.tron"},
|
||||||
|
})
|
||||||
|
|
||||||
|
rec := doPost(e, "/pay/switch-network", map[string]interface{}{
|
||||||
|
"trade_id": tradeID,
|
||||||
|
"token": "USDT",
|
||||||
|
"network": "solana",
|
||||||
|
})
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("switch epay parent to solana failed: %d %s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
resp := parseResp(t, rec)
|
||||||
|
respData, _ := resp["data"].(map[string]interface{})
|
||||||
|
subTradeID, _ := respData["trade_id"].(string)
|
||||||
|
if subTradeID == "" || subTradeID == tradeID {
|
||||||
|
t.Fatalf("expected child trade_id, got %q", subTradeID)
|
||||||
|
}
|
||||||
|
|
||||||
|
subOrder, err := data.GetOrderInfoByTradeId(subTradeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("load sub-order: %v", err)
|
||||||
|
}
|
||||||
|
if subOrder.EpayType != "usdt.tron" {
|
||||||
|
t.Fatalf("sub-order epay_type = %q, want usdt.tron", subOrder.EpayType)
|
||||||
|
}
|
||||||
|
apiKeyRow, err := data.GetApiKeyByID(subOrder.ApiKeyID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("load api key: %v", err)
|
||||||
|
}
|
||||||
|
params, err := service.BuildEPayResultParams(subOrder, apiKeyRow)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("BuildEPayResultParams(): %v", err)
|
||||||
|
}
|
||||||
|
if params["type"] != "usdt.tron" {
|
||||||
|
t.Fatalf("callback type = %q, want usdt.tron", params["type"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSwitchNetwork_OkPayIntegration(t *testing.T) {
|
func TestSwitchNetwork_OkPayIntegration(t *testing.T) {
|
||||||
shopID := strings.TrimSpace(os.Getenv("EPUSDT_OKPAY_ID"))
|
shopID := strings.TrimSpace(os.Getenv("EPUSDT_OKPAY_ID"))
|
||||||
if shopID == "" {
|
if shopID == "" {
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
import{t as e}from"./unauthorized-error-B6bKLdq-.js";var t=e;export{t as component};
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{t as e}from"./unauthorized-error-TaUhj35c.js";var t=e;export{t as component};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{t as e}from"./forbidden-BCyOYrFV.js";var t=e;export{t as component};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{t as e}from"./forbidden-DZPSchCU.js";var t=e;export{t as component};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{t as e}from"./not-found-error-CHHM1I1c.js";var t=e;export{t as component};
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{t as e}from"./not-found-error-D4F_Uu-C.js";var t=e;export{t as component};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{t as e}from"./general-error-Drsf0vjz.js";var t=e;export{t as component};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{t as e}from"./general-error-BoIfl_4Z.js";var t=e;export{t as component};
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{t as e}from"./maintenance-error-lgcDljP-.js";var t=e;export{t as component};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{t as e}from"./maintenance-error-CuCw7L8t.js";var t=e;export{t as component};
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{o as r,s as i,t as a}from"./useRouter-DtTm7XkK.js";import{t as o}from"./useStore-CupyIEEP.js";import{f as s}from"./ClientOnly-fFIveJVd.js";import"./redirect-DMNGvjzO.js";import{a as c,i as l,r as u,s as d,t as f}from"./Match-Cm64cgS9.js";import{n as p}from"./matchContext-BFCdcHzo.js";import{t as m}from"./atom-DQpaPCwp.js";function h(e){if(typeof document<`u`&&document.querySelector){let t=e.stores.location.get(),n=t.state.__hashScrollIntoViewOptions??!0;if(n&&t.hash!==``){let e=document.getElementById(t.hash);e&&e.scrollIntoView(n)}}}var g=e(t(),1);function _(){let e=a(),t=g.useRef({router:e,mounted:!1}),[n,c]=g.useState(!1),l=o(e.stores.isLoading,e=>e),u=o(e.stores.hasPending,e=>e),f=i(l),p=l||n||u,_=i(p),v=l||u,y=i(v);return e.startTransition=e=>{c(!0),g.startTransition(()=>{e(),c(!1)})},g.useEffect(()=>{let t=e.history.subscribe(e.load),n=e.buildLocation({to:e.latestLocation.pathname,search:!0,params:!0,hash:!0,state:!0,_includeValidateSearch:!0});return s(e.latestLocation.publicHref)!==s(n.publicHref)&&e.commitLocation({...n,replace:!0}),()=>{t()}},[e,e.history]),r(()=>{typeof window<`u`&&e.ssr||t.current.router===e&&t.current.mounted||(t.current={router:e,mounted:!0},(async()=>{try{await e.load()}catch(e){console.error(e)}})())},[e]),r(()=>{f&&!l&&e.emit({type:`onLoad`,...d(e.stores.location.get(),e.stores.resolvedLocation.get())})},[f,e,l]),r(()=>{y&&!v&&e.emit({type:`onBeforeRouteMount`,...d(e.stores.location.get(),e.stores.resolvedLocation.get())})},[v,y,e]),r(()=>{if(_&&!p){let t=d(e.stores.location.get(),e.stores.resolvedLocation.get());e.emit({type:`onResolved`,...t}),m(()=>{e.stores.status.set(`idle`),e.stores.resolvedLocation.set(e.stores.location.get())}),t.hrefChanged&&h(e)}},[p,_,e]),null}var v=n();function y(){let e=a(),t=e.routesById.__root__.options.pendingComponent??e.options.defaultPendingComponent,n=t?(0,v.jsx)(t,{}):null,r=(0,v.jsxs)(typeof document<`u`&&e.ssr?u:g.Suspense,{fallback:n,children:[(0,v.jsx)(_,{}),(0,v.jsx)(b,{})]});return e.options.InnerWrap?(0,v.jsx)(e.options.InnerWrap,{children:r}):r}function b(){let e=a(),t=o(e.stores.firstId,e=>e),n=o(e.stores.loadedAt,e=>e),r=t?(0,v.jsx)(f,{matchId:t}):null;return(0,v.jsx)(p.Provider,{value:t,children:e.options.disableGlobalCatchBoundary?r:(0,v.jsx)(l,{getResetKey:()=>n,errorComponent:c,onCatch:void 0,children:r})})}function x(){let e=a();return o(e.stores.matchRouteDeps,e=>e),g.useCallback(t=>{let{pending:n,caseSensitive:r,fuzzy:i,includeSearch:a,...o}=t;return e.matchRoute(o,{pending:n,caseSensitive:r,fuzzy:i,includeSearch:a})},[e])}export{x as n,y as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{o as r,s as i,t as a}from"./useRouter-DtTm7XkK.js";import{t as o}from"./useStore-CupyIEEP.js";import{f as s}from"./ClientOnly-DHd0jlDY.js";import"./redirect-DMNGvjzO.js";import{a as c,i as l,r as u,s as d,t as f}from"./Match-onTP_fNL.js";import{n as p}from"./matchContext-BFCdcHzo.js";import{t as m}from"./atom-DQpaPCwp.js";function h(e){if(typeof document<`u`&&document.querySelector){let t=e.stores.location.get(),n=t.state.__hashScrollIntoViewOptions??!0;if(n&&t.hash!==``){let e=document.getElementById(t.hash);e&&e.scrollIntoView(n)}}}var g=e(t(),1);function _(){let e=a(),t=g.useRef({router:e,mounted:!1}),[n,c]=g.useState(!1),l=o(e.stores.isLoading,e=>e),u=o(e.stores.hasPending,e=>e),f=i(l),p=l||n||u,_=i(p),v=l||u,y=i(v);return e.startTransition=e=>{c(!0),g.startTransition(()=>{e(),c(!1)})},g.useEffect(()=>{let t=e.history.subscribe(e.load),n=e.buildLocation({to:e.latestLocation.pathname,search:!0,params:!0,hash:!0,state:!0,_includeValidateSearch:!0});return s(e.latestLocation.publicHref)!==s(n.publicHref)&&e.commitLocation({...n,replace:!0}),()=>{t()}},[e,e.history]),r(()=>{typeof window<`u`&&e.ssr||t.current.router===e&&t.current.mounted||(t.current={router:e,mounted:!0},(async()=>{try{await e.load()}catch(e){console.error(e)}})())},[e]),r(()=>{f&&!l&&e.emit({type:`onLoad`,...d(e.stores.location.get(),e.stores.resolvedLocation.get())})},[f,e,l]),r(()=>{y&&!v&&e.emit({type:`onBeforeRouteMount`,...d(e.stores.location.get(),e.stores.resolvedLocation.get())})},[v,y,e]),r(()=>{if(_&&!p){let t=d(e.stores.location.get(),e.stores.resolvedLocation.get());e.emit({type:`onResolved`,...t}),m(()=>{e.stores.status.set(`idle`),e.stores.resolvedLocation.set(e.stores.location.get())}),t.hrefChanged&&h(e)}},[p,_,e]),null}var v=n();function y(){let e=a(),t=e.routesById.__root__.options.pendingComponent??e.options.defaultPendingComponent,n=t?(0,v.jsx)(t,{}):null,r=(0,v.jsxs)(typeof document<`u`&&e.ssr?u:g.Suspense,{fallback:n,children:[(0,v.jsx)(_,{}),(0,v.jsx)(b,{})]});return e.options.InnerWrap?(0,v.jsx)(e.options.InnerWrap,{children:r}):r}function b(){let e=a(),t=o(e.stores.firstId,e=>e),n=o(e.stores.loadedAt,e=>e),r=t?(0,v.jsx)(f,{matchId:t}):null;return(0,v.jsx)(p.Provider,{value:t,children:e.options.disableGlobalCatchBoundary?r:(0,v.jsx)(l,{getResetKey:()=>n,errorComponent:c,onCatch:void 0,children:r})})}function x(){let e=a();return o(e.stores.matchRouteDeps,e=>e),g.useCallback(t=>{let{pending:n,caseSensitive:r,fuzzy:i,includeSearch:a,...o}=t;return e.matchRoute(o,{pending:n,caseSensitive:r,fuzzy:i,includeSearch:a})},[e])}export{x as n,y as t};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{em as e}from"./messages-Bp0bCjzp.js";import{m as t}from"./search-provider-Bl2HDfcG.js";import{n,t as r}from"./theme-switch-B3Qb32n8.js";import{t as i}from"./general-error-BoIfl_4Z.js";import{t as a}from"./not-found-error-CHHM1I1c.js";import{t as o}from"./_error-CeoUllM-.js";import{t as s}from"./unauthorized-error-B6bKLdq-.js";import{t as c}from"./forbidden-DZPSchCU.js";import{t as l}from"./maintenance-error-CuCw7L8t.js";import{n as u,r as d,t as f}from"./header-D45l3Ai7.js";var p=e();function m(){let{error:e}=o.useParams(),m={unauthorized:s,forbidden:c,"not-found":a,"internal-server-error":i,"maintenance-error":l}[e]||a;return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(f,{className:`border-b`,fixed:!0,children:[(0,p.jsx)(u,{}),(0,p.jsxs)(`div`,{className:`ms-auto flex items-center space-x-4`,children:[(0,p.jsx)(n,{}),(0,p.jsx)(r,{}),(0,p.jsx)(t,{}),(0,p.jsx)(d,{})]})]}),(0,p.jsx)(`div`,{className:`flex-1 [&>div]:h-full`,children:(0,p.jsx)(m,{})})]})}export{m as component};
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/_error-BSLzv73v.js","assets/search-provider-Bl2HDfcG.js","assets/chunk-DECur_0Z.js","assets/dist-CRowTfGU.js","assets/dist-CKFLmh1A.js","assets/messages-Bp0bCjzp.js","assets/react-CO2uhaBc.js","assets/confirm-dialog-YmxNnOr3.js","assets/button-BgMnOYKD.js","assets/clsx-D9aGYY3V.js","assets/dist-CPQ-sRtL.js","assets/dist-_ND6L-P3.js","assets/dist-B0ikDpJU.js","assets/dist-BFnxq45V.js","assets/es2015-D8VLlhse.js","assets/dist-Clua1vrx.js","assets/dist-C97YBjnT.js","assets/dist-036CEgdV.js","assets/dist-D7AUoOWu.js","assets/dist-C6i4A_Js.js","assets/dist-BixeH3nX.js","assets/dist-DGDEBCW9.js","assets/separator-DbmFQXe4.js","assets/tooltip-Gx9CUpPD.js","assets/dist-BSXD7MjW.js","assets/dist-Bmn8KNt7.js","assets/auth-store-Csn6HPxJ.js","assets/dist-BGqHIBUe.js","assets/with-selector-DBfssCrY.js","assets/cookies-BzZOQYPw.js","assets/useRouter-DtTm7XkK.js","assets/useNavigate-7u4DX0Ho.js","assets/useStore-CupyIEEP.js","assets/command-CIv3ggHf.js","assets/createLucideIcon-Br0Bd5k2.js","assets/dialog-BJ5VA2v_.js","assets/skeleton-BQsmx80h.js","assets/wallet-Bgblr4kl.js","assets/sun-JU8p4FoE.js","assets/shield-check-MAPDL1u8.js","assets/logo-Ce__4GTc.js","assets/input-BleRUV2A.js","assets/font-provider-CtpKPVa7.js","assets/theme-provider-CyJJNAox.js","assets/theme-switch-B3Qb32n8.js","assets/dropdown-menu-8-hEBtzr.js","assets/check-CHp0nSkR.js","assets/header-D45l3Ai7.js","assets/link-BYG8nKNO.js","assets/ClientOnly-fFIveJVd.js","assets/forbidden-DZPSchCU.js","assets/general-error-BoIfl_4Z.js","assets/maintenance-error-CuCw7L8t.js","assets/not-found-error-CHHM1I1c.js","assets/unauthorized-error-B6bKLdq-.js"])))=>i.map(i=>d[i]);
|
|
||||||
import{n as e,t}from"./lazyRouteComponent-iygd3-DM.js";import{t as n}from"./preload-helper-DoS0eHac.js";var r=e(`/_authenticated/errors/$error`)({component:t(()=>n(()=>import(`./_error-BSLzv73v.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54])),`component`)});export{r as t};
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{tm as e}from"./messages-CL4J6BaJ.js";import{m as t}from"./search-provider-CTRbHqNx.js";import{n,t as r}from"./theme-switch-CdEcHkcU.js";import{t as i}from"./general-error-Drsf0vjz.js";import{t as a}from"./not-found-error-D4F_Uu-C.js";import{t as o}from"./_error-DypydLD1.js";import{t as s}from"./unauthorized-error-TaUhj35c.js";import{t as c}from"./forbidden-BCyOYrFV.js";import{t as l}from"./maintenance-error-lgcDljP-.js";import{n as u,r as d,t as f}from"./header-vUJd_CA5.js";var p=e();function m(){let{error:e}=o.useParams(),m={unauthorized:s,forbidden:c,"not-found":a,"internal-server-error":i,"maintenance-error":l}[e]||a;return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(f,{className:`border-b`,fixed:!0,children:[(0,p.jsx)(u,{}),(0,p.jsxs)(`div`,{className:`ms-auto flex items-center space-x-4`,children:[(0,p.jsx)(n,{}),(0,p.jsx)(r,{}),(0,p.jsx)(t,{}),(0,p.jsx)(d,{})]})]}),(0,p.jsx)(`div`,{className:`flex-1 [&>div]:h-full`,children:(0,p.jsx)(m,{})})]})}export{m as component};
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/_error-D2USOC7M.js","assets/search-provider-CTRbHqNx.js","assets/chunk-DECur_0Z.js","assets/dist-CRowTfGU.js","assets/dist-DmeeHi7K.js","assets/messages-CL4J6BaJ.js","assets/react-CO2uhaBc.js","assets/confirm-dialog-Crc1Jrzv.js","assets/button-NLSeBFht.js","assets/clsx-D9aGYY3V.js","assets/dist-DPYswSIO.js","assets/dist-esC74fSg.js","assets/dist-SR6sl-WU.js","assets/dist-D3WFT-Yo.js","assets/es2015-3J9GnV9P.js","assets/dist-BZMqLvO-.js","assets/dist-CGRahgI2.js","assets/dist-DA1qWiix.js","assets/dist-DhcQhr4B.js","assets/dist-UaPzzPYf.js","assets/dist-BixeH3nX.js","assets/dist-B0pRVbY9.js","assets/separator-CqhQIQ-B.js","assets/tooltip-QxnX5RKP.js","assets/dist-DB-jLX48.js","assets/dist-CjidLXaw.js","assets/auth-store-8ocF_FHU.js","assets/dist-Dd-sCJIt.js","assets/with-selector-DBfssCrY.js","assets/cookies-BzZOQYPw.js","assets/useRouter-DtTm7XkK.js","assets/useNavigate-7u4DX0Ho.js","assets/useStore-CupyIEEP.js","assets/command-vy8966UO.js","assets/createLucideIcon-Br0Bd5k2.js","assets/dialog-CtyiwzAl.js","assets/skeleton-B4TLI5_E.js","assets/wallet-Cdhl16hF.js","assets/sun-JU8p4FoE.js","assets/shield-check-MAPDL1u8.js","assets/logo-CBibDHP9.js","assets/input-DAqep8ZY.js","assets/font-provider-C4_iupSb.js","assets/theme-provider-ixHkEVGI.js","assets/theme-switch-CdEcHkcU.js","assets/dropdown-menu-D72UcvWG.js","assets/check-CHp0nSkR.js","assets/header-vUJd_CA5.js","assets/link-6i3yGmK_.js","assets/ClientOnly-DHd0jlDY.js","assets/forbidden-BCyOYrFV.js","assets/general-error-Drsf0vjz.js","assets/maintenance-error-lgcDljP-.js","assets/not-found-error-D4F_Uu-C.js","assets/unauthorized-error-TaUhj35c.js"])))=>i.map(i=>d[i]);
|
||||||
|
import{n as e,t}from"./lazyRouteComponent-CleTUoKA.js";import{t as n}from"./preload-helper-DoS0eHac.js";var r=e(`/_authenticated/errors/$error`)({component:t(()=>n(()=>import(`./_error-D2USOC7M.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54])),`component`)});export{r as t};
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/_trade_id-Busmu9hU.js","assets/chunk-DECur_0Z.js","assets/button-BgMnOYKD.js","assets/clsx-D9aGYY3V.js","assets/messages-Bp0bCjzp.js","assets/react-CO2uhaBc.js","assets/select-C9s05In_.js","assets/dist-BSXD7MjW.js","assets/dist-CKFLmh1A.js","assets/dist-B0ikDpJU.js","assets/dist-BFnxq45V.js","assets/dist-DGDEBCW9.js","assets/dist-CRowTfGU.js","assets/dist-C6i4A_Js.js","assets/dist-C97YBjnT.js","assets/dist-_ND6L-P3.js","assets/es2015-D8VLlhse.js","assets/dist-BixeH3nX.js","assets/dist-Bmn8KNt7.js","assets/createLucideIcon-Br0Bd5k2.js","assets/check-CHp0nSkR.js","assets/chevron-down-BB5h1CsX.js","assets/auth-store-Csn6HPxJ.js","assets/dist-BGqHIBUe.js","assets/with-selector-DBfssCrY.js","assets/cookies-BzZOQYPw.js","assets/useNavigate-7u4DX0Ho.js","assets/useRouter-DtTm7XkK.js","assets/copy-to-clipboard-C1tj4a8X.js","assets/arrow-left-right-CcCrkQiR.js","assets/arrow-left-BpZwGREZ.js","assets/radio-group-DrQ9k883.js","assets/dist-036CEgdV.js","assets/dist-Clua1vrx.js","assets/dist-D7AUoOWu.js","assets/loader-circle-DpEz1fQv.js","assets/send-BNvceEpO.js","assets/triangle-alert-DB5v_9sS.js","assets/dialog-BJ5VA2v_.js","assets/dist-CPQ-sRtL.js","assets/crypto-icon-DsKMU9xz.js","assets/labels-D0HnAPk9.js","assets/input-BleRUV2A.js","assets/checkout-model-CQ3aqlob.js"])))=>i.map(i=>d[i]);
|
|
||||||
import{n as e,t}from"./lazyRouteComponent-iygd3-DM.js";import{t as n}from"./preload-helper-DoS0eHac.js";var r=e(`/cashier/$trade_id/`)({component:t(()=>n(()=>import(`./_trade_id-Busmu9hU.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43])),`component`)});export{r as t};
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
|||||||
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/_trade_id-BUpVePSs.js","assets/chunk-DECur_0Z.js","assets/button-NLSeBFht.js","assets/clsx-D9aGYY3V.js","assets/messages-CL4J6BaJ.js","assets/react-CO2uhaBc.js","assets/select-D2uO5-De.js","assets/dist-DB-jLX48.js","assets/dist-DmeeHi7K.js","assets/dist-SR6sl-WU.js","assets/dist-D3WFT-Yo.js","assets/dist-B0pRVbY9.js","assets/dist-CRowTfGU.js","assets/dist-UaPzzPYf.js","assets/dist-CGRahgI2.js","assets/dist-esC74fSg.js","assets/es2015-3J9GnV9P.js","assets/dist-BixeH3nX.js","assets/dist-CjidLXaw.js","assets/createLucideIcon-Br0Bd5k2.js","assets/check-CHp0nSkR.js","assets/chevron-down-BB5h1CsX.js","assets/auth-store-8ocF_FHU.js","assets/dist-Dd-sCJIt.js","assets/with-selector-DBfssCrY.js","assets/cookies-BzZOQYPw.js","assets/useNavigate-7u4DX0Ho.js","assets/useRouter-DtTm7XkK.js","assets/copy-to-clipboard-C1tj4a8X.js","assets/arrow-left-right-CcCrkQiR.js","assets/arrow-left-BpZwGREZ.js","assets/radio-group-yaBPIkVa.js","assets/dist-DA1qWiix.js","assets/dist-BZMqLvO-.js","assets/dist-DhcQhr4B.js","assets/loader-circle-DpEz1fQv.js","assets/send-BNvceEpO.js","assets/triangle-alert-DB5v_9sS.js","assets/dialog-CtyiwzAl.js","assets/dist-DPYswSIO.js","assets/crypto-icon-BPgcAvNF.js","assets/labels-CQIGkPR0.js","assets/input-DAqep8ZY.js","assets/checkout-model-CQ3aqlob.js"])))=>i.map(i=>d[i]);
|
||||||
|
import{n as e,t}from"./lazyRouteComponent-CleTUoKA.js";import{t as n}from"./preload-helper-DoS0eHac.js";var r=e(`/cashier/$trade_id/`)({component:t(()=>n(()=>import(`./_trade_id-BUpVePSs.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43])),`component`)});export{r as t};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{Cn as e,Hp as t,Sn as n,Up as r,_n as i,bn as a,em as o,vn as s,xn as c,yn as l}from"./messages-Bp0bCjzp.js";import{i as u,n as d,t as f}from"./button-BgMnOYKD.js";import{n as p,r as m}from"./font-provider-CtpKPVa7.js";import{n as h}from"./theme-provider-CyJJNAox.js";import{t as g}from"./chevron-down-BB5h1CsX.js";import{n as _,t as v}from"./radio-group-DrQ9k883.js";import{r as y,s as b}from"./zod-rwFXxHlg.js";import{a as x,c as S,i as C,l as w,n as T,o as E,r as D,s as O,t as k}from"./form-BhKmyN6D.js";import{t as A}from"./page-header-CDwG3nxs.js";import{t as j}from"./show-submitted-data-C8ocsjDF.js";var M=o(),N=b({theme:y([`light`,`dark`]),font:y(m)});function P(){let{font:e,setFont:n}=p(),{theme:o,setTheme:y}=h(),b={theme:o,font:e},A=w({resolver:S(N),defaultValues:b});function P(t){t.font!==e&&n(t.font),t.theme!==o&&y(t.theme),j(t)}return(0,M.jsx)(k,{...A,children:(0,M.jsxs)(`form`,{className:`space-y-8`,onSubmit:A.handleSubmit(P),children:[(0,M.jsx)(C,{control:A.control,name:`font`,render:({field:e})=>(0,M.jsxs)(x,{children:[(0,M.jsx)(E,{children:c()}),(0,M.jsxs)(`div`,{className:`relative w-max`,children:[(0,M.jsx)(T,{children:(0,M.jsx)(`select`,{className:u(d({variant:`outline`}),`w-50 appearance-none font-normal capitalize`,`dark:bg-background dark:hover:bg-background`),...e,children:m.map(e=>(0,M.jsx)(`option`,{value:e,children:e},e))})}),(0,M.jsx)(g,{className:`absolute inset-e-3 top-2.5 h-4 w-4 opacity-50`})]}),(0,M.jsx)(D,{className:`font-manrope`,children:a()}),(0,M.jsx)(O,{})]})}),(0,M.jsx)(C,{control:A.control,name:`theme`,render:({field:e})=>(0,M.jsxs)(x,{children:[(0,M.jsx)(E,{children:l()}),(0,M.jsx)(D,{children:s()}),(0,M.jsx)(O,{}),(0,M.jsxs)(v,{className:`grid max-w-md grid-cols-2 gap-8 pt-2`,defaultValue:e.value,onValueChange:e.onChange,children:[(0,M.jsx)(x,{children:(0,M.jsxs)(E,{className:`[&:has([data-state=checked])>div]:border-primary`,children:[(0,M.jsx)(T,{children:(0,M.jsx)(_,{className:`sr-only`,value:`light`})}),(0,M.jsx)(`div`,{className:`items-center rounded-md border-2 border-muted p-1 hover:border-accent`,children:(0,M.jsxs)(`div`,{className:`space-y-2 rounded-sm bg-[#ecedef] p-2`,children:[(0,M.jsxs)(`div`,{className:`space-y-2 rounded-md bg-white p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-2 w-20 rounded-lg bg-[#ecedef]`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-[#ecedef]`})]}),(0,M.jsxs)(`div`,{className:`flex items-center space-x-2 rounded-md bg-white p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-4 w-4 rounded-full bg-[#ecedef]`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-[#ecedef]`})]}),(0,M.jsxs)(`div`,{className:`flex items-center space-x-2 rounded-md bg-white p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-4 w-4 rounded-full bg-[#ecedef]`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-[#ecedef]`})]})]})}),(0,M.jsx)(`span`,{className:`block w-full p-2 text-center font-normal`,children:r()})]})}),(0,M.jsx)(x,{children:(0,M.jsxs)(E,{className:`[&:has([data-state=checked])>div]:border-primary`,children:[(0,M.jsx)(T,{children:(0,M.jsx)(_,{className:`sr-only`,value:`dark`})}),(0,M.jsx)(`div`,{className:`items-center rounded-md border-2 border-muted bg-popover p-1 hover:bg-accent hover:text-accent-foreground`,children:(0,M.jsxs)(`div`,{className:`space-y-2 rounded-sm bg-slate-950 p-2`,children:[(0,M.jsxs)(`div`,{className:`space-y-2 rounded-md bg-slate-800 p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-2 w-20 rounded-lg bg-slate-400`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-slate-400`})]}),(0,M.jsxs)(`div`,{className:`flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-4 w-4 rounded-full bg-slate-400`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-slate-400`})]}),(0,M.jsxs)(`div`,{className:`flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-4 w-4 rounded-full bg-slate-400`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-slate-400`})]})]})}),(0,M.jsx)(`span`,{className:`block w-full p-2 text-center font-normal`,children:t()})]})})]})]})}),(0,M.jsx)(f,{type:`submit`,children:i()})]})})}function F(){return(0,M.jsx)(A,{description:n(),title:e(),variant:`section`,children:(0,M.jsx)(P,{})})}var I=F;export{I as component};
|
import{Cn as e,Sn as t,Up as n,Wp as r,_n as i,bn as a,tm as o,vn as s,xn as c,yn as l}from"./messages-CL4J6BaJ.js";import{i as u,n as d,t as f}from"./button-NLSeBFht.js";import{n as p,r as m}from"./font-provider-C4_iupSb.js";import{n as h}from"./theme-provider-ixHkEVGI.js";import{t as g}from"./chevron-down-BB5h1CsX.js";import{n as _,t as v}from"./radio-group-yaBPIkVa.js";import{r as y,s as b}from"./zod-rwFXxHlg.js";import{a as x,c as S,i as C,l as w,n as T,o as E,r as D,s as O,t as k}from"./form-C_YekIvK.js";import{t as A}from"./page-header-B7O10aw9.js";import{t as j}from"./show-submitted-data-DwaVTW9K.js";var M=o(),N=b({theme:y([`light`,`dark`]),font:y(m)});function P(){let{font:e,setFont:t}=p(),{theme:o,setTheme:y}=h(),b={theme:o,font:e},A=w({resolver:S(N),defaultValues:b});function P(n){n.font!==e&&t(n.font),n.theme!==o&&y(n.theme),j(n)}return(0,M.jsx)(k,{...A,children:(0,M.jsxs)(`form`,{className:`space-y-8`,onSubmit:A.handleSubmit(P),children:[(0,M.jsx)(C,{control:A.control,name:`font`,render:({field:e})=>(0,M.jsxs)(x,{children:[(0,M.jsx)(E,{children:c()}),(0,M.jsxs)(`div`,{className:`relative w-max`,children:[(0,M.jsx)(T,{children:(0,M.jsx)(`select`,{className:u(d({variant:`outline`}),`w-50 appearance-none font-normal capitalize`,`dark:bg-background dark:hover:bg-background`),...e,children:m.map(e=>(0,M.jsx)(`option`,{value:e,children:e},e))})}),(0,M.jsx)(g,{className:`absolute inset-e-3 top-2.5 h-4 w-4 opacity-50`})]}),(0,M.jsx)(D,{className:`font-manrope`,children:a()}),(0,M.jsx)(O,{})]})}),(0,M.jsx)(C,{control:A.control,name:`theme`,render:({field:e})=>(0,M.jsxs)(x,{children:[(0,M.jsx)(E,{children:l()}),(0,M.jsx)(D,{children:s()}),(0,M.jsx)(O,{}),(0,M.jsxs)(v,{className:`grid max-w-md grid-cols-2 gap-8 pt-2`,defaultValue:e.value,onValueChange:e.onChange,children:[(0,M.jsx)(x,{children:(0,M.jsxs)(E,{className:`[&:has([data-state=checked])>div]:border-primary`,children:[(0,M.jsx)(T,{children:(0,M.jsx)(_,{className:`sr-only`,value:`light`})}),(0,M.jsx)(`div`,{className:`items-center rounded-md border-2 border-muted p-1 hover:border-accent`,children:(0,M.jsxs)(`div`,{className:`space-y-2 rounded-sm bg-[#ecedef] p-2`,children:[(0,M.jsxs)(`div`,{className:`space-y-2 rounded-md bg-white p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-2 w-20 rounded-lg bg-[#ecedef]`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-[#ecedef]`})]}),(0,M.jsxs)(`div`,{className:`flex items-center space-x-2 rounded-md bg-white p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-4 w-4 rounded-full bg-[#ecedef]`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-[#ecedef]`})]}),(0,M.jsxs)(`div`,{className:`flex items-center space-x-2 rounded-md bg-white p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-4 w-4 rounded-full bg-[#ecedef]`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-[#ecedef]`})]})]})}),(0,M.jsx)(`span`,{className:`block w-full p-2 text-center font-normal`,children:r()})]})}),(0,M.jsx)(x,{children:(0,M.jsxs)(E,{className:`[&:has([data-state=checked])>div]:border-primary`,children:[(0,M.jsx)(T,{children:(0,M.jsx)(_,{className:`sr-only`,value:`dark`})}),(0,M.jsx)(`div`,{className:`items-center rounded-md border-2 border-muted bg-popover p-1 hover:bg-accent hover:text-accent-foreground`,children:(0,M.jsxs)(`div`,{className:`space-y-2 rounded-sm bg-slate-950 p-2`,children:[(0,M.jsxs)(`div`,{className:`space-y-2 rounded-md bg-slate-800 p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-2 w-20 rounded-lg bg-slate-400`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-slate-400`})]}),(0,M.jsxs)(`div`,{className:`flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-4 w-4 rounded-full bg-slate-400`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-slate-400`})]}),(0,M.jsxs)(`div`,{className:`flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-xs`,children:[(0,M.jsx)(`div`,{className:`h-4 w-4 rounded-full bg-slate-400`}),(0,M.jsx)(`div`,{className:`h-2 w-25 rounded-lg bg-slate-400`})]})]})}),(0,M.jsx)(`span`,{className:`block w-full p-2 text-center font-normal`,children:n()})]})})]})]})}),(0,M.jsx)(f,{type:`submit`,children:i()})]})})}function F(){return(0,M.jsx)(A,{description:t(),title:e(),variant:`section`,children:(0,M.jsx)(P,{})})}var I=F;export{I as component};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";var r=e(t(),1),i=n(),a=(0,r.createContext)({isTyping:!1,passwordLength:0,setIsTyping:()=>void 0,setPasswordLength:()=>void 0,setShowPassword:()=>void 0,showPassword:!1});function o({children:e}){let[t,n]=(0,r.useState)(!1),[o,s]=(0,r.useState)(!1),[c,l]=(0,r.useState)(0);return(0,i.jsx)(a.Provider,{value:{isTyping:t,passwordLength:c,setIsTyping:n,setPasswordLength:l,setShowPassword:s,showPassword:o},children:e})}function s(){return(0,r.useContext)(a)}export{s as n,o as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";var r=e(t(),1),i=n(),a=(0,r.createContext)({isTyping:!1,passwordLength:0,setIsTyping:()=>void 0,setPasswordLength:()=>void 0,setShowPassword:()=>void 0,showPassword:!1});function o({children:e}){let[t,n]=(0,r.useState)(!1),[o,s]=(0,r.useState)(!1),[c,l]=(0,r.useState)(0);return(0,i.jsx)(a.Provider,{value:{isTyping:t,passwordLength:c,setIsTyping:n,setPasswordLength:l,setShowPassword:s,showPassword:o},children:e})}function s(){return(0,r.useContext)(a)}export{s as n,o as t};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{em as e}from"./messages-Bp0bCjzp.js";import{i as t,o as n,r}from"./button-BgMnOYKD.js";var i=e(),a=r(`inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-full border border-transparent px-2 py-0.5 font-medium text-xs transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3`,{variants:{variant:{default:`bg-primary text-primary-foreground [a&]:hover:bg-primary/90`,secondary:`bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90`,destructive:`bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90`,outline:`border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground`,ghost:`[a&]:hover:bg-accent [a&]:hover:text-accent-foreground`,link:`text-primary underline-offset-4 [a&]:hover:underline`}},defaultVariants:{variant:`default`}});function o({className:e,variant:r=`default`,asChild:o=!1,...s}){return(0,i.jsx)(o?n:`span`,{className:t(a({variant:r}),e),"data-slot":`badge`,"data-variant":r,...s})}export{o as t};
|
import{tm as e}from"./messages-CL4J6BaJ.js";import{i as t,o as n,r}from"./button-NLSeBFht.js";var i=e(),a=r(`inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-full border border-transparent px-2 py-0.5 font-medium text-xs transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3`,{variants:{variant:{default:`bg-primary text-primary-foreground [a&]:hover:bg-primary/90`,secondary:`bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90`,destructive:`bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90`,outline:`border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground`,ghost:`[a&]:hover:bg-accent [a&]:hover:text-accent-foreground`,link:`text-primary underline-offset-4 [a&]:hover:underline`}},defaultVariants:{variant:`default`}});function o({className:e,variant:r=`default`,asChild:o=!1,...s}){return(0,i.jsx)(o?n:`span`,{className:t(a({variant:r}),e),"data-slot":`badge`,"data-variant":r,...s})}export{o as t};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{em as e}from"./messages-Bp0bCjzp.js";import{i as t}from"./button-BgMnOYKD.js";var n=e();function r({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm`,e),"data-slot":`card`,...r})}function i({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6`,e),"data-slot":`card-header`,...r})}function a({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`font-semibold leading-none`,e),"data-slot":`card-title`,...r})}function o({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`text-muted-foreground text-sm`,e),"data-slot":`card-description`,...r})}function s({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`px-6`,e),"data-slot":`card-content`,...r})}export{a,i,s as n,o as r,r as t};
|
import{tm as e}from"./messages-CL4J6BaJ.js";import{i as t}from"./button-NLSeBFht.js";var n=e();function r({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm`,e),"data-slot":`card`,...r})}function i({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6`,e),"data-slot":`card-header`,...r})}function a({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`font-semibold leading-none`,e),"data-slot":`card-title`,...r})}function o({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`text-muted-foreground text-sm`,e),"data-slot":`card-description`,...r})}function s({className:e,...r}){return(0,n.jsx)(`div`,{className:t(`px-6`,e),"data-slot":`card-content`,...r})}export{a,i,s as n,o as r,r as t};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{a as t,d as n,f as r}from"./auth-store-Csn6HPxJ.js";import{t as i}from"./react-CO2uhaBc.js";import{t as a}from"./createLucideIcon-Br0Bd5k2.js";var o=a(`pen-line`,[[`path`,{d:`M13 21h8`,key:`1jsn5i`}],[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`,key:`1a8usu`}]]),s=e(i(),1),c=new n({chains:[],loading:!1});function l(e){c.setState(t=>({...t,chains:e}))}function u(e){c.setState(t=>({...t,loading:e}))}function d(){let e=r(c,e=>e.chains),n=r(c,e=>e.loading),i=t.useQuery(`get`,`/admin/api/v1/chains`);return(0,s.useEffect)(()=>{u(i.isLoading)},[i.isLoading]),(0,s.useEffect)(()=>{i.data?.data&&l(i.data.data)},[i.data?.data]),{chains:e,loading:n,refetch:i.refetch}}export{o as n,d as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{a as t,d as n,f as r}from"./auth-store-8ocF_FHU.js";import{t as i}from"./react-CO2uhaBc.js";import{t as a}from"./createLucideIcon-Br0Bd5k2.js";var o=a(`pen-line`,[[`path`,{d:`M13 21h8`,key:`1jsn5i`}],[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`,key:`1a8usu`}]]),s=e(i(),1),c=new n({chains:[],loading:!1});function l(e){c.setState(t=>({...t,chains:e}))}function u(e){c.setState(t=>({...t,loading:e}))}function d(){let e=r(c,e=>e.chains),n=r(c,e=>e.loading),i=t.useQuery(`get`,`/admin/api/v1/chains`);return(0,s.useEffect)(()=>{u(i.isLoading)},[i.isLoading]),(0,s.useEffect)(()=>{i.data?.data&&l(i.data.data)},[i.data?.data]),{chains:e,loading:n,refetch:i.refetch}}export{o as n,d as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{t as r}from"./dist-BFnxq45V.js";import{i,u as a}from"./button-BgMnOYKD.js";import{a as o,r as s,t as c}from"./dist-CKFLmh1A.js";import{t as l}from"./dist-Clua1vrx.js";import{t as u}from"./dist-BixeH3nX.js";import{t as d}from"./dist-DGDEBCW9.js";import{t as f}from"./check-CHp0nSkR.js";var p=e(t(),1),m=n(),h=`Checkbox`,[g,_]=o(h),[v,y]=g(h);function b(e){let{__scopeCheckbox:t,checked:n,children:r,defaultChecked:i,disabled:a,form:o,name:s,onCheckedChange:l,required:u,value:d=`on`,internal_do_not_use_render:f}=e,[g,_]=c({prop:n,defaultProp:i??!1,onChange:l,caller:h}),[y,b]=p.useState(null),[x,S]=p.useState(null),C=p.useRef(!1),w=y?!!o||!!y.closest(`form`):!0,T={checked:g,disabled:a,setChecked:_,control:y,setControl:b,name:s,form:o,value:d,hasConsumerStoppedPropagationRef:C,required:u,defaultChecked:k(i)?!1:i,isFormControl:w,bubbleInput:x,setBubbleInput:S};return(0,m.jsx)(v,{scope:t,...T,children:O(f)?f(T):r})}var x=`CheckboxTrigger`,S=p.forwardRef(({__scopeCheckbox:e,onKeyDown:t,onClick:n,...i},o)=>{let{control:c,value:l,disabled:u,checked:d,required:f,setControl:h,setChecked:g,hasConsumerStoppedPropagationRef:_,isFormControl:v,bubbleInput:b}=y(x,e),S=a(o,h),C=p.useRef(d);return p.useEffect(()=>{let e=c?.form;if(e){let t=()=>g(C.current);return e.addEventListener(`reset`,t),()=>e.removeEventListener(`reset`,t)}},[c,g]),(0,m.jsx)(r.button,{type:`button`,role:`checkbox`,"aria-checked":k(d)?`mixed`:d,"aria-required":f,"data-state":A(d),"data-disabled":u?``:void 0,disabled:u,value:l,...i,ref:S,onKeyDown:s(t,e=>{e.key===`Enter`&&e.preventDefault()}),onClick:s(n,e=>{g(e=>k(e)?!0:!e),b&&v&&(_.current=e.isPropagationStopped(),_.current||e.stopPropagation())})})});S.displayName=x;var C=p.forwardRef((e,t)=>{let{__scopeCheckbox:n,name:r,checked:i,defaultChecked:a,required:o,disabled:s,value:c,onCheckedChange:l,form:u,...d}=e;return(0,m.jsx)(b,{__scopeCheckbox:n,checked:i,defaultChecked:a,disabled:s,required:o,onCheckedChange:l,name:r,form:u,value:c,internal_do_not_use_render:({isFormControl:e})=>(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(S,{...d,ref:t,__scopeCheckbox:n}),e&&(0,m.jsx)(D,{__scopeCheckbox:n})]})})});C.displayName=h;var w=`CheckboxIndicator`,T=p.forwardRef((e,t)=>{let{__scopeCheckbox:n,forceMount:i,...a}=e,o=y(w,n);return(0,m.jsx)(l,{present:i||k(o.checked)||o.checked===!0,children:(0,m.jsx)(r.span,{"data-state":A(o.checked),"data-disabled":o.disabled?``:void 0,...a,ref:t,style:{pointerEvents:`none`,...e.style}})})});T.displayName=w;var E=`CheckboxBubbleInput`,D=p.forwardRef(({__scopeCheckbox:e,...t},n)=>{let{control:i,hasConsumerStoppedPropagationRef:o,checked:s,defaultChecked:c,required:l,disabled:f,name:h,value:g,form:_,bubbleInput:v,setBubbleInput:b}=y(E,e),x=a(n,b),S=u(s),C=d(i);p.useEffect(()=>{let e=v;if(!e)return;let t=window.HTMLInputElement.prototype,n=Object.getOwnPropertyDescriptor(t,`checked`).set,r=!o.current;if(S!==s&&n){let t=new Event(`click`,{bubbles:r});e.indeterminate=k(s),n.call(e,k(s)?!1:s),e.dispatchEvent(t)}},[v,S,s,o]);let w=p.useRef(k(s)?!1:s);return(0,m.jsx)(r.input,{type:`checkbox`,"aria-hidden":!0,defaultChecked:c??w.current,required:l,disabled:f,name:h,value:g,form:_,...t,tabIndex:-1,ref:x,style:{...t.style,...C,position:`absolute`,pointerEvents:`none`,opacity:0,margin:0,transform:`translateX(-100%)`}})});D.displayName=E;function O(e){return typeof e==`function`}function k(e){return e===`indeterminate`}function A(e){return k(e)?`indeterminate`:e?`checked`:`unchecked`}function j({className:e,...t}){return(0,m.jsx)(C,{className:i(`peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs outline-none transition-shadow focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:data-[state=checked]:bg-primary dark:aria-invalid:ring-destructive/40`,e),"data-slot":`checkbox`,...t,children:(0,m.jsx)(T,{className:`grid place-content-center text-current transition-none`,"data-slot":`checkbox-indicator`,children:(0,m.jsx)(f,{className:`size-3.5`})})})}export{j as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{t as r}from"./dist-D3WFT-Yo.js";import{i,u as a}from"./button-NLSeBFht.js";import{a as o,r as s,t as c}from"./dist-DmeeHi7K.js";import{t as l}from"./dist-BZMqLvO-.js";import{t as u}from"./dist-BixeH3nX.js";import{t as d}from"./dist-B0pRVbY9.js";import{t as f}from"./check-CHp0nSkR.js";var p=e(t(),1),m=n(),h=`Checkbox`,[g,_]=o(h),[v,y]=g(h);function b(e){let{__scopeCheckbox:t,checked:n,children:r,defaultChecked:i,disabled:a,form:o,name:s,onCheckedChange:l,required:u,value:d=`on`,internal_do_not_use_render:f}=e,[g,_]=c({prop:n,defaultProp:i??!1,onChange:l,caller:h}),[y,b]=p.useState(null),[x,S]=p.useState(null),C=p.useRef(!1),w=y?!!o||!!y.closest(`form`):!0,T={checked:g,disabled:a,setChecked:_,control:y,setControl:b,name:s,form:o,value:d,hasConsumerStoppedPropagationRef:C,required:u,defaultChecked:k(i)?!1:i,isFormControl:w,bubbleInput:x,setBubbleInput:S};return(0,m.jsx)(v,{scope:t,...T,children:O(f)?f(T):r})}var x=`CheckboxTrigger`,S=p.forwardRef(({__scopeCheckbox:e,onKeyDown:t,onClick:n,...i},o)=>{let{control:c,value:l,disabled:u,checked:d,required:f,setControl:h,setChecked:g,hasConsumerStoppedPropagationRef:_,isFormControl:v,bubbleInput:b}=y(x,e),S=a(o,h),C=p.useRef(d);return p.useEffect(()=>{let e=c?.form;if(e){let t=()=>g(C.current);return e.addEventListener(`reset`,t),()=>e.removeEventListener(`reset`,t)}},[c,g]),(0,m.jsx)(r.button,{type:`button`,role:`checkbox`,"aria-checked":k(d)?`mixed`:d,"aria-required":f,"data-state":A(d),"data-disabled":u?``:void 0,disabled:u,value:l,...i,ref:S,onKeyDown:s(t,e=>{e.key===`Enter`&&e.preventDefault()}),onClick:s(n,e=>{g(e=>k(e)?!0:!e),b&&v&&(_.current=e.isPropagationStopped(),_.current||e.stopPropagation())})})});S.displayName=x;var C=p.forwardRef((e,t)=>{let{__scopeCheckbox:n,name:r,checked:i,defaultChecked:a,required:o,disabled:s,value:c,onCheckedChange:l,form:u,...d}=e;return(0,m.jsx)(b,{__scopeCheckbox:n,checked:i,defaultChecked:a,disabled:s,required:o,onCheckedChange:l,name:r,form:u,value:c,internal_do_not_use_render:({isFormControl:e})=>(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(S,{...d,ref:t,__scopeCheckbox:n}),e&&(0,m.jsx)(D,{__scopeCheckbox:n})]})})});C.displayName=h;var w=`CheckboxIndicator`,T=p.forwardRef((e,t)=>{let{__scopeCheckbox:n,forceMount:i,...a}=e,o=y(w,n);return(0,m.jsx)(l,{present:i||k(o.checked)||o.checked===!0,children:(0,m.jsx)(r.span,{"data-state":A(o.checked),"data-disabled":o.disabled?``:void 0,...a,ref:t,style:{pointerEvents:`none`,...e.style}})})});T.displayName=w;var E=`CheckboxBubbleInput`,D=p.forwardRef(({__scopeCheckbox:e,...t},n)=>{let{control:i,hasConsumerStoppedPropagationRef:o,checked:s,defaultChecked:c,required:l,disabled:f,name:h,value:g,form:_,bubbleInput:v,setBubbleInput:b}=y(E,e),x=a(n,b),S=u(s),C=d(i);p.useEffect(()=>{let e=v;if(!e)return;let t=window.HTMLInputElement.prototype,n=Object.getOwnPropertyDescriptor(t,`checked`).set,r=!o.current;if(S!==s&&n){let t=new Event(`click`,{bubbles:r});e.indeterminate=k(s),n.call(e,k(s)?!1:s),e.dispatchEvent(t)}},[v,S,s,o]);let w=p.useRef(k(s)?!1:s);return(0,m.jsx)(r.input,{type:`checkbox`,"aria-hidden":!0,defaultChecked:c??w.current,required:l,disabled:f,name:h,value:g,form:_,...t,tabIndex:-1,ref:x,style:{...t.style,...C,position:`absolute`,pointerEvents:`none`,opacity:0,margin:0,transform:`translateX(-100%)`}})});D.displayName=E;function O(e){return typeof e==`function`}function k(e){return e===`indeterminate`}function A(e){return k(e)?`indeterminate`:e?`checked`:`unchecked`}function j({className:e,...t}){return(0,m.jsx)(C,{className:i(`peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs outline-none transition-shadow focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:data-[state=checked]:bg-primary dark:aria-invalid:ring-destructive/40`,e),"data-slot":`checkbox`,...t,children:(0,m.jsx)(T,{className:`grid place-content-center text-current transition-none`,"data-slot":`checkbox-indicator`,children:(0,m.jsx)(f,{className:`size-3.5`})})})}export{j as t};
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import{Fp as e,Ip as t,Lp as n,em as r}from"./messages-Bp0bCjzp.js";import{t as i}from"./telescope-DU0wiTDw.js";import{i as a,o,r as s,s as c,t as l}from"./dialog-BJ5VA2v_.js";var u=r();function d({open:r,onOpenChange:d}){return(0,u.jsx)(l,{onOpenChange:d,open:r,children:(0,u.jsx)(s,{className:`sm:max-w-sm`,children:(0,u.jsxs)(o,{className:`items-center text-center`,children:[(0,u.jsx)(i,{className:`mb-2 size-12 text-muted-foreground`}),(0,u.jsx)(c,{children:n()}),(0,u.jsxs)(a,{children:[t(),(0,u.jsx)(`br`,{}),(0,u.jsx)(`p`,{className:`mt-2 text-center`,children:e()})]})]})})})}export{d as t};
|
import{Ip as e,Lp as t,Rp as n,tm as r}from"./messages-CL4J6BaJ.js";import{t as i}from"./telescope-DU0wiTDw.js";import{i as a,o,r as s,s as c,t as l}from"./dialog-CtyiwzAl.js";var u=r();function d({open:r,onOpenChange:d}){return(0,u.jsx)(l,{onOpenChange:d,open:r,children:(0,u.jsx)(s,{className:`sm:max-w-sm`,children:(0,u.jsxs)(o,{className:`items-center text-center`,children:[(0,u.jsx)(i,{className:`mb-2 size-12 text-muted-foreground`}),(0,u.jsx)(c,{children:n()}),(0,u.jsxs)(a,{children:[t(),(0,u.jsx)(`br`,{}),(0,u.jsx)(`p`,{className:`mt-2 text-center`,children:e()})]})]})})})}export{d as t};
|
||||||
File diff suppressed because one or more lines are too long
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{Jp as n,Yp as r,em as i}from"./messages-Bp0bCjzp.js";import{c as a,i as o,t as s,u as c}from"./button-BgMnOYKD.js";import{a as l,r as u}from"./dist-CKFLmh1A.js";import{a as d,c as f,i as p,l as m,n as h,o as g,r as _,s as ee,t as v,u as y}from"./dist-CPQ-sRtL.js";var b=e(t(),1),x=i(),S=`AlertDialog`,[C,te]=l(S,[y]),w=y(),T=e=>{let{__scopeAlertDialog:t,...n}=e,r=w(t);return(0,x.jsx)(g,{...r,...n,modal:!0})};T.displayName=S;var E=`AlertDialogTrigger`,D=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(f,{...i,...r,ref:t})});D.displayName=E;var O=`AlertDialogPortal`,k=e=>{let{__scopeAlertDialog:t,...n}=e,r=w(t);return(0,x.jsx)(d,{...r,...n})};k.displayName=O;var A=`AlertDialogOverlay`,j=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(p,{...i,...r,ref:t})});j.displayName=A;var M=`AlertDialogContent`,[N,P]=C(M),F=a(`AlertDialogContent`),I=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,children:r,...i}=e,a=w(n),o=b.useRef(null),s=c(t,o),l=b.useRef(null);return(0,x.jsx)(m,{contentName:M,titleName:L,docsSlug:`alert-dialog`,children:(0,x.jsx)(N,{scope:n,cancelRef:l,children:(0,x.jsxs)(h,{role:`alertdialog`,...a,...i,ref:s,onOpenAutoFocus:u(i.onOpenAutoFocus,e=>{e.preventDefault(),l.current?.focus({preventScroll:!0})}),onPointerDownOutside:e=>e.preventDefault(),onInteractOutside:e=>e.preventDefault(),children:[(0,x.jsx)(F,{children:r}),(0,x.jsx)(G,{contentRef:o})]})})})});I.displayName=M;var L=`AlertDialogTitle`,R=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(ee,{...i,...r,ref:t})});R.displayName=L;var z=`AlertDialogDescription`,B=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(_,{...i,...r,ref:t})});B.displayName=z;var V=`AlertDialogAction`,H=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(v,{...i,...r,ref:t})});H.displayName=V;var U=`AlertDialogCancel`,W=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,{cancelRef:i}=P(U,n),a=w(n),o=c(t,i);return(0,x.jsx)(v,{...a,...r,ref:o})});W.displayName=U;var G=({contentRef:e})=>{let t=`\`${M}\` requires a description for the component to be accessible for screen reader users.
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{Xp as n,Yp as r,tm as i}from"./messages-CL4J6BaJ.js";import{c as a,i as o,t as s,u as c}from"./button-NLSeBFht.js";import{a as l,r as u}from"./dist-DmeeHi7K.js";import{a as d,c as f,i as p,l as m,n as h,o as g,r as _,s as ee,t as v,u as y}from"./dist-DPYswSIO.js";var b=e(t(),1),x=i(),S=`AlertDialog`,[C,te]=l(S,[y]),w=y(),T=e=>{let{__scopeAlertDialog:t,...n}=e,r=w(t);return(0,x.jsx)(g,{...r,...n,modal:!0})};T.displayName=S;var E=`AlertDialogTrigger`,D=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(f,{...i,...r,ref:t})});D.displayName=E;var O=`AlertDialogPortal`,k=e=>{let{__scopeAlertDialog:t,...n}=e,r=w(t);return(0,x.jsx)(d,{...r,...n})};k.displayName=O;var A=`AlertDialogOverlay`,j=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(p,{...i,...r,ref:t})});j.displayName=A;var M=`AlertDialogContent`,[N,P]=C(M),F=a(`AlertDialogContent`),I=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,children:r,...i}=e,a=w(n),o=b.useRef(null),s=c(t,o),l=b.useRef(null);return(0,x.jsx)(m,{contentName:M,titleName:L,docsSlug:`alert-dialog`,children:(0,x.jsx)(N,{scope:n,cancelRef:l,children:(0,x.jsxs)(h,{role:`alertdialog`,...a,...i,ref:s,onOpenAutoFocus:u(i.onOpenAutoFocus,e=>{e.preventDefault(),l.current?.focus({preventScroll:!0})}),onPointerDownOutside:e=>e.preventDefault(),onInteractOutside:e=>e.preventDefault(),children:[(0,x.jsx)(F,{children:r}),(0,x.jsx)(G,{contentRef:o})]})})})});I.displayName=M;var L=`AlertDialogTitle`,R=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(ee,{...i,...r,ref:t})});R.displayName=L;var z=`AlertDialogDescription`,B=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(_,{...i,...r,ref:t})});B.displayName=z;var V=`AlertDialogAction`,H=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,i=w(n);return(0,x.jsx)(v,{...i,...r,ref:t})});H.displayName=V;var U=`AlertDialogCancel`,W=b.forwardRef((e,t)=>{let{__scopeAlertDialog:n,...r}=e,{cancelRef:i}=P(U,n),a=w(n),o=c(t,i);return(0,x.jsx)(v,{...a,...r,ref:o})});W.displayName=U;var G=({contentRef:e})=>{let t=`\`${M}\` requires a description for the component to be accessible for screen reader users.
|
||||||
|
|
||||||
You can add a description to the \`${M}\` by passing a \`${z}\` component as a child, which also benefits sighted users by adding visible context to the dialog.
|
You can add a description to the \`${M}\` by passing a \`${z}\` component as a child, which also benefits sighted users by adding visible context to the dialog.
|
||||||
|
|
||||||
Alternatively, you can use your own component as a description by assigning it an \`id\` and passing the same value to the \`aria-describedby\` prop in \`${M}\`. If the description is confusing or duplicative for sighted users, you can use the \`@radix-ui/react-visually-hidden\` primitive as a wrapper around your description component.
|
Alternatively, you can use your own component as a description by assigning it an \`id\` and passing the same value to the \`aria-describedby\` prop in \`${M}\`. If the description is confusing or duplicative for sighted users, you can use the \`@radix-ui/react-visually-hidden\` primitive as a wrapper around your description component.
|
||||||
|
|
||||||
For more information, see https://radix-ui.com/primitives/docs/components/alert-dialog`;return b.useEffect(()=>{document.getElementById(e.current?.getAttribute(`aria-describedby`))||console.warn(t)},[t,e]),null},K=T,q=k,J=j,Y=I,X=W,Z=R,Q=B;function ne({...e}){return(0,x.jsx)(K,{"data-slot":`alert-dialog`,...e})}function re({...e}){return(0,x.jsx)(q,{"data-slot":`alert-dialog-portal`,...e})}function ie({className:e,...t}){return(0,x.jsx)(J,{className:o(`data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=open]:animate-in`,e),"data-slot":`alert-dialog-overlay`,...t})}function ae({className:e,size:t=`default`,...n}){return(0,x.jsxs)(re,{children:[(0,x.jsx)(ie,{}),(0,x.jsx)(Y,{className:o(`group/alert-dialog-content data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[size=sm]:max-w-xs data-[state=closed]:animate-out data-[state=open]:animate-in data-[size=default]:sm:max-w-lg`,e),"data-size":t,"data-slot":`alert-dialog-content`,...n})]})}function oe({className:e,...t}){return(0,x.jsx)(`div`,{className:o(`grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]`,e),"data-slot":`alert-dialog-header`,...t})}function $({className:e,...t}){return(0,x.jsx)(`div`,{className:o(`flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end`,e),"data-slot":`alert-dialog-footer`,...t})}function se({className:e,...t}){return(0,x.jsx)(Z,{className:o(`font-semibold text-lg sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2`,e),"data-slot":`alert-dialog-title`,...t})}function ce({className:e,...t}){return(0,x.jsx)(Q,{className:o(`text-muted-foreground text-sm`,e),"data-slot":`alert-dialog-description`,...t})}function le({className:e,variant:t=`outline`,size:n=`default`,...r}){return(0,x.jsx)(s,{asChild:!0,size:n,variant:t,children:(0,x.jsx)(X,{className:o(e),"data-slot":`alert-dialog-cancel`,...r})})}function ue(e){let{title:t,desc:i,children:a,className:c,confirmText:l,cancelBtnText:u,destructive:d,isLoading:f,disabled:p=!1,form:m,handleConfirm:h,...g}=e;return(0,x.jsx)(ne,{...g,children:(0,x.jsxs)(ae,{className:o(c&&c),children:[(0,x.jsxs)(oe,{className:`text-start`,children:[(0,x.jsx)(se,{children:t}),(0,x.jsx)(ce,{asChild:!0,children:(0,x.jsx)(`div`,{children:i})})]}),a,(0,x.jsxs)($,{children:[(0,x.jsx)(le,{disabled:f,children:u??r()}),(0,x.jsx)(s,{disabled:p||f,form:m,onClick:h,type:m?`submit`:`button`,variant:d?`destructive`:`default`,children:l??n()})]})]})})}export{ue as t};
|
For more information, see https://radix-ui.com/primitives/docs/components/alert-dialog`;return b.useEffect(()=>{document.getElementById(e.current?.getAttribute(`aria-describedby`))||console.warn(t)},[t,e]),null},K=T,q=k,J=j,Y=I,X=W,Z=R,Q=B;function ne({...e}){return(0,x.jsx)(K,{"data-slot":`alert-dialog`,...e})}function re({...e}){return(0,x.jsx)(q,{"data-slot":`alert-dialog-portal`,...e})}function ie({className:e,...t}){return(0,x.jsx)(J,{className:o(`data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=open]:animate-in`,e),"data-slot":`alert-dialog-overlay`,...t})}function ae({className:e,size:t=`default`,...n}){return(0,x.jsxs)(re,{children:[(0,x.jsx)(ie,{}),(0,x.jsx)(Y,{className:o(`group/alert-dialog-content data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[size=sm]:max-w-xs data-[state=closed]:animate-out data-[state=open]:animate-in data-[size=default]:sm:max-w-lg`,e),"data-size":t,"data-slot":`alert-dialog-content`,...n})]})}function oe({className:e,...t}){return(0,x.jsx)(`div`,{className:o(`grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]`,e),"data-slot":`alert-dialog-header`,...t})}function $({className:e,...t}){return(0,x.jsx)(`div`,{className:o(`flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end`,e),"data-slot":`alert-dialog-footer`,...t})}function se({className:e,...t}){return(0,x.jsx)(Z,{className:o(`font-semibold text-lg sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2`,e),"data-slot":`alert-dialog-title`,...t})}function ce({className:e,...t}){return(0,x.jsx)(Q,{className:o(`text-muted-foreground text-sm`,e),"data-slot":`alert-dialog-description`,...t})}function le({className:e,variant:t=`outline`,size:n=`default`,...r}){return(0,x.jsx)(s,{asChild:!0,size:n,variant:t,children:(0,x.jsx)(X,{className:o(e),"data-slot":`alert-dialog-cancel`,...r})})}function ue(e){let{title:t,desc:i,children:a,className:c,confirmText:l,cancelBtnText:u,destructive:d,isLoading:f,disabled:p=!1,form:m,handleConfirm:h,...g}=e;return(0,x.jsx)(ne,{...g,children:(0,x.jsxs)(ae,{className:o(c&&c),children:[(0,x.jsxs)(oe,{className:`text-start`,children:[(0,x.jsx)(se,{children:t}),(0,x.jsx)(ce,{asChild:!0,children:(0,x.jsx)(`div`,{children:i})})]}),a,(0,x.jsxs)($,{children:[(0,x.jsx)(le,{disabled:f,children:u??n()}),(0,x.jsx)(s,{disabled:p||f,form:m,onClick:h,type:m?`submit`:`button`,variant:d?`destructive`:`default`,children:l??r()})]})]})})}export{ue as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";var r=e(t(),1);function i(e){let t=new Map,n=new Map;return{get(e){return t.get(e)},load(r){let i=t.get(r);if(i)return Promise.resolve(i);let a=n.get(r);if(a)return a;let o=e(r).then(e=>(t.set(r,e),e)).finally(()=>{n.delete(r)});return n.set(r,o),o}}}async function a(e,t,n){for(let n of e){let e=`${n.base}/${t}`;try{let t=await fetch(e,{signal:AbortSignal.timeout(3e3)});if(t.ok)return await t.json()}catch{}}return n}function o({cdnList:e,fallback:t,path:n}){return i(r=>a(e,n(r),t))}var s=`GMWalletApp/crypto-icons`,c=`latest`,l=[{base:`https://cdn.jsdmirror.com/gh/${s}@${c}`,name:`jsdmirror`},{base:`https://cdn.jsdelivr.net/gh/${s}@${c}`,name:`jsdelivr`},{base:`https://fastly.jsdelivr.net/gh/${s}@${c}`,name:`fastly.jsdelivr`},{base:`https://gcore.jsdelivr.net/gh/${s}@${c}`,name:`gcore.jsdelivr`}],u={exchange:`exchanges`,network:`networks`,token:`tokens`,wallet:`wallets`},d=o({cdnList:l,fallback:{},path:e=>`aliases/${u[e]}.json`}),f=o({cdnList:l,fallback:[],path:e=>`maps/${u[e]}.json`});function p(e){return String(e??``).trim().toLowerCase()}function m(e){return p(e).replace(/\s+/g,`-`)}function h(e){let t=e?.split(`:`).pop();return t?t.trim():``}function g(e){return[e.id,e.symbol,e.name,e.shortName,h(e.filePath)].map(e=>m(e??``)).filter(Boolean)}function _(e,t){let n=e.find(e=>g(e).includes(t));return n&&(h(n.filePath)||n.id||n.symbol)||null}async function v(e,t){let n=m(t);if(!n)return``;let[r,i]=await Promise.all([f.load(e),d.load(e)]),a=m(i[n]??``);return _(r,n)||(a?_(r,a):null)||i[n]||n}function y(e,t,n={}){let{variant:r=`branded`}=n,i=m(t);return i?`${l[0].base}/assets/${u[e]}/${r}/${i}.svg`:null}async function b(e,t,n={}){let{variant:r=`branded`}=n,i=await v(e,t),a=`assets/${u[e]}/${r}/${i}.svg`;for(let e of l){let t=`${e.base}/${a}`;try{if((await fetch(t,{method:`HEAD`,signal:AbortSignal.timeout(2500)})).ok)return{url:t}}catch{}}return{url:`${l[0].base}/${a}`}}function x(e,t){return t?.trim()||e||`--`}var S=n();function C({type:e,name:t,variant:n=`branded`,size:i=16,width:a,height:o,className:s,alt:c,style:l,onError:u,...d}){let f=y(e,t,{variant:n}),[p,m]=(0,r.useState)(null),[h,g]=(0,r.useState)(f),_=h??f,v=a??i,x=o??i;return(0,r.useEffect)(()=>{let r=!1;return m(null),g(y(e,t,{variant:n})),b(e,t,{variant:n}).then(e=>{r||g(e.url)}),()=>{r=!0}},[t,e,n]),!(_&&t)||p===_?null:(0,S.jsx)(`img`,{alt:c??``,className:s,height:x,onError:e=>{m(_),u?.(e)},src:_,style:{display:`inline-block`,...l},width:v,...d})}export{p as a,l as i,x as n,v as o,u as r,o as s,C as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";var r=e(t(),1);function i(e){let t=new Map,n=new Map;return{get(e){return t.get(e)},load(r){let i=t.get(r);if(i)return Promise.resolve(i);let a=n.get(r);if(a)return a;let o=e(r).then(e=>(t.set(r,e),e)).finally(()=>{n.delete(r)});return n.set(r,o),o}}}async function a(e,t,n){for(let n of e){let e=`${n.base}/${t}`;try{let t=await fetch(e,{signal:AbortSignal.timeout(3e3)});if(t.ok)return await t.json()}catch{}}return n}function o({cdnList:e,fallback:t,path:n}){return i(r=>a(e,n(r),t))}var s=`GMWalletApp/crypto-icons`,c=`latest`,l=[{base:`https://cdn.jsdmirror.com/gh/${s}@${c}`,name:`jsdmirror`},{base:`https://cdn.jsdelivr.net/gh/${s}@${c}`,name:`jsdelivr`},{base:`https://fastly.jsdelivr.net/gh/${s}@${c}`,name:`fastly.jsdelivr`},{base:`https://gcore.jsdelivr.net/gh/${s}@${c}`,name:`gcore.jsdelivr`}],u={exchange:`exchanges`,network:`networks`,token:`tokens`,wallet:`wallets`},d=o({cdnList:l,fallback:{},path:e=>`aliases/${u[e]}.json`}),f=o({cdnList:l,fallback:[],path:e=>`maps/${u[e]}.json`});function p(e){return String(e??``).trim().toLowerCase()}function m(e){return p(e).replace(/\s+/g,`-`)}function h(e){let t=e?.split(`:`).pop();return t?t.trim():``}function g(e){return[e.id,e.symbol,e.name,e.shortName,h(e.filePath)].map(e=>m(e??``)).filter(Boolean)}function _(e,t){let n=e.find(e=>g(e).includes(t));return n&&(h(n.filePath)||n.id||n.symbol)||null}async function v(e,t){let n=m(t);if(!n)return``;let[r,i]=await Promise.all([f.load(e),d.load(e)]),a=m(i[n]??``);return _(r,n)||(a?_(r,a):null)||i[n]||n}function y(e,t,n={}){let{variant:r=`branded`}=n,i=m(t);return i?`${l[0].base}/assets/${u[e]}/${r}/${i}.svg`:null}async function b(e,t,n={}){let{variant:r=`branded`}=n,i=await v(e,t),a=`assets/${u[e]}/${r}/${i}.svg`;for(let e of l){let t=`${e.base}/${a}`;try{if((await fetch(t,{method:`HEAD`,signal:AbortSignal.timeout(2500)})).ok)return{url:t}}catch{}}return{url:`${l[0].base}/${a}`}}function x(e,t){return t?.trim()||e||`--`}var S=n();function C({type:e,name:t,variant:n=`branded`,size:i=16,width:a,height:o,className:s,alt:c,style:l,onError:u,...d}){let f=y(e,t,{variant:n}),[p,m]=(0,r.useState)(null),[h,g]=(0,r.useState)(f),_=h??f,v=a??i,x=o??i;return(0,r.useEffect)(()=>{let r=!1;return m(null),g(y(e,t,{variant:n})),b(e,t,{variant:n}).then(e=>{r||g(e.url)}),()=>{r=!0}},[t,e,n]),!(_&&t)||p===_?null:(0,S.jsx)(`img`,{alt:c??``,className:s,height:x,onError:e=>{m(_),u?.(e)},src:_,style:{display:`inline-block`,...l},width:v,...d})}export{p as a,l as i,x as n,v as o,u as r,o as s,C as t};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{em as e}from"./messages-Bp0bCjzp.js";import{i as t,t as n}from"./button-BgMnOYKD.js";import{a as r,c as i,i as a,n as o,o as s,r as c,s as l,t as u}from"./dist-CPQ-sRtL.js";import{t as d}from"./createLucideIcon-Br0Bd5k2.js";var f=d(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]),p=e();function m({...e}){return(0,p.jsx)(s,{"data-slot":`dialog`,...e})}function h({...e}){return(0,p.jsx)(i,{"data-slot":`dialog-trigger`,...e})}function g({...e}){return(0,p.jsx)(r,{"data-slot":`dialog-portal`,...e})}function _({...e}){return(0,p.jsx)(u,{"data-slot":`dialog-close`,...e})}function v({className:e,...n}){return(0,p.jsx)(a,{className:t(`data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=open]:animate-in`,e),"data-slot":`dialog-overlay`,...n})}function y({className:e,children:n,showCloseButton:r=!0,...i}){return(0,p.jsxs)(g,{"data-slot":`dialog-portal`,children:[(0,p.jsx)(v,{}),(0,p.jsxs)(o,{className:t(`data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg outline-none duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg`,e),"data-slot":`dialog-content`,...i,children:[n,r&&(0,p.jsxs)(u,{className:`absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0`,"data-slot":`dialog-close`,children:[(0,p.jsx)(f,{}),(0,p.jsx)(`span`,{className:`sr-only`,children:`Close`})]})]})]})}function b({className:e,...n}){return(0,p.jsx)(`div`,{className:t(`flex flex-col gap-2 text-center sm:text-left`,e),"data-slot":`dialog-header`,...n})}function x({className:e,showCloseButton:r=!1,children:i,...a}){return(0,p.jsxs)(`div`,{className:t(`flex flex-col-reverse gap-2 sm:flex-row sm:justify-end`,e),"data-slot":`dialog-footer`,...a,children:[i,r&&(0,p.jsx)(u,{asChild:!0,children:(0,p.jsx)(n,{variant:`outline`,children:`Close`})})]})}function S({className:e,...n}){return(0,p.jsx)(l,{className:t(`font-semibold text-lg leading-none`,e),"data-slot":`dialog-title`,...n})}function C({className:e,...n}){return(0,p.jsx)(c,{className:t(`text-muted-foreground text-sm`,e),"data-slot":`dialog-description`,...n})}export{x as a,h as c,C as i,f as l,_ as n,b as o,y as r,S as s,m as t};
|
import{tm as e}from"./messages-CL4J6BaJ.js";import{i as t,t as n}from"./button-NLSeBFht.js";import{a as r,c as i,i as a,n as o,o as s,r as c,s as l,t as u}from"./dist-DPYswSIO.js";import{t as d}from"./createLucideIcon-Br0Bd5k2.js";var f=d(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]),p=e();function m({...e}){return(0,p.jsx)(s,{"data-slot":`dialog`,...e})}function h({...e}){return(0,p.jsx)(i,{"data-slot":`dialog-trigger`,...e})}function g({...e}){return(0,p.jsx)(r,{"data-slot":`dialog-portal`,...e})}function _({...e}){return(0,p.jsx)(u,{"data-slot":`dialog-close`,...e})}function v({className:e,...n}){return(0,p.jsx)(a,{className:t(`data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=open]:animate-in`,e),"data-slot":`dialog-overlay`,...n})}function y({className:e,children:n,showCloseButton:r=!0,...i}){return(0,p.jsxs)(g,{"data-slot":`dialog-portal`,children:[(0,p.jsx)(v,{}),(0,p.jsxs)(o,{className:t(`data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg outline-none duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg`,e),"data-slot":`dialog-content`,...i,children:[n,r&&(0,p.jsxs)(u,{className:`absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0`,"data-slot":`dialog-close`,children:[(0,p.jsx)(f,{}),(0,p.jsx)(`span`,{className:`sr-only`,children:`Close`})]})]})]})}function b({className:e,...n}){return(0,p.jsx)(`div`,{className:t(`flex flex-col gap-2 text-center sm:text-left`,e),"data-slot":`dialog-header`,...n})}function x({className:e,showCloseButton:r=!1,children:i,...a}){return(0,p.jsxs)(`div`,{className:t(`flex flex-col-reverse gap-2 sm:flex-row sm:justify-end`,e),"data-slot":`dialog-footer`,...a,children:[i,r&&(0,p.jsx)(u,{asChild:!0,children:(0,p.jsx)(n,{variant:`outline`,children:`Close`})})]})}function S({className:e,...n}){return(0,p.jsx)(l,{className:t(`font-semibold text-lg leading-none`,e),"data-slot":`dialog-title`,...n})}function C({className:e,...n}){return(0,p.jsx)(c,{className:t(`text-muted-foreground text-sm`,e),"data-slot":`dialog-description`,...n})}export{x as a,h as c,C as i,f as l,_ as n,b as o,y as r,S as s,m as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{an as e,cn as t,dn as n,em as r,fn as i,gn as a,hn as o,ln as s,mn as c,on as l,pn as u,sn as d,un as f}from"./messages-Bp0bCjzp.js";import{t as p}from"./button-BgMnOYKD.js";import{t as m}from"./checkbox-CKrZFk1G.js";import{c as h,i as g,s as _}from"./zod-rwFXxHlg.js";import{a as v,c as y,i as b,l as x,n as S,o as C,r as w,s as T,t as E}from"./form-BhKmyN6D.js";import{t as D}from"./page-header-CDwG3nxs.js";import{t as O}from"./show-submitted-data-C8ocsjDF.js";var k=r(),A=[{id:`recents`,label:c()},{id:`home`,label:u()},{id:`applications`,label:i()},{id:`desktop`,label:n()},{id:`downloads`,label:f()},{id:`documents`,label:s()}],j=_({items:g(h()).refine(e=>e.some(e=>e),{message:t()})}),M={items:[`recents`,`home`]};function N(){let t=x({resolver:y(j),defaultValues:M});return(0,k.jsx)(E,{...t,children:(0,k.jsxs)(`form`,{className:`space-y-8`,onSubmit:t.handleSubmit(e=>O(e)),children:[(0,k.jsx)(b,{control:t.control,name:`items`,render:()=>(0,k.jsxs)(v,{children:[(0,k.jsxs)(`div`,{className:`mb-4`,children:[(0,k.jsx)(C,{className:`text-base`,children:d()}),(0,k.jsx)(w,{children:l()})]}),A.map(e=>(0,k.jsx)(b,{control:t.control,name:`items`,render:({field:t})=>(0,k.jsxs)(v,{className:`flex flex-row items-start`,children:[(0,k.jsx)(S,{children:(0,k.jsx)(m,{checked:t.value?.includes(e.id),onCheckedChange:n=>n?t.onChange([...t.value,e.id]):t.onChange(t.value?.filter(t=>t!==e.id))})}),(0,k.jsx)(C,{className:`font-normal`,children:e.label})]},e.id)},e.id)),(0,k.jsx)(T,{})]})}),(0,k.jsx)(p,{type:`submit`,children:e()})]})})}function P(){return(0,k.jsx)(D,{description:o(),title:a(),variant:`section`,children:(0,k.jsx)(N,{})})}var F=P;export{F as component};
|
import{an as e,cn as t,dn as n,fn as r,gn as i,hn as a,ln as o,mn as s,on as c,pn as l,sn as u,tm as d,un as f}from"./messages-CL4J6BaJ.js";import{t as p}from"./button-NLSeBFht.js";import{t as m}from"./checkbox-DcRUgRHr.js";import{c as h,i as g,s as _}from"./zod-rwFXxHlg.js";import{a as v,c as y,i as b,l as x,n as S,o as C,r as w,s as T,t as E}from"./form-C_YekIvK.js";import{t as D}from"./page-header-B7O10aw9.js";import{t as O}from"./show-submitted-data-DwaVTW9K.js";var k=d(),A=[{id:`recents`,label:s()},{id:`home`,label:l()},{id:`applications`,label:r()},{id:`desktop`,label:n()},{id:`downloads`,label:f()},{id:`documents`,label:o()}],j=_({items:g(h()).refine(e=>e.some(e=>e),{message:t()})}),M={items:[`recents`,`home`]};function N(){let t=x({resolver:y(j),defaultValues:M});return(0,k.jsx)(E,{...t,children:(0,k.jsxs)(`form`,{className:`space-y-8`,onSubmit:t.handleSubmit(e=>O(e)),children:[(0,k.jsx)(b,{control:t.control,name:`items`,render:()=>(0,k.jsxs)(v,{children:[(0,k.jsxs)(`div`,{className:`mb-4`,children:[(0,k.jsx)(C,{className:`text-base`,children:u()}),(0,k.jsx)(w,{children:c()})]}),A.map(e=>(0,k.jsx)(b,{control:t.control,name:`items`,render:({field:t})=>(0,k.jsxs)(v,{className:`flex flex-row items-start`,children:[(0,k.jsx)(S,{children:(0,k.jsx)(m,{checked:t.value?.includes(e.id),onCheckedChange:n=>n?t.onChange([...t.value,e.id]):t.onChange(t.value?.filter(t=>t!==e.id))})}),(0,k.jsx)(C,{className:`font-normal`,children:e.label})]},e.id)},e.id)),(0,k.jsx)(T,{})]})}),(0,k.jsx)(p,{type:`submit`,children:e()})]})})}function P(){return(0,k.jsx)(D,{description:a(),title:i(),variant:`section`,children:(0,k.jsx)(N,{})})}var F=P;export{F as component};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{n}from"./dist-CKFLmh1A.js";var r=e(t(),1);function i(e){let[t,i]=r.useState(void 0);return n(()=>{if(e){i({width:e.offsetWidth,height:e.offsetHeight});let t=new ResizeObserver(t=>{if(!Array.isArray(t)||!t.length)return;let n=t[0],r,a;if(`borderBoxSize`in n){let e=n.borderBoxSize,t=Array.isArray(e)?e[0]:e;r=t.inlineSize,a=t.blockSize}else r=e.offsetWidth,a=e.offsetHeight;i({width:r,height:a})});return t.observe(e,{box:`border-box`}),()=>t.unobserve(e)}else i(void 0)},[e]),t}export{i as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{n}from"./dist-DmeeHi7K.js";var r=e(t(),1);function i(e){let[t,i]=r.useState(void 0);return n(()=>{if(e){i({width:e.offsetWidth,height:e.offsetHeight});let t=new ResizeObserver(t=>{if(!Array.isArray(t)||!t.length)return;let n=t[0],r,a;if(`borderBoxSize`in n){let e=n.borderBoxSize,t=Array.isArray(e)?e[0]:e;r=t.inlineSize,a=t.blockSize}else r=e.offsetWidth,a=e.offsetHeight;i({width:r,height:a})});return t.observe(e,{box:`border-box`}),()=>t.unobserve(e)}else i(void 0)},[e]),t}export{i as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{u as n}from"./button-BgMnOYKD.js";import{n as r}from"./dist-CKFLmh1A.js";var i=e(t(),1);function a(e,t){return i.useReducer((e,n)=>t[e][n]??e,e)}var o=e=>{let{present:t,children:r}=e,a=s(t),o=typeof r==`function`?r({present:a.isPresent}):i.Children.only(r),c=n(a.ref,l(o));return typeof r==`function`||a.isPresent?i.cloneElement(o,{ref:c}):null};o.displayName=`Presence`;function s(e){let[t,n]=i.useState(),o=i.useRef(null),s=i.useRef(e),l=i.useRef(`none`),[u,d]=a(e?`mounted`:`unmounted`,{mounted:{UNMOUNT:`unmounted`,ANIMATION_OUT:`unmountSuspended`},unmountSuspended:{MOUNT:`mounted`,ANIMATION_END:`unmounted`},unmounted:{MOUNT:`mounted`}});return i.useEffect(()=>{let e=c(o.current);l.current=u===`mounted`?e:`none`},[u]),r(()=>{let t=o.current,n=s.current;if(n!==e){let r=l.current,i=c(t);e?d(`MOUNT`):i===`none`||t?.display===`none`?d(`UNMOUNT`):d(n&&r!==i?`ANIMATION_OUT`:`UNMOUNT`),s.current=e}},[e,d]),r(()=>{if(t){let e,n=t.ownerDocument.defaultView??window,r=r=>{let i=c(o.current).includes(CSS.escape(r.animationName));if(r.target===t&&i&&(d(`ANIMATION_END`),!s.current)){let r=t.style.animationFillMode;t.style.animationFillMode=`forwards`,e=n.setTimeout(()=>{t.style.animationFillMode===`forwards`&&(t.style.animationFillMode=r)})}},i=e=>{e.target===t&&(l.current=c(o.current))};return t.addEventListener(`animationstart`,i),t.addEventListener(`animationcancel`,r),t.addEventListener(`animationend`,r),()=>{n.clearTimeout(e),t.removeEventListener(`animationstart`,i),t.removeEventListener(`animationcancel`,r),t.removeEventListener(`animationend`,r)}}else d(`ANIMATION_END`)},[t,d]),{isPresent:[`mounted`,`unmountSuspended`].includes(u),ref:i.useCallback(e=>{o.current=e?getComputedStyle(e):null,n(e)},[])}}function c(e){return e?.animationName||`none`}function l(e){let t=Object.getOwnPropertyDescriptor(e.props,`ref`)?.get,n=t&&`isReactWarning`in t&&t.isReactWarning;return n?e.ref:(t=Object.getOwnPropertyDescriptor(e,`ref`)?.get,n=t&&`isReactWarning`in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}export{o as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{u as n}from"./button-NLSeBFht.js";import{n as r}from"./dist-DmeeHi7K.js";var i=e(t(),1);function a(e,t){return i.useReducer((e,n)=>t[e][n]??e,e)}var o=e=>{let{present:t,children:r}=e,a=s(t),o=typeof r==`function`?r({present:a.isPresent}):i.Children.only(r),c=n(a.ref,l(o));return typeof r==`function`||a.isPresent?i.cloneElement(o,{ref:c}):null};o.displayName=`Presence`;function s(e){let[t,n]=i.useState(),o=i.useRef(null),s=i.useRef(e),l=i.useRef(`none`),[u,d]=a(e?`mounted`:`unmounted`,{mounted:{UNMOUNT:`unmounted`,ANIMATION_OUT:`unmountSuspended`},unmountSuspended:{MOUNT:`mounted`,ANIMATION_END:`unmounted`},unmounted:{MOUNT:`mounted`}});return i.useEffect(()=>{let e=c(o.current);l.current=u===`mounted`?e:`none`},[u]),r(()=>{let t=o.current,n=s.current;if(n!==e){let r=l.current,i=c(t);e?d(`MOUNT`):i===`none`||t?.display===`none`?d(`UNMOUNT`):d(n&&r!==i?`ANIMATION_OUT`:`UNMOUNT`),s.current=e}},[e,d]),r(()=>{if(t){let e,n=t.ownerDocument.defaultView??window,r=r=>{let i=c(o.current).includes(CSS.escape(r.animationName));if(r.target===t&&i&&(d(`ANIMATION_END`),!s.current)){let r=t.style.animationFillMode;t.style.animationFillMode=`forwards`,e=n.setTimeout(()=>{t.style.animationFillMode===`forwards`&&(t.style.animationFillMode=r)})}},i=e=>{e.target===t&&(l.current=c(o.current))};return t.addEventListener(`animationstart`,i),t.addEventListener(`animationcancel`,r),t.addEventListener(`animationend`,r),()=>{n.clearTimeout(e),t.removeEventListener(`animationstart`,i),t.removeEventListener(`animationcancel`,r),t.removeEventListener(`animationend`,r)}}else d(`ANIMATION_END`)},[t,d]),{isPresent:[`mounted`,`unmountSuspended`].includes(u),ref:i.useCallback(e=>{o.current=e?getComputedStyle(e):null,n(e)},[])}}function c(e){return e?.animationName||`none`}function l(e){let t=Object.getOwnPropertyDescriptor(e.props,`ref`)?.get,n=t&&`isReactWarning`in t&&t.isReactWarning;return n?e.ref:(t=Object.getOwnPropertyDescriptor(e,`ref`)?.get,n=t&&`isReactWarning`in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}export{o as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";var r=e(t(),1),i=n(),a=r.createContext(void 0),o=e=>{let{dir:t,children:n}=e;return(0,i.jsx)(a.Provider,{value:t,children:n})};function s(e){let t=r.useContext(a);return e||t||`ltr`}export{s as n,o as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";var r=e(t(),1),i=n(),a=r.createContext(void 0),o=e=>{let{dir:t,children:n}=e;return(0,i.jsx)(a.Provider,{value:t,children:n})};function s(e){let t=r.useContext(a);return e||t||`ltr`}export{s as n,o as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{t as r}from"./dist-BFnxq45V.js";var i=e(t(),1),a=n(),o=Object.freeze({position:`absolute`,border:0,width:1,height:1,padding:0,margin:-1,overflow:`hidden`,clip:`rect(0, 0, 0, 0)`,whiteSpace:`nowrap`,wordWrap:`normal`}),s=`VisuallyHidden`,c=i.forwardRef((e,t)=>(0,a.jsx)(r.span,{...e,ref:t,style:{...o,...e.style}}));c.displayName=s;var l=c;export{o as n,l as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{t as r}from"./dist-D3WFT-Yo.js";var i=e(t(),1),a=n(),o=Object.freeze({position:`absolute`,border:0,width:1,height:1,padding:0,margin:-1,overflow:`hidden`,clip:`rect(0, 0, 0, 0)`,whiteSpace:`nowrap`,wordWrap:`normal`}),s=`VisuallyHidden`,c=i.forwardRef((e,t)=>(0,a.jsx)(r.span,{...e,ref:t,style:{...o,...e.style}}));c.displayName=s;var l=c;export{o as n,l as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e,t}from"./chunk-DECur_0Z.js";import{t as n}from"./react-CO2uhaBc.js";import{em as r}from"./messages-Bp0bCjzp.js";import{s as i}from"./button-BgMnOYKD.js";var a=t((e=>{var t=n();function r(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function i(){}var a={d:{f:i,r:function(){throw Error(r(522))},D:i,C:i,L:i,m:i,X:i,S:i,M:i},p:0,findDOMNode:null},o=Symbol.for(`react.portal`);function s(e,t,n){var r=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:o,key:r==null?null:``+r,children:e,containerInfo:t,implementation:n}}var c=t.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function l(e,t){if(e===`font`)return``;if(typeof t==`string`)return t===`use-credentials`?t:``}e.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a,e.createPortal=function(e,t){var n=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)throw Error(r(299));return s(e,t,null,n)},e.flushSync=function(e){var t=c.T,n=a.p;try{if(c.T=null,a.p=2,e)return e()}finally{c.T=t,a.p=n,a.d.f()}},e.preconnect=function(e,t){typeof e==`string`&&(t?(t=t.crossOrigin,t=typeof t==`string`?t===`use-credentials`?t:``:void 0):t=null,a.d.C(e,t))},e.prefetchDNS=function(e){typeof e==`string`&&a.d.D(e)},e.preinit=function(e,t){if(typeof e==`string`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin),i=typeof t.integrity==`string`?t.integrity:void 0,o=typeof t.fetchPriority==`string`?t.fetchPriority:void 0;n===`style`?a.d.S(e,typeof t.precedence==`string`?t.precedence:void 0,{crossOrigin:r,integrity:i,fetchPriority:o}):n===`script`&&a.d.X(e,{crossOrigin:r,integrity:i,fetchPriority:o,nonce:typeof t.nonce==`string`?t.nonce:void 0})}},e.preinitModule=function(e,t){if(typeof e==`string`)if(typeof t==`object`&&t){if(t.as==null||t.as===`script`){var n=l(t.as,t.crossOrigin);a.d.M(e,{crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0})}}else t??a.d.M(e)},e.preload=function(e,t){if(typeof e==`string`&&typeof t==`object`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin);a.d.L(e,n,{crossOrigin:r,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0,type:typeof t.type==`string`?t.type:void 0,fetchPriority:typeof t.fetchPriority==`string`?t.fetchPriority:void 0,referrerPolicy:typeof t.referrerPolicy==`string`?t.referrerPolicy:void 0,imageSrcSet:typeof t.imageSrcSet==`string`?t.imageSrcSet:void 0,imageSizes:typeof t.imageSizes==`string`?t.imageSizes:void 0,media:typeof t.media==`string`?t.media:void 0})}},e.preloadModule=function(e,t){if(typeof e==`string`)if(t){var n=l(t.as,t.crossOrigin);a.d.m(e,{as:typeof t.as==`string`&&t.as!==`script`?t.as:void 0,crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0})}else a.d.m(e)},e.requestFormReset=function(e){a.d.r(e)},e.unstable_batchedUpdates=function(e,t){return e(t)},e.useFormState=function(e,t,n){return c.H.useFormState(e,t,n)},e.useFormStatus=function(){return c.H.useHostTransitionStatus()},e.version=`19.2.5`})),o=t(((e,t)=>{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=a()})),s=e(n(),1),c=e(o(),1),l=r(),u=[`a`,`button`,`div`,`form`,`h2`,`h3`,`img`,`input`,`label`,`li`,`nav`,`ol`,`p`,`select`,`span`,`svg`,`ul`].reduce((e,t)=>{let n=i(`Primitive.${t}`),r=s.forwardRef((e,r)=>{let{asChild:i,...a}=e,o=i?n:t;return typeof window<`u`&&(window[Symbol.for(`radix-ui`)]=!0),(0,l.jsx)(o,{...a,ref:r})});return r.displayName=`Primitive.${t}`,{...e,[t]:r}},{});function d(e,t){e&&c.flushSync(()=>e.dispatchEvent(t))}export{d as n,o as r,u as t};
|
import{r as e,t}from"./chunk-DECur_0Z.js";import{t as n}from"./react-CO2uhaBc.js";import{tm as r}from"./messages-CL4J6BaJ.js";import{s as i}from"./button-NLSeBFht.js";var a=t((e=>{var t=n();function r(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function i(){}var a={d:{f:i,r:function(){throw Error(r(522))},D:i,C:i,L:i,m:i,X:i,S:i,M:i},p:0,findDOMNode:null},o=Symbol.for(`react.portal`);function s(e,t,n){var r=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:o,key:r==null?null:``+r,children:e,containerInfo:t,implementation:n}}var c=t.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function l(e,t){if(e===`font`)return``;if(typeof t==`string`)return t===`use-credentials`?t:``}e.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a,e.createPortal=function(e,t){var n=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)throw Error(r(299));return s(e,t,null,n)},e.flushSync=function(e){var t=c.T,n=a.p;try{if(c.T=null,a.p=2,e)return e()}finally{c.T=t,a.p=n,a.d.f()}},e.preconnect=function(e,t){typeof e==`string`&&(t?(t=t.crossOrigin,t=typeof t==`string`?t===`use-credentials`?t:``:void 0):t=null,a.d.C(e,t))},e.prefetchDNS=function(e){typeof e==`string`&&a.d.D(e)},e.preinit=function(e,t){if(typeof e==`string`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin),i=typeof t.integrity==`string`?t.integrity:void 0,o=typeof t.fetchPriority==`string`?t.fetchPriority:void 0;n===`style`?a.d.S(e,typeof t.precedence==`string`?t.precedence:void 0,{crossOrigin:r,integrity:i,fetchPriority:o}):n===`script`&&a.d.X(e,{crossOrigin:r,integrity:i,fetchPriority:o,nonce:typeof t.nonce==`string`?t.nonce:void 0})}},e.preinitModule=function(e,t){if(typeof e==`string`)if(typeof t==`object`&&t){if(t.as==null||t.as===`script`){var n=l(t.as,t.crossOrigin);a.d.M(e,{crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0})}}else t??a.d.M(e)},e.preload=function(e,t){if(typeof e==`string`&&typeof t==`object`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin);a.d.L(e,n,{crossOrigin:r,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0,type:typeof t.type==`string`?t.type:void 0,fetchPriority:typeof t.fetchPriority==`string`?t.fetchPriority:void 0,referrerPolicy:typeof t.referrerPolicy==`string`?t.referrerPolicy:void 0,imageSrcSet:typeof t.imageSrcSet==`string`?t.imageSrcSet:void 0,imageSizes:typeof t.imageSizes==`string`?t.imageSizes:void 0,media:typeof t.media==`string`?t.media:void 0})}},e.preloadModule=function(e,t){if(typeof e==`string`)if(t){var n=l(t.as,t.crossOrigin);a.d.m(e,{as:typeof t.as==`string`&&t.as!==`script`?t.as:void 0,crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0})}else a.d.m(e)},e.requestFormReset=function(e){a.d.r(e)},e.unstable_batchedUpdates=function(e,t){return e(t)},e.useFormState=function(e,t,n){return c.H.useFormState(e,t,n)},e.useFormStatus=function(){return c.H.useHostTransitionStatus()},e.version=`19.2.5`})),o=t(((e,t)=>{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=a()})),s=e(n(),1),c=e(o(),1),l=r(),u=[`a`,`button`,`div`,`form`,`h2`,`h3`,`img`,`input`,`label`,`li`,`nav`,`ol`,`p`,`select`,`span`,`svg`,`ul`].reduce((e,t)=>{let n=i(`Primitive.${t}`),r=s.forwardRef((e,r)=>{let{asChild:i,...a}=e,o=i?n:t;return typeof window<`u`&&(window[Symbol.for(`radix-ui`)]=!0),(0,l.jsx)(o,{...a,ref:r})});return r.displayName=`Primitive.${t}`,{...e,[t]:r}},{});function d(e,t){e&&c.flushSync(()=>e.dispatchEvent(t))}export{d as n,o as r,u as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{t as r}from"./dist-BFnxq45V.js";import{u as i}from"./button-BgMnOYKD.js";import{a,r as o,t as s}from"./dist-CKFLmh1A.js";import{t as c}from"./dist-Clua1vrx.js";import{n as l}from"./dist-C97YBjnT.js";import{t as u}from"./dist-BixeH3nX.js";import{t as d}from"./dist-DGDEBCW9.js";import{n as f,r as p,t as m}from"./dist-D7AUoOWu.js";var h=e(t(),1),g=n(),_=`Radio`,[v,y]=a(_),[b,x]=v(_),S=h.forwardRef((e,t)=>{let{__scopeRadio:n,name:a,checked:s=!1,required:c,disabled:l,value:u=`on`,onCheck:d,form:f,...p}=e,[m,_]=h.useState(null),v=i(t,e=>_(e)),y=h.useRef(!1),x=m?f||!!m.closest(`form`):!0;return(0,g.jsxs)(b,{scope:n,checked:s,disabled:l,children:[(0,g.jsx)(r.button,{type:`button`,role:`radio`,"aria-checked":s,"data-state":D(s),"data-disabled":l?``:void 0,disabled:l,value:u,...p,ref:v,onClick:o(e.onClick,e=>{s||d?.(),x&&(y.current=e.isPropagationStopped(),y.current||e.stopPropagation())})}),x&&(0,g.jsx)(E,{control:m,bubbles:!y.current,name:a,value:u,checked:s,required:c,disabled:l,form:f,style:{transform:`translateX(-100%)`}})]})});S.displayName=_;var C=`RadioIndicator`,w=h.forwardRef((e,t)=>{let{__scopeRadio:n,forceMount:i,...a}=e,o=x(C,n);return(0,g.jsx)(c,{present:i||o.checked,children:(0,g.jsx)(r.span,{"data-state":D(o.checked),"data-disabled":o.disabled?``:void 0,...a,ref:t})})});w.displayName=C;var T=`RadioBubbleInput`,E=h.forwardRef(({__scopeRadio:e,control:t,checked:n,bubbles:a=!0,...o},s)=>{let c=h.useRef(null),l=i(c,s),f=u(n),p=d(t);return h.useEffect(()=>{let e=c.current;if(!e)return;let t=window.HTMLInputElement.prototype,r=Object.getOwnPropertyDescriptor(t,`checked`).set;if(f!==n&&r){let t=new Event(`click`,{bubbles:a});r.call(e,n),e.dispatchEvent(t)}},[f,n,a]),(0,g.jsx)(r.input,{type:`radio`,"aria-hidden":!0,defaultChecked:n,...o,tabIndex:-1,ref:l,style:{...o.style,...p,position:`absolute`,pointerEvents:`none`,opacity:0,margin:0}})});E.displayName=T;function D(e){return e?`checked`:`unchecked`}var O=[`ArrowUp`,`ArrowDown`,`ArrowLeft`,`ArrowRight`],k=`RadioGroup`,[A,j]=a(k,[p,y]),M=p(),N=y(),[P,F]=A(k),I=h.forwardRef((e,t)=>{let{__scopeRadioGroup:n,name:i,defaultValue:a,value:o,required:c=!1,disabled:u=!1,orientation:d,dir:p,loop:m=!0,onValueChange:h,..._}=e,v=M(n),y=l(p),[b,x]=s({prop:o,defaultProp:a??null,onChange:h,caller:k});return(0,g.jsx)(P,{scope:n,name:i,required:c,disabled:u,value:b,onValueChange:x,children:(0,g.jsx)(f,{asChild:!0,...v,orientation:d,dir:y,loop:m,children:(0,g.jsx)(r.div,{role:`radiogroup`,"aria-required":c,"aria-orientation":d,"data-disabled":u?``:void 0,dir:y,..._,ref:t})})})});I.displayName=k;var L=`RadioGroupItem`,R=h.forwardRef((e,t)=>{let{__scopeRadioGroup:n,disabled:r,...a}=e,s=F(L,n),c=s.disabled||r,l=M(n),u=N(n),d=h.useRef(null),f=i(t,d),p=s.value===a.value,_=h.useRef(!1);return h.useEffect(()=>{let e=e=>{O.includes(e.key)&&(_.current=!0)},t=()=>_.current=!1;return document.addEventListener(`keydown`,e),document.addEventListener(`keyup`,t),()=>{document.removeEventListener(`keydown`,e),document.removeEventListener(`keyup`,t)}},[]),(0,g.jsx)(m,{asChild:!0,...l,focusable:!c,active:p,children:(0,g.jsx)(S,{disabled:c,required:s.required,checked:p,...u,...a,name:s.name,ref:f,onCheck:()=>s.onValueChange(a.value),onKeyDown:o(e=>{e.key===`Enter`&&e.preventDefault()}),onFocus:o(a.onFocus,()=>{_.current&&d.current?.click()})})})});R.displayName=L;var z=`RadioGroupIndicator`,B=h.forwardRef((e,t)=>{let{__scopeRadioGroup:n,...r}=e;return(0,g.jsx)(w,{...N(n),...r,ref:t})});B.displayName=z;var V=I,H=R,U=B;export{H as n,V as r,U as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{t as r}from"./dist-D3WFT-Yo.js";import{u as i}from"./button-NLSeBFht.js";import{a,r as o,t as s}from"./dist-DmeeHi7K.js";import{t as c}from"./dist-BZMqLvO-.js";import{n as l}from"./dist-CGRahgI2.js";import{t as u}from"./dist-BixeH3nX.js";import{t as d}from"./dist-B0pRVbY9.js";import{n as f,r as p,t as m}from"./dist-DhcQhr4B.js";var h=e(t(),1),g=n(),_=`Radio`,[v,y]=a(_),[b,x]=v(_),S=h.forwardRef((e,t)=>{let{__scopeRadio:n,name:a,checked:s=!1,required:c,disabled:l,value:u=`on`,onCheck:d,form:f,...p}=e,[m,_]=h.useState(null),v=i(t,e=>_(e)),y=h.useRef(!1),x=m?f||!!m.closest(`form`):!0;return(0,g.jsxs)(b,{scope:n,checked:s,disabled:l,children:[(0,g.jsx)(r.button,{type:`button`,role:`radio`,"aria-checked":s,"data-state":D(s),"data-disabled":l?``:void 0,disabled:l,value:u,...p,ref:v,onClick:o(e.onClick,e=>{s||d?.(),x&&(y.current=e.isPropagationStopped(),y.current||e.stopPropagation())})}),x&&(0,g.jsx)(E,{control:m,bubbles:!y.current,name:a,value:u,checked:s,required:c,disabled:l,form:f,style:{transform:`translateX(-100%)`}})]})});S.displayName=_;var C=`RadioIndicator`,w=h.forwardRef((e,t)=>{let{__scopeRadio:n,forceMount:i,...a}=e,o=x(C,n);return(0,g.jsx)(c,{present:i||o.checked,children:(0,g.jsx)(r.span,{"data-state":D(o.checked),"data-disabled":o.disabled?``:void 0,...a,ref:t})})});w.displayName=C;var T=`RadioBubbleInput`,E=h.forwardRef(({__scopeRadio:e,control:t,checked:n,bubbles:a=!0,...o},s)=>{let c=h.useRef(null),l=i(c,s),f=u(n),p=d(t);return h.useEffect(()=>{let e=c.current;if(!e)return;let t=window.HTMLInputElement.prototype,r=Object.getOwnPropertyDescriptor(t,`checked`).set;if(f!==n&&r){let t=new Event(`click`,{bubbles:a});r.call(e,n),e.dispatchEvent(t)}},[f,n,a]),(0,g.jsx)(r.input,{type:`radio`,"aria-hidden":!0,defaultChecked:n,...o,tabIndex:-1,ref:l,style:{...o.style,...p,position:`absolute`,pointerEvents:`none`,opacity:0,margin:0}})});E.displayName=T;function D(e){return e?`checked`:`unchecked`}var O=[`ArrowUp`,`ArrowDown`,`ArrowLeft`,`ArrowRight`],k=`RadioGroup`,[A,j]=a(k,[p,y]),M=p(),N=y(),[P,F]=A(k),I=h.forwardRef((e,t)=>{let{__scopeRadioGroup:n,name:i,defaultValue:a,value:o,required:c=!1,disabled:u=!1,orientation:d,dir:p,loop:m=!0,onValueChange:h,..._}=e,v=M(n),y=l(p),[b,x]=s({prop:o,defaultProp:a??null,onChange:h,caller:k});return(0,g.jsx)(P,{scope:n,name:i,required:c,disabled:u,value:b,onValueChange:x,children:(0,g.jsx)(f,{asChild:!0,...v,orientation:d,dir:y,loop:m,children:(0,g.jsx)(r.div,{role:`radiogroup`,"aria-required":c,"aria-orientation":d,"data-disabled":u?``:void 0,dir:y,..._,ref:t})})})});I.displayName=k;var L=`RadioGroupItem`,R=h.forwardRef((e,t)=>{let{__scopeRadioGroup:n,disabled:r,...a}=e,s=F(L,n),c=s.disabled||r,l=M(n),u=N(n),d=h.useRef(null),f=i(t,d),p=s.value===a.value,_=h.useRef(!1);return h.useEffect(()=>{let e=e=>{O.includes(e.key)&&(_.current=!0)},t=()=>_.current=!1;return document.addEventListener(`keydown`,e),document.addEventListener(`keyup`,t),()=>{document.removeEventListener(`keydown`,e),document.removeEventListener(`keyup`,t)}},[]),(0,g.jsx)(m,{asChild:!0,...l,focusable:!c,active:p,children:(0,g.jsx)(S,{disabled:c,required:s.required,checked:p,...u,...a,name:s.name,ref:f,onCheck:()=>s.onValueChange(a.value),onKeyDown:o(e=>{e.key===`Enter`&&e.preventDefault()}),onFocus:o(a.onFocus,()=>{_.current&&d.current?.click()})})})});R.displayName=L;var z=`RadioGroupIndicator`,B=h.forwardRef((e,t)=>{let{__scopeRadioGroup:n,...r}=e;return(0,g.jsx)(w,{...N(n),...r,ref:t})});B.displayName=z;var V=I,H=R,U=B;export{H as n,V as r,U as t};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{t as r}from"./dist-BFnxq45V.js";import{s as i,u as a}from"./button-BgMnOYKD.js";import{a as o,i as s,r as c,t as l}from"./dist-CKFLmh1A.js";import{t as u}from"./dist-Clua1vrx.js";import{n as d}from"./dist-B0ikDpJU.js";import{n as f,t as p}from"./dist-_ND6L-P3.js";import{i as m,n as h,r as g,t as _}from"./es2015-D8VLlhse.js";var v=e(t(),1),y=n(),b=`Dialog`,[x,S]=o(b),[C,w]=x(b),T=e=>{let{__scopeDialog:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!0}=e,s=v.useRef(null),c=v.useRef(null),[u,f]=l({prop:r,defaultProp:i??!1,onChange:a,caller:b});return(0,y.jsx)(C,{scope:t,triggerRef:s,contentRef:c,contentId:d(),titleId:d(),descriptionId:d(),open:u,onOpenChange:f,onOpenToggle:v.useCallback(()=>f(e=>!e),[f]),modal:o,children:n})};T.displayName=b;var E=`DialogTrigger`,D=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,o=w(E,n),s=a(t,o.triggerRef);return(0,y.jsx)(r.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":o.open,"aria-controls":o.contentId,"data-state":q(o.open),...i,ref:s,onClick:c(e.onClick,o.onOpenToggle)})});D.displayName=E;var O=`DialogPortal`,[k,A]=x(O,{forceMount:void 0}),j=e=>{let{__scopeDialog:t,forceMount:n,children:r,container:i}=e,a=w(O,t);return(0,y.jsx)(k,{scope:t,forceMount:n,children:v.Children.map(r,e=>(0,y.jsx)(u,{present:n||a.open,children:(0,y.jsx)(p,{asChild:!0,container:i,children:e})}))})};j.displayName=O;var M=`DialogOverlay`,N=v.forwardRef((e,t)=>{let n=A(M,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=w(M,e.__scopeDialog);return a.modal?(0,y.jsx)(u,{present:r||a.open,children:(0,y.jsx)(F,{...i,ref:t})}):null});N.displayName=M;var P=i(`DialogOverlay.RemoveScroll`),F=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,a=w(M,n);return(0,y.jsx)(h,{as:P,allowPinchZoom:!0,shards:[a.contentRef],children:(0,y.jsx)(r.div,{"data-state":q(a.open),...i,ref:t,style:{pointerEvents:`auto`,...i.style}})})}),I=`DialogContent`,L=v.forwardRef((e,t)=>{let n=A(I,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=w(I,e.__scopeDialog);return(0,y.jsx)(u,{present:r||a.open,children:a.modal?(0,y.jsx)(R,{...i,ref:t}):(0,y.jsx)(z,{...i,ref:t})})});L.displayName=I;var R=v.forwardRef((e,t)=>{let n=w(I,e.__scopeDialog),r=v.useRef(null),i=a(t,n.contentRef,r);return v.useEffect(()=>{let e=r.current;if(e)return _(e)},[]),(0,y.jsx)(B,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:c(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:c(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;(t.button===2||n)&&e.preventDefault()}),onFocusOutside:c(e.onFocusOutside,e=>e.preventDefault())})}),z=v.forwardRef((e,t)=>{let n=w(I,e.__scopeDialog),r=v.useRef(!1),i=v.useRef(!1);return(0,y.jsx)(B,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),B=v.forwardRef((e,t)=>{let{__scopeDialog:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:o,...s}=e,c=w(I,n),l=v.useRef(null),u=a(t,l);return g(),(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(m,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:o,children:(0,y.jsx)(f,{role:`dialog`,id:c.contentId,"aria-describedby":c.descriptionId,"aria-labelledby":c.titleId,"data-state":q(c.open),...s,ref:u,onDismiss:()=>c.onOpenChange(!1)})}),(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(Z,{titleId:c.titleId}),(0,y.jsx)($,{contentRef:l,descriptionId:c.descriptionId})]})]})}),V=`DialogTitle`,H=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,a=w(V,n);return(0,y.jsx)(r.h2,{id:a.titleId,...i,ref:t})});H.displayName=V;var U=`DialogDescription`,W=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,a=w(U,n);return(0,y.jsx)(r.p,{id:a.descriptionId,...i,ref:t})});W.displayName=U;var G=`DialogClose`,K=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,a=w(G,n);return(0,y.jsx)(r.button,{type:`button`,...i,ref:t,onClick:c(e.onClick,()=>a.onOpenChange(!1))})});K.displayName=G;function q(e){return e?`open`:`closed`}var J=`DialogTitleWarning`,[Y,X]=s(J,{contentName:I,titleName:V,docsSlug:`dialog`}),Z=({titleId:e})=>{let t=X(J),n=`\`${t.contentName}\` requires a \`${t.titleName}\` for the component to be accessible for screen reader users.
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{t as r}from"./dist-D3WFT-Yo.js";import{s as i,u as a}from"./button-NLSeBFht.js";import{a as o,i as s,r as c,t as l}from"./dist-DmeeHi7K.js";import{t as u}from"./dist-BZMqLvO-.js";import{n as d}from"./dist-SR6sl-WU.js";import{n as f,t as p}from"./dist-esC74fSg.js";import{i as m,n as h,r as g,t as _}from"./es2015-3J9GnV9P.js";var v=e(t(),1),y=n(),b=`Dialog`,[x,S]=o(b),[C,w]=x(b),T=e=>{let{__scopeDialog:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!0}=e,s=v.useRef(null),c=v.useRef(null),[u,f]=l({prop:r,defaultProp:i??!1,onChange:a,caller:b});return(0,y.jsx)(C,{scope:t,triggerRef:s,contentRef:c,contentId:d(),titleId:d(),descriptionId:d(),open:u,onOpenChange:f,onOpenToggle:v.useCallback(()=>f(e=>!e),[f]),modal:o,children:n})};T.displayName=b;var E=`DialogTrigger`,D=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,o=w(E,n),s=a(t,o.triggerRef);return(0,y.jsx)(r.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":o.open,"aria-controls":o.contentId,"data-state":q(o.open),...i,ref:s,onClick:c(e.onClick,o.onOpenToggle)})});D.displayName=E;var O=`DialogPortal`,[k,A]=x(O,{forceMount:void 0}),j=e=>{let{__scopeDialog:t,forceMount:n,children:r,container:i}=e,a=w(O,t);return(0,y.jsx)(k,{scope:t,forceMount:n,children:v.Children.map(r,e=>(0,y.jsx)(u,{present:n||a.open,children:(0,y.jsx)(p,{asChild:!0,container:i,children:e})}))})};j.displayName=O;var M=`DialogOverlay`,N=v.forwardRef((e,t)=>{let n=A(M,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=w(M,e.__scopeDialog);return a.modal?(0,y.jsx)(u,{present:r||a.open,children:(0,y.jsx)(F,{...i,ref:t})}):null});N.displayName=M;var P=i(`DialogOverlay.RemoveScroll`),F=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,a=w(M,n);return(0,y.jsx)(h,{as:P,allowPinchZoom:!0,shards:[a.contentRef],children:(0,y.jsx)(r.div,{"data-state":q(a.open),...i,ref:t,style:{pointerEvents:`auto`,...i.style}})})}),I=`DialogContent`,L=v.forwardRef((e,t)=>{let n=A(I,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=w(I,e.__scopeDialog);return(0,y.jsx)(u,{present:r||a.open,children:a.modal?(0,y.jsx)(R,{...i,ref:t}):(0,y.jsx)(z,{...i,ref:t})})});L.displayName=I;var R=v.forwardRef((e,t)=>{let n=w(I,e.__scopeDialog),r=v.useRef(null),i=a(t,n.contentRef,r);return v.useEffect(()=>{let e=r.current;if(e)return _(e)},[]),(0,y.jsx)(B,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:c(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:c(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;(t.button===2||n)&&e.preventDefault()}),onFocusOutside:c(e.onFocusOutside,e=>e.preventDefault())})}),z=v.forwardRef((e,t)=>{let n=w(I,e.__scopeDialog),r=v.useRef(!1),i=v.useRef(!1);return(0,y.jsx)(B,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),B=v.forwardRef((e,t)=>{let{__scopeDialog:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:o,...s}=e,c=w(I,n),l=v.useRef(null),u=a(t,l);return g(),(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(m,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:o,children:(0,y.jsx)(f,{role:`dialog`,id:c.contentId,"aria-describedby":c.descriptionId,"aria-labelledby":c.titleId,"data-state":q(c.open),...s,ref:u,onDismiss:()=>c.onOpenChange(!1)})}),(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(Z,{titleId:c.titleId}),(0,y.jsx)($,{contentRef:l,descriptionId:c.descriptionId})]})]})}),V=`DialogTitle`,H=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,a=w(V,n);return(0,y.jsx)(r.h2,{id:a.titleId,...i,ref:t})});H.displayName=V;var U=`DialogDescription`,W=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,a=w(U,n);return(0,y.jsx)(r.p,{id:a.descriptionId,...i,ref:t})});W.displayName=U;var G=`DialogClose`,K=v.forwardRef((e,t)=>{let{__scopeDialog:n,...i}=e,a=w(G,n);return(0,y.jsx)(r.button,{type:`button`,...i,ref:t,onClick:c(e.onClick,()=>a.onOpenChange(!1))})});K.displayName=G;function q(e){return e?`open`:`closed`}var J=`DialogTitleWarning`,[Y,X]=s(J,{contentName:I,titleName:V,docsSlug:`dialog`}),Z=({titleId:e})=>{let t=X(J),n=`\`${t.contentName}\` requires a \`${t.titleName}\` for the component to be accessible for screen reader users.
|
||||||
|
|
||||||
If you want to hide the \`${t.titleName}\`, you can wrap it with our VisuallyHidden component.
|
If you want to hide the \`${t.titleName}\`, you can wrap it with our VisuallyHidden component.
|
||||||
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{t as r}from"./dist-BFnxq45V.js";import{u as i}from"./button-BgMnOYKD.js";import{a,r as o,t as s}from"./dist-CKFLmh1A.js";import{t as c}from"./dist-C6i4A_Js.js";import{n as l,t as u}from"./dist-B0ikDpJU.js";import{n as d}from"./dist-C97YBjnT.js";var f=e(t(),1),p=n(),m=`rovingFocusGroup.onEntryFocus`,h={bubbles:!1,cancelable:!0},g=`RovingFocusGroup`,[_,v,y]=c(g),[b,x]=a(g,[y]),[S,C]=b(g),w=f.forwardRef((e,t)=>(0,p.jsx)(_.Provider,{scope:e.__scopeRovingFocusGroup,children:(0,p.jsx)(_.Slot,{scope:e.__scopeRovingFocusGroup,children:(0,p.jsx)(T,{...e,ref:t})})}));w.displayName=g;var T=f.forwardRef((e,t)=>{let{__scopeRovingFocusGroup:n,orientation:a,loop:c=!1,dir:l,currentTabStopId:_,defaultCurrentTabStopId:y,onCurrentTabStopIdChange:b,onEntryFocus:x,preventScrollOnEntryFocus:C=!1,...w}=e,T=f.useRef(null),E=i(t,T),D=d(l),[O,k]=s({prop:_,defaultProp:y??null,onChange:b,caller:g}),[A,M]=f.useState(!1),N=u(x),P=v(n),F=f.useRef(!1),[I,L]=f.useState(0);return f.useEffect(()=>{let e=T.current;if(e)return e.addEventListener(m,N),()=>e.removeEventListener(m,N)},[N]),(0,p.jsx)(S,{scope:n,orientation:a,dir:D,loop:c,currentTabStopId:O,onItemFocus:f.useCallback(e=>k(e),[k]),onItemShiftTab:f.useCallback(()=>M(!0),[]),onFocusableItemAdd:f.useCallback(()=>L(e=>e+1),[]),onFocusableItemRemove:f.useCallback(()=>L(e=>e-1),[]),children:(0,p.jsx)(r.div,{tabIndex:A||I===0?-1:0,"data-orientation":a,...w,ref:E,style:{outline:`none`,...e.style},onMouseDown:o(e.onMouseDown,()=>{F.current=!0}),onFocus:o(e.onFocus,e=>{let t=!F.current;if(e.target===e.currentTarget&&t&&!A){let t=new CustomEvent(m,h);if(e.currentTarget.dispatchEvent(t),!t.defaultPrevented){let e=P().filter(e=>e.focusable);j([e.find(e=>e.active),e.find(e=>e.id===O),...e].filter(Boolean).map(e=>e.ref.current),C)}}F.current=!1}),onBlur:o(e.onBlur,()=>M(!1))})})}),E=`RovingFocusGroupItem`,D=f.forwardRef((e,t)=>{let{__scopeRovingFocusGroup:n,focusable:i=!0,active:a=!1,tabStopId:s,children:c,...u}=e,d=l(),m=s||d,h=C(E,n),g=h.currentTabStopId===m,y=v(n),{onFocusableItemAdd:b,onFocusableItemRemove:x,currentTabStopId:S}=h;return f.useEffect(()=>{if(i)return b(),()=>x()},[i,b,x]),(0,p.jsx)(_.ItemSlot,{scope:n,id:m,focusable:i,active:a,children:(0,p.jsx)(r.span,{tabIndex:g?0:-1,"data-orientation":h.orientation,...u,ref:t,onMouseDown:o(e.onMouseDown,e=>{i?h.onItemFocus(m):e.preventDefault()}),onFocus:o(e.onFocus,()=>h.onItemFocus(m)),onKeyDown:o(e.onKeyDown,e=>{if(e.key===`Tab`&&e.shiftKey){h.onItemShiftTab();return}if(e.target!==e.currentTarget)return;let t=A(e,h.orientation,h.dir);if(t!==void 0){if(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey)return;e.preventDefault();let n=y().filter(e=>e.focusable).map(e=>e.ref.current);if(t===`last`)n.reverse();else if(t===`prev`||t===`next`){t===`prev`&&n.reverse();let r=n.indexOf(e.currentTarget);n=h.loop?M(n,r+1):n.slice(r+1)}setTimeout(()=>j(n))}}),children:typeof c==`function`?c({isCurrentTabStop:g,hasTabStop:S!=null}):c})})});D.displayName=E;var O={ArrowLeft:`prev`,ArrowUp:`prev`,ArrowRight:`next`,ArrowDown:`next`,PageUp:`first`,Home:`first`,PageDown:`last`,End:`last`};function k(e,t){return t===`rtl`?e===`ArrowLeft`?`ArrowRight`:e===`ArrowRight`?`ArrowLeft`:e:e}function A(e,t,n){let r=k(e.key,n);if(!(t===`vertical`&&[`ArrowLeft`,`ArrowRight`].includes(r))&&!(t===`horizontal`&&[`ArrowUp`,`ArrowDown`].includes(r)))return O[r]}function j(e,t=!1){let n=document.activeElement;for(let r of e)if(r===n||(r.focus({preventScroll:t}),document.activeElement!==n))return}function M(e,t){return e.map((n,r)=>e[(t+r)%e.length])}var N=w,P=D;export{N as n,x as r,P as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{t as r}from"./dist-D3WFT-Yo.js";import{u as i}from"./button-NLSeBFht.js";import{a,r as o,t as s}from"./dist-DmeeHi7K.js";import{t as c}from"./dist-UaPzzPYf.js";import{n as l,t as u}from"./dist-SR6sl-WU.js";import{n as d}from"./dist-CGRahgI2.js";var f=e(t(),1),p=n(),m=`rovingFocusGroup.onEntryFocus`,h={bubbles:!1,cancelable:!0},g=`RovingFocusGroup`,[_,v,y]=c(g),[b,x]=a(g,[y]),[S,C]=b(g),w=f.forwardRef((e,t)=>(0,p.jsx)(_.Provider,{scope:e.__scopeRovingFocusGroup,children:(0,p.jsx)(_.Slot,{scope:e.__scopeRovingFocusGroup,children:(0,p.jsx)(T,{...e,ref:t})})}));w.displayName=g;var T=f.forwardRef((e,t)=>{let{__scopeRovingFocusGroup:n,orientation:a,loop:c=!1,dir:l,currentTabStopId:_,defaultCurrentTabStopId:y,onCurrentTabStopIdChange:b,onEntryFocus:x,preventScrollOnEntryFocus:C=!1,...w}=e,T=f.useRef(null),E=i(t,T),D=d(l),[O,k]=s({prop:_,defaultProp:y??null,onChange:b,caller:g}),[A,M]=f.useState(!1),N=u(x),P=v(n),F=f.useRef(!1),[I,L]=f.useState(0);return f.useEffect(()=>{let e=T.current;if(e)return e.addEventListener(m,N),()=>e.removeEventListener(m,N)},[N]),(0,p.jsx)(S,{scope:n,orientation:a,dir:D,loop:c,currentTabStopId:O,onItemFocus:f.useCallback(e=>k(e),[k]),onItemShiftTab:f.useCallback(()=>M(!0),[]),onFocusableItemAdd:f.useCallback(()=>L(e=>e+1),[]),onFocusableItemRemove:f.useCallback(()=>L(e=>e-1),[]),children:(0,p.jsx)(r.div,{tabIndex:A||I===0?-1:0,"data-orientation":a,...w,ref:E,style:{outline:`none`,...e.style},onMouseDown:o(e.onMouseDown,()=>{F.current=!0}),onFocus:o(e.onFocus,e=>{let t=!F.current;if(e.target===e.currentTarget&&t&&!A){let t=new CustomEvent(m,h);if(e.currentTarget.dispatchEvent(t),!t.defaultPrevented){let e=P().filter(e=>e.focusable);j([e.find(e=>e.active),e.find(e=>e.id===O),...e].filter(Boolean).map(e=>e.ref.current),C)}}F.current=!1}),onBlur:o(e.onBlur,()=>M(!1))})})}),E=`RovingFocusGroupItem`,D=f.forwardRef((e,t)=>{let{__scopeRovingFocusGroup:n,focusable:i=!0,active:a=!1,tabStopId:s,children:c,...u}=e,d=l(),m=s||d,h=C(E,n),g=h.currentTabStopId===m,y=v(n),{onFocusableItemAdd:b,onFocusableItemRemove:x,currentTabStopId:S}=h;return f.useEffect(()=>{if(i)return b(),()=>x()},[i,b,x]),(0,p.jsx)(_.ItemSlot,{scope:n,id:m,focusable:i,active:a,children:(0,p.jsx)(r.span,{tabIndex:g?0:-1,"data-orientation":h.orientation,...u,ref:t,onMouseDown:o(e.onMouseDown,e=>{i?h.onItemFocus(m):e.preventDefault()}),onFocus:o(e.onFocus,()=>h.onItemFocus(m)),onKeyDown:o(e.onKeyDown,e=>{if(e.key===`Tab`&&e.shiftKey){h.onItemShiftTab();return}if(e.target!==e.currentTarget)return;let t=A(e,h.orientation,h.dir);if(t!==void 0){if(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey)return;e.preventDefault();let n=y().filter(e=>e.focusable).map(e=>e.ref.current);if(t===`last`)n.reverse();else if(t===`prev`||t===`next`){t===`prev`&&n.reverse();let r=n.indexOf(e.currentTarget);n=h.loop?M(n,r+1):n.slice(r+1)}setTimeout(()=>j(n))}}),children:typeof c==`function`?c({isCurrentTabStop:g,hasTabStop:S!=null}):c})})});D.displayName=E;var O={ArrowLeft:`prev`,ArrowUp:`prev`,ArrowRight:`next`,ArrowDown:`next`,PageUp:`first`,Home:`first`,PageDown:`last`,End:`last`};function k(e,t){return t===`rtl`?e===`ArrowLeft`?`ArrowRight`:e===`ArrowRight`?`ArrowLeft`:e:e}function A(e,t,n){let r=k(e.key,n);if(!(t===`vertical`&&[`ArrowLeft`,`ArrowRight`].includes(r))&&!(t===`horizontal`&&[`ArrowUp`,`ArrowDown`].includes(r)))return O[r]}function j(e,t=!1){let n=document.activeElement;for(let r of e)if(r===n||(r.focus({preventScroll:t}),document.activeElement!==n))return}function M(e,t){return e.map((n,r)=>e[(t+r)%e.length])}var N=w,P=D;export{N as n,x as r,P as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";var r=e(t(),1),i=n();function a(e,t){let n=r.createContext(t),a=e=>{let{children:t,...a}=e,o=r.useMemo(()=>a,Object.values(a));return(0,i.jsx)(n.Provider,{value:o,children:t})};a.displayName=e+`Provider`;function o(i){let a=r.useContext(n);if(a)return a;if(t!==void 0)return t;throw Error(`\`${i}\` must be used within \`${e}\``)}return[a,o]}function o(e,t=[]){let n=[];function a(t,a){let o=r.createContext(a),s=n.length;n=[...n,a];let c=t=>{let{scope:n,children:a,...c}=t,l=n?.[e]?.[s]||o,u=r.useMemo(()=>c,Object.values(c));return(0,i.jsx)(l.Provider,{value:u,children:a})};c.displayName=t+`Provider`;function l(n,i){let c=i?.[e]?.[s]||o,l=r.useContext(c);if(l)return l;if(a!==void 0)return a;throw Error(`\`${n}\` must be used within \`${t}\``)}return[c,l]}let o=()=>{let t=n.map(e=>r.createContext(e));return function(n){let i=n?.[e]||t;return r.useMemo(()=>({[`__scope${e}`]:{...n,[e]:i}}),[n,i])}};return o.scopeName=e,[a,s(o,...t)]}function s(...e){let t=e[0];if(e.length===1)return t;let n=()=>{let n=e.map(e=>({useScope:e(),scopeName:e.scopeName}));return function(e){let i=n.reduce((t,{useScope:n,scopeName:r})=>{let i=n(e)[`__scope${r}`];return{...t,...i}},{});return r.useMemo(()=>({[`__scope${t.scopeName}`]:i}),[i])}};return n.scopeName=t.scopeName,n}typeof window<`u`&&window.document&&window.document.createElement;function c(e,t,{checkForDefaultPrevented:n=!0}={}){return function(r){if(e?.(r),n===!1||!r.defaultPrevented)return t?.(r)}}var l=globalThis?.document?r.useLayoutEffect:()=>{},u=r.useInsertionEffect||l;function d({prop:e,defaultProp:t,onChange:n=()=>{},caller:i}){let[a,o,s]=f({defaultProp:t,onChange:n}),c=e!==void 0,l=c?e:a;{let t=r.useRef(e!==void 0);r.useEffect(()=>{let e=t.current;e!==c&&console.warn(`${i} is changing from ${e?`controlled`:`uncontrolled`} to ${c?`controlled`:`uncontrolled`}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),t.current=c},[c,i])}return[l,r.useCallback(t=>{if(c){let n=p(t)?t(e):t;n!==e&&s.current?.(n)}else o(t)},[c,e,o,s])]}function f({defaultProp:e,onChange:t}){let[n,i]=r.useState(e),a=r.useRef(n),o=r.useRef(t);return u(()=>{o.current=t},[t]),r.useEffect(()=>{a.current!==n&&(o.current?.(n),a.current=n)},[n,a]),[n,i,o]}function p(e){return typeof e==`function`}export{o as a,a as i,l as n,c as r,d as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";var r=e(t(),1),i=n();function a(e,t){let n=r.createContext(t),a=e=>{let{children:t,...a}=e,o=r.useMemo(()=>a,Object.values(a));return(0,i.jsx)(n.Provider,{value:o,children:t})};a.displayName=e+`Provider`;function o(i){let a=r.useContext(n);if(a)return a;if(t!==void 0)return t;throw Error(`\`${i}\` must be used within \`${e}\``)}return[a,o]}function o(e,t=[]){let n=[];function a(t,a){let o=r.createContext(a),s=n.length;n=[...n,a];let c=t=>{let{scope:n,children:a,...c}=t,l=n?.[e]?.[s]||o,u=r.useMemo(()=>c,Object.values(c));return(0,i.jsx)(l.Provider,{value:u,children:a})};c.displayName=t+`Provider`;function l(n,i){let c=i?.[e]?.[s]||o,l=r.useContext(c);if(l)return l;if(a!==void 0)return a;throw Error(`\`${n}\` must be used within \`${t}\``)}return[c,l]}let o=()=>{let t=n.map(e=>r.createContext(e));return function(n){let i=n?.[e]||t;return r.useMemo(()=>({[`__scope${e}`]:{...n,[e]:i}}),[n,i])}};return o.scopeName=e,[a,s(o,...t)]}function s(...e){let t=e[0];if(e.length===1)return t;let n=()=>{let n=e.map(e=>({useScope:e(),scopeName:e.scopeName}));return function(e){let i=n.reduce((t,{useScope:n,scopeName:r})=>{let i=n(e)[`__scope${r}`];return{...t,...i}},{});return r.useMemo(()=>({[`__scope${t.scopeName}`]:i}),[i])}};return n.scopeName=t.scopeName,n}typeof window<`u`&&window.document&&window.document.createElement;function c(e,t,{checkForDefaultPrevented:n=!0}={}){return function(r){if(e?.(r),n===!1||!r.defaultPrevented)return t?.(r)}}var l=globalThis?.document?r.useLayoutEffect:()=>{},u=r.useInsertionEffect||l;function d({prop:e,defaultProp:t,onChange:n=()=>{},caller:i}){let[a,o,s]=f({defaultProp:t,onChange:n}),c=e!==void 0,l=c?e:a;{let t=r.useRef(e!==void 0);r.useEffect(()=>{let e=t.current;e!==c&&console.warn(`${i} is changing from ${e?`controlled`:`uncontrolled`} to ${c?`controlled`:`uncontrolled`}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),t.current=c},[c,i])}return[l,r.useCallback(t=>{if(c){let n=p(t)?t(e):t;n!==e&&s.current?.(n)}else o(t)},[c,e,o,s])]}function f({defaultProp:e,onChange:t}){let[n,i]=r.useState(e),a=r.useRef(n),o=r.useRef(t);return u(()=>{o.current=t},[t]),r.useEffect(()=>{a.current!==n&&(o.current?.(n),a.current=n)},[n,a]),[n,i,o]}function p(e){return typeof e==`function`}export{o as a,a as i,l as n,c as r,d as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{n}from"./dist-CKFLmh1A.js";var r=e(t(),1),i=r.useId||(()=>void 0),a=0;function o(e){let[t,o]=r.useState(i());return n(()=>{e||o(e=>e??String(a++))},[e]),e||(t?`radix-${t}`:``)}function s(e){let t=r.useRef(e);return r.useEffect(()=>{t.current=e}),r.useMemo(()=>(...e)=>t.current?.(...e),[])}export{o as n,s as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{n}from"./dist-DmeeHi7K.js";var r=e(t(),1),i=r.useId||(()=>void 0),a=0;function o(e){let[t,o]=r.useState(i());return n(()=>{e||o(e=>e??String(a++))},[e]),e||(t?`radix-${t}`:``)}function s(e){let t=r.useRef(e);return r.useEffect(()=>{t.current=e}),r.useMemo(()=>(...e)=>t.current?.(...e),[])}export{o as n,s as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{s as r,u as i}from"./button-BgMnOYKD.js";import{a}from"./dist-CKFLmh1A.js";var o=e(t(),1),s=n();function c(e){let t=e+`CollectionProvider`,[n,c]=a(t),[l,u]=n(t,{collectionRef:{current:null},itemMap:new Map}),d=e=>{let{scope:t,children:n}=e,r=o.useRef(null),i=o.useRef(new Map).current;return(0,s.jsx)(l,{scope:t,itemMap:i,collectionRef:r,children:n})};d.displayName=t;let f=e+`CollectionSlot`,p=r(f),m=o.forwardRef((e,t)=>{let{scope:n,children:r}=e;return(0,s.jsx)(p,{ref:i(t,u(f,n).collectionRef),children:r})});m.displayName=f;let h=e+`CollectionItemSlot`,g=`data-radix-collection-item`,_=r(h),v=o.forwardRef((e,t)=>{let{scope:n,children:r,...a}=e,c=o.useRef(null),l=i(t,c),d=u(h,n);return o.useEffect(()=>(d.itemMap.set(c,{ref:c,...a}),()=>void d.itemMap.delete(c))),(0,s.jsx)(_,{[g]:``,ref:l,children:r})});v.displayName=h;function y(t){let n=u(e+`CollectionConsumer`,t);return o.useCallback(()=>{let e=n.collectionRef.current;if(!e)return[];let t=Array.from(e.querySelectorAll(`[${g}]`));return Array.from(n.itemMap.values()).sort((e,n)=>t.indexOf(e.ref.current)-t.indexOf(n.ref.current))},[n.collectionRef,n.itemMap])}return[{Provider:d,Slot:m,ItemSlot:v},y,c]}export{c as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{s as r,u as i}from"./button-NLSeBFht.js";import{a}from"./dist-DmeeHi7K.js";var o=e(t(),1),s=n();function c(e){let t=e+`CollectionProvider`,[n,c]=a(t),[l,u]=n(t,{collectionRef:{current:null},itemMap:new Map}),d=e=>{let{scope:t,children:n}=e,r=o.useRef(null),i=o.useRef(new Map).current;return(0,s.jsx)(l,{scope:t,itemMap:i,collectionRef:r,children:n})};d.displayName=t;let f=e+`CollectionSlot`,p=r(f),m=o.forwardRef((e,t)=>{let{scope:n,children:r}=e;return(0,s.jsx)(p,{ref:i(t,u(f,n).collectionRef),children:r})});m.displayName=f;let h=e+`CollectionItemSlot`,g=`data-radix-collection-item`,_=r(h),v=o.forwardRef((e,t)=>{let{scope:n,children:r,...a}=e,c=o.useRef(null),l=i(t,c),d=u(h,n);return o.useEffect(()=>(d.itemMap.set(c,{ref:c,...a}),()=>void d.itemMap.delete(c))),(0,s.jsx)(_,{[g]:``,ref:l,children:r})});v.displayName=h;function y(t){let n=u(e+`CollectionConsumer`,t);return o.useCallback(()=>{let e=n.collectionRef.current;if(!e)return[];let t=Array.from(e.querySelectorAll(`[${g}]`));return Array.from(n.itemMap.values()).sort((e,n)=>t.indexOf(e.ref.current)-t.indexOf(n.ref.current))},[n.collectionRef,n.itemMap])}return[{Provider:d,Slot:m,ItemSlot:v},y,c]}export{c as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{n as r,r as i,t as a}from"./dist-BFnxq45V.js";import{u as o}from"./button-BgMnOYKD.js";import{n as s,r as c}from"./dist-CKFLmh1A.js";import{t as l}from"./dist-B0ikDpJU.js";var u=e(t(),1);function d(e,t=globalThis?.document){let n=l(e);u.useEffect(()=>{let e=e=>{e.key===`Escape`&&n(e)};return t.addEventListener(`keydown`,e,{capture:!0}),()=>t.removeEventListener(`keydown`,e,{capture:!0})},[n,t])}var f=n(),p=`DismissableLayer`,m=`dismissableLayer.update`,h=`dismissableLayer.pointerDownOutside`,g=`dismissableLayer.focusOutside`,_,v=u.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),y=u.forwardRef((e,t)=>{let{disableOutsidePointerEvents:n=!1,onEscapeKeyDown:r,onPointerDownOutside:i,onFocusOutside:s,onInteractOutside:l,onDismiss:p,...h}=e,g=u.useContext(v),[y,b]=u.useState(null),x=y?.ownerDocument??globalThis?.document,[,T]=u.useState({}),E=o(t,e=>b(e)),D=Array.from(g.layers),[O]=[...g.layersWithOutsidePointerEventsDisabled].slice(-1),k=D.indexOf(O),A=y?D.indexOf(y):-1,j=g.layersWithOutsidePointerEventsDisabled.size>0,M=A>=k,N=S(e=>{let t=e.target,n=[...g.branches].some(e=>e.contains(t));!M||n||(i?.(e),l?.(e),e.defaultPrevented||p?.())},x),P=C(e=>{let t=e.target;[...g.branches].some(e=>e.contains(t))||(s?.(e),l?.(e),e.defaultPrevented||p?.())},x);return d(e=>{A===g.layers.size-1&&(r?.(e),!e.defaultPrevented&&p&&(e.preventDefault(),p()))},x),u.useEffect(()=>{if(y)return n&&(g.layersWithOutsidePointerEventsDisabled.size===0&&(_=x.body.style.pointerEvents,x.body.style.pointerEvents=`none`),g.layersWithOutsidePointerEventsDisabled.add(y)),g.layers.add(y),w(),()=>{n&&g.layersWithOutsidePointerEventsDisabled.size===1&&(x.body.style.pointerEvents=_)}},[y,x,n,g]),u.useEffect(()=>()=>{y&&(g.layers.delete(y),g.layersWithOutsidePointerEventsDisabled.delete(y),w())},[y,g]),u.useEffect(()=>{let e=()=>T({});return document.addEventListener(m,e),()=>document.removeEventListener(m,e)},[]),(0,f.jsx)(a.div,{...h,ref:E,style:{pointerEvents:j?M?`auto`:`none`:void 0,...e.style},onFocusCapture:c(e.onFocusCapture,P.onFocusCapture),onBlurCapture:c(e.onBlurCapture,P.onBlurCapture),onPointerDownCapture:c(e.onPointerDownCapture,N.onPointerDownCapture)})});y.displayName=p;var b=`DismissableLayerBranch`,x=u.forwardRef((e,t)=>{let n=u.useContext(v),r=u.useRef(null),i=o(t,r);return u.useEffect(()=>{let e=r.current;if(e)return n.branches.add(e),()=>{n.branches.delete(e)}},[n.branches]),(0,f.jsx)(a.div,{...e,ref:i})});x.displayName=b;function S(e,t=globalThis?.document){let n=l(e),r=u.useRef(!1),i=u.useRef(()=>{});return u.useEffect(()=>{let e=e=>{if(e.target&&!r.current){let r=function(){T(h,n,a,{discrete:!0})},a={originalEvent:e};e.pointerType===`touch`?(t.removeEventListener(`click`,i.current),i.current=r,t.addEventListener(`click`,i.current,{once:!0})):r()}else t.removeEventListener(`click`,i.current);r.current=!1},a=window.setTimeout(()=>{t.addEventListener(`pointerdown`,e)},0);return()=>{window.clearTimeout(a),t.removeEventListener(`pointerdown`,e),t.removeEventListener(`click`,i.current)}},[t,n]),{onPointerDownCapture:()=>r.current=!0}}function C(e,t=globalThis?.document){let n=l(e),r=u.useRef(!1);return u.useEffect(()=>{let e=e=>{e.target&&!r.current&&T(g,n,{originalEvent:e},{discrete:!1})};return t.addEventListener(`focusin`,e),()=>t.removeEventListener(`focusin`,e)},[t,n]),{onFocusCapture:()=>r.current=!0,onBlurCapture:()=>r.current=!1}}function w(){let e=new CustomEvent(m);document.dispatchEvent(e)}function T(e,t,n,{discrete:i}){let a=n.originalEvent.target,o=new CustomEvent(e,{bubbles:!1,cancelable:!0,detail:n});t&&a.addEventListener(e,t,{once:!0}),i?r(a,o):a.dispatchEvent(o)}var E=e(i(),1),D=`Portal`,O=u.forwardRef((e,t)=>{let{container:n,...r}=e,[i,o]=u.useState(!1);s(()=>o(!0),[]);let c=n||i&&globalThis?.document?.body;return c?E.createPortal((0,f.jsx)(a.div,{...r,ref:t}),c):null});O.displayName=D;export{y as n,O as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{n as r,r as i,t as a}from"./dist-D3WFT-Yo.js";import{u as o}from"./button-NLSeBFht.js";import{n as s,r as c}from"./dist-DmeeHi7K.js";import{t as l}from"./dist-SR6sl-WU.js";var u=e(t(),1);function d(e,t=globalThis?.document){let n=l(e);u.useEffect(()=>{let e=e=>{e.key===`Escape`&&n(e)};return t.addEventListener(`keydown`,e,{capture:!0}),()=>t.removeEventListener(`keydown`,e,{capture:!0})},[n,t])}var f=n(),p=`DismissableLayer`,m=`dismissableLayer.update`,h=`dismissableLayer.pointerDownOutside`,g=`dismissableLayer.focusOutside`,_,v=u.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),y=u.forwardRef((e,t)=>{let{disableOutsidePointerEvents:n=!1,onEscapeKeyDown:r,onPointerDownOutside:i,onFocusOutside:s,onInteractOutside:l,onDismiss:p,...h}=e,g=u.useContext(v),[y,b]=u.useState(null),x=y?.ownerDocument??globalThis?.document,[,T]=u.useState({}),E=o(t,e=>b(e)),D=Array.from(g.layers),[O]=[...g.layersWithOutsidePointerEventsDisabled].slice(-1),k=D.indexOf(O),A=y?D.indexOf(y):-1,j=g.layersWithOutsidePointerEventsDisabled.size>0,M=A>=k,N=S(e=>{let t=e.target,n=[...g.branches].some(e=>e.contains(t));!M||n||(i?.(e),l?.(e),e.defaultPrevented||p?.())},x),P=C(e=>{let t=e.target;[...g.branches].some(e=>e.contains(t))||(s?.(e),l?.(e),e.defaultPrevented||p?.())},x);return d(e=>{A===g.layers.size-1&&(r?.(e),!e.defaultPrevented&&p&&(e.preventDefault(),p()))},x),u.useEffect(()=>{if(y)return n&&(g.layersWithOutsidePointerEventsDisabled.size===0&&(_=x.body.style.pointerEvents,x.body.style.pointerEvents=`none`),g.layersWithOutsidePointerEventsDisabled.add(y)),g.layers.add(y),w(),()=>{n&&g.layersWithOutsidePointerEventsDisabled.size===1&&(x.body.style.pointerEvents=_)}},[y,x,n,g]),u.useEffect(()=>()=>{y&&(g.layers.delete(y),g.layersWithOutsidePointerEventsDisabled.delete(y),w())},[y,g]),u.useEffect(()=>{let e=()=>T({});return document.addEventListener(m,e),()=>document.removeEventListener(m,e)},[]),(0,f.jsx)(a.div,{...h,ref:E,style:{pointerEvents:j?M?`auto`:`none`:void 0,...e.style},onFocusCapture:c(e.onFocusCapture,P.onFocusCapture),onBlurCapture:c(e.onBlurCapture,P.onBlurCapture),onPointerDownCapture:c(e.onPointerDownCapture,N.onPointerDownCapture)})});y.displayName=p;var b=`DismissableLayerBranch`,x=u.forwardRef((e,t)=>{let n=u.useContext(v),r=u.useRef(null),i=o(t,r);return u.useEffect(()=>{let e=r.current;if(e)return n.branches.add(e),()=>{n.branches.delete(e)}},[n.branches]),(0,f.jsx)(a.div,{...e,ref:i})});x.displayName=b;function S(e,t=globalThis?.document){let n=l(e),r=u.useRef(!1),i=u.useRef(()=>{});return u.useEffect(()=>{let e=e=>{if(e.target&&!r.current){let r=function(){T(h,n,a,{discrete:!0})},a={originalEvent:e};e.pointerType===`touch`?(t.removeEventListener(`click`,i.current),i.current=r,t.addEventListener(`click`,i.current,{once:!0})):r()}else t.removeEventListener(`click`,i.current);r.current=!1},a=window.setTimeout(()=>{t.addEventListener(`pointerdown`,e)},0);return()=>{window.clearTimeout(a),t.removeEventListener(`pointerdown`,e),t.removeEventListener(`click`,i.current)}},[t,n]),{onPointerDownCapture:()=>r.current=!0}}function C(e,t=globalThis?.document){let n=l(e),r=u.useRef(!1);return u.useEffect(()=>{let e=e=>{e.target&&!r.current&&T(g,n,{originalEvent:e},{discrete:!1})};return t.addEventListener(`focusin`,e),()=>t.removeEventListener(`focusin`,e)},[t,n]),{onFocusCapture:()=>r.current=!0,onBlurCapture:()=>r.current=!1}}function w(){let e=new CustomEvent(m);document.dispatchEvent(e)}function T(e,t,n,{discrete:i}){let a=n.originalEvent.target,o=new CustomEvent(e,{bubbles:!1,cancelable:!0,detail:n});t&&a.addEventListener(e,t,{once:!0}),i?r(a,o):a.dispatchEvent(o)}var E=e(i(),1),D=`Portal`,O=u.forwardRef((e,t)=>{let{container:n,...r}=e,[i,o]=u.useState(!1);s(()=>o(!0),[]);let c=n||i&&globalThis?.document?.body;return c?E.createPortal((0,f.jsx)(a.div,{...r,ref:t}),c):null});O.displayName=D;export{y as n,O as t};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{em as e,ft as t}from"./messages-Bp0bCjzp.js";import{i as n}from"./button-BgMnOYKD.js";import{t as r}from"./createLucideIcon-Br0Bd5k2.js";var i=r(`inbox`,[[`polyline`,{points:`22 12 16 12 14 15 10 15 8 12 2 12`,key:`o97t9d`}],[`path`,{d:`M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`oot6mr`}]]),a=r(`refresh-cw`,[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]),o=r(`sliders-horizontal`,[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]]),s=e();function c({className:e,description:r=t(),icon:a,title:o}){return(0,s.jsxs)(`div`,{className:n(`flex flex-col items-center justify-center gap-3 py-16 text-center`,e),children:[(0,s.jsx)(`div`,{className:`flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground`,children:a??(0,s.jsx)(i,{className:`size-6`})}),o&&(0,s.jsx)(`p`,{className:`font-medium text-sm`,children:o}),(0,s.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:r})]})}export{o as n,a as r,c as t};
|
import{ft as e,tm as t}from"./messages-CL4J6BaJ.js";import{i as n}from"./button-NLSeBFht.js";import{t as r}from"./createLucideIcon-Br0Bd5k2.js";var i=r(`inbox`,[[`polyline`,{points:`22 12 16 12 14 15 10 15 8 12 2 12`,key:`o97t9d`}],[`path`,{d:`M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`oot6mr`}]]),a=r(`refresh-cw`,[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]),o=r(`sliders-horizontal`,[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]]),s=t();function c({className:t,description:r=e(),icon:a,title:o}){return(0,s.jsxs)(`div`,{className:n(`flex flex-col items-center justify-center gap-3 py-16 text-center`,t),children:[(0,s.jsx)(`div`,{className:`flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground`,children:a??(0,s.jsx)(i,{className:`size-6`})}),o&&(0,s.jsx)(`p`,{className:`font-medium text-sm`,children:o}),(0,s.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:r})]})}export{o as n,a as r,c as t};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{_t as e,bt as t,gt as n,ht as r,mt as i,pt as a,vt as o,xt as s,yt as c}from"./messages-Bp0bCjzp.js";import{n as l,t as u}from"./wallet-Bgblr4kl.js";import{t as d}from"./createLucideIcon-Br0Bd5k2.js";var f=d(`circle-pause`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`10`,x2:`10`,y1:`15`,y2:`9`,key:`c1nkhi`}],[`line`,{x1:`14`,x2:`14`,y1:`15`,y2:`9`,key:`h65svq`}]]),p=d(`clock-3`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6h4`,key:`135r8i`}]]),m=d(`link-2-off`,[[`path`,{d:`M9 17H7A5 5 0 0 1 7 7`,key:`10o201`}],[`path`,{d:`M15 7h2a5 5 0 0 1 4 8`,key:`1d3206`}],[`line`,{x1:`8`,x2:`12`,y1:`12`,y2:`12`,key:`rvw6j4`}],[`line`,{x1:`2`,x2:`22`,y1:`2`,y2:`22`,key:`a6p6uj`}]]),h=[{label:s(),value:`1`,icon:p},{label:t(),value:`2`,icon:l},{label:c(),value:`3`,icon:m},{label:o(),value:`4`,icon:u}],g={1:`bg-amber-500/10 text-amber-600`,2:`bg-emerald-500/10 text-emerald-600`,3:`bg-rose-500/10 text-rose-600`,4:`bg-cyan-500/10 text-cyan-600`};function _(e){return h.find(t=>t.value===String(e??1))?.label??String(e??`-`)}var v=[{label:e(),value:`enabled`,icon:u},{label:n(),value:`disabled`,icon:f},{label:r(),value:`monitoring`,icon:l}];i(),a();var y=[{label:i(),value:`true`},{label:a(),value:`false`}];export{h as a,g as i,y as n,p as o,_ as r,v as t};
|
import{_t as e,bt as t,gt as n,ht as r,mt as i,pt as a,vt as o,xt as s,yt as c}from"./messages-CL4J6BaJ.js";import{n as l,t as u}from"./wallet-Cdhl16hF.js";import{t as d}from"./createLucideIcon-Br0Bd5k2.js";var f=d(`circle-pause`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`10`,x2:`10`,y1:`15`,y2:`9`,key:`c1nkhi`}],[`line`,{x1:`14`,x2:`14`,y1:`15`,y2:`9`,key:`h65svq`}]]),p=d(`clock-3`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6h4`,key:`135r8i`}]]),m=d(`link-2-off`,[[`path`,{d:`M9 17H7A5 5 0 0 1 7 7`,key:`10o201`}],[`path`,{d:`M15 7h2a5 5 0 0 1 4 8`,key:`1d3206`}],[`line`,{x1:`8`,x2:`12`,y1:`12`,y2:`12`,key:`rvw6j4`}],[`line`,{x1:`2`,x2:`22`,y1:`2`,y2:`22`,key:`a6p6uj`}]]),h=[{label:s(),value:`1`,icon:p},{label:t(),value:`2`,icon:l},{label:c(),value:`3`,icon:m},{label:o(),value:`4`,icon:u}],g={1:`bg-amber-500/10 text-amber-600`,2:`bg-emerald-500/10 text-emerald-600`,3:`bg-rose-500/10 text-rose-600`,4:`bg-cyan-500/10 text-cyan-600`};function _(e){return h.find(t=>t.value===String(e??1))?.label??String(e??`-`)}var v=[{label:e(),value:`enabled`,icon:u},{label:n(),value:`disabled`,icon:f},{label:r(),value:`monitoring`,icon:l}];i(),a();var y=[{label:i(),value:`true`},{label:a(),value:`false`}];export{h as a,g as i,y as n,p as o,_ as r,v as t};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{em as n}from"./messages-Bp0bCjzp.js";import{n as r,r as i,t as a}from"./cookies-BzZOQYPw.js";var o=e(t(),1),s=[`inter`,`manrope`,`noto`,`system`],c=n(),l=`font`,u=3600*24*365,d=(0,o.createContext)(null);function f({children:e}){let[t,n]=(0,o.useState)(()=>{let e=a(l);return s.includes(e)?e:s[0]});return(0,o.useEffect)(()=>{(e=>{let t=document.documentElement;t.classList.remove(...[...t.classList].filter(e=>e.startsWith(`font-`))),t.classList.add(`font-${e}`)})(t)},[t]),(0,c.jsx)(d,{value:{font:t,setFont:e=>{i(l,e,u),n(e)},resetFont:()=>{r(l),n(s[0])}},children:e})}var p=()=>{let e=(0,o.useContext)(d);if(!e)throw Error(`useFont must be used within a FontProvider`);return e};export{p as n,s as r,f as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{tm as n}from"./messages-CL4J6BaJ.js";import{n as r,r as i,t as a}from"./cookies-BzZOQYPw.js";var o=e(t(),1),s=[`inter`,`manrope`,`noto`,`system`],c=n(),l=`font`,u=3600*24*365,d=(0,o.createContext)(null);function f({children:e}){let[t,n]=(0,o.useState)(()=>{let e=a(l);return s.includes(e)?e:s[0]});return(0,o.useEffect)(()=>{(e=>{let t=document.documentElement;t.classList.remove(...[...t.classList].filter(e=>e.startsWith(`font-`))),t.classList.add(`font-${e}`)})(t)},[t]),(0,c.jsx)(d,{value:{font:t,setFont:e=>{i(l,e,u),n(e)},resetFont:()=>{r(l),n(s[0])}},children:e})}var p=()=>{let e=(0,o.useContext)(d);if(!e)throw Error(`useFont must be used within a FontProvider`);return e};export{p as n,s as r,f as t};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{Mt as e,Nt as t,Od as n,Pt as r,kd as i,tm as a}from"./messages-CL4J6BaJ.js";import{t as o}from"./useRouter-DtTm7XkK.js";import{t as s}from"./useNavigate-7u4DX0Ho.js";import{t as c}from"./button-NLSeBFht.js";var l=a();function u(){let a=s(),{history:u}=o();return(0,l.jsx)(`div`,{className:`h-svh`,children:(0,l.jsxs)(`div`,{className:`m-auto flex h-full w-full flex-col items-center justify-center gap-2`,children:[(0,l.jsx)(`h1`,{className:`font-bold text-[7rem] leading-tight`,children:`403`}),(0,l.jsx)(`span`,{className:`font-medium`,children:r()}),(0,l.jsxs)(`p`,{className:`text-center text-muted-foreground`,children:[t(),` `,(0,l.jsx)(`br`,{}),e()]}),(0,l.jsxs)(`div`,{className:`mt-6 flex gap-4`,children:[(0,l.jsx)(c,{onClick:()=>u.go(-1),variant:`outline`,children:i()}),(0,l.jsx)(c,{onClick:()=>a({to:`/dashboard`}),children:n()})]})]})})}export{u as t};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{Dd as e,Mt as t,Nt as n,Od as r,Pt as i,em as a}from"./messages-Bp0bCjzp.js";import{t as o}from"./useRouter-DtTm7XkK.js";import{t as s}from"./useNavigate-7u4DX0Ho.js";import{t as c}from"./button-BgMnOYKD.js";var l=a();function u(){let a=s(),{history:u}=o();return(0,l.jsx)(`div`,{className:`h-svh`,children:(0,l.jsxs)(`div`,{className:`m-auto flex h-full w-full flex-col items-center justify-center gap-2`,children:[(0,l.jsx)(`h1`,{className:`font-bold text-[7rem] leading-tight`,children:`403`}),(0,l.jsx)(`span`,{className:`font-medium`,children:i()}),(0,l.jsxs)(`p`,{className:`text-center text-muted-foreground`,children:[n(),` `,(0,l.jsx)(`br`,{}),t()]}),(0,l.jsxs)(`div`,{className:`mt-6 flex gap-4`,children:[(0,l.jsx)(c,{onClick:()=>u.go(-1),variant:`outline`,children:r()}),(0,l.jsx)(c,{onClick:()=>a({to:`/dashboard`}),children:e()})]})]})})}export{u as t};
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{Ad as e,Dd as t,Od as n,em as r,kd as i}from"./messages-Bp0bCjzp.js";import{t as a}from"./useRouter-DtTm7XkK.js";import{t as o}from"./useNavigate-7u4DX0Ho.js";import{i as s,t as c}from"./button-BgMnOYKD.js";var l=r();function u({className:r,minimal:u=!1}){let d=o(),{history:f}=a();return(0,l.jsx)(`div`,{className:s(`h-svh w-full`,r),children:(0,l.jsxs)(`div`,{className:`m-auto flex h-full w-full flex-col items-center justify-center gap-2`,children:[!u&&(0,l.jsx)(`h1`,{className:`font-bold text-[7rem] leading-tight`,children:`500`}),(0,l.jsx)(`span`,{className:`font-medium`,children:e()}),(0,l.jsx)(`p`,{className:`text-center text-muted-foreground`,children:i()}),!u&&(0,l.jsxs)(`div`,{className:`mt-6 flex gap-4`,children:[(0,l.jsx)(c,{onClick:()=>f.go(-1),variant:`outline`,children:n()}),(0,l.jsx)(c,{onClick:()=>d({to:`/dashboard`}),children:t()})]})]})})}export{u as t};
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{Ad as e,Od as t,jd as n,kd as r,tm as i}from"./messages-CL4J6BaJ.js";import{t as a}from"./useRouter-DtTm7XkK.js";import{t as o}from"./useNavigate-7u4DX0Ho.js";import{i as s,t as c}from"./button-NLSeBFht.js";var l=i();function u({className:i,minimal:u=!1}){let d=o(),{history:f}=a();return(0,l.jsx)(`div`,{className:s(`h-svh w-full`,i),children:(0,l.jsxs)(`div`,{className:`m-auto flex h-full w-full flex-col items-center justify-center gap-2`,children:[!u&&(0,l.jsx)(`h1`,{className:`font-bold text-[7rem] leading-tight`,children:`500`}),(0,l.jsx)(`span`,{className:`font-medium`,children:n()}),(0,l.jsx)(`p`,{className:`text-center text-muted-foreground`,children:e()}),!u&&(0,l.jsxs)(`div`,{className:`mt-6 flex gap-4`,children:[(0,l.jsx)(c,{onClick:()=>f.go(-1),variant:`outline`,children:r()}),(0,l.jsx)(c,{onClick:()=>d({to:`/dashboard`}),children:t()})]})]})})}export{u as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{i as t}from"./auth-store-Csn6HPxJ.js";import{t as n}from"./react-CO2uhaBc.js";import{Au as r,Kp as i,Su as a,Tt as o,Xp as s,em as c,qp as l,xu as u}from"./messages-Bp0bCjzp.js";import{t as d}from"./link-BYG8nKNO.js";import{F as f,L as p,R as m,d as h,f as g,h as _,j as v,l as y,n as b,o as x,p as S,u as C,z as w}from"./search-provider-Bl2HDfcG.js";import{i as T,t as E}from"./button-BgMnOYKD.js";import{a as D,i as O,l as k,o as A,r as j,s as M,t as N}from"./dropdown-menu-8-hEBtzr.js";import{t as P}from"./separator-DbmFQXe4.js";import{l as F}from"./command-CIv3ggHf.js";var I=e(n(),1),L=c();function R(){let[e,n]=y(),[s,c]=(0,I.useState)(!1),{user:v}=t(),b=v?.username?.trim()||o(),T=b.charAt(0).toUpperCase()||`U`,P=v?.last_login_at?a({time:x(v.last_login_at)}):u();return(0,L.jsxs)(L.Fragment,{children:[(0,L.jsx)(f,{onOpenChange:c,open:s,children:(0,L.jsx)(_,{})}),(0,L.jsxs)(N,{modal:!1,children:[(0,L.jsx)(k,{asChild:!0,children:(0,L.jsx)(E,{className:`relative h-8 w-8 rounded-full`,variant:`ghost`,children:(0,L.jsxs)(C,{className:`h-8 w-8`,children:[(0,L.jsx)(g,{alt:b,src:`/avatars/01.png`}),(0,L.jsx)(h,{children:T})]})})}),(0,L.jsxs)(j,{align:`end`,className:`w-56`,forceMount:!0,children:[(0,L.jsx)(A,{className:`p-0 font-normal`,children:(0,L.jsxs)(`div`,{className:`flex items-center gap-2 px-1 py-1.5 text-start text-sm`,children:[(0,L.jsxs)(C,{className:`h-8 w-8 rounded-lg`,children:[(0,L.jsx)(g,{alt:b,src:`/avatars/01.png`}),(0,L.jsx)(h,{className:`rounded-lg`,children:T})]}),(0,L.jsxs)(`div`,{className:`grid flex-1 text-start text-sm leading-tight`,children:[(0,L.jsx)(`span`,{className:`truncate font-semibold`,children:b}),(0,L.jsx)(`span`,{className:`truncate text-muted-foreground text-xs`,children:P})]})]})}),(0,L.jsx)(M,{}),(0,L.jsxs)(O,{children:[(0,L.jsx)(D,{asChild:!0,children:(0,L.jsxs)(d,{to:`/account/password`,children:[(0,L.jsx)(w,{className:`mr-2 size-4`}),l()]})}),(0,L.jsxs)(D,{onClick:()=>c(!0),onSelect:e=>e.preventDefault(),children:[(0,L.jsx)(p,{className:`mr-2 size-4`}),r()]})]}),(0,L.jsx)(M,{}),(0,L.jsxs)(D,{onClick:()=>n(!0),variant:`destructive`,children:[(0,L.jsx)(m,{className:`mr-2 size-4`}),i()]})]})]}),(0,L.jsx)(S,{onOpenChange:n,open:!!e})]})}function z({className:e=``,placeholder:t}){let{setOpen:n}=b();return(0,L.jsxs)(E,{className:T(`group relative h-8 w-full flex-1 justify-start rounded-md bg-muted/25 font-normal text-muted-foreground text-sm shadow-none hover:bg-accent sm:w-40 sm:pe-12 md:flex-none lg:w-52 xl:w-64`,e),onClick:()=>n(!0),variant:`outline`,children:[(0,L.jsx)(F,{"aria-hidden":`true`,className:`absolute inset-s-1.5 top-1/2 -translate-y-1/2`,size:16}),(0,L.jsx)(`span`,{className:`ms-4`,children:t??s()}),(0,L.jsxs)(`kbd`,{className:`pointer-events-none absolute inset-e-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-medium font-mono text-[10px] opacity-100 group-hover:bg-accent sm:flex`,children:[(0,L.jsx)(`span`,{className:`text-xs`,children:`⌘`}),`K`]})]})}function B({className:e,fixed:t,children:n,...r}){let[i,a]=(0,I.useState)(0);return(0,I.useEffect)(()=>{let e=()=>{a(document.body.scrollTop||document.documentElement.scrollTop)};return document.addEventListener(`scroll`,e,{passive:!0}),()=>document.removeEventListener(`scroll`,e)},[]),(0,L.jsx)(`header`,{className:T(`z-50 h-16`,t&&`header-fixed peer/header sticky top-0 w-[inherit]`,i>10&&t?`shadow`:`shadow-none`,e),...r,children:(0,L.jsxs)(`div`,{className:T(`relative flex h-full items-center gap-3 p-4 sm:gap-4`,i>10&&t&&`after:absolute after:inset-0 after:-z-10 after:bg-background/20 after:backdrop-blur-lg`),children:[(0,L.jsx)(v,{className:`max-md:scale-125`,variant:`outline`}),(0,L.jsx)(P,{className:`h-6`,orientation:`vertical`}),n]})})}export{z as n,R as r,B as t};
|
import{r as e}from"./chunk-DECur_0Z.js";import{i as t}from"./auth-store-8ocF_FHU.js";import{t as n}from"./react-CO2uhaBc.js";import{Au as r,Jp as i,Su as a,Tt as o,Zp as s,qp as c,tm as l,xu as u}from"./messages-CL4J6BaJ.js";import{t as d}from"./link-6i3yGmK_.js";import{F as f,L as p,R as m,d as h,f as g,h as _,j as v,l as y,n as b,o as x,p as S,u as C,z as w}from"./search-provider-CTRbHqNx.js";import{i as T,t as E}from"./button-NLSeBFht.js";import{a as D,i as O,l as k,o as A,r as j,s as M,t as N}from"./dropdown-menu-D72UcvWG.js";import{t as P}from"./separator-CqhQIQ-B.js";import{l as F}from"./command-vy8966UO.js";var I=e(n(),1),L=l();function R(){let[e,n]=y(),[s,l]=(0,I.useState)(!1),{user:v}=t(),b=v?.username?.trim()||o(),T=b.charAt(0).toUpperCase()||`U`,P=v?.last_login_at?a({time:x(v.last_login_at)}):u();return(0,L.jsxs)(L.Fragment,{children:[(0,L.jsx)(f,{onOpenChange:l,open:s,children:(0,L.jsx)(_,{})}),(0,L.jsxs)(N,{modal:!1,children:[(0,L.jsx)(k,{asChild:!0,children:(0,L.jsx)(E,{className:`relative h-8 w-8 rounded-full`,variant:`ghost`,children:(0,L.jsxs)(C,{className:`h-8 w-8`,children:[(0,L.jsx)(g,{alt:b,src:`/avatars/01.png`}),(0,L.jsx)(h,{children:T})]})})}),(0,L.jsxs)(j,{align:`end`,className:`w-56`,forceMount:!0,children:[(0,L.jsx)(A,{className:`p-0 font-normal`,children:(0,L.jsxs)(`div`,{className:`flex items-center gap-2 px-1 py-1.5 text-start text-sm`,children:[(0,L.jsxs)(C,{className:`h-8 w-8 rounded-lg`,children:[(0,L.jsx)(g,{alt:b,src:`/avatars/01.png`}),(0,L.jsx)(h,{className:`rounded-lg`,children:T})]}),(0,L.jsxs)(`div`,{className:`grid flex-1 text-start text-sm leading-tight`,children:[(0,L.jsx)(`span`,{className:`truncate font-semibold`,children:b}),(0,L.jsx)(`span`,{className:`truncate text-muted-foreground text-xs`,children:P})]})]})}),(0,L.jsx)(M,{}),(0,L.jsxs)(O,{children:[(0,L.jsx)(D,{asChild:!0,children:(0,L.jsxs)(d,{to:`/account/password`,children:[(0,L.jsx)(w,{className:`mr-2 size-4`}),i()]})}),(0,L.jsxs)(D,{onClick:()=>l(!0),onSelect:e=>e.preventDefault(),children:[(0,L.jsx)(p,{className:`mr-2 size-4`}),r()]})]}),(0,L.jsx)(M,{}),(0,L.jsxs)(D,{onClick:()=>n(!0),variant:`destructive`,children:[(0,L.jsx)(m,{className:`mr-2 size-4`}),c()]})]})]}),(0,L.jsx)(S,{onOpenChange:n,open:!!e})]})}function z({className:e=``,placeholder:t}){let{setOpen:n}=b();return(0,L.jsxs)(E,{className:T(`group relative h-8 w-full flex-1 justify-start rounded-md bg-muted/25 font-normal text-muted-foreground text-sm shadow-none hover:bg-accent sm:w-40 sm:pe-12 md:flex-none lg:w-52 xl:w-64`,e),onClick:()=>n(!0),variant:`outline`,children:[(0,L.jsx)(F,{"aria-hidden":`true`,className:`absolute inset-s-1.5 top-1/2 -translate-y-1/2`,size:16}),(0,L.jsx)(`span`,{className:`ms-4`,children:t??s()}),(0,L.jsxs)(`kbd`,{className:`pointer-events-none absolute inset-e-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-medium font-mono text-[10px] opacity-100 group-hover:bg-accent sm:flex`,children:[(0,L.jsx)(`span`,{className:`text-xs`,children:`⌘`}),`K`]})]})}function B({className:e,fixed:t,children:n,...r}){let[i,a]=(0,I.useState)(0);return(0,I.useEffect)(()=>{let e=()=>{a(document.body.scrollTop||document.documentElement.scrollTop)};return document.addEventListener(`scroll`,e,{passive:!0}),()=>document.removeEventListener(`scroll`,e)},[]),(0,L.jsx)(`header`,{className:T(`z-50 h-16`,t&&`header-fixed peer/header sticky top-0 w-[inherit]`,i>10&&t?`shadow`:`shadow-none`,e),...r,children:(0,L.jsxs)(`div`,{className:T(`relative flex h-full items-center gap-3 p-4 sm:gap-4`,i>10&&t&&`after:absolute after:inset-0 after:-z-10 after:bg-background/20 after:backdrop-blur-lg`),children:[(0,L.jsx)(v,{className:`max-md:scale-125`,variant:`outline`}),(0,L.jsx)(P,{className:`h-6`,orientation:`vertical`}),n]})})}export{z as n,R as r,B as t};
|
||||||
@@ -1 +1 @@
|
|||||||
import{Fp as e,Ip as t,Lp as n,em as r}from"./messages-Bp0bCjzp.js";import{t as i}from"./telescope-DU0wiTDw.js";var a=r();function o(){return(0,a.jsx)(`div`,{className:`h-svh`,children:(0,a.jsxs)(`div`,{className:`m-auto flex h-full w-full flex-col items-center justify-center gap-2`,children:[(0,a.jsx)(i,{size:72}),(0,a.jsx)(`h1`,{className:`font-bold text-4xl leading-tight`,children:n()}),(0,a.jsxs)(`p`,{className:`text-center text-muted-foreground`,children:[t(),` `,(0,a.jsx)(`br`,{}),e()]})]})})}var s=o;export{s as component};
|
import{Ip as e,Lp as t,Rp as n,tm as r}from"./messages-CL4J6BaJ.js";import{t as i}from"./telescope-DU0wiTDw.js";var a=r();function o(){return(0,a.jsx)(`div`,{className:`h-svh`,children:(0,a.jsxs)(`div`,{className:`m-auto flex h-full w-full flex-col items-center justify-center gap-2`,children:[(0,a.jsx)(i,{size:72}),(0,a.jsx)(`h1`,{className:`font-bold text-4xl leading-tight`,children:n()}),(0,a.jsxs)(`p`,{className:`text-center text-muted-foreground`,children:[t(),` `,(0,a.jsx)(`br`,{}),e()]})]})})}var s=o;export{s as component};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{em as e}from"./messages-Bp0bCjzp.js";import{i as t}from"./button-BgMnOYKD.js";var n=e();function r({className:e,type:r,...i}){return(0,n.jsx)(`input`,{className:t(`h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs outline-none transition-[color,box-shadow] selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:font-medium file:text-foreground file:text-sm placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30`,`focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50`,`aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40`,e),"data-slot":`input`,type:r,...i})}export{r as t};
|
import{tm as e}from"./messages-CL4J6BaJ.js";import{i as t}from"./button-NLSeBFht.js";var n=e();function r({className:e,type:r,...i}){return(0,n.jsx)(`input`,{className:t(`h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs outline-none transition-[color,box-shadow] selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:font-medium file:text-foreground file:text-sm placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30`,`focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50`,`aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40`,e),"data-slot":`input`,type:r,...i})}export{r as t};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{As as n,Ds as r,Fs as i,Ms as a,Ns as o,Os as s,Ps as c,em as l,js as u,ks as d}from"./messages-Bp0bCjzp.js";import{r as f}from"./route-Bin9ihv_.js";import{d as p,n as m,o as h,r as g,s as _}from"./data-table-C3Nm2K6Z.js";import{t as v}from"./badge-BP05f1dq.js";import{t as y}from"./use-table-url-state-DP0Y4QjR.js";var b=e(t(),1),x=l(),S=[{name:`GMPay`,entries:[{method:`POST`,path:`/payments/gmpay/v1/order/create-transaction`}],requestFields:[`order_id`,`currency`,`token`,`network`,`amount`,`notify_url`,`signature`,`redirect_url?`,`name?`,`payment_type?`],callbackNote:d()},{name:`EPay Compatible`,entries:[{method:`POST`,path:`/payments/epay/v1/order/create-transaction/submit.php`},{method:`GET`,path:`/payments/epay/v1/order/create-transaction/submit.php`}],requestFields:[`pid`,`money`,`out_trade_no`,`notify_url`,`return_url?`,`name?`,`type?`,`sign`,`sign_type?`],callbackNote:s()},{name:`OKPay`,entries:[{method:`POST`,path:`/payments/okpay/v1/notify`}],requestFields:[`OkPay notify payload`],callbackNote:r()}];function C({method:e}){return(0,x.jsx)(v,{className:e===`GET`?`rounded border border-blue-500/30 bg-blue-500/10 font-mono text-blue-600 dark:text-blue-400`:`rounded border border-emerald-500/30 bg-emerald-500/10 font-mono text-emerald-600 dark:text-emerald-400`,variant:`outline`,children:e})}function w({field:e}){return(0,x.jsx)(`code`,{className:`rounded bg-muted px-1.5 py-0.5 font-mono text-foreground text-xs`,children:e})}function T({item:e}){let t=e.entries.reduce((e,t)=>(e[t.path]||(e[t.path]=[]),e[t.path].push(t.method),e),{});return(0,x.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:Object.entries(t).map(([e,t])=>(0,x.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,x.jsx)(`div`,{className:`flex gap-1.5`,children:t.map(e=>(0,x.jsx)(C,{method:e},e))}),(0,x.jsx)(`code`,{className:`whitespace-normal break-words font-mono text-sm`,children:e})]},e))})}function E({fields:e}){return(0,x.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:e.map(e=>(0,x.jsx)(w,{field:e},e))})}var D=f(`/_authenticated/payment-setup/integrations`);function O(){let{pagination:e,onPaginationChange:t,ensurePageInRange:r}=y({search:D.useSearch(),navigate:D.useNavigate(),pagination:{defaultPage:1,defaultPageSize:10}}),s=h({data:S,columns:(0,b.useMemo)(()=>[{accessorKey:`name`,header:o(),cell:({row:e})=>(0,x.jsx)(`span`,{className:`font-medium`,children:e.original.name})},{accessorKey:`entries`,header:a(),cell:({row:e})=>(0,x.jsx)(T,{item:e.original})},{accessorKey:`requestFields`,header:u(),cell:({row:e})=>(0,x.jsx)(E,{fields:e.original.requestFields})},{accessorKey:`callbackNote`,header:n(),cell:({row:e})=>(0,x.jsx)(`span`,{className:`whitespace-normal break-words text-muted-foreground text-sm`,children:e.original.callbackNote})}],[]),state:{pagination:e},onPaginationChange:t,getCoreRowModel:_(),getPaginationRowModel:p()});return(0,b.useEffect)(()=>{r(s.getPageCount())},[s,r]),(0,x.jsxs)(`div`,{className:`flex flex-1 flex-col gap-4`,children:[(0,x.jsxs)(`div`,{className:`space-y-1`,children:[(0,x.jsx)(`h3`,{className:`font-semibold text-lg`,children:i()}),(0,x.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:c()})]}),(0,x.jsx)(g,{table:s}),(0,x.jsx)(m,{className:`mt-auto`,table:s})]})}function k(){return(0,x.jsx)(O,{})}var A=k;export{A as component};
|
import{r as e}from"./chunk-DECur_0Z.js";import{t}from"./react-CO2uhaBc.js";import{As as n,Ds as r,Fs as i,Ms as a,Ns as o,Os as s,Ps as c,js as l,ks as u,tm as d}from"./messages-CL4J6BaJ.js";import{r as f}from"./route-gtb8yu3E.js";import{d as p,n as m,o as h,r as g,s as _}from"./data-table-DC6T69tr.js";import{t as v}from"./badge-BRKB3301.js";import{t as y}from"./use-table-url-state-DP0Y4QjR.js";var b=e(t(),1),x=d(),S=[{name:`GMPay`,entries:[{method:`POST`,path:`/payments/gmpay/v1/order/create-transaction`}],requestFields:[`order_id`,`currency`,`token`,`network`,`amount`,`notify_url`,`signature`,`redirect_url?`,`name?`,`payment_type?`],callbackNote:u()},{name:`EPay Compatible`,entries:[{method:`POST`,path:`/payments/epay/v1/order/create-transaction/submit.php`},{method:`GET`,path:`/payments/epay/v1/order/create-transaction/submit.php`}],requestFields:[`pid`,`money`,`out_trade_no`,`notify_url`,`return_url?`,`name?`,`type?`,`sign`,`sign_type?`],callbackNote:s()},{name:`OKPay`,entries:[{method:`POST`,path:`/payments/okpay/v1/notify`}],requestFields:[`OkPay notify payload`],callbackNote:r()}];function C({method:e}){return(0,x.jsx)(v,{className:e===`GET`?`rounded border border-blue-500/30 bg-blue-500/10 font-mono text-blue-600 dark:text-blue-400`:`rounded border border-emerald-500/30 bg-emerald-500/10 font-mono text-emerald-600 dark:text-emerald-400`,variant:`outline`,children:e})}function w({field:e}){return(0,x.jsx)(`code`,{className:`rounded bg-muted px-1.5 py-0.5 font-mono text-foreground text-xs`,children:e})}function T({item:e}){let t=e.entries.reduce((e,t)=>(e[t.path]||(e[t.path]=[]),e[t.path].push(t.method),e),{});return(0,x.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:Object.entries(t).map(([e,t])=>(0,x.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,x.jsx)(`div`,{className:`flex gap-1.5`,children:t.map(e=>(0,x.jsx)(C,{method:e},e))}),(0,x.jsx)(`code`,{className:`whitespace-normal break-words font-mono text-sm`,children:e})]},e))})}function E({fields:e}){return(0,x.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:e.map(e=>(0,x.jsx)(w,{field:e},e))})}var D=f(`/_authenticated/payment-setup/integrations`);function O(){let{pagination:e,onPaginationChange:t,ensurePageInRange:r}=y({search:D.useSearch(),navigate:D.useNavigate(),pagination:{defaultPage:1,defaultPageSize:10}}),s=h({data:S,columns:(0,b.useMemo)(()=>[{accessorKey:`name`,header:o(),cell:({row:e})=>(0,x.jsx)(`span`,{className:`font-medium`,children:e.original.name})},{accessorKey:`entries`,header:a(),cell:({row:e})=>(0,x.jsx)(T,{item:e.original})},{accessorKey:`requestFields`,header:l(),cell:({row:e})=>(0,x.jsx)(E,{fields:e.original.requestFields})},{accessorKey:`callbackNote`,header:n(),cell:({row:e})=>(0,x.jsx)(`span`,{className:`whitespace-normal break-words text-muted-foreground text-sm`,children:e.original.callbackNote})}],[]),state:{pagination:e},onPaginationChange:t,getCoreRowModel:_(),getPaginationRowModel:p()});return(0,b.useEffect)(()=>{r(s.getPageCount())},[s,r]),(0,x.jsxs)(`div`,{className:`flex flex-1 flex-col gap-4`,children:[(0,x.jsxs)(`div`,{className:`space-y-1`,children:[(0,x.jsx)(`h3`,{className:`font-semibold text-lg`,children:i()}),(0,x.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:c()})]}),(0,x.jsx)(g,{table:s}),(0,x.jsx)(m,{className:`mt-auto`,table:s})]})}function k(){return(0,x.jsx)(O,{})}var A=k;export{A as component};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user