Compare commits
2 Commits
932033682d
...
a482828244
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a482828244 | ||
|
|
8ba41b06c6 |
@ -6,6 +6,6 @@ DB_PORT=5432
|
|||||||
DB_NAME=
|
DB_NAME=
|
||||||
PORT=5000
|
PORT=5000
|
||||||
JWT_SECRET=change-me
|
JWT_SECRET=change-me
|
||||||
ALLOWED_ORIGINS=http://localhost:3000
|
ALLOWED_ORIGINS=http://localhost:3010,http://127.0.0.1:3010,http://192.168.7.45:3010
|
||||||
SESSION_COOKIE_NAME=sid
|
SESSION_COOKIE_NAME=sid
|
||||||
SESSION_TTL_DAYS=30
|
SESSION_TTL_DAYS=30
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
VITE_API_URL=http://localhost:5000
|
# Leave blank to infer the API host from the browser URL, e.g. http://192.168.7.45:5000.
|
||||||
VITE_ALLOWED_HOSTS=localhost,127.0.0.1
|
VITE_API_URL=
|
||||||
|
VITE_ALLOWED_HOSTS=localhost,127.0.0.1,192.168.7.45
|
||||||
|
|||||||
@ -1 +1,41 @@
|
|||||||
export const API_BASE_URL = import.meta.env.VITE_API_URL || "http://localhost:5000";
|
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "::1"]);
|
||||||
|
|
||||||
|
function trimTrailingSlash(value: string) {
|
||||||
|
return value.replace(/\/+$/, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultApiBaseUrl() {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return "http://localhost:5000";
|
||||||
|
}
|
||||||
|
|
||||||
|
const protocol = window.location.protocol === "https:" ? "https:" : "http:";
|
||||||
|
return `${protocol}//${window.location.hostname}:5000`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldUseBrowserHostForApi(url: URL) {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LOOPBACK_HOSTS.has(url.hostname) && !LOOPBACK_HOSTS.has(window.location.hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveApiBaseUrl() {
|
||||||
|
const configuredApiUrl = import.meta.env.VITE_API_URL?.trim();
|
||||||
|
if (!configuredApiUrl) {
|
||||||
|
return getDefaultApiBaseUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const apiUrl = new URL(configuredApiUrl);
|
||||||
|
if (shouldUseBrowserHostForApi(apiUrl)) {
|
||||||
|
apiUrl.hostname = window.location.hostname;
|
||||||
|
}
|
||||||
|
return trimTrailingSlash(apiUrl.toString());
|
||||||
|
} catch {
|
||||||
|
return trimTrailingSlash(configuredApiUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const API_BASE_URL = resolveApiBaseUrl();
|
||||||
|
|||||||
@ -1200,7 +1200,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.location-map-toolbar {
|
.location-map-toolbar {
|
||||||
--location-map-mode-slot: 168px;
|
--location-map-mode-slot: 132px;
|
||||||
--location-map-history-slot: 84px;
|
--location-map-history-slot: 84px;
|
||||||
column-gap: 0.15rem;
|
column-gap: 0.15rem;
|
||||||
row-gap: 0.35rem;
|
row-gap: 0.35rem;
|
||||||
@ -1219,13 +1219,6 @@
|
|||||||
min-width: 28px;
|
min-width: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.location-map-toolbar.has-history-slot .location-map-zoom-controls {
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
width: 100%;
|
|
||||||
justify-self: stretch;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.location-map-display-controls {
|
.location-map-display-controls {
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1443,8 +1443,8 @@ test("mobile keeps viewing draft status compact in the topbar", async ({ page })
|
|||||||
expect(statusBox.y).toBeLessThan(titleBox.y + titleBox.height);
|
expect(statusBox.y).toBeLessThan(titleBox.y + titleBox.height);
|
||||||
expect(statusBox.x).toBeGreaterThan(titleBox.x);
|
expect(statusBox.x).toBeGreaterThan(titleBox.x);
|
||||||
expect(toolbarBox.height).toBeLessThanOrEqual(64);
|
expect(toolbarBox.height).toBeLessThanOrEqual(64);
|
||||||
expect(modeBox.width).toBeGreaterThanOrEqual(166);
|
expect(modeBox.width).toBeGreaterThanOrEqual(130);
|
||||||
expect(modeBox.width).toBeLessThanOrEqual(172);
|
expect(modeBox.width).toBeLessThanOrEqual(136);
|
||||||
await expect(historyActions).toHaveCount(0);
|
await expect(historyActions).toHaveCount(0);
|
||||||
expect(zoomBox.y).toBeLessThan(modeBox.y + modeBox.height);
|
expect(zoomBox.y).toBeLessThan(modeBox.y + modeBox.height);
|
||||||
expect(zoomBox.x).toBeGreaterThan(modeBox.x + modeBox.width - 1);
|
expect(zoomBox.x).toBeGreaterThan(modeBox.x + modeBox.width - 1);
|
||||||
@ -1470,13 +1470,14 @@ test("mobile keeps viewing draft status compact in the topbar", async ({ page })
|
|||||||
expect(Math.abs(editModeBox.x - modeBox.x)).toBeLessThanOrEqual(1);
|
expect(Math.abs(editModeBox.x - modeBox.x)).toBeLessThanOrEqual(1);
|
||||||
expect(Math.abs(editModeGroupBox.width - modeGroupBox.width)).toBeLessThanOrEqual(1);
|
expect(Math.abs(editModeGroupBox.width - modeGroupBox.width)).toBeLessThanOrEqual(1);
|
||||||
expect(Math.abs(editModeBox.width - modeBox.width)).toBeLessThanOrEqual(1);
|
expect(Math.abs(editModeBox.width - modeBox.width)).toBeLessThanOrEqual(1);
|
||||||
expect(editModeBox.width).toBeGreaterThanOrEqual(166);
|
expect(editToolbarBox.height).toBeLessThanOrEqual(64);
|
||||||
expect(editModeBox.width).toBeLessThanOrEqual(172);
|
expect(editModeBox.width).toBeGreaterThanOrEqual(130);
|
||||||
|
expect(editModeBox.width).toBeLessThanOrEqual(136);
|
||||||
expect(editHistoryBox.width).toBeGreaterThanOrEqual(82);
|
expect(editHistoryBox.width).toBeGreaterThanOrEqual(82);
|
||||||
expect(editHistoryBox.x).toBeGreaterThan(editModeBox.x + editModeBox.width);
|
expect(editHistoryBox.x).toBeGreaterThan(editModeBox.x + editModeBox.width);
|
||||||
expect(editHistoryBox.x + editHistoryBox.width).toBeLessThanOrEqual(editToolbarBox.x + editToolbarBox.width + 1);
|
expect(editHistoryBox.x + editHistoryBox.width).toBeLessThanOrEqual(editToolbarBox.x + editToolbarBox.width + 1);
|
||||||
expect(editZoomBox.y).toBeGreaterThan(editModeBox.y + editModeBox.height - 1);
|
expect(editZoomBox.y).toBeLessThan(editModeBox.y + editModeBox.height);
|
||||||
expect(editZoomBox.x).toBeGreaterThanOrEqual(editToolbarBox.x);
|
expect(editZoomBox.x).toBeGreaterThan(editHistoryBox.x + editHistoryBox.width - 1);
|
||||||
expect(editZoomBox.x + editZoomBox.width).toBeLessThanOrEqual(editToolbarBox.x + editToolbarBox.width + 1);
|
expect(editZoomBox.x + editZoomBox.width).toBeLessThanOrEqual(editToolbarBox.x + editToolbarBox.width + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1582,8 +1583,8 @@ test("narrow mobile toolbar keeps map controls tappable without overflow", async
|
|||||||
|
|
||||||
expect(toolbarBox.x).toBeGreaterThanOrEqual(0);
|
expect(toolbarBox.x).toBeGreaterThanOrEqual(0);
|
||||||
expect(toolbarBox.x + toolbarBox.width).toBeLessThanOrEqual(361);
|
expect(toolbarBox.x + toolbarBox.width).toBeLessThanOrEqual(361);
|
||||||
expect(modeBox.width).toBeGreaterThanOrEqual(166);
|
expect(modeBox.width).toBeGreaterThanOrEqual(130);
|
||||||
expect(modeBox.width).toBeLessThanOrEqual(172);
|
expect(modeBox.width).toBeLessThanOrEqual(136);
|
||||||
expect(modeBox.x + modeBox.width).toBeLessThanOrEqual(historyBox.x);
|
expect(modeBox.x + modeBox.width).toBeLessThanOrEqual(historyBox.x);
|
||||||
expect(zoomBox.y).toBeGreaterThan(modeBox.y + modeBox.height - 1);
|
expect(zoomBox.y).toBeGreaterThan(modeBox.y + modeBox.height - 1);
|
||||||
expect(zoomBox.x).toBeGreaterThanOrEqual(toolbarBox.x);
|
expect(zoomBox.x).toBeGreaterThanOrEqual(toolbarBox.x);
|
||||||
|
|||||||
@ -2,9 +2,12 @@ import react from '@vitejs/plugin-react';
|
|||||||
import { defineConfig, loadEnv } from 'vite';
|
import { defineConfig, loadEnv } from 'vite';
|
||||||
|
|
||||||
const env = loadEnv('', process.cwd());
|
const env = loadEnv('', process.cwd());
|
||||||
const allowedHosts = env.VITE_ALLOWED_HOSTS
|
const configuredAllowedHosts = env.VITE_ALLOWED_HOSTS
|
||||||
? env.VITE_ALLOWED_HOSTS.split(',').map((host) => host.trim())
|
? env.VITE_ALLOWED_HOSTS.split(',').map((host) => host.trim())
|
||||||
: [];
|
: [];
|
||||||
|
const allowedHosts = Array.from(
|
||||||
|
new Set(['localhost', '127.0.0.1', '192.168.7.45', ...configuredAllowedHosts].filter(Boolean))
|
||||||
|
);
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user