fix(docker): добавить переменную окружения для внутреннего URL бэкенда
Docker images / prepare-release (push) Successful in 6s
Docker images / backend-image (push) Successful in 1m34s
Docker images / frontend-image (push) Successful in 1m38s
Docker images / updater-image (push) Successful in 37s
Docker images / notify-webhook (push) Has been skipped
Docker images / publish-release (push) Successful in 6s
Docker images / prepare-release (push) Successful in 6s
Docker images / backend-image (push) Successful in 1m34s
Docker images / frontend-image (push) Successful in 1m38s
Docker images / updater-image (push) Successful in 37s
Docker images / notify-webhook (push) Has been skipped
Docker images / publish-release (push) Successful in 6s
This commit is contained in:
@@ -40,6 +40,7 @@ ENV NODE_ENV=production
|
|||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
ENV HOSTNAME=0.0.0.0
|
ENV HOSTNAME=0.0.0.0
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
|
ENV BACKEND_INTERNAL_URL=http://backend:8000
|
||||||
COPY --from=build /app/public ./public
|
COPY --from=build /app/public ./public
|
||||||
COPY --from=build /app/.next/standalone ./
|
COPY --from=build /app/.next/standalone ./
|
||||||
COPY --from=build /app/.next/static ./.next/static
|
COPY --from=build /app/.next/static ./.next/static
|
||||||
|
|||||||
@@ -751,8 +751,8 @@ function RunRowDetail({ r }: { r: SchedulerRunRowDto }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function DataCollectionPage() {
|
export default function DataCollectionPage() {
|
||||||
const { mode, backendUrl } = useDataSource()
|
const { mode, backendUrl, prefsHydrated } = useDataSource()
|
||||||
const isLive = mode === "live"
|
const isLive = prefsHydrated && mode === "live"
|
||||||
const apiFetch = useMemo(() => makeApiFetch(backendUrl), [backendUrl])
|
const apiFetch = useMemo(() => makeApiFetch(backendUrl), [backendUrl])
|
||||||
|
|
||||||
const [trafficCollector, setTrafficCollector] = useState<CollectorSettingsDto | null>(null)
|
const [trafficCollector, setTrafficCollector] = useState<CollectorSettingsDto | null>(null)
|
||||||
@@ -1003,7 +1003,18 @@ export default function DataCollectionPage() {
|
|||||||
|
|
||||||
<div className="flex-1 overflow-y-auto p-6">
|
<div className="flex-1 overflow-y-auto p-6">
|
||||||
<div className="flex flex-col gap-5 max-w-[1100px] mx-auto w-full">
|
<div className="flex flex-col gap-5 max-w-[1100px] mx-auto w-full">
|
||||||
{!isLive && (
|
{!prefsHydrated && (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-base">Загрузка настроек подключения</CardTitle>
|
||||||
|
<CardDescription className="text-xs">
|
||||||
|
Читаем режим данных и адрес API из локальных настроек.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{prefsHydrated && !isLive && (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-base">Нужен live-режим</CardTitle>
|
<CardTitle className="text-base">Нужен live-режим</CardTitle>
|
||||||
|
|||||||
@@ -18,8 +18,12 @@ services:
|
|||||||
image: git.shts.su/denozord/mikrotikmanager-frontend:latest
|
image: git.shts.su/denozord/mikrotikmanager-frontend:latest
|
||||||
container_name: mmapp-frontend
|
container_name: mmapp-frontend
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
BACKEND_INTERNAL_URL: http://backend:8000
|
||||||
labels:
|
labels:
|
||||||
mmapp.updater.managed: "true"
|
mmapp.updater.managed: "true"
|
||||||
mmapp.updater.target: frontend
|
mmapp.updater.target: frontend
|
||||||
|
|||||||
+12
-5
@@ -59,9 +59,13 @@ function normalizeBackendUrl(url: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function DataSourceProvider({ children }: { children: React.ReactNode }) {
|
export function DataSourceProvider({ children }: { children: React.ReactNode }) {
|
||||||
const [mode, setModeState] = useState<DataSourceMode>(defaultDataSourceMode)
|
const [mode, setModeState] = useState<DataSourceMode>(() =>
|
||||||
const [backendUrl, setBackendUrlState] = useState(LOCAL_DEFAULT_BACKEND_URL)
|
typeof window === "undefined" ? defaultDataSourceMode() : readStoredMode(),
|
||||||
const [prefsHydrated, setPrefsHydrated] = useState(false)
|
)
|
||||||
|
const [backendUrl, setBackendUrlState] = useState(() =>
|
||||||
|
typeof window === "undefined" ? LOCAL_DEFAULT_BACKEND_URL : readStoredBackendUrl(),
|
||||||
|
)
|
||||||
|
const [prefsHydrated, setPrefsHydrated] = useState(() => typeof window !== "undefined")
|
||||||
const [backendStatus, setBackendStatus] = useState<boolean | undefined>(undefined)
|
const [backendStatus, setBackendStatus] = useState<boolean | undefined>(undefined)
|
||||||
const backendUrlLocked = isBackendUrlLocked()
|
const backendUrlLocked = isBackendUrlLocked()
|
||||||
const mockModeAvailable = isMockDataSourceAvailable()
|
const mockModeAvailable = isMockDataSourceAvailable()
|
||||||
@@ -91,9 +95,12 @@ export function DataSourceProvider({ children }: { children: React.ReactNode })
|
|||||||
}, [backendUrlLocked])
|
}, [backendUrlLocked])
|
||||||
|
|
||||||
const checkBackend = useCallback(async () => {
|
const checkBackend = useCallback(async () => {
|
||||||
const url = normalizeBackendUrl(backendUrl)
|
const healthUrl =
|
||||||
|
configuredBackendUrl().kind === "same-origin"
|
||||||
|
? "/health"
|
||||||
|
: `${normalizeBackendUrl(backendUrl)}/health`
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${url}/health`, { signal: AbortSignal.timeout(3000) })
|
const res = await fetch(healthUrl, { signal: AbortSignal.timeout(3000) })
|
||||||
setBackendStatus(res.ok)
|
setBackendStatus(res.ok)
|
||||||
} catch {
|
} catch {
|
||||||
setBackendStatus(false)
|
setBackendStatus(false)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { configuredBackendUrl } from "@/lib/backend-url"
|
||||||
|
|
||||||
export class ApiClientError extends Error {
|
export class ApiClientError extends Error {
|
||||||
constructor(
|
constructor(
|
||||||
message: string,
|
message: string,
|
||||||
@@ -13,13 +15,20 @@ function trimBaseUrl(baseUrl: string): string {
|
|||||||
return baseUrl.replace(/\/$/, "")
|
return baseUrl.replace(/\/$/, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveRequestUrl(baseUrl: string, path: string): string {
|
||||||
|
if (path.startsWith("/") && configuredBackendUrl().kind === "same-origin") {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
return trimBaseUrl(baseUrl) + path
|
||||||
|
}
|
||||||
|
|
||||||
export async function requestJson<T>(
|
export async function requestJson<T>(
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
path: string,
|
path: string,
|
||||||
init?: RequestInit,
|
init?: RequestInit,
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const hasBody = init?.body != null
|
const hasBody = init?.body != null
|
||||||
const res = await fetch(trimBaseUrl(baseUrl) + path, {
|
const res = await fetch(resolveRequestUrl(baseUrl, path), {
|
||||||
...init,
|
...init,
|
||||||
headers: {
|
headers: {
|
||||||
...(hasBody ? { "Content-Type": "application/json" } : {}),
|
...(hasBody ? { "Content-Type": "application/json" } : {}),
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user