Skip to content

Commit 1c53b8a

Browse files
committed
fix(frontend): replace placeholder states with coming-soon + modal fallbacks
- SettingsPage: disabled cards → 'coming-soon' badge (primary blue, opacity-75) - LoginPage: Terms/Privacy # links → modal overlay (reuses SettingsPage dialog pattern) - tokenManager: refreshToken TODO → @see GitHub issue reference - i18n: added comingSoon + legal modal translations (zh-CN/en-US/ja-JP) - npm run build: zero type errors
1 parent 699b7e3 commit 1c53b8a

6 files changed

Lines changed: 71 additions & 7 deletions

File tree

frontend/src/api/client/tokenManager.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
// entirely (the browser will attach the cookie automatically on refresh
2020
// requests). Until then, sessionStorage is the lowest-cost mitigation that
2121
// does not require backend changes.
22+
//
23+
// @see https://github.com/chyinan/AetherFlow/issues
2224
const REFRESH_STORAGE_KEY = 'af_auth_refresh'
2325
// Pre-fix keys kept only for one-time migration; new code never writes to
2426
// them.

frontend/src/i18n/locales/en-US.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ export const enUS = {
206206
termsPrefix: 'By using AetherFlow, you agree to our',
207207
termsOfUse: 'Terms of Use',
208208
privacyPolicy: 'Privacy Policy',
209+
termsModalPlaceholder: 'Terms of Service — Coming Soon',
210+
privacyModalPlaceholder: 'Privacy Policy — Coming Soon',
209211
newToAetherFlow: 'New to AetherFlow?',
210212
createAccount: 'Create an account',
211213
signInWithPasskey: 'Sign in with a passkey',
@@ -1045,6 +1047,7 @@ export const enUS = {
10451047
configured: 'configured',
10461048
connected: 'connected',
10471049
disabled: 'disabled',
1050+
'coming-soon': 'coming soon',
10481051
installed: 'installed',
10491052
invited: 'invited',
10501053
missing: 'missing',
@@ -1203,6 +1206,7 @@ export const enUS = {
12031206
developerGuardrailRealtime: 'SSE / WebSocket must pass through Nginx and Gateway, never direct container addresses.',
12041207
developerGuardrailTimeout: 'Frontend request timeout is {timeout}ms; long tasks should recover through queues and realtime events.',
12051208
configuredApiExtensions: 'Configured APIs',
1209+
comingSoon: 'Coming Soon',
12061210
reserved: 'Reserved',
12071211
configure: 'Configure',
12081212
customizationTitle: 'Customization',

frontend/src/i18n/locales/ja-JP.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ export const jaJP = {
208208
termsPrefix: '利用することで、以下に同意したものとみなされます:',
209209
termsOfUse: '利用規約',
210210
privacyPolicy: 'プライバシーポリシー',
211+
termsModalPlaceholder: '利用規約 — 近日公開',
212+
privacyModalPlaceholder: 'プライバシーポリシー — 近日公開',
211213
newToAetherFlow: 'AetherFlow を初めて使いますか?',
212214
createAccount: 'アカウントを作成',
213215
signInWithPasskey: 'パスキーでサインイン',
@@ -1047,6 +1049,7 @@ export const jaJP = {
10471049
configured: '設定済み',
10481050
connected: '接続済み',
10491051
disabled: '無効',
1052+
'coming-soon': '近日公開',
10501053
installed: 'インストール済み',
10511054
invited: '招待済み',
10521055
missing: '欠落',
@@ -1205,6 +1208,7 @@ export const jaJP = {
12051208
developerGuardrailRealtime: 'SSE / WebSocket は Nginx と Gateway を経由し、コンテナの直接アドレスを使わないでください。',
12061209
developerGuardrailTimeout: 'フロントエンドのタイムアウトは {timeout}ms です。長時間タスクはキューとリアルタイムイベントで回復させてください。',
12071210
configuredApiExtensions: '設定済み API',
1211+
comingSoon: '近日公開',
12081212
reserved: '予約済み',
12091213
configure: '設定',
12101214
customizationTitle: 'カスタマイズ',

frontend/src/i18n/locales/zh-CN.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ export const zhCN = {
206206
termsPrefix: '使用即代表您同意我们的',
207207
termsOfUse: '使用协议',
208208
privacyPolicy: '隐私政策',
209+
termsModalPlaceholder: '使用协议 — 即将上线',
210+
privacyModalPlaceholder: '隐私政策 — 即将上线',
209211
newToAetherFlow: '第一次使用 AetherFlow?',
210212
createAccount: '创建账户',
211213
signInWithPasskey: '使用通行密钥登录',
@@ -1045,6 +1047,7 @@ export const zhCN = {
10451047
configured: '已配置',
10461048
connected: '已连接',
10471049
disabled: '已停用',
1050+
'coming-soon': '即将上线',
10481051
installed: '已安装',
10491052
invited: '已邀请',
10501053
missing: '缺失',
@@ -1203,6 +1206,7 @@ export const zhCN = {
12031206
developerGuardrailRealtime: 'SSE / WebSocket 必须经过 Nginx 和 Gateway,避免浏览器访问内部容器地址。',
12041207
developerGuardrailTimeout: '前端请求超时当前为 {timeout}ms,长任务应使用运行队列和实时事件恢复。',
12051208
configuredApiExtensions: '已配置 API',
1209+
comingSoon: '即将上线',
12061210
reserved: '预留',
12071211
configure: '配置',
12081212
customizationTitle: '定制',

frontend/src/pages/auth/LoginPage.vue

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { Eye, EyeOff } from 'lucide-vue-next'
2+
import { Eye, EyeOff, X } from 'lucide-vue-next'
33
import { computed, reactive, ref } from 'vue'
44
import { useI18n } from 'vue-i18n'
55
import { useRoute, useRouter } from 'vue-router'
@@ -21,6 +21,7 @@ const form = reactive({
2121
const errorMessage = ref('')
2222
const showPassword = ref(false)
2323
const authMode = ref<'login' | 'register'>('login')
24+
const showLegalModal = ref<'none' | 'terms' | 'privacy'>('none')
2425
const canSubmitCredentials = computed(
2526
() =>
2627
form.username.trim().length > 0 &&
@@ -218,13 +219,49 @@ function toggleAuthMode() {
218219

219220
<p class="mt-8 text-left text-sm font-medium leading-6 text-[#667085]">
220221
{{ t('auth.termsPrefix') }}
221-
<a href="#" class="font-semibold text-[#111827] hover:text-[#2563eb]">{{ t('auth.termsOfUse') }}</a>
222+
<button type="button" class="font-semibold text-[#111827] hover:text-[#2563eb]" @click="showLegalModal = 'terms'">{{ t('auth.termsOfUse') }}</button>
222223
<span class="px-1">&amp;</span>
223-
<a href="#" class="font-semibold text-[#111827] hover:text-[#2563eb]">{{ t('auth.privacyPolicy') }}</a>
224+
<button type="button" class="font-semibold text-[#111827] hover:text-[#2563eb]" @click="showLegalModal = 'privacy'">{{ t('auth.privacyPolicy') }}</button>
224225
</p>
225226
</div>
226227
</section>
227228

229+
<div
230+
v-if="showLegalModal !== 'none'"
231+
class="fixed inset-0 z-50 grid place-items-center bg-slate-950/55 p-4 backdrop-blur-sm"
232+
@click.self="showLegalModal = 'none'"
233+
>
234+
<section class="w-full max-w-md overflow-hidden rounded-2xl border border-app-border bg-white shadow-panel">
235+
<header class="flex items-start justify-between gap-4 border-b border-app-border px-5 py-4">
236+
<p class="text-base font-semibold text-text-primary">
237+
{{ showLegalModal === 'terms' ? t('auth.termsOfUse') : t('auth.privacyPolicy') }}
238+
</p>
239+
<button
240+
type="button"
241+
class="grid h-8 w-8 shrink-0 place-items-center rounded-md text-text-muted transition hover:bg-app-bg2 hover:text-text-primary"
242+
:aria-label="t('settings.close')"
243+
@click="showLegalModal = 'none'"
244+
>
245+
<X class="h-4 w-4" />
246+
</button>
247+
</header>
248+
<div class="px-5 py-8 text-center">
249+
<p class="text-sm leading-6 text-text-secondary">
250+
{{ showLegalModal === 'terms' ? t('auth.termsModalPlaceholder') : t('auth.privacyModalPlaceholder') }}
251+
</p>
252+
</div>
253+
<footer class="flex justify-end border-t border-app-border px-5 py-4">
254+
<button
255+
type="button"
256+
class="rounded-md border border-app-border bg-white px-3 py-2 text-sm font-medium text-text-secondary transition hover:text-text-primary"
257+
@click="showLegalModal = 'none'"
258+
>
259+
{{ t('settings.close') }}
260+
</button>
261+
</footer>
262+
</section>
263+
</div>
264+
228265
<footer class="relative z-10 px-5 py-8 text-center text-base font-medium text-[#667085]">
229266
© 2026 AetherFlow. All rights reserved.
230267
</footer>

frontend/src/pages/settings/SettingsPage.vue

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ const dataAccessCards = computed(() => [
316316
titleKey: 'settings.dataAccessUrl',
317317
detailKey: 'settings.dataAccessUrlHint',
318318
endpoint: `${runtimeEnv.apiBase}/ingestion/url`,
319-
status: 'disabled',
319+
status: 'coming-soon',
320320
value: t('settings.reserved'),
321321
valueLabelKey: 'settings.dataAccessState',
322322
icon: ExternalLink,
@@ -325,7 +325,7 @@ const dataAccessCards = computed(() => [
325325
titleKey: 'settings.dataAccessVectorStore',
326326
detailKey: 'settings.dataAccessVectorStoreHint',
327327
endpoint: `${runtimeEnv.apiBase}/knowledge/vector-stores`,
328-
status: 'disabled',
328+
status: 'coming-soon',
329329
value: t('settings.reserved'),
330330
valueLabelKey: 'settings.dataAccessState',
331331
icon: Server,
@@ -618,6 +618,9 @@ function statusBadgeClass(status: string) {
618618
if (status === 'available' || status === 'invited' || status === 'rotating') {
619619
return 'border-status-warning/30 bg-status-warning/10 text-status-warning'
620620
}
621+
if (status === 'coming-soon') {
622+
return 'border-primary/30 bg-primary-soft text-primary'
623+
}
621624
return 'border-status-paused/30 bg-status-paused/10 text-text-muted'
622625
}
623626
@@ -1136,10 +1139,20 @@ watch(
11361139
<article
11371140
v-for="card in dataAccessCards"
11381141
:key="card.titleKey"
1139-
class="rounded-xl border border-app-border bg-white p-4 shadow-sm transition hover:border-primary/40 hover:shadow-node"
1142+
class="relative rounded-xl border border-app-border bg-white p-4 shadow-sm transition hover:border-primary/40 hover:shadow-node"
1143+
:class="{ 'opacity-75': card.status === 'coming-soon' }"
11401144
>
1145+
<span
1146+
v-if="card.status === 'coming-soon'"
1147+
class="absolute right-3 top-3 rounded-full border border-primary/25 bg-primary-soft px-2 py-0.5 text-[11px] font-medium text-primary"
1148+
>
1149+
{{ t('settings.comingSoon') }}
1150+
</span>
11411151
<div class="flex items-start justify-between gap-3">
1142-
<span class="grid h-10 w-10 shrink-0 place-items-center rounded-lg bg-primary-soft text-primary">
1152+
<span
1153+
class="grid h-10 w-10 shrink-0 place-items-center rounded-lg"
1154+
:class="card.status === 'coming-soon' ? 'bg-primary-soft/60 text-primary/60' : 'bg-primary-soft text-primary'"
1155+
>
11431156
<component :is="card.icon" class="h-4 w-4" />
11441157
</span>
11451158
<span class="rounded-full border px-2 py-0.5 text-xs font-medium" :class="statusBadgeClass(card.status)">

0 commit comments

Comments
 (0)