internal
Итак, вы выбрали в типе визуализаций «Внутрений» (view_class = internal
в JSON editor).
Для internal
так же нужен ключ url
, который строится по тем же правилам, что и в external
, но указывается уже js
файл.
Так же можно в случае, если компонент находится в ресурсах датасета ds_res
прописать вместо view_class = название_файла_собранного компонента (без расширения .js)
, например
view_class = MyComponent
, тогда блок с ключом url
уже не нужен.
В данном случае веб-клиент ожидает, что ему будет отдан js
файл, являющийся собранной версией tsx
или jsx
наследника React.Component
. Соответственно в разделе resources.
откуда будет браться такой файл (н-р, MyComponent.js
) должны быть два файла: MyComponent.js
и MyComponent.js.map
, нативно берущиеся как результат сборки webpack
. Но собирать такие файлы вручную вам не придется, за это отвечает проект luxmsbi-web-resources
, созданный для манипуляции всеми resources
всех датасетов сервера, с которым вы работаете.
Рассмотрим проект luxmsbi-web-resources
.
Проект создан для упрощения работы с ресурсами Luxms BI и для организации их хранения в репозитории.
Для каждого проекта создается своя ветка, которая будет хранить все ресурсные файлы, их историю и скрипты для синхронизации
Сценарий использования
Требования:
- Наличие админского имени пользователя и пароля для доступа к Luxms BI
- Перейдите в ветку проекта
git checkout <project_name>
- Установите зависимости
npm install
- Запустите команду
npm run pull
- которая скачает с сервера последнюю версию ресурсов (потребуются имя пользователя и пароль). Если ресурсы на сервере отличаются от локальных, будет выведен список изменений и ожидаться подтверждение перезаписи локальных файлов
- Запустите проект
npm start
- Зайдите браузером по адресу
http://localhost:3000
, там будет доступен сервер проекта, но файлы ресурсов будут браться из папки/src
проекта - Работайте над файлами в папке
/src
и проверяйте их работу в браузере. - По окончании закоммитьте код в git-репозиторий и выполните команду
npm run push
- Для отправки изменений в ресурсы сервера. Потребуются имя пользователя и пароль. Команда выведет список измененных файлов и запросит подтверждение их отправки на сервер.
Команды
Реализованы три команды
npm run pull
Все ресурсы с сервера будут скачены в папку/src
проекта. Лишние локальные файлы будут удалены.
Команда запросит имя пользователя и пароль (если не указаны к конфиге), сравнит ресурсы сервера с локальными файлами, напечатает список измененных файлов и запросит подтверждение.npm run push
Заливает все локальные файлы на сервер. Отсутствующие локально файлы будут удалены на сервере.
Команда запросит имя пользователя и пароль (если не указаны в конфиге), сравнит локальные файлы с серверными, напечатает список измененных файлов и запросит подтверждение.npm start
Запускает наhttp://localhost:3000
http сервер для разработки с настроенным проксированием на указанный в конфиге сервер. Проксируются все файлы, кроме/srv/resources
которые берутся из папки/src
Конфигурация
Проект считывает конфигурацию последовательно из разных источников.
В конфигурацию входят:
server
- http адрес сервера, например http://project.luxmsbi.com/username
- имя пользователя для доступа к серверу. Требуются админские праваpassword
- пароль для пользователя usernameport
- порт для запуска локального сервера для npm startforce
- выдавать ли предупреждение перед обновлением источникаnoRemove
- запрещает удалять файлы, если при синхронизации они не найеныinclude
- регулярное выражение для схем, которые следует включить (^ds_\w+$
по умолчанию)exclude
- регулярное выражение для схем, которые следует исключить
Если значенияserver
,username
илиpassword
нигде не найдены, то их потребуется ввести с клавиатуры.
Источники конфигурации
Опции командной строки
При запуске команды можно указать любые из опций:
--server=...
--username=...
--password=...
--port=...
--force
--no-remove
--include=...
--exclude=...
Опции командной строки необходимо отделять от команды знаком --
npm run push -- --server=http://project.luxmsbi.com/ --username=admin --password=secret --exclude=ds_resnpm start -- --server=http://project.luxmsbi.com/
Переменные окружения
Те же имена, но должны быть написаны заглавными буквами с префиксом BI_:
BI_SERVER
BI_USERNAME
BI_PASSWORD
BI_PORT
BI_FORCE
BI_NO_REMOVE
BI_INCLUDE
BI_EXCLUDE
Например:
BI_SERVER=http://project.luxmsbi.com/ npm startBI_FORCE=yes BI_EXCLUDE=ds_res npm start
export BI_USERNAME=adminexport BI_PASSWORD=secretnpm run push
Файлы конфигурации
В корне проекта лежит файл config.json
, который хранит значение конфигурации server
{ "server": "http://project.luxmsbi.com/"}
Этот файл должен лежать в каждой ветке проекта и указывать корректный сервер. Можно создать в корне проекта файл authConfig.json
и в нем указать имя пользователя и пароль
{ "username": "admin", "password": "secret"}
Этот файл занесен в .gitignore
и не должен попасть в git
.
Для работы с разными проектами можно в файл authConfig занести разные записи, для каждой ветки. Ключем явояется название ветки git
, значениями - username
и password
{ "project1": { "username": "project1admin", "password": "secret" }, "project2": { "username": "project2admin", "password": "secret2" }}
Приложение будет брать соотвествующий конфиг по названию текущей ветки git
.
Ввод с клавиатуры Если значение не найдено ни одим из предыдущих способов, команды npm start
, npm run pull
и npm run push
запросят их ввод с клавиатуры
Примеры
server
- указать удаленный сервер, с которым синхронизировать ресурсы
Способы указать сервер Аргументами командной строки:
$ npm run push -- --server=http://project.luxmsbi.com:8000/
Через переменную окружения
$ export BI_SERVER=http://project.luxmsbi.com:8000/$ npm run push
$ BI_SERVER=http://project.luxmsbi.com:8000/ npm run push
Через конфиг файл
$ cat config.json{ "server": "http://project.luxmsbi.com:8000/"}$ npm run push
port
- локальный порт для запуска npm start
Способы запустить проект на порту 8080, вместо порта по умолчанию 3000
$ npm start -- --port=8080
$ BI_PORT=8080 npm start
$ cat config.json{ "server": "http://project.luxmsbi.com", "port": 8080}$ npm start
Примечания
Команда npm start
не требует ввода имени пользователя и пароля, для работы ей требуется только server.
Однако, если перейти в браузере на http://localhost:3000/#/ds/ds_xxx/resources
то в консоли может запроситься имя пользователя и пароль (если не указаны каким либо другим образом). Они необходимы для конвертации resource.id
в имя файла.
Этот проект позволяет вам использовать git
, чтобы синхронизовать работу разработчиков над ресурсами сервера и без проблем совместно разрабатывать.
Важно помнить, что тому, что вы сами коммитите и пушите в репозиторий вы должны доверять больше, чем тому, что получили средствами npm run pull
. Эту команду следует использовать единожды при первичной инициализации проекта web-resources. Проще говоря: если src
пустой.
Итого ваша работа должна быть следующей: вы создали ряд файлов, написали код компонентов и провели какую-то иную работу, убедились, что все работает на вашем локальном сервере так, как нужно, совершили git commit
, git pull
, git push
(попутно на этих этапах вы разрешили конфликты при мердже, если они будут) и уже после этого вызываете npm run push
. Эта команда соберет все ваши jsx-tsx
файлы и массово зальет все ваши ресурсы на сервер. Произойдет сравнение файлов на предмет различий и вам выдастся вопрос на подтверждение действий (залить новые файлы (список), удалить файлы (список)) + укажется общее число файлов, которые отправляются на сервер. В случае подтверждения - вы перезапишите все файлы на сервере вашей версией файлов. Это важно помнить, так как в случае совместной работы вы можете перезатереть файлы друг друга. Именно поэтому настоящие версии файлов хранятся в git
, а не на сервере. Именно поэтому обязательно перед git push
делайте git pull
и не доверяйте npm run pull
(эту команду использовать только в крайних случаях, в идеале единожды за все время использования проекта).
Если же кто-то зальет на сервер файл обычным способом через drug’n’drop, то ваш проект об этом не узнает, как он не узнает, что кто-то вручную изменил код файла, зайдя на раздел resources
и через редактирование файла изменив его контент. Здесь необходима договоренность между собой разработчиков и всех, кто управляет файлами о едином способе взаимодействия с ними. Плюс разумеется запрещать это правами доступа, где это уместно.
Итак, мы развернли локальный сервер на проекте luxmsbi-web-resources
. Открываем страницу дешборда датасета с нужным дешлетом (он вполне может быть единственным и занимать все доступное для дешлетов пространство). После того как вы загрузили основную картину проекта через npm run pull
команду проекта, т.е. у вас уже есть папки с названиями существующих датасетов, внутри одной из таких папок вы можете создавать реакт-компонент в виде tsx
или jsx
файлов с кодом например таким:
import React from "react";
export default class MyComponent extends React.Component<any> {
public state: {
someState: any;
};
public constructor(props) {
super(props);
this.state = {
someState: [],
};
public render() {
return (
<>Hello Word!</>
);
}
}
Такой файл вы прежде всего в базовом виде должны залить на сервер через команду npm run push
, где он будет существовать как пара js
и js.map
файлов с тем же именем.
Теперь вы можете выбрать новый файл в режиме редактирования дешлета как источник типа визуализации «Внутренний».
Все, теперь вы должны увидеть результат рендера вашего компонента в рабочей области дешлета. и вы можете писать код внутри своего файла на компьютере, где просто обновлять страницу при изменениях (хотя в большинстве случаев вы сразу увидите изменения без нее).
В качестве props вам придут несколько переменных, в основном служебны, но значимые для разработки эти:
dp, cfg, subspace
cfg:
Объект типа IVizelConfig
содержащий информацию о текущем дешлете, его конфигурации и ряд методов для получения его основных полей
интерфейс IVizelConfig
:
_raw: any;
dataset: IDatasetModel;
getDataset(): IDatasetModel;
getProperty(key): any;
setProperty(key: string, value: any): void;
getLegendItem(e: IEntity, idx?: number): tables.ILegendItem;
serialize(): tables.IRawVizelConfig;
clone(): IVizelConfig;
getDisplay(vizelType?: string): IVizelConfigDisplay;
getRange(): IRange;
disableRange(): void;
getUrl(): string;
dataSource?: tables.IDataSource;
getVizelType(): string;
setVizelType(vizelType: string): void;
setTitle(title: string): void;
getSubspacePtr(): ISubspacePtr;
controller: IVizelController;
title?: string;
description?: string;
legend?: { [id: string]: tables.ILegendItem; };
badValueColor?: string;
goodValueColor?: string;
normsMainColor?: string;
onClickDataPoint?: string | any;
onClick?: string | any;
cardId?: string;
externalUrl?: IUrl;
dashboardId?: string;
dashId?: string;
normStrategy?: string;
context?: any;
titleContext?: string[];
colorResolver?: IColorResolver;
titleResolver?: ITitleResolver;
getRaw(): tables.IRawVizelConfig;
Самый простой случай , при котором этот объект вам понадобится - использование метода getRaw()
чтобы получить тот конфиг, что вы видите в режиме редактирования дешлета и поле title
- название дешлета, плюс метод getTitle
, которому на вход можно отдать межу или дименшн и получить итоговое значение его названия, взятое с учетом того, что для него может быть прописано в блоке style
раздела datasource
.
subspace
- Собирательная модель, описывающая сущности, с которыми мы работаем,. Что на осях лежит и чем придется манипулировать.
интерфейс ISubspace:
koob?: string;
filters?: any;
axesOrder: any;
ms: IMetric[];
ls: ILocation[];
ps: IPeriod[];
xs: IEntity[];
ys: IEntity[];
zs: IEntity[];
aas?: IEntity[];
abs?: IEntity[];
dimensions?: any[];
measures?: any[];
getZ(idx: number): IEntity;
getY(idx: number): IEntity;
getX(idx: number): IEntity;
getMLP(z: IEntity, y: IEntity, x: IEntity): any;
reduce(nx: number, ny: number, nz: number): ISubspace;
isEmpty(): boolean;
splitByZ?(): ISubspace[];
splitByY?(): ISubspace[];
splitByX?(): ISubspace[];
getZYXIndexesByMLPIds(mid: string, lid: string, pid: string): [number, number, number];
projectData(mlpCube: any): IValue[][][];
getArity(): number;
getRawConfig(): any;
toString(): string;
Вам потребуются значения xs
, ys
и zs
, чтобы из них строить логику отрисовки графика, а также получения информации о каждом фигуранте на осях через методы getY
, getX
, getZ
.
dp
- Датапровайдер, обеспечивает методы для получения данных с сервера в рамках того, что указано в subspace
.
Модуль data_engine:
export declare module data_engine {
export type IMLPSubscribeCallback = (m: IMetric, l: ILocation, p: IPeriod, v: number) => void;
export type ISubscribeCallback = (z: IEntity, y: IEntity, x: IEntity, v: number) => void;
export interface IRawRequest {
data?: boolean;
norms?: boolean;
aggregate?: boolean;
}
export interface IRawResponse {
data?: tables.IDataEntry[];
norms?: tables.INormDataEntry[];
aggregate?: IAggregate;
}
export interface IRawDataProvider {
getRawData(mlpSubspace: IMLPSubspace, closest?: boolean): Promise<tables.IDataEntry[]>;
getRawNorms(mlpSubspace: IMLPSubspace): Promise<tables.INormDataEntry[]>;
getRawColors(mlpSubspace: IMLPSubspace): Promise<any>;
getAggregate(mlpSubspace: IMLPSubspace): Promise<any>;
load(request: IRawRequest, mlpSubspace: IMLPSubspace, closest?: boolean): Promise<IRawResponse>;
rawSubscribe(mlpSubspace: IMLPSubspace, callback: IMLPSubscribeCallback): IDisposable;
}
export interface ICubeProvider {
getCube(subspace: ISubspace, closest?: boolean): Promise<IValue[][][]>;
}
export interface IMatrixProvider {
getMatrixYX(subspace: ISubspace, closest?: boolean): Promise<IValue[][]>;
}
export interface IVectorProvider {
getVectorX(subspace: ISubspace, closest?: boolean): Promise<IValue[]>;
getVectorY(subspace: ISubspace, closest?: boolean): Promise<IValue[]>;
}
export interface IValueProvider {
getValue(subspace: ISubspace, closest?: boolean): Promise<IValue>;
}
export interface INormsProvider {
getNorms(subspace: ISubspace): Promise<INormsResponse>;
}
export interface IColorsProvider {
// getColors
}
export interface IDataProvider extends IRawDataProvider, ICubeProvider, IMatrixProvider, IVectorProvider, IValueProvider, INormsProvider, IColorsProvider {
subscribe(subspace: ISubspace, callback: ISubscribeCallback): IDisposable;
}
}
Для получения декартового произведения фигурантов на оси Х и У - нужно вызвать метод
dp.getMatrixYX(subspace).then(data => {
// тут обработка данных в виде массива массивов значений (строка или число)
})
Если же вся картина не нужна, можно вызвать лишь одну строку или один столбец такой матрицы через методы getVectorX
, getVectorY
, аналогично методу выше, но массив data
будет одномерный.