fix: Delete ai comments

This commit is contained in:
2025-11-06 00:58:10 +03:00
parent 5298fb9f60
commit 1917b2cf5a
41 changed files with 203 additions and 1107 deletions

View File

@@ -171,7 +171,6 @@ class CarrierStore {
this.carriers[language].data.push(response.data);
});
// Create translations for other languages
for (const lang of ["ru", "en", "zh"].filter((l) => l !== language)) {
const patchPayload = {
// @ts-ignore

View File

@@ -1,4 +1,3 @@
// @shared/stores/createSightStore.ts
import {
articlesStore,
Language,
@@ -27,7 +26,6 @@ type SightLanguageInfo = {
};
type SightCommonInfo = {
// id: number; // ID is 0 until created
city_id: number;
city: string;
latitude: number;
@@ -35,13 +33,11 @@ type SightCommonInfo = {
thumbnail: string | null;
watermark_lu: string | null;
watermark_rd: string | null;
left_article: number; // Can be 0 or a real ID, or placeholder like 10000000
left_article: number;
preview_media: string | null;
video_preview: string | null;
};
// SightBaseInfo combines common info with language-specific info
// The 'id' for the sight itself will be assigned upon creation by the backend.
type SightBaseInfo = SightCommonInfo & {
[key in Language]: SightLanguageInfo;
};
@@ -78,7 +74,7 @@ const initialSightState: SightBaseInfo = {
};
class CreateSightStore {
sight: SightBaseInfo = JSON.parse(JSON.stringify(initialSightState)); // Deep copy for reset
sight: SightBaseInfo = JSON.parse(JSON.stringify(initialSightState));
uploadMediaOpen = false;
setUploadMediaOpen = (open: boolean) => {
@@ -93,9 +89,7 @@ class CreateSightStore {
makeAutoObservable(this);
}
// --- Right Article Management ---
createNewRightArticle = async () => {
// Create article in DB for all languages
const articleRuData = {
heading: "Новый заголовок (RU)",
body: "Новый текст (RU)",
@@ -125,7 +119,7 @@ class CreateSightStore {
},
},
});
const { id } = articleRes.data; // New article's ID
const { id } = articleRes.data;
runInAction(() => {
const newArticleEntry = { id, media: [] };
@@ -133,7 +127,7 @@ class CreateSightStore {
this.sight.en.right.push({ ...newArticleEntry, ...articleEnData });
this.sight.zh.right.push({ ...newArticleEntry, ...articleZhData });
});
return id; // Return ID for potential immediate use
return id;
} catch (error) {
console.error("Error creating new right article:", error);
throw error;
@@ -169,7 +163,7 @@ class CreateSightStore {
});
});
return articleId; // Return the linked article ID
return articleId;
} catch (error) {
console.error("Error linking existing right article:", error);
throw error;
@@ -188,9 +182,7 @@ class CreateSightStore {
}
};
// "Unlink" in create mode means just removing from the list to be created with the sight
unlinkRightAritcle = (articleId: number) => {
// Changed from 'unlinkRightAritcle' spelling
runInAction(() => {
this.sight.ru.right = this.sight.ru.right.filter(
(article) => article.id !== articleId
@@ -202,16 +194,12 @@ class CreateSightStore {
(article) => article.id !== articleId
);
});
// Note: If this article was created via createNewRightArticle, it still exists in the DB.
// Consider if an orphaned article should be deleted here or managed separately.
// For now, it just removes it from the list associated with *this specific sight creation process*.
};
deleteRightArticle = async (articleId: number) => {
try {
await authInstance.delete(`/article/${articleId}`); // Delete from backend
await authInstance.delete(`/article/${articleId}`);
runInAction(() => {
// Remove from local store for all languages
this.sight.ru.right = this.sight.ru.right.filter(
(article) => article.id !== articleId
);
@@ -228,12 +216,11 @@ class CreateSightStore {
}
};
// --- Right Article Media Management ---
createLinkWithRightArticle = async (media: MediaItem, articleId: number) => {
try {
await authInstance.post(`/article/${articleId}/media`, {
media_id: media.id,
media_order: 1, // Or calculate based on existing media.length + 1
media_order: 1,
});
runInAction(() => {
(["ru", "en", "zh"] as Language[]).forEach((lang) => {
@@ -242,7 +229,7 @@ class CreateSightStore {
);
if (article) {
if (!article.media) article.media = [];
article.media.unshift(media); // Add to the beginning
article.media.unshift(media);
}
});
});
@@ -273,7 +260,6 @@ class CreateSightStore {
}
};
// --- Left Article Management (largely unchanged from your provided store) ---
updateLeftInfo = (language: Language, heading: string, body: string) => {
this.sight[language].left.heading = heading;
this.sight[language].left.body = body;
@@ -323,7 +309,7 @@ class CreateSightStore {
deleteLeftArticle = async (articleId: number) => {
/* ... your existing logic ... */
await authInstance.delete(`/article/${articleId}`);
// articlesStore.getArticles(languageStore.language); // If still neede
runInAction(() => {
articlesStore.articles.ru = articlesStore.articles.ru.filter(
(article) => article.id !== articleId
@@ -344,7 +330,6 @@ class CreateSightStore {
const enName = (this.sight.en.name || "").trim();
const zhName = (this.sight.zh.name || "").trim();
// If all names are empty, skip defaulting and use empty headings
const hasAnyName = !!(ruName || enName || zhName);
const response = await languageInstance("ru").post("/article", {
@@ -363,7 +348,7 @@ class CreateSightStore {
});
runInAction(() => {
this.sight.left_article = newLeftArticleId; // Store the actual ID
this.sight.left_article = newLeftArticleId;
this.sight.ru.left = {
heading: hasAnyName ? ruName : "",
body: "",
@@ -402,9 +387,8 @@ class CreateSightStore {
return newLeftArticleId;
};
// Placeholder for a "new" unsaved left article
setNewLeftArticlePlaceholder = () => {
this.sight.left_article = 10000000; // Special placeholder ID
this.sight.left_article = 10000000;
this.sight.ru.left = {
heading: "Новая левая статья",
body: "Заполните контентом",
@@ -422,7 +406,6 @@ class CreateSightStore {
};
};
// --- Sight Preview Media ---
linkPreviewMedia = (mediaId: string) => {
this.sight.preview_media = mediaId;
};
@@ -431,32 +414,27 @@ class CreateSightStore {
this.sight.preview_media = null;
};
// --- General Store Methods ---
clearCreateSight = () => {
this.needLeaveAgree = false;
this.sight = JSON.parse(JSON.stringify(initialSightState)); // Reset to initial
this.sight = JSON.parse(JSON.stringify(initialSightState));
};
updateSightInfo = (
content: Partial<SightLanguageInfo | SightCommonInfo>, // Corrected types
content: Partial<SightLanguageInfo | SightCommonInfo>,
language?: Language
) => {
this.needLeaveAgree = true;
if (language) {
this.sight[language] = { ...this.sight[language], ...content };
} else {
// Assuming content here is for SightCommonInfo
this.sight = { ...this.sight, ...(content as Partial<SightCommonInfo>) };
}
};
// --- Main Sight Creation Logic ---
createSight = async (primaryLanguage: Language) => {
let finalLeftArticleId = this.sight.left_article;
// 1. Handle Left Article (Create if new, or use existing ID)
if (this.sight.left_article === 10000000) {
// Placeholder for new
const res = await languageInstance("ru").post("/article", {
heading: this.sight.ru.left.heading,
body: this.sight.ru.left.body,
@@ -474,7 +452,6 @@ class CreateSightStore {
this.sight.left_article !== 0 &&
this.sight.left_article !== null
) {
// Existing, ensure it's up-to-date
await languageInstance("ru").patch(
`/article/${this.sight.left_article}`,
{ heading: this.sight.ru.left.heading, body: this.sight.ru.left.body }
@@ -488,10 +465,7 @@ class CreateSightStore {
{ heading: this.sight.zh.left.heading, body: this.sight.zh.left.body }
);
}
// else: left_article is 0, so no left article
// 2. Right articles are already created in DB and their IDs are in this.sight[lang].right.
// We just need to update their content if changed before saving the sight.
for (const lang of ["ru", "en", "zh"] as Language[]) {
for (const article of this.sight[lang].right) {
if (article.id == 0 || article.id == null) {
@@ -501,14 +475,12 @@ class CreateSightStore {
heading: article.heading,
body: article.body,
});
// Media for these articles are already linked via createLinkWithRightArticle
}
}
const rightArticleIdsForLink = this.sight[primaryLanguage].right.map(
(a) => a.id
);
// 3. Create Sight object in DB
const sightPayload = {
city_id: this.sight.city_id,
city: this.sight.city,
@@ -528,9 +500,8 @@ class CreateSightStore {
"/sight",
sightPayload
);
const newSightId = response.data.id; // ID of the newly created sight
const newSightId = response.data.id;
// 4. Update other languages for the sight
const otherLanguages = (["ru", "en", "zh"] as Language[]).filter(
(l) => l !== primaryLanguage
);
@@ -551,20 +522,17 @@ class CreateSightStore {
});
}
// 5. Link Right Articles to the new Sight
for (let i = 0; i < rightArticleIdsForLink.length; i++) {
await authInstance.post(`/sight/${newSightId}/article`, {
article_id: rightArticleIdsForLink[i],
page_num: i + 1, // Or other logic for page_num
page_num: i + 1,
});
}
// Optionally: this.clearCreateSight(); // To reset form after successful creation
this.needLeaveAgree = false;
return newSightId;
};
// --- Media Upload (Generic, used by dialogs) ---
uploadMedia = async (
filename: string,
type: number,
@@ -583,12 +551,12 @@ class CreateSightStore {
this.fileToUpload = null;
this.uploadMediaOpen = false;
});
mediaStore.getMedia(); // Refresh global media list
mediaStore.getMedia();
return {
id: response.data.id,
filename: filename, // Or response.data.filename if backend returns it
media_name: media_name, // Or response.data.media_name
media_type: type, // Or response.data.type
filename: filename,
media_name: media_name,
media_type: type,
};
} catch (error) {
console.error("Error uploading media:", error);
@@ -596,15 +564,12 @@ class CreateSightStore {
}
};
// For Left Article Media
createLinkWithLeftArticle = async (media: MediaItem) => {
if (!this.sight.left_article || this.sight.left_article === 10000000) {
console.warn(
"Left article not selected or is a placeholder. Cannot link media yet."
);
// If it's a placeholder, we could store the media temporarily and link it after the article is created.
// For simplicity, we'll assume the article must exist.
// A more robust solution might involve creating the article first if it's a placeholder.
return;
}
try {
@@ -663,7 +628,7 @@ class CreateSightStore {
this.sight.ru.right = sortArticles(this.sight.ru.right);
this.sight.en.right = sortArticles(this.sight.en.right);
this.sight.zh.right = sortArticles(this.sight.zh.right); // теперь zh тоже сортируется одинаково
this.sight.zh.right = sortArticles(this.sight.zh.right);
this.needLeaveAgree = true;
};

View File

@@ -1,4 +1,3 @@
// @shared/stores/editSightStore.ts
import {
articlesStore,
authInstance,
@@ -96,13 +95,11 @@ class EditSightStore {
}
runInAction(() => {
// Обновляем языковую часть
this.sight[language] = {
...this.sight[language],
...data,
};
// Только при первом запросе обновляем общую часть
if (!this.hasLoadedCommon) {
this.sight.common = {
...this.sight.common,
@@ -123,7 +120,6 @@ class EditSightStore {
let responseEn = await languageInstance("en").get(`/sight/${id}/article`);
let responseZh = await languageInstance("zh").get(`/sight/${id}/article`);
// Create a map of article IDs to their media
const mediaMap = new Map();
for (const article of responseRu.data) {
const responseMedia = await authInstance.get(
@@ -132,7 +128,6 @@ class EditSightStore {
mediaMap.set(article.id, responseMedia.data);
}
// Function to add media to articles
const addMediaToArticles = (articles: any[]) => {
return articles.map((article) => ({
...article,
@@ -327,28 +322,6 @@ class EditSightStore {
articles: articleIdsInObject,
});
// await languageInstance("ru").patch(
// `/sight/${this.sight.common.left_article}/article`,
// {
// heading: this.sight.ru.left.heading,
// body: this.sight.ru.left.body,
// }
// );
// await languageInstance("en").patch(
// `/sight/${this.sight.common.left_article}/article`,
// {
// heading: this.sight.en.left.heading,
// body: this.sight.en.left.body,
// }
// );
// await languageInstance("zh").patch(
// `/sight/${this.sight.common.left_article}/article`,
// {
// heading: this.sight.zh.left.heading,
// body: this.sight.zh.left.body,
// }
// );
this.needLeaveAgree = false;
};
@@ -589,7 +562,7 @@ class EditSightStore {
});
});
return article_id; // Return the linked article ID
return article_id;
};
deleteRightArticleMedia = async (article_id: number, media_id: string) => {
@@ -695,7 +668,7 @@ class EditSightStore {
});
});
return id; // Return the ID of the newly created article
return id;
};
createLinkWithRightArticle = async (
@@ -770,7 +743,7 @@ class EditSightStore {
this.sight.ru.right = sortArticles(this.sight.ru.right);
this.sight.en.right = sortArticles(this.sight.en.right);
this.sight.zh.right = sortArticles(this.sight.zh.right); // теперь zh тоже сортируется одинаково
this.sight.zh.right = sortArticles(this.sight.zh.right);
this.needLeaveAgree = true;
};

View File

@@ -39,12 +39,11 @@ class MediaStore {
updateMedia = async (id: string, data: Partial<Media>) => {
const response = await authInstance.patch(`/media/${id}`, data);
runInAction(() => {
// Update in media array
const index = this.media.findIndex((m) => m.id === id);
if (index !== -1) {
this.media[index] = { ...this.media[index], ...response.data };
}
// Update oneMedia if it's the current media being viewed
if (this.oneMedia?.id === id) {
this.oneMedia = { ...this.oneMedia, ...response.data };
}
@@ -64,12 +63,11 @@ class MediaStore {
});
runInAction(() => {
// Update in media array
const index = this.media.findIndex((m) => m.id === id);
if (index !== -1) {
this.media[index] = { ...this.media[index], ...response.data };
}
// Update oneMedia if it's the current media being viewed
if (this.oneMedia?.id === id) {
this.oneMedia = { ...this.oneMedia, ...response.data };
}

View File

@@ -15,7 +15,6 @@ class ModelLoadingStore {
makeAutoObservable(this);
}
// Начать отслеживание загрузки модели
startLoading(modelId: string) {
this.loadingStates.set(modelId, {
isLoading: true,
@@ -25,7 +24,6 @@ class ModelLoadingStore {
});
}
// Обновить прогресс загрузки
updateProgress(modelId: string, progress: number) {
const state = this.loadingStates.get(modelId);
if (state) {
@@ -33,7 +31,6 @@ class ModelLoadingStore {
}
}
// Завершить загрузку модели
finishLoading(modelId: string) {
const state = this.loadingStates.get(modelId);
if (state) {
@@ -42,12 +39,10 @@ class ModelLoadingStore {
}
}
// Остановить загрузку (в случае ошибки)
stopLoading(modelId: string) {
this.loadingStates.delete(modelId);
}
// Обработать ошибку загрузки
handleError(modelId: string, error?: string) {
const state = this.loadingStates.get(modelId);
if (state) {
@@ -56,26 +51,22 @@ class ModelLoadingStore {
}
}
// Получить состояние загрузки для конкретной модели
getLoadingState(modelId: string): ModelLoadingState | undefined {
return this.loadingStates.get(modelId);
}
// Проверить, загружается ли какая-либо модель
get isAnyModelLoading(): boolean {
return Array.from(this.loadingStates.values()).some(
(state) => state.isLoading
);
}
// Получить все загружающиеся модели
get loadingModels(): ModelLoadingState[] {
return Array.from(this.loadingStates.values()).filter(
(state) => state.isLoading
);
}
// Получить общий прогресс всех загружающихся моделей
get overallProgress(): number {
const loadingModels = this.loadingModels;
if (loadingModels.length === 0) return 100;
@@ -87,12 +78,10 @@ class ModelLoadingStore {
return Math.round(totalProgress / loadingModels.length);
}
// Проверить, заблокировано ли сохранение (есть ли загружающиеся модели)
get isSaveBlocked(): boolean {
return this.isAnyModelLoading;
}
// Очистить все состояния загрузки
clearAll() {
this.loadingStates.clear();
}

View File

@@ -58,41 +58,6 @@ class SightsStore {
});
};
// getSight = async (id: number) => {
// const response = await authInstance.get(`/sight/${id}`);
// runInAction(() => {
// this.sight = response.data;
// editSightStore.sightInfo = {
// ...editSightStore.sightInfo,
// id: response.data.id,
// city_id: response.data.city_id,
// city: response.data.city,
// latitude: response.data.latitude,
// longitude: response.data.longitude,
// thumbnail: response.data.thumbnail,
// watermark_lu: response.data.watermark_lu,
// watermark_rd: response.data.watermark_rd,
// left_article: response.data.left_article,
// preview_media: response.data.preview_media,
// video_preview: response.data.video_preview,
// [languageStore.language]: {
// info: {
// name: response.data.name,
// address: response.data.address,
// },
// left: {
// heading: articlesStore.articles[languageStore.language].find(
// (article) => article.id === response.data.left_article
// )?.heading,
// body: articlesStore.articles[languageStore.language].find(
// },
// },
// };
// });
// };
createSightAction = async (
city: number,
coordinates: { latitude: number; longitude: number }
@@ -167,16 +132,12 @@ class SightsStore {
common: boolean
) => {
if (common) {
// @ts-ignore
this.sight!.common = {
// @ts-ignore
...this.sight!.common,
...content,
};
} else {
// @ts-ignore
this.sight![language] = {
// @ts-ignore
...this.sight![language],
...content,
};

View File

@@ -1,8 +1,6 @@
import { authInstance } from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
// Импорт функции сброса кешей карты
// import { clearMapCaches } from "../../pages/MapPage";
import {
articlesStore,
cityStore,
@@ -35,9 +33,7 @@ class SnapshotStore {
makeAutoObservable(this);
}
// Функция для сброса всех кешей в приложении
private clearAllCaches = () => {
// Сброс кешей статей
articlesStore.articleList = {
ru: { data: [], loaded: false },
en: { data: [], loaded: false },
@@ -47,7 +43,6 @@ class SnapshotStore {
articlesStore.articleData = null;
articlesStore.articleMedia = null;
// Сброс кешей городов
cityStore.cities = {
ru: { data: [], loaded: false },
en: { data: [], loaded: false },
@@ -56,21 +51,18 @@ class SnapshotStore {
cityStore.ruCities = { data: [], loaded: false };
cityStore.city = {};
// Сброс кешей стран
countryStore.countries = {
ru: { data: [], loaded: false },
en: { data: [], loaded: false },
zh: { data: [], loaded: false },
};
// Сброс кешей перевозчиков
carrierStore.carriers = {
ru: { data: [], loaded: false },
en: { data: [], loaded: false },
zh: { data: [], loaded: false },
};
// Сброс кешей станций
stationsStore.stationLists = {
ru: { data: [], loaded: false },
en: { data: [], loaded: false },
@@ -78,24 +70,18 @@ class SnapshotStore {
};
stationsStore.stationPreview = {};
// Сброс кешей достопримечательностей
sightsStore.sights = [];
sightsStore.sight = null;
// Сброс кешей маршрутов
routeStore.routes = { data: [], loaded: false };
// Сброс кешей транспорта
vehicleStore.vehicles = { data: [], loaded: false };
// Сброс кешей пользователей
userStore.users = { data: [], loaded: false };
// Сброс кешей медиа
mediaStore.media = [];
mediaStore.oneMedia = null;
// Сброс кешей создания и редактирования достопримечательностей
createSightStore.sight = JSON.parse(
JSON.stringify({
city_id: 0,
@@ -173,26 +159,21 @@ class SnapshotStore {
editSightStore.fileToUpload = null;
editSightStore.needLeaveAgree = false;
// Сброс кешей устройств
devicesStore.devices = [];
devicesStore.uuid = null;
devicesStore.sendSnapshotModalOpen = false;
// Сброс кешей авторизации (кроме токена)
authStore.payload = null;
authStore.error = null;
authStore.isLoading = false;
// Сброс кешей карты (если они загружены)
try {
// Сбрасываем кеши mapStore если он доступен
if (typeof window !== "undefined" && (window as any).mapStore) {
(window as any).mapStore.routes = [];
(window as any).mapStore.stations = [];
(window as any).mapStore.sights = [];
}
// Сбрасываем кеши MapService если он доступен
if (typeof window !== "undefined" && (window as any).mapServiceInstance) {
(window as any).mapServiceInstance.clearCaches();
}
@@ -200,7 +181,6 @@ class SnapshotStore {
console.warn("Не удалось сбросить кеши карты:", error);
}
// Сброс localStorage кешей (кроме токена авторизации)
const token = localStorage.getItem("token");
const rememberedEmail = localStorage.getItem("rememberedEmail");
const rememberedPassword = localStorage.getItem("rememberedPassword");
@@ -208,14 +188,12 @@ class SnapshotStore {
localStorage.clear();
sessionStorage.clear();
// Восстанавливаем важные данные
if (token) localStorage.setItem("token", token);
if (rememberedEmail)
localStorage.setItem("rememberedEmail", rememberedEmail);
if (rememberedPassword)
localStorage.setItem("rememberedPassword", rememberedPassword);
// Сброс кешей карты (если они есть)
const mapPositionKey = "mapPosition";
const activeSectionKey = "mapActiveSection";
if (localStorage.getItem(mapPositionKey)) {
@@ -225,7 +203,6 @@ class SnapshotStore {
localStorage.removeItem(activeSectionKey);
}
// Попытка очистить кеш браузера (если поддерживается)
if ("caches" in window) {
try {
caches.keys().then((cacheNames) => {
@@ -240,7 +217,6 @@ class SnapshotStore {
}
}
// Попытка очистить IndexedDB (если поддерживается)
if ("indexedDB" in window) {
try {
indexedDB.databases().then((databases) => {
@@ -284,10 +260,8 @@ class SnapshotStore {
};
restoreSnapshot = async (id: string) => {
// Сначала сбрасываем все кеши
this.clearAllCaches();
// Затем восстанавливаем снапшот
await authInstance.post(`/snapshots/${id}/restore`);
};

View File

@@ -7,7 +7,7 @@ type StationLanguageData = {
name: string;
system_name: string;
address: string;
loaded: boolean; // Indicates if this language's data has been loaded/modified
loaded: boolean;
};
type StationCommonData = {
@@ -92,7 +92,6 @@ class StationsStore {
},
};
// This will store the full station data, keyed by ID and then by language
stationPreview: Record<
string,
Record<string, { loaded: boolean; data: Station }>
@@ -264,7 +263,6 @@ class StationsStore {
};
};
// Sets language-specific station data
setLanguageEditStationData = (
language: Language,
data: Partial<StationLanguageData>
@@ -295,7 +293,7 @@ class StationsStore {
`/station/${id}`,
{
name: name || "",
system_name: name || "", // system_name is often derived from name
system_name: name || "",
description: description || "",
address: address || "",
...commonDataPayload,
@@ -303,7 +301,6 @@ class StationsStore {
);
runInAction(() => {
// Update the cached preview data and station lists after successful patch
if (this.stationPreview[id]) {
this.stationPreview[id][language] = {
loaded: true,
@@ -343,11 +340,11 @@ class StationsStore {
runInAction(() => {
this.stations = this.stations.filter((station) => station.id !== id);
// Also clear from stationPreview cache
if (this.stationPreview[id]) {
delete this.stationPreview[id];
}
// Clear from stationLists as well for all languages
for (const lang of ["ru", "en", "zh"] as const) {
if (this.stationLists[lang].data) {
this.stationLists[lang].data = this.stationLists[lang].data.filter(
@@ -421,12 +418,11 @@ class StationsStore {
delete commonDataPayload.icon;
}
// First create station in Russian
const { name, address } = this.createStationData[language];
const description = this.createStationData.common.description;
const response = await languageInstance(language).post("/station", {
name: name || "",
system_name: name || "", // system_name is often derived from name
system_name: name || "",
description: description || "",
address: address || "",
...commonDataPayload,
@@ -438,7 +434,6 @@ class StationsStore {
const stationId = response.data.id;
// Then update for other languages
for (const lang of ["ru", "en", "zh"].filter(
(lang) => lang !== language
) as Language[]) {
@@ -448,7 +443,7 @@ class StationsStore {
`/station/${stationId}`,
{
name: name || "",
system_name: name || "", // system_name is often derived from name
system_name: name || "",
description: description || "",
address: address || "",
...commonDataPayload,
@@ -507,7 +502,6 @@ class StationsStore {
return response.data;
};
// Reset editStationData when navigating away or after saving
resetEditStationData = () => {
this.editStationData = {
ru: {