Merge branch 'dev' into 'main'

Dev to main

See merge request spatial/postamates_frontend!74
dev
Timofey Malinin 2 years ago
commit a67d69d2e1

@ -1 +1,4 @@
VITE_API_URL=https://postnet.dev.selftech.ru
VITE_KEYCLOAK_CLIENT_ID=postnet
VITE_KEYCLOAK_CLIENT_SECRET=K2yHweEUispkVeWn03VMk843sW2Moic5
VITE_KEYCLOAK_URL=https://kk.dev.selftech.ru/

@ -17,8 +17,13 @@ build-docker-dev:
docker build
--build-arg YC_CONTAINER_REGISTRY=${YC_CONTAINER_REGISTRY}
--build-arg VITE_API_URL="https://postnet.dev.selftech.ru"
--build-arg VITE_KEYCLOAK_CLIENT_ID="postnet"
--build-arg VITE_KEYCLOAK_CLIENT_SECRET=${VITE_KEYCLOAK_CLIENT_SECRET}
--build-arg VITE_KEYCLOAK_URL="https://kk.dev.selftech.ru/"
-t ${DOCKER_IMAGE_TAG}-dev .
- docker push ${DOCKER_IMAGE_TAG}-dev
environment:
name: dev
build-docker-prod:
stage: build
@ -29,8 +34,13 @@ build-docker-prod:
docker build
--build-arg YC_CONTAINER_REGISTRY=${YC_CONTAINER_REGISTRY}
--build-arg VITE_API_URL="https://postnet.selftech.ru"
--build-arg VITE_KEYCLOAK_CLIENT_ID=""
--build-arg VITE_KEYCLOAK_CLIENT_SECRET=${VITE_KEYCLOAK_CLIENT_SECRET}
--build-arg VITE_KEYCLOAK_URL=""
-t ${DOCKER_IMAGE_TAG}-prod .
- docker push ${DOCKER_IMAGE_TAG}-prod
environment:
name: prod
auto-deploy-dev-kuber:
extends: .deploy_base_kuber

@ -1,6 +1,9 @@
ARG YC_CONTAINER_REGISTRY
FROM ${YC_CONTAINER_REGISTRY}/public/node:16 as builder
ARG VITE_API_URL
ARG VITE_KEYCLOAK_CLIENT_ID
ARG VITE_KEYCLOAK_CLIENT_SECRET
ARG VITE_KEYCLOAK_URL
WORKDIR /usr/src/postamates_frontend
ENV NODE_OPTIONS=--max_old_space_size=4096
COPY package*.json ./

@ -1,13 +1,16 @@
import { Points } from "./Points";
import { Layer, Source } from "react-map-gl";
import { aoLayer, rayonLayer } from "./layers-config";
import { BASE_URL } from "../../api";
import { PVZ } from "./PVZ";
import { OtherPostamates } from "./OtherPostamates";
import { SelectedRegion } from "./SelectedRegion";
import { transliterate } from "../../utils.js";
import {Points} from "./Points";
import {Layer, Source} from "react-map-gl";
import {aoLayer, rayonLayer} from "./layers-config";
import {BASE_URL} from "../../api";
import {PVZ} from "./PVZ";
import {OtherPostamates} from "./OtherPostamates";
import {SelectedRegion} from "./SelectedRegion";
import {transliterate} from "../../utils.js";
import {useUpdateLayerCounter} from "../../stores/useUpdateLayerCounter.js";
export const Layers = ({ postGroups, otherGroups }) => {
const { updateCounter } = useUpdateLayerCounter();
return (
<>
<Source
@ -42,6 +45,7 @@ export const Layers = ({ postGroups, otherGroups }) => {
<Source
id="pvz"
key={`pvz-${updateCounter}`}
type="vector"
tiles={[`${BASE_URL}/martin/public.service_post_and_pvz/{z}/{x}/{y}.pbf`]}
>
@ -58,6 +62,7 @@ export const Layers = ({ postGroups, otherGroups }) => {
<Source
id="other"
key={`other-${updateCounter}`}
type="vector"
tiles={[`${BASE_URL}/martin/public.service_otherobjects/{z}/{x}/{y}.pbf`]}
>

@ -5,15 +5,16 @@ import { setAuth } from "./stores/auth";
import { useQuery } from "@tanstack/react-query";
import { Title } from "./components/Title";
export function SignOut() {
const logOut = async () => {
await api.post("accounts/logout/");
setAuth(false);
};
export const logOut = () => {
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
localStorage.removeItem('expires_in');
setAuth(false);
};
export function SignOut() {
const { data } = useQuery(["profile"], async () => {
const { data } = await api.get("/accounts/profile/");
const { data } = await api.get("/api/me/");
return data;
});
@ -22,7 +23,7 @@ export function SignOut() {
<Popover
content={
<>
<Title text={data?.email} classNameText={"lowercase"} />
<Title text={data?.username} classNameText={"lowercase"} />
<Button type="primary" block onClick={logOut}>
<span className="mr-1">Выйти</span>
<ArrowRightOutlined />

@ -15,9 +15,15 @@ export const api = axios.create({
import.meta.env.MODE === "development"
? "http://localhost:5173/"
: BASE_URL,
withCredentials: true,
xsrfHeaderName: "X-CSRFToken",
xsrfCookieName: "csrftoken",
});
api.interceptors.request.use(function (config) {
const token = localStorage.getItem("access_token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
export const useDbTableName = () => {
@ -215,7 +221,7 @@ export const useGetPermissions = () => {
return useQuery(["permissions"], async () => {
const { data } = await api.get("/api/me/");
if (data?.groups?.includes("Редактор")) {
if (data?.groups?.includes("postnet_editor")) {
return "editor";
}
@ -332,7 +338,7 @@ export const useGetPendingPointsRange = (dbTable) => {
const rangesArr = RANGE_FILTERS_KEYS.map((key) => {
if ((/d[0-9]/.test(key))) return;
return {
[key]: [Math.floor(data[key][0]), Math.min(Math.ceil(data[key][1]), 4000)]
[key]: [Math.floor(data[key][0]), Math.ceil(data[key][1])]
}
}).filter(item => !!item);
const ranges = Object.assign({}, ...rangesArr);

@ -26,9 +26,10 @@ export const PointsFileUploadModal = ({onClose, isOpened}) => {
const myInterval = setInterval(async () => {
const response = await getImportStatus();
setImportStatus(response.task_status);
if (response.task_status === "Перерасчет ML завершен") {
if (response.task_status === "Перерасчет ML завершен" || !isOpened) {
setReport(response.data);
setIsImporting(false);
toggleUpdateCounter();
clearInterval(myInterval);
}
}, 2000);
@ -68,13 +69,6 @@ export const PointsFileUploadModal = ({onClose, isOpened}) => {
</Button>
]
return [
<Button
key="close-button"
type="default"
onClick={onClose}
>
Отмена
</Button>,
<Button
key="ok-button"
type="primary"
@ -112,7 +106,7 @@ export const PointsFileUploadModal = ({onClose, isOpened}) => {
<Modal
open={isOpened}
title="Импорт точек"
onCancel={onClose}
onCancel={() => {if (!isImporting) onClose()}}
width={400}
footer={getFooter()}
>

@ -32,8 +32,8 @@ export const PendingPointsFilters = () => {
setFilterWithKey(newRanges[key], key);
return;
}
const gtChanged = ranges[key][0] !== newRanges[key][0];
const ltChanged = ranges[key][1] !== newRanges[key][1];
const gtChanged = ranges[key] && newRanges[key] && ranges[key][0] !== newRanges[key][0];
const ltChanged = ranges[key] && newRanges[key] && ranges[key][1] !== newRanges[key][1];
if (gtChanged || ltChanged) setFilterWithKey(newRanges[key], key);
});

@ -3,15 +3,25 @@ import { Alert, Button, Form, Input, Space, Typography } from "antd";
import { LockOutlined, UserOutlined } from "@ant-design/icons";
import React from "react";
import { Navigate } from "react-router-dom";
import { isAuthorized$ } from "../stores/auth";
import { isAuthorized$, refreshTokenIntervalFunction, setAuthLocalStorage } from "../stores/auth";
import { signin, signinError$, signinLoading$ } from "../stores/signin";
function LoginForm() {
const signinError = useStore(signinError$);
const signinLoading = useStore(signinLoading$);
const onFinish = (values) => {
signin(values);
const onFinish = async (values) => {
const data = await signin(values);
setAuthLocalStorage(data);
let interval;
setTimeout(async () => {
await refreshTokenIntervalFunction();
interval = setInterval(async () => {
await refreshTokenIntervalFunction();
}, (data.expires_in - 5) * 1000)
}, 0);
};
return (

@ -1,5 +1,6 @@
import { action, atom } from "nanostores";
import { api } from "../api";
import { logOut } from "../SignOut.jsx";
export const userInfoLoading$ = atom(true);
@ -9,13 +10,63 @@ export const setAuth = action(isAuthorized$, "setAuth", (store, newValue) => {
store.set(newValue);
});
export const refreshToken = () => {
const url = import.meta.env.VITE_KEYCLOAK_URL || 'https://kk.dev.selftech.ru/';
const clientId = import.meta.env.VITE_KEYCLOAK_CLIENT_ID || 'postnet';
const clientSecret = import.meta.env.VITE_KEYCLOAK_CLIENT_SECRET || 'K2yHweEUispkVeWn03VMk843sW2Moic5';
return api.request({
url: "/realms/SST/protocol/openid-connect/token",
baseURL: url,
method: "POST",
data: {
grant_type: "refresh_token",
client_id: clientId,
client_secret: clientSecret,
token_type: "bearer",
refresh_token: localStorage.getItem("refresh_token")
},
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
});
}
export const setAuthLocalStorage = (data) => {
localStorage.setItem("access_token", data.access_token);
localStorage.setItem("refresh_token", data.refresh_token);
localStorage.setItem("expires_in", data.expires_in);
}
export const refreshTokenIntervalFunction = async () => {
try {
const { data: refreshData } = await refreshToken();
setAuthLocalStorage(refreshData);
} catch (error) {
clearInterval(interval);
logOut();
throw error;
}
}
async function checkAuth() {
try {
await api.get("/accounts/profile/");
const { data } = await refreshToken();
setAuthLocalStorage(data);
let interval;
setTimeout(async () => {
await refreshTokenIntervalFunction();
interval = setInterval(async () => {
await refreshTokenIntervalFunction();
}, (data.expires_in - 5) * 1000)
}, 0);
setAuth(true);
} catch (e) {
console.log("Not authorized");
clearInterval(interval);
} finally {
userInfoLoading$.set(false);
}

@ -31,8 +31,30 @@ export async function signin(values) {
signinLoading$.set(true);
signinError$.set("");
const url = import.meta.env.VITE_KEYCLOAK_URL || 'https://kk.dev.selftech.ru/';
const clientId = import.meta.env.VITE_KEYCLOAK_CLIENT_ID || 'postnet';
const clientSecret = import.meta.env.VITE_KEYCLOAK_CLIENT_SECRET || 'K2yHweEUispkVeWn03VMk843sW2Moic5';
const auth = () => {
return api.request({
url: "/realms/SST/protocol/openid-connect/token",
baseURL: url,
method: "POST",
data: {
"grant_type": "password",
client_id: clientId,
client_secret: clientSecret,
username: values.login,
password: values.password,
},
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
});
}
try {
const { data } = await api.post("accounts/login/", values);
const { data } = await auth();
setAuth(true);
return data;
@ -50,8 +72,6 @@ export async function signin(values) {
}
}
export const resetSignin = function () {};
export const signupLoading$ = atom(false);
export const signupError$ = atom("");

@ -11,8 +11,8 @@ export default defineConfig(({ mode }) => {
plugins: [svgr(), react()],
server: {
proxy: {
"/account": env.VITE_API_URL,
"/api": env.VITE_API_URL,
"/realms": "https://kk.dev.selftech.ru/",
},
},
css: {

Loading…
Cancel
Save