Перейти к основному содержимому

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
  1. Перейдите в ветку проекта
  2. git checkout <project_name>
  3. Установите зависимости
  4. npm install
  5. Запустите команду
  6. npm run pull
  7. которая скачает с сервера последнюю версию ресурсов (потребуются имя пользователя и пароль). Если ресурсы на сервере отличаются от локальных, будет выведен список изменений и ожидаться подтверждение перезаписи локальных файлов
  8. Запустите проект
  9. npm start
  10. Зайдите браузером по адресу http://localhost:3000, там будет доступен сервер проекта, но файлы ресурсов будут браться из папки /src проекта
  11. Работайте над файлами в папке /src и проверяйте их работу в браузере.
  12. По окончании закоммитьте код в git-репозиторий и выполните команду
  13. npm run push
  14. Для отправки изменений в ресурсы сервера. Потребуются имя пользователя и пароль. Команда выведет список измененных файлов и запросит подтверждение их отправки на сервер.

Команды

Реализованы три команды

  1. npm run pull
    Все ресурсы с сервера будут скачены в папку /src проекта. Лишние локальные файлы будут удалены.
    Команда запросит имя пользователя и пароль (если не указаны к конфиге), сравнит ресурсы сервера с локальными файлами, напечатает список измененных файлов и запросит подтверждение.

  2. npm run push
    Заливает все локальные файлы на сервер. Отсутствующие локально файлы будут удалены на сервере.
    Команда запросит имя пользователя и пароль (если не указаны в конфиге), сравнит локальные файлы с серверными, напечатает список измененных файлов и запросит подтверждение.

  3. npm start
    Запускает на http://localhost:3000 http сервер для разработки с настроенным проксированием на указанный в конфиге сервер. Проксируются все файлы, кроме /srv/resources которые берутся из папки /src

Конфигурация

Проект считывает конфигурацию последовательно из разных источников.
В конфигурацию входят:

  • server - http адрес сервера, например http://project.luxmsbi.com/
  • username - имя пользователя для доступа к серверу. Требуются админские права
  • password - пароль для пользователя username
  • port - порт для запуска локального сервера для npm start
  • force - выдавать ли предупреждение перед обновлением источника
  • 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 будет одномерный.