* Добавлено базовое описание README.md

* TODO.md удалён за ненадобностью
* В index.html добавлено более подробное описание цветовых тем
* Части методов utils добавлена документация, явно указаны типа данных
This commit is contained in:
goodmice 2022-05-17 16:12:22 +05:00
parent 5f03b751ee
commit 3af90800ff
7 changed files with 134 additions and 29 deletions

View File

@ -1 +1,61 @@
Проект веб части ASB cloud ![ASB Logo](concept/ImagesSrc/logo_Asb.svg)
# Проект веб части ASB cloud
# Порядок запуска
## 1. Установка пакетов
Для запуска установки необходимо иметь уже установленый [NPM](https://www.npmjs.com).
Установка выполняется одной командой:
```bash
npm i
```
## 2. Автогенерация сервисов
Для корректной работы веб-приложения необходимо наличие сервисов работы с RestAPI.
Для их автогенерации требуется уже запущенная серверная часть.
Автогенерацию можно запустить с помощью уже прописанных в [package.json](package.json) скриптов, либо вручную.
Если сервер запущен на текущей машине достаточно написать:
```bash
npm run update_openapi
```
Для получения сервисов с основного сервера:
```bash
npm run update_openapi_server
```
или же ручной вариант:
```bash
npx openapi -i http://{IP_ADDRESS}:{PORT}/swagger/v1/swagger.json -o src/services/api
```
где ***IP_ADDRESS*** и ***PORT*** это соответственно IP-адрес и порт сервера.
На данный момент имеются следующие IP-адреса:
| IP-адрес | Описание |
|:-|:-|
| 127.0.0.1:5000 | Локальный адрес вашей машины (привязан к `update_openapi`) |
| 192.168.1.70:5000 | Локальный адрес development-сервера (привязан к `update_openapi_server`) |
| 46.146.209.148:89 | Внешний адрес development-сервера |
| 46.146.209.148 | Внешний адрес production-сервера |
## 3. Компиляция production-версии приложения
После выполнения вышеописанных пунктов приложение готово к компиляции.
Для компиляции досточно выполнить команду:
```bash
npm run build
```
После завершения этой команды скомпилированное приложение будет находиться в появившейся директории [build/](build/).
## 4. Запуск development-версии приложения
В [package.json](package.json) необходимо проверить и при необходимости изменить значение в поле ***proxy*** (пара адрес-порт сервера с RestAPI) на актуальное.
После чего выполнить запуск командой:
```bash
npm start
```

View File

@ -1 +0,0 @@
env params prod/dev

View File

@ -1,13 +1,15 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="ru">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="white" />
<meta name="theme-color" media="(prefers-color-scheme: light)" content="white" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />
<meta <meta
name="description" name="description"
content="онлайн мониторинг процесса бурения в реальном времени в офисе заказчика" content="Онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"
/> />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>АСБ Vision</title> <title>АСБ Vision</title>

View File

@ -19,7 +19,7 @@ export function isRawDate(value: unknown): value is RawDate {
return !isNaN(Date.parse(String(value))) return !isNaN(Date.parse(String(value)))
} }
export const formatDate = (date: unknown, utc = false, format = defaultFormat) => { export const formatDate = (date: unknown, utc: boolean = false, format: string = defaultFormat) => {
if (!isRawDate(date)) return null if (!isRawDate(date)) return null
const out = utc ? moment.utc(date).local() : moment(date) const out = utc ? moment.utc(date).local() : moment(date)
return out.format(format) return out.format(format)
@ -40,8 +40,8 @@ export const periodToString = (time?: number) => {
return `${days > 0 ? days : ''} ${toFixed(hours)}:${toFixed(minutes)}:${toFixed(seconds)}` return `${days > 0 ? days : ''} ${toFixed(hours)}:${toFixed(minutes)}:${toFixed(seconds)}`
} }
export const calcDuration = (start: unknown, end: unknown) => { export const calcDuration = (start: unknown, end: unknown): number | undefined => {
if (!isRawDate(start) || !isRawDate(end)) return if (!isRawDate(start) || !isRawDate(end)) return undefined
return (+new Date(end) - +new Date(start)) * timeInS.millisecond / timeInS.day return (+new Date(end) - +new Date(start)) * timeInS.millisecond / timeInS.day
} }

View File

@ -1,20 +1,25 @@
import { OperationStatService, WellOperationDto, WellOperationDtoPlanFactPredictBase } from '@api' import { OperationStatService, WellOperationDto, WellOperationDtoPlanFactPredictBase } from '@api'
const maxPrefix = 'isMax' const maxPrefix: string = 'isMax'
const minPrefix = 'isMin' const minPrefix: string = 'isMin'
export const getPrecision = (number: number) => Number.isFinite(number) ? number.toFixed(2) : '-' export const getPrecision = (number: number): string => Number.isFinite(number) ? number.toFixed(2) : '-'
export type KeyType = number | string export type KeyType = number | string
export const nwtIdCategory = 1043 export const nwtIdCategory: number = 1043
export type SaubData = WellOperationDto & { export type SaubData = WellOperationDto & {
isNPT?: boolean // Относится ли операция к НПВ /** Относится ли операция к НПВ */
key?: number // ID операции isNPT?: boolean
depth?: number // Глубина /** ID операции */
date?: string // Дата key?: number
nptHours?: number // Колличество часов НПВ с начала бурения до текущего момента /** Глубина */
depth?: number
/** Дата */
date?: string
/** Колличество часов НПВ с начала бурения до текущего момента */
nptHours?: number
} }
export const getOperations = async (idWell: number): Promise<{ export const getOperations = async (idWell: number): Promise<{
@ -25,12 +30,14 @@ export const getOperations = async (idWell: number): Promise<{
}> => { }> => {
const ops = await OperationStatService.getTvd(idWell) const ops = await OperationStatService.getTvd(idWell)
if (!ops) return { if (!ops) {
return {
operations: [], operations: [],
plan: [], plan: [],
fact: [], fact: [],
predict: [], predict: [],
} }
}
const convert = (operation?: WellOperationDto): SaubData => ({ const convert = (operation?: WellOperationDto): SaubData => ({
...operation, ...operation,

View File

@ -1,25 +1,62 @@
export type { RawDate, timeInS } from './datetime'
export { isRawDate, formatDate, defaultFormat, periodToString } from './datetime' export { isRawDate, formatDate, defaultFormat, periodToString } from './datetime'
export type { RawDate, timeInS } from './datetime'
export const headerHeight = 64 export const headerHeight: number = 64
export const mainFrameSize = () => ({ export const mainFrameSize = () => ({
width: window.innerWidth, width: window.innerWidth,
height: window.innerHeight - headerHeight height: window.innerHeight - headerHeight
}) })
/**
* Возвращает
*
* @param arr Входящие данные
* @param def Значение по-умолчанию
*
* @returns Если `arr` - массив будет возвращено оно, иначе `def`
*/
export const arrayOrDefault = <T extends unknown>(arr?: unknown, def: T[] = []): T[] => Array.isArray(arr) ? arr : def export const arrayOrDefault = <T extends unknown>(arr?: unknown, def: T[] = []): T[] => Array.isArray(arr) ? arr : def
/**
* Копирует данные в глубину.
*
* @remarks
* При копированиий объектов, содержащих функций может возникнуть исключение.
* Не предназначено для копирования функций.
*
* @param data Копируемые данные
* @returns Полная копия `data`
*/
export const deepCopy = <T extends any>(data: T): T => JSON.parse(JSON.stringify(data ?? null)) export const deepCopy = <T extends any>(data: T): T => JSON.parse(JSON.stringify(data ?? null))
/**
* Маппинг полей объекта
*
* @param data Входящие данные
* @param handler Обработчик
*
* @returns Объект с обработанными полями
*/
export const wrapValues = <T, R>(data: Record<string, T>, handler: (data: T, key: string, object: Record<string, T>) => R): Record<string, R> => export const wrapValues = <T, R>(data: Record<string, T>, handler: (data: T, key: string, object: Record<string, T>) => R): Record<string, R> =>
Object.fromEntries(Object.entries(data).map(([key, value]) => [key, handler(value, key, data)])) Object.fromEntries(Object.entries(data).map(([key, value]) => [key, handler(value, key, data)]))
/**
* Генерирует массив чисел в заданном диапазоне
*
* @param end Конечное значение
* @param start Начальное значение
*
* @returns Массив чисел в диапазоне от `start` до `end`
*/
export const range = (end: number, start: number = 0) => Array.from({ length: end - start }, (_, i) => start + i) export const range = (end: number, start: number = 0) => Array.from({ length: end - start }, (_, i) => start + i)
/** /**
* Объединить типы, исключив совпадающие поля справа * Объединить типы, исключив совпадающие поля справа.
* @param T Тип, передаваемый полностью *
* @param R Аддитивный тип * @typeParam T - Тип, передаваемый полностью
* @typeParam R - Аддитивный тип
*
* @returns Общий тип с полным `T` и несовпадающими полями из `R`
*/ */
export type OmitExtends<T, R> = T & Omit<R, keyof T> export type OmitExtends<T, R> = T & Omit<R, keyof T>

View File

@ -1,7 +1,7 @@
export const makeStringCutter = (maxLength = 100, separator = ' ', suffix = '...') => (comment?: string) => { export const makeStringCutter = (maxLength: number = 100, separator: string = ' ', suffix: string = '...') => (comment?: string) => {
if (!comment || comment.length < maxLength) if (!comment || comment.length < maxLength)
return comment return comment
let lastSep = comment.lastIndexOf(separator, maxLength) const lastSep = comment.lastIndexOf(separator, maxLength)
if (lastSep < 0) if (lastSep < 0)
return comment.substring(0, maxLength - suffix.length) + suffix return comment.substring(0, maxLength - suffix.length) + suffix
return comment.substring(0, lastSep) return comment.substring(0, lastSep)