From dc483d62de056f9dbdc5daae30b5a9a901777fde Mon Sep 17 00:00:00 2001 From: itoshi Date: Tue, 29 Apr 2025 22:10:50 +0300 Subject: [PATCH] added old preview components --- src/pages/media/ModelViewer/index.tsx | 5 +- src/pages/media/show.tsx | 2 +- src/pages/sight/edit.tsx | 456 ++-- .../AttractionShortPreview.css | 39 + .../AttractionShortPreview.tsx | 55 + .../AttractionWidget/AttractionWidget.css | 126 ++ .../AttractionWidget/AttractionWidget.tsx | 114 + .../media/AttractionMedia.css | 52 + .../media/AttractionMedia.tsx | 36 + .../AttractionWidget/media/ImageMedia.tsx | 25 + .../AttractionWidget/media/Object3DMedia.tsx | 52 + .../media/PhotoSphereMedia.tsx | 62 + .../AttractionWidget/media/VideoMedia.tsx | 26 + .../components/Drawer/Drawer.styles.tsx | 47 + src/preview/components/Drawer/Drawer.tsx | 53 + src/preview/components/Drawer/index.ts | 1 + .../components/MapWidget/MapWidgetContext.tsx | 274 +++ .../components/MapWidget/MapContent.tsx | 25 + .../components/MapWidget/MapWidget.module.css | 4 + .../components/MapWidget/MapWidget.tsx | 65 + .../MapWidget/components/MapWidget/index.ts | 1 + .../AttractionMarker.module.css | 41 + .../TrackAttractions/AttractionMarker.tsx | 40 + .../TrackAttractions/TrackAttractions.tsx | 25 + .../components/TrackAttractions/index.ts | 1 + .../MapWidget/components/TrackLine.tsx | 37 + .../components/TrackStations/StationLabel.tsx | 8 + .../TrackStations/StationLabelContent.tsx | 55 + .../TrackStations/StationLabelEdit.tsx | 63 + .../TrackStations/TrackStations.css | 68 + .../TrackStations/TrackStations.tsx | 71 + .../components/TrackStations/index.ts | 1 + .../TramMarker/TramMarker.module.css | 36 + .../components/TramMarker/TramMarker.tsx | 52 + .../MapWidget/components/TramMarker/index.ts | 1 + .../components/MapWidget/components/index.ts | 5 + .../components/MapWidget/hooks/index.ts | 2 + .../MapWidget/hooks/useNearStation.ts | 61 + .../MapWidget/hooks/usePassedTrackIndex.ts | 61 + src/preview/components/MapWidget/index.ts | 5 + .../MapWidget/map-widget-context.interface.ts | 50 + .../MapWidget/map-widget.constant.ts | 10 + .../MapWidget/map-widget.interface.ts | 38 + .../MapWidget/utils/get-deviation.ts | 23 + .../MapWidget/utils/get-distance.ts | 28 + .../MapWidget/utils/get-map-point.ts | 6 + .../components/MapWidget/utils/index.ts | 4 + .../MapWidget/utils/intersections.ts | 30 + src/preview/components/MyComponent/index.tsx | 7 + .../RoutInfoWidget/RouteInfoWidget.module.css | 67 + .../RoutInfoWidget/RouteInfoWidget.tsx | 74 + .../TouchScrollWrapper.module.css | 24 + .../TouchScrollWrapper/TouchScrollWrapper.tsx | 142 ++ .../TransportIcon/TransportIcon.tsx | 24 + .../WeatherWidget/icons/DetHumidity.tsx | 16 + .../WeatherWidget/icons/DetWind.tsx | 24 + .../WeatherWidget/icons/cond_cloudy.svg | 3 + .../WeatherWidget/icons/cond_partlycloudy.svg | 4 + .../WeatherWidget/icons/cond_rainy.svg | 7 + .../WeatherWidget/icons/cond_snow.svg | 11 + .../WeatherWidget/icons/cond_snowy.svg | 11 + .../WeatherWidget/icons/cond_sunny.svg | 18 + .../WeatherWidget/icons/cond_thunder.svg | 4 + .../WeatherWidget/icons/det_humidity.svg | 3 + .../WeatherWidget/icons/det_wind.svg | 5 + src/preview/components/WeatherWidget/index.ts | 3 + .../WeatherWidget/weather-widget-icon.tsx | 44 + .../WeatherWidget/weather-widget-right.tsx | 77 + .../WeatherWidget/weather-widget-time.tsx | 54 + .../WeatherWidget/weather-widget-today.tsx | 48 + .../WeatherWidget/weather-widget.tsx | 46 + .../WeatherWidget/weather.constant.ts | 28 + .../WeatherWidget/weather.interface.ts | 29 + src/preview/components/fonts/LICENSE.txt | 202 ++ src/preview/components/fonts/Roboto-Black.ttf | Bin 0 -> 168060 bytes .../components/fonts/Roboto-BlackItalic.ttf | Bin 0 -> 174108 bytes src/preview/components/fonts/Roboto-Bold.ttf | Bin 0 -> 167336 bytes .../components/fonts/Roboto-BoldItalic.ttf | Bin 0 -> 171508 bytes .../components/fonts/Roboto-Italic.ttf | Bin 0 -> 170504 bytes src/preview/components/fonts/Roboto-Light.ttf | Bin 0 -> 167000 bytes .../components/fonts/Roboto-LightItalic.ttf | Bin 0 -> 173172 bytes .../components/fonts/Roboto-Medium.ttf | Bin 0 -> 168644 bytes .../components/fonts/Roboto-MediumItalic.ttf | Bin 0 -> 173416 bytes .../components/fonts/Roboto-Regular.ttf | Bin 0 -> 168260 bytes src/preview/components/fonts/Roboto-Thin.ttf | Bin 0 -> 168488 bytes .../components/fonts/Roboto-ThinItalic.ttf | Bin 0 -> 172860 bytes src/preview/components/icons/index.tsx | 1938 +++++++++++++++++ src/preview/components/index.ts | 12 + src/preview/components/lightbox/Lightbox.css | 61 + src/preview/components/lightbox/Lightbox.tsx | 40 + .../components/lightbox/LightboxContent.tsx | 26 + .../components/lightbox/LightboxContext.tsx | 51 + .../components/lightbox/Object3DLightbox.tsx | 9 + .../lightbox/PhotoSphereLightbox.tsx | 32 + src/preview/components/lightbox/index.ts | 2 + src/preview/components/model-viewer/Model.tsx | 32 + .../components/model-viewer/ModelViewer.tsx | 56 + .../OrbitControls/TreeOrbitControls.js | 1131 ++++++++++ .../model-viewer/OrbitControls/index.d.ts | 31 + .../model-viewer/OrbitControls/index.js | 96 + .../model-viewer/fitCameraToObject.ts | 22 + src/preview/components/model-viewer/index.ts | 1 + .../route-preview/components/RoutePreview.tsx | 8 + .../components/RoutePreviewContainer.tsx | 82 + .../RoutePreviewDashboard.module.css | 79 + .../RoutePreviewDashboard.tsx | 54 + .../SettingsPanel/SettingsPanel.module.css | 28 + .../SettingsPanel/SettingsPanel.tsx | 105 + .../settigs-fields/CoordinateField.tsx | 59 + .../settigs-fields/RotationField.tsx | 61 + .../settigs-fields/ScaleField.tsx | 50 + .../settigs-fields/StationSelectField.tsx | 65 + .../settigs-fields/field-props.interface.ts | 8 + .../SettingsPanel/settigs-fields/index.ts | 5 + .../route-preview/hooks/useGetRouteData.ts | 58 + .../route-preview/hooks/useUpdateRouteData.ts | 21 + src/preview/components/route-preview/index.ts | 1 + .../route-preview/mappers/mapRouteFromApi.ts | 141 ++ .../route-preview/mappers/mapRouteToApi.ts | 25 + src/preview/components/styles/global.scss | 115 + src/preview/components/styles/grid.scss | 123 ++ .../i18n/LocaleSwitcher/LocaleSwitcher.css | 37 + .../i18n/LocaleSwitcher/LocaleSwitcher.tsx | 50 + src/preview/i18n/en.json | 10 + src/preview/i18n/i18n.interface.ts | 10 + src/preview/i18n/index.ts | 5 + src/preview/i18n/language-loader.ts | 15 + src/preview/i18n/localization-context.tsx | 25 + src/preview/i18n/ru.json | 10 + src/preview/i18n/useServerLocalization.ts | 19 + src/preview/i18n/zh.json | 10 + src/preview/types/article.interface.ts | 9 + .../types/attraction-group-icon-size.type.ts | 1 + .../types/attraction-widget.interface.ts | 12 + src/preview/types/attraction.interface.ts | 24 + src/preview/types/constants.ts | 5 + src/preview/types/coordinates.type.ts | 4 + src/preview/types/index.ts | 248 +++ src/preview/types/lightbox.interface.ts | 14 + src/preview/types/media.type.ts | 7 + src/preview/types/on-map.type.ts | 6 + src/preview/types/option.type.ts | 4 + src/preview/types/order.type.ts | 1 + src/preview/types/set-state.type.ts | 3 + src/preview/types/station.interface.ts | 19 + src/preview/types/station.ts | 84 + src/preview/types/track.type.ts | 3 + src/preview/types/transport.type.ts | 10 + src/preview/types/uuid.type.ts | 1 + .../MapWidgetContainer/MapWidgetContainer.tsx | 50 + .../widgets/MapWidgetContainer/index.ts | 1 + .../MapWidgetContainer/mapStationsFromApi.ts | 19 + .../MapWidgetContainer/useGetMapData.ts | 21 + .../RouteInfoWidgetContainer.tsx | 9 + .../useGetRouteInfo.ts | 28 + .../WeatherWidget/WeatherWidgetContainer.tsx | 9 + .../widgets/WeatherWidget/useWeatherData.ts | 38 + .../AllAttractionsDropdown.css | 160 ++ .../all-attractions-dropdown.tsx | 127 ++ .../useGetAttractionList.ts | 42 + .../AttractionWidgetContainer.tsx | 168 ++ .../AttractionsWidgetContainer.css | 4 + src/preview/widgets/dashboard/Dashboard.tsx | 115 + src/preview/widgets/main/MainScreen.tsx | 35 + src/preview/widgets/main/useBackendStatus.ts | 52 + .../widgets/main/useSplashScreenStatus.ts | 27 + .../AccordionListTab/AccordionListTab.tsx | 108 + .../AttractionCard/AttractionCard.module.css | 5 + .../AttractionCard/AttractionCard.tsx | 21 + .../nav-widget/components/HomeTab/HomeTab.tsx | 51 + .../components/get-distance-formatter.ts | 29 + .../widgets/nav-widget/components/index.ts | 3 + src/preview/widgets/nav-widget/hooks/index.ts | 1 + .../hooks/useGetAttractionDetails.ts | 27 + .../nav-widget/hooks/useGetAttractions.ts | 28 + .../nav-widget/hooks/useGetStations.ts | 31 + .../nav-widget/nav-widget-container.tsx | 15 + .../nav-widget/nav-widget.interface.ts | 24 + .../widgets/nav-widget/nav-widget.styles.tsx | 169 ++ src/preview/widgets/nav-widget/nav-widget.tsx | 119 + .../OperativeInfoWidget.css | 76 + .../operative-info-widget/alert.interface.ts | 15 + .../operative-info-widget.tsx | 73 + .../transfer.interface.ts | 18 + .../operative-info-widget/useOperativeInfo.ts | 89 + .../weather-widget/weather.interface.ts | 29 + 186 files changed, 10269 insertions(+), 158 deletions(-) create mode 100644 src/preview/components/AttractionShortPreview/AttractionShortPreview.css create mode 100644 src/preview/components/AttractionShortPreview/AttractionShortPreview.tsx create mode 100644 src/preview/components/AttractionWidget/AttractionWidget.css create mode 100644 src/preview/components/AttractionWidget/AttractionWidget.tsx create mode 100644 src/preview/components/AttractionWidget/media/AttractionMedia.css create mode 100644 src/preview/components/AttractionWidget/media/AttractionMedia.tsx create mode 100644 src/preview/components/AttractionWidget/media/ImageMedia.tsx create mode 100644 src/preview/components/AttractionWidget/media/Object3DMedia.tsx create mode 100644 src/preview/components/AttractionWidget/media/PhotoSphereMedia.tsx create mode 100644 src/preview/components/AttractionWidget/media/VideoMedia.tsx create mode 100644 src/preview/components/Drawer/Drawer.styles.tsx create mode 100644 src/preview/components/Drawer/Drawer.tsx create mode 100644 src/preview/components/Drawer/index.ts create mode 100644 src/preview/components/MapWidget/MapWidgetContext.tsx create mode 100644 src/preview/components/MapWidget/components/MapWidget/MapContent.tsx create mode 100644 src/preview/components/MapWidget/components/MapWidget/MapWidget.module.css create mode 100644 src/preview/components/MapWidget/components/MapWidget/MapWidget.tsx create mode 100644 src/preview/components/MapWidget/components/MapWidget/index.ts create mode 100644 src/preview/components/MapWidget/components/TrackAttractions/AttractionMarker.module.css create mode 100644 src/preview/components/MapWidget/components/TrackAttractions/AttractionMarker.tsx create mode 100644 src/preview/components/MapWidget/components/TrackAttractions/TrackAttractions.tsx create mode 100644 src/preview/components/MapWidget/components/TrackAttractions/index.ts create mode 100644 src/preview/components/MapWidget/components/TrackLine.tsx create mode 100644 src/preview/components/MapWidget/components/TrackStations/StationLabel.tsx create mode 100644 src/preview/components/MapWidget/components/TrackStations/StationLabelContent.tsx create mode 100644 src/preview/components/MapWidget/components/TrackStations/StationLabelEdit.tsx create mode 100644 src/preview/components/MapWidget/components/TrackStations/TrackStations.css create mode 100644 src/preview/components/MapWidget/components/TrackStations/TrackStations.tsx create mode 100644 src/preview/components/MapWidget/components/TrackStations/index.ts create mode 100644 src/preview/components/MapWidget/components/TramMarker/TramMarker.module.css create mode 100644 src/preview/components/MapWidget/components/TramMarker/TramMarker.tsx create mode 100644 src/preview/components/MapWidget/components/TramMarker/index.ts create mode 100644 src/preview/components/MapWidget/components/index.ts create mode 100644 src/preview/components/MapWidget/hooks/index.ts create mode 100644 src/preview/components/MapWidget/hooks/useNearStation.ts create mode 100644 src/preview/components/MapWidget/hooks/usePassedTrackIndex.ts create mode 100644 src/preview/components/MapWidget/index.ts create mode 100644 src/preview/components/MapWidget/map-widget-context.interface.ts create mode 100644 src/preview/components/MapWidget/map-widget.constant.ts create mode 100644 src/preview/components/MapWidget/map-widget.interface.ts create mode 100644 src/preview/components/MapWidget/utils/get-deviation.ts create mode 100644 src/preview/components/MapWidget/utils/get-distance.ts create mode 100644 src/preview/components/MapWidget/utils/get-map-point.ts create mode 100644 src/preview/components/MapWidget/utils/index.ts create mode 100644 src/preview/components/MapWidget/utils/intersections.ts create mode 100644 src/preview/components/MyComponent/index.tsx create mode 100644 src/preview/components/RoutInfoWidget/RouteInfoWidget.module.css create mode 100644 src/preview/components/RoutInfoWidget/RouteInfoWidget.tsx create mode 100644 src/preview/components/TouchScrollWrapper/TouchScrollWrapper.module.css create mode 100644 src/preview/components/TouchScrollWrapper/TouchScrollWrapper.tsx create mode 100644 src/preview/components/TransportIcon/TransportIcon.tsx create mode 100644 src/preview/components/WeatherWidget/icons/DetHumidity.tsx create mode 100644 src/preview/components/WeatherWidget/icons/DetWind.tsx create mode 100644 src/preview/components/WeatherWidget/icons/cond_cloudy.svg create mode 100644 src/preview/components/WeatherWidget/icons/cond_partlycloudy.svg create mode 100644 src/preview/components/WeatherWidget/icons/cond_rainy.svg create mode 100644 src/preview/components/WeatherWidget/icons/cond_snow.svg create mode 100644 src/preview/components/WeatherWidget/icons/cond_snowy.svg create mode 100644 src/preview/components/WeatherWidget/icons/cond_sunny.svg create mode 100644 src/preview/components/WeatherWidget/icons/cond_thunder.svg create mode 100644 src/preview/components/WeatherWidget/icons/det_humidity.svg create mode 100644 src/preview/components/WeatherWidget/icons/det_wind.svg create mode 100644 src/preview/components/WeatherWidget/index.ts create mode 100644 src/preview/components/WeatherWidget/weather-widget-icon.tsx create mode 100644 src/preview/components/WeatherWidget/weather-widget-right.tsx create mode 100644 src/preview/components/WeatherWidget/weather-widget-time.tsx create mode 100644 src/preview/components/WeatherWidget/weather-widget-today.tsx create mode 100644 src/preview/components/WeatherWidget/weather-widget.tsx create mode 100644 src/preview/components/WeatherWidget/weather.constant.ts create mode 100644 src/preview/components/WeatherWidget/weather.interface.ts create mode 100644 src/preview/components/fonts/LICENSE.txt create mode 100644 src/preview/components/fonts/Roboto-Black.ttf create mode 100644 src/preview/components/fonts/Roboto-BlackItalic.ttf create mode 100644 src/preview/components/fonts/Roboto-Bold.ttf create mode 100644 src/preview/components/fonts/Roboto-BoldItalic.ttf create mode 100644 src/preview/components/fonts/Roboto-Italic.ttf create mode 100644 src/preview/components/fonts/Roboto-Light.ttf create mode 100644 src/preview/components/fonts/Roboto-LightItalic.ttf create mode 100644 src/preview/components/fonts/Roboto-Medium.ttf create mode 100644 src/preview/components/fonts/Roboto-MediumItalic.ttf create mode 100644 src/preview/components/fonts/Roboto-Regular.ttf create mode 100644 src/preview/components/fonts/Roboto-Thin.ttf create mode 100644 src/preview/components/fonts/Roboto-ThinItalic.ttf create mode 100644 src/preview/components/icons/index.tsx create mode 100644 src/preview/components/index.ts create mode 100644 src/preview/components/lightbox/Lightbox.css create mode 100644 src/preview/components/lightbox/Lightbox.tsx create mode 100644 src/preview/components/lightbox/LightboxContent.tsx create mode 100644 src/preview/components/lightbox/LightboxContext.tsx create mode 100644 src/preview/components/lightbox/Object3DLightbox.tsx create mode 100644 src/preview/components/lightbox/PhotoSphereLightbox.tsx create mode 100644 src/preview/components/lightbox/index.ts create mode 100644 src/preview/components/model-viewer/Model.tsx create mode 100644 src/preview/components/model-viewer/ModelViewer.tsx create mode 100644 src/preview/components/model-viewer/OrbitControls/TreeOrbitControls.js create mode 100644 src/preview/components/model-viewer/OrbitControls/index.d.ts create mode 100644 src/preview/components/model-viewer/OrbitControls/index.js create mode 100644 src/preview/components/model-viewer/fitCameraToObject.ts create mode 100644 src/preview/components/model-viewer/index.ts create mode 100644 src/preview/components/route-preview/components/RoutePreview.tsx create mode 100644 src/preview/components/route-preview/components/RoutePreviewContainer.tsx create mode 100644 src/preview/components/route-preview/components/RoutePreviewDashboard/RoutePreviewDashboard.module.css create mode 100644 src/preview/components/route-preview/components/RoutePreviewDashboard/RoutePreviewDashboard.tsx create mode 100644 src/preview/components/route-preview/components/SettingsPanel/SettingsPanel.module.css create mode 100644 src/preview/components/route-preview/components/SettingsPanel/SettingsPanel.tsx create mode 100644 src/preview/components/route-preview/components/SettingsPanel/settigs-fields/CoordinateField.tsx create mode 100644 src/preview/components/route-preview/components/SettingsPanel/settigs-fields/RotationField.tsx create mode 100644 src/preview/components/route-preview/components/SettingsPanel/settigs-fields/ScaleField.tsx create mode 100644 src/preview/components/route-preview/components/SettingsPanel/settigs-fields/StationSelectField.tsx create mode 100644 src/preview/components/route-preview/components/SettingsPanel/settigs-fields/field-props.interface.ts create mode 100644 src/preview/components/route-preview/components/SettingsPanel/settigs-fields/index.ts create mode 100644 src/preview/components/route-preview/hooks/useGetRouteData.ts create mode 100644 src/preview/components/route-preview/hooks/useUpdateRouteData.ts create mode 100644 src/preview/components/route-preview/index.ts create mode 100644 src/preview/components/route-preview/mappers/mapRouteFromApi.ts create mode 100644 src/preview/components/route-preview/mappers/mapRouteToApi.ts create mode 100644 src/preview/components/styles/global.scss create mode 100644 src/preview/components/styles/grid.scss create mode 100644 src/preview/i18n/LocaleSwitcher/LocaleSwitcher.css create mode 100644 src/preview/i18n/LocaleSwitcher/LocaleSwitcher.tsx create mode 100644 src/preview/i18n/en.json create mode 100644 src/preview/i18n/i18n.interface.ts create mode 100644 src/preview/i18n/index.ts create mode 100644 src/preview/i18n/language-loader.ts create mode 100644 src/preview/i18n/localization-context.tsx create mode 100644 src/preview/i18n/ru.json create mode 100644 src/preview/i18n/useServerLocalization.ts create mode 100644 src/preview/i18n/zh.json create mode 100644 src/preview/types/article.interface.ts create mode 100644 src/preview/types/attraction-group-icon-size.type.ts create mode 100644 src/preview/types/attraction-widget.interface.ts create mode 100644 src/preview/types/attraction.interface.ts create mode 100644 src/preview/types/constants.ts create mode 100644 src/preview/types/coordinates.type.ts create mode 100644 src/preview/types/index.ts create mode 100644 src/preview/types/lightbox.interface.ts create mode 100644 src/preview/types/media.type.ts create mode 100644 src/preview/types/on-map.type.ts create mode 100644 src/preview/types/option.type.ts create mode 100644 src/preview/types/order.type.ts create mode 100644 src/preview/types/set-state.type.ts create mode 100644 src/preview/types/station.interface.ts create mode 100644 src/preview/types/station.ts create mode 100644 src/preview/types/track.type.ts create mode 100644 src/preview/types/transport.type.ts create mode 100644 src/preview/types/uuid.type.ts create mode 100644 src/preview/widgets/MapWidgetContainer/MapWidgetContainer.tsx create mode 100644 src/preview/widgets/MapWidgetContainer/index.ts create mode 100644 src/preview/widgets/MapWidgetContainer/mapStationsFromApi.ts create mode 100644 src/preview/widgets/MapWidgetContainer/useGetMapData.ts create mode 100644 src/preview/widgets/RouteInfoWidgetContainer/RouteInfoWidgetContainer.tsx create mode 100644 src/preview/widgets/RouteInfoWidgetContainer/useGetRouteInfo.ts create mode 100644 src/preview/widgets/WeatherWidget/WeatherWidgetContainer.tsx create mode 100644 src/preview/widgets/WeatherWidget/useWeatherData.ts create mode 100644 src/preview/widgets/all-attractions-dropdown/AllAttractionsDropdown.css create mode 100644 src/preview/widgets/all-attractions-dropdown/all-attractions-dropdown.tsx create mode 100644 src/preview/widgets/all-attractions-dropdown/useGetAttractionList.ts create mode 100644 src/preview/widgets/attractions-widget/AttractionWidgetContainer.tsx create mode 100644 src/preview/widgets/attractions-widget/AttractionsWidgetContainer.css create mode 100644 src/preview/widgets/dashboard/Dashboard.tsx create mode 100644 src/preview/widgets/main/MainScreen.tsx create mode 100644 src/preview/widgets/main/useBackendStatus.ts create mode 100644 src/preview/widgets/main/useSplashScreenStatus.ts create mode 100644 src/preview/widgets/nav-widget/components/AccordionListTab/AccordionListTab.tsx create mode 100644 src/preview/widgets/nav-widget/components/AttractionCard/AttractionCard.module.css create mode 100644 src/preview/widgets/nav-widget/components/AttractionCard/AttractionCard.tsx create mode 100644 src/preview/widgets/nav-widget/components/HomeTab/HomeTab.tsx create mode 100644 src/preview/widgets/nav-widget/components/get-distance-formatter.ts create mode 100644 src/preview/widgets/nav-widget/components/index.ts create mode 100644 src/preview/widgets/nav-widget/hooks/index.ts create mode 100644 src/preview/widgets/nav-widget/hooks/useGetAttractionDetails.ts create mode 100644 src/preview/widgets/nav-widget/hooks/useGetAttractions.ts create mode 100644 src/preview/widgets/nav-widget/hooks/useGetStations.ts create mode 100644 src/preview/widgets/nav-widget/nav-widget-container.tsx create mode 100644 src/preview/widgets/nav-widget/nav-widget.interface.ts create mode 100644 src/preview/widgets/nav-widget/nav-widget.styles.tsx create mode 100644 src/preview/widgets/nav-widget/nav-widget.tsx create mode 100644 src/preview/widgets/operative-info-widget/OperativeInfoWidget.css create mode 100644 src/preview/widgets/operative-info-widget/alert.interface.ts create mode 100644 src/preview/widgets/operative-info-widget/operative-info-widget.tsx create mode 100644 src/preview/widgets/operative-info-widget/transfer.interface.ts create mode 100644 src/preview/widgets/operative-info-widget/useOperativeInfo.ts create mode 100644 src/preview/widgets/weather-widget/weather.interface.ts diff --git a/src/pages/media/ModelViewer/index.tsx b/src/pages/media/ModelViewer/index.tsx index 36d0442..ce75996 100644 --- a/src/pages/media/ModelViewer/index.tsx +++ b/src/pages/media/ModelViewer/index.tsx @@ -3,13 +3,14 @@ import { OrbitControls, Stage, useGLTF } from "@react-three/drei"; type ModelViewerProps = { fileUrl: string; + height?: string; }; -export const ModelViewer = ({ fileUrl }: ModelViewerProps) => { +export const ModelViewer = ({ fileUrl, height }: ModelViewerProps) => { const { scene } = useGLTF(fileUrl); return ( - + diff --git a/src/pages/media/show.tsx b/src/pages/media/show.tsx index a12e0c6..c5dc884 100644 --- a/src/pages/media/show.tsx +++ b/src/pages/media/show.tsx @@ -94,7 +94,7 @@ export const MediaShow = () => { src={`${import.meta.env.VITE_KRBL_MEDIA}${ record?.id }/download?token=${token}`} - width={"100%px"} + width={"100%"} height={"80vh"} /> )} diff --git a/src/pages/sight/edit.tsx b/src/pages/sight/edit.tsx index a71c7f2..994c9ca 100644 --- a/src/pages/sight/edit.tsx +++ b/src/pages/sight/edit.tsx @@ -21,6 +21,8 @@ import { observer } from "mobx-react-lite"; import { languageStore } from "../../store/LanguageStore"; import axios from "axios"; import { LanguageSwitch } from "../../components/LanguageSwitch/index"; +import { ReactPhotoSphereViewer } from "react-photo-sphere-viewer"; +import { ModelViewer } from "../media/ModelViewer"; function a11yProps(index: number) { return { @@ -109,9 +111,11 @@ export const SightEdit = observer(() => { }); const [mediaFile, setMediaFile] = useState<{ src: string; + media_type: number; filename: string; }>({ src: "", + media_type: 1, filename: "", }); @@ -249,18 +253,20 @@ export const SightEdit = observer(() => { src: `${import.meta.env.VITE_KRBL_MEDIA}${ media.id }/download?token=${localStorage.getItem(TOKEN_KEY)}`, + media_type: media.media_type, filename: media.filename, }); - console.log(media); } else { setMediaFile({ src: "", + media_type: 1, filename: "", }); // или другой дефолт } } catch (error) { setMediaFile({ src: "", + media_type: 1, filename: "", }); // или обработка ошибки } @@ -360,160 +366,6 @@ export const SightEdit = observer(() => { - - - - - - - - - type="edit" - parentId={sightId!} - dragAllowed={true} - setItemsParent={setLinkedArticles} - parentResource="sight" - fields={articleFields} - childResource="article" - title="статьи" - /> - - - - - - - theme.palette.mode === "dark" ? "background.paper" : "#fff", - }} - > - - Предпросмотр - - - - {mediaFile.src && ( - <> - {mediaFile.filename.endsWith(".mp4") ? ( - - {/* Водяные знаки */} - - - {selectedArticle && ( - - {selectedArticle.heading} - - )} - - {selectedArticle && ( - - {selectedArticle.body} - - )} - - {/* Координаты */} - - {linkedArticles.map((article, index) => ( - setSelectedArticleIndex(index)} - sx={{ - cursor: "pointer", - bgcolor: - selectedArticleIndex === index - ? "primary.main" - : "transparent", - color: selectedArticleIndex === index ? "white" : "inherit", - p: 1, - borderRadius: 1, - }} - > - - {article.heading} - - - ))} - - - - - - { + + + + + + + + + + + type="edit" + parentId={sightId!} + dragAllowed={true} + setItemsParent={setLinkedArticles} + parentResource="sight" + fields={articleFields} + childResource="article" + title="статьи" + /> + + + + + + + theme.palette.mode === "dark" ? "background.paper" : "#fff", + }} + > + + Предпросмотр + + + + {mediaFile && mediaFile.src && mediaFile.media_type === 1 && ( + {mediaFile.filename} + )} + + {mediaFile && mediaFile.media_type === 2 && ( + + {/* Водяные знаки */} + + + {selectedArticle && ( + + {selectedArticle.heading} + + )} + + {selectedArticle && ( + + {selectedArticle.body} + + )} + {selectedArticle && ( + + {selectedArticle.body} + + )} + {selectedArticle && ( + + {selectedArticle.body} + + )} + + + + {linkedArticles.map((article, index) => ( + setSelectedArticleIndex(index)} + sx={{ + cursor: "pointer", + bgcolor: + selectedArticleIndex === index + ? "primary.main" + : "transparent", + color: selectedArticleIndex === index ? "white" : "inherit", + p: 1, + borderRadius: 1, + }} + > + + {article.heading} + + + ))} + + + + + { autoComplete="off" > + ( + + option.id === field.value && option.media_type === 3 + ) || null + } + onChange={(_, value) => { + field.onChange(value?.id || ""); + }} + getOptionLabel={(item) => { + return item ? item.media_name : ""; + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id; + }} + filterOptions={(options, { inputValue }) => { + return options.filter((option) => + option.media_name + .toLowerCase() + .includes(inputValue.toLowerCase()) + ); + }} + renderInput={(params) => ( + + )} + /> + )} + /> + { Предпросмотр + {thumbnailPreview && ( + + + Логотип достопримечательности: + + + + )} + {/* Водяные знаки */} , "title" | "content"> { + img: string; + title: LocalizedString; + subtitle: LocalizedString; + content: LocalizedString; +} + +export function AttractionShortPreview({ + img, + title, + subtitle, + content, + className, + ...props +}: AttractionShortPreviewProps) { + const localizeText = useServerLocalization(); + + return ( +
+ {img && ( + {localizeText(title)} + )} + + +
+

{localizeText(title)}

+ +
+ {localizeText(subtitle)} +
+ +

+

+
+
+ ); +} diff --git a/src/preview/components/AttractionWidget/AttractionWidget.css b/src/preview/components/AttractionWidget/AttractionWidget.css new file mode 100644 index 0000000..3ae3c4e --- /dev/null +++ b/src/preview/components/AttractionWidget/AttractionWidget.css @@ -0,0 +1,126 @@ +.widget-container { + width: 545px; + height: var(--attraction-widget-container-height, 100%); + max-height: calc(100% - 90px); + color: #ffffff; + background: #806c59; + border: 2px solid #806c59; + border-radius: 10px; +} + +.widget-content { + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + width: 100%; + height: 100%; + overflow: hidden; +} + +.widget-slide { + position: relative; + display: none; + top: 0; + left: 0; + flex-direction: column; + justify-content: flex-start; + align-items: center; + width: 100%; +} + +.widget-slide.active, +.widget-slide.preview { + display: flex; + flex: 1; + overflow: auto; +} + +.widget-media { + width: 100%; + height: auto; + max-height: 644px; +} + +.view-container { + border-radius: 8px 8px 0 0; +} + +.widget-header { + background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%), + rgba(179, 165, 152, 0.4); + box-shadow: inset 4px 4px 12px rgba(255, 255, 255, 0.12); + width: 100%; + padding: 9px 16px; + font-weight: 700; + font-size: 24px; + line-height: 120%; +} + +.widget-text { + width: 100%; + align-self: self-start; + padding: 16px; + font-weight: 400; + font-size: 18px; + line-height: 150%; /* or 27px */ + opacity: 0; + transition: opacity 0.5s ease-in-out; + user-select: none; + word-break: break-word; + white-space: pre-wrap; +} + +.widget-text p { + margin: 0; +} + +.widget-text.preview { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + font-weight: 700; + font-size: 48px; + line-height: 120%; + text-align: center; +} + +.widget-text.active { + opacity: 1; +} + +.widget-titles { + display: flex; + height: 50px; + justify-content: space-evenly; + align-items: center; + width: 100%; + margin: 5px 0 0 0; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%), + rgba(179, 165, 152, 0.4); + box-shadow: inset 4px 4px 12px rgba(255, 255, 255, 0.12); + border-radius: 0 0 10px 10px; + padding: 12px 0; +} + +.widget-title { + font-weight: 400; + font-size: 18px; + line-height: 21px; + cursor: pointer; + user-select: none; + width: 100px; + text-align: center; +} + +.widget-title.active { + font-weight: bold; + text-decoration: underline; + text-underline-offset: 5px; +} + +.widget-title.preview { + display: none; +} diff --git a/src/preview/components/AttractionWidget/AttractionWidget.tsx b/src/preview/components/AttractionWidget/AttractionWidget.tsx new file mode 100644 index 0000000..b682909 --- /dev/null +++ b/src/preview/components/AttractionWidget/AttractionWidget.tsx @@ -0,0 +1,114 @@ +import React, { HTMLAttributes, useEffect, useState } from "react"; +import { useServerLocalization } from "@mt/i18n"; +import cn from "classnames"; +import { useSwipeable } from "react-swipeable"; +import { ArticleBase } from "@mt/common-types"; +import "./AttractionWidget.css"; +import { usePrevious } from "@mt/utils"; +import { AttractionMedia } from "./media/AttractionMedia"; +import { TouchScrollWrapper } from "../TouchScrollWrapper/TouchScrollWrapper"; + +export interface AttractionsWidgetProps extends HTMLAttributes { + articles: ArticleBase[]; + isIdleMode: boolean; + isPreviewOnly?: boolean; +} + +export function AttractionWidget({ + articles, + isIdleMode, + isPreviewOnly = false, + ...props +}: AttractionsWidgetProps) { + const [activeIndex, setActiveIndex] = useState(0); + const prevArticles = usePrevious(articles) || []; + const localizeText = useServerLocalization(); + + const swipeHandlers = useSwipeable({ + onSwipedLeft: ({ event }) => { + event.preventDefault(); + setActiveIndex((activeIndex) => (activeIndex + 1) % articles.length); + }, + onSwipedRight: ({ event }) => { + event.preventDefault(); + setActiveIndex( + (activeIndex) => (activeIndex - 1 + articles.length) % articles.length + ); + }, + swipeDuration: 500, + preventScrollOnSwipe: true, + trackMouse: true, + }); + + const handleClick = (index: number) => { + setActiveIndex(index); + document.querySelector(".widget-text.active")!.scrollTop = 0; + }; + + useEffect(() => setActiveIndex(activeIndex), [activeIndex]); + + useEffect(() => { + if ( + !isPreviewOnly && + (isIdleMode || JSON.stringify(prevArticles) !== JSON.stringify(articles)) + ) { + setActiveIndex(0); + } + + // admin specific case: during edit we removed active article + if (prevArticles?.length > articles?.length) { + setActiveIndex(0); + } + }, [isPreviewOnly, isIdleMode, articles]); + + return ( +
+
+ {articles?.map((article, index) => ( +
handleClick(index)} + > +
+ +
+ + {index !== 0 && ( +
+ {localizeText(articles[0].text)} +
+ )} + + +
+ +
+ ))} + +
+ {articles?.map((article, index) => ( +
handleClick(index)} + > + {localizeText(article.name)} +
+ ))} +
+
+
+ ); +} diff --git a/src/preview/components/AttractionWidget/media/AttractionMedia.css b/src/preview/components/AttractionWidget/media/AttractionMedia.css new file mode 100644 index 0000000..34774e4 --- /dev/null +++ b/src/preview/components/AttractionWidget/media/AttractionMedia.css @@ -0,0 +1,52 @@ +.widget-image, +.widget-video, +.widget-3d-model { + max-width: 100%; + max-height: 100%; + width: 100%; + height: 100%; + display: block; + border-radius: 8px 8px 0 0; +} + +.widget-3d-model { + height: 350px; +} + +.widget-media__wrapper { + position: relative; + /*TODO: it worth to investigate it further... quite weird behavior of */ + box-sizing: content-box !important; +} + +.fullscreen-photo-sphere-btn, +.fullscreen-3d-btn { + width: 20px; + height: 20px; + position: absolute; + right: 10px; + bottom: 10px; + cursor: pointer; + z-index: 100; + opacity: 0.7; +} + +.media-with-watermark { + position: relative; +} + +.watermark { + position: absolute; + top: 10px; + left: 10px; + width: 50px; + height: auto; +} + +.psv-autorotate-button { + display: block !important; +} + +.psv-menu-button { + display: none !important; +} diff --git a/src/preview/components/AttractionWidget/media/AttractionMedia.tsx b/src/preview/components/AttractionWidget/media/AttractionMedia.tsx new file mode 100644 index 0000000..a0f9b32 --- /dev/null +++ b/src/preview/components/AttractionWidget/media/AttractionMedia.tsx @@ -0,0 +1,36 @@ +import { Media } from "@mt/common-types"; +import { ImageMedia } from "./ImageMedia"; +import { VideoMedia } from "./VideoMedia"; +import { PhotoSphereMedia } from "./PhotoSphereMedia"; +import { Object3DMedia } from "./Object3DMedia"; +import { memo } from "react"; + +export const AttractionMedia = memo( + ({ media }: { media: Media }) => { + const { type, url, watermarkUrl } = media; + + if (!url) return null; + + switch (type) { + case "IMAGE": + return ( + + ); + case "VIDEO": + return ; + case "PHOTO_SPHERE": + return ; + case "OBJECT_3D": + return ; + default: + return null; + } + }, + ({ media }, { media: newMedia }) => { + return ( + media.url === newMedia.url && + media.watermarkUrl === newMedia.watermarkUrl && + media.type === newMedia.type + ); + } +); diff --git a/src/preview/components/AttractionWidget/media/ImageMedia.tsx b/src/preview/components/AttractionWidget/media/ImageMedia.tsx new file mode 100644 index 0000000..94f4934 --- /dev/null +++ b/src/preview/components/AttractionWidget/media/ImageMedia.tsx @@ -0,0 +1,25 @@ +import cn from 'classnames'; +import React from 'react'; + +import './AttractionMedia.css'; + +interface ImageMediaProps { + url: string; + alt: string; + watermarkUrl?: string; +} + +export const ImageMedia = ({ url, alt, watermarkUrl }: ImageMediaProps) => ( + <> + {alt} + {watermarkUrl && ( + Watermark + )} + +); diff --git a/src/preview/components/AttractionWidget/media/Object3DMedia.tsx b/src/preview/components/AttractionWidget/media/Object3DMedia.tsx new file mode 100644 index 0000000..853600a --- /dev/null +++ b/src/preview/components/AttractionWidget/media/Object3DMedia.tsx @@ -0,0 +1,52 @@ +import cn from "classnames"; +import React, { useEffect, useState } from "react"; + +import "./AttractionMedia.css"; +import ModelViewer from "../../model-viewer/ModelViewer"; +import { Icons, useLightboxContext } from "@mt/components"; +import { Object3DLightboxData } from "@mt/common-types"; + +interface Object3DMediaProps { + url: string; + watermarkUrl?: string; +} + +export const Object3DMedia = ({ url, watermarkUrl }: Object3DMediaProps) => { + // prettier-ignore + const { setData, openLightbox } = useLightboxContext(); + const [autoRotate, setAutoRotate] = useState(true); + + const handle3DFullscreenOpen = () => { + setAutoRotate(false); + setData({ + type: "OBJECT_3D", + modelUrl: url, + watermarkUrl, + }); + openLightbox(); + }; + + useEffect(() => { + setAutoRotate(true); + }, [url]); + + return ( +
+
+ + {watermarkUrl && ( + Watermark + )} +
+ + handle3DFullscreenOpen()} + /> +
+ ); +}; diff --git a/src/preview/components/AttractionWidget/media/PhotoSphereMedia.tsx b/src/preview/components/AttractionWidget/media/PhotoSphereMedia.tsx new file mode 100644 index 0000000..15c9ed6 --- /dev/null +++ b/src/preview/components/AttractionWidget/media/PhotoSphereMedia.tsx @@ -0,0 +1,62 @@ +import cn from "classnames"; +import React, { useRef } from "react"; +import { ReactPhotoSphereViewer } from "react-photo-sphere-viewer"; + +import { PhotoSphereLightboxData } from "@mt/common-types"; + +import "./AttractionMedia.css"; +import { useLightboxContext } from "../../lightbox"; +import { Icons } from "@mt/components"; + +interface PhotoSphereMediaProps { + url: string; + watermarkUrl?: string; +} + +export const PhotoSphereMedia = ({ + url, + watermarkUrl, +}: PhotoSphereMediaProps) => { + // prettier-ignore + const { setData, openLightbox } = useLightboxContext(); + // react-photo-sphere-viewer doesn't have exported types, so here's a bit of a hardcoded piece + const photoSphereRef = useRef(null); + + const handlePhotoSphereFullscreenOpen = () => { + photoSphereRef.current?.stopAutoRotate(); + setData({ + type: "PHOTO_SPHERE", + imageUrl: url, + watermarkUrl, + }); + openLightbox(); + }; + + return ( +
+ + {watermarkUrl && ( + Watermark + )} + {/* the following is a workaround to open lightbox-like preview in the middle of the screen instead of the real fullscreen */} + handlePhotoSphereFullscreenOpen()} + /> +
+ ); +}; diff --git a/src/preview/components/AttractionWidget/media/VideoMedia.tsx b/src/preview/components/AttractionWidget/media/VideoMedia.tsx new file mode 100644 index 0000000..c8af0f6 --- /dev/null +++ b/src/preview/components/AttractionWidget/media/VideoMedia.tsx @@ -0,0 +1,26 @@ +import cn from "classnames"; +import React from "react"; + +import "./AttractionMedia.css"; + +interface VideoMediaProps { + url: string; + watermarkUrl?: string; +} + +export const VideoMedia = ({ url, watermarkUrl }: VideoMediaProps) => ( + <> +