Skip to content

spbd/dashboard

Repository files navigation

Dashboard для BEM-хакатона

Разработка

Установка зависимостей

Клонировать git репозиторий:

git clone [email protected]:spbd/dashboard.git dashboard && cd $_

Установить npm и bower зависимости:

npm i && bower i

Сборка

Проект собирается с помощью enb-сборщика.

Собрать проект:

./node_modules/.bin/enb make

Так как у нас всего одна нода, ее можно не указывать (enb make dashboard).

От однократной сборки проекта пользы мало. Для комфортной разработки необходимо запустить сервер:

./node_modules/.bin/enb server

Страница будет доступна по адресу - localhost:8080. При обновлении страницы сборщик будет выполнять сборку автоматически.

Контрибьютинг

Рекомендации по именованию веток:

  • widgets/base/<block-name>
  • widgets/specific/<block-name>
  • core/<block-name>
  • core/ui/<block-name>

Для веток c правками добавляется префикс fix, refactor, etc (fix/core/server).

Перед тем как сделать push ветки, необходимо убедиться, что код соответствует заданному CodeStyle:

npm run lint

Перед созданием PR, следует сделать rebase по ветке master:

git rebase master

После создания PR, запустится процесс сборки и выкладки проекта, результаты которого будут доступны по адресу http://spbd.github.io/builds/pr-<PRno>/src. Имеет смысл добавить в описание PR эту ссылку.

При push в ветку master, так же запускается процесс сборки и выкладки. Последний build доступен по адресу - http://spbd.github.io/builds/stable.

Написание виджетов

Макеты к виджетам доступны по адресу: https://github.com/spbd/specs

Конкретный виджет

Как виджет попадает на dashboard

Конкретные виджеты находятся в директории ./widgets.specific. Для добавления виджета на dashboard, никаких манипуляций проводить не нужно. В процессе сборки произойдет все необходимое. А именно:

  • Технология widgets-list прочитает список директорий (одна директория = один виджет) из ./widgets.specific, и создаст CommonJS-модуль, экспортирующий список виджетов и preview для них:
module.exports = [
    {
        "widget": "simple",
        "image": "simple.preview.png"
    }
];
  • Технология widgets-decl расширит файл декларации и допишет имена виджетов, чтобы они попали в зависимости.
  • Технология widgets-manifest создаст CSS файл (он приклеится к основному CSS), который описывает preview виджетов:
.widget-name__manifest_preview
{
   background-image: url(path-to-widget/widget-name.preview.png);
   /* ... */
}

Эти классы автоматически проставятся к нужным виджетам.

  • Технология widgets-ym создаст ym-модуль, содержащий список виджетов, чтобы они были доступны из клиентского кода:
modules.define('widgets-list', function(provide) {
    provide(["widget1", "widget2"]);
});

Заготовка виджета

Стили и шаблоны

Стили можно писать как на CSS так и на Stylus. В роли шаблонизатора выступает BH.

Изображение виджета

Виджет обязательно должен включать файл изображения в технологии preview - .preview.{svg,png,jpg,etc}. Например: ./widgets.specific/name/name.preview.svg.

Зависимости

Базовым блоком для виджета всегда должен служить блок widget, либо блок, который наследует от него. name.deps.js:

({
    shouldDeps: [
        {block: 'widget'}
    ]
});
JS реализация

Конкретный виджет обязательно должен быть инициализирован (метод init()).

modules.define(
    'simple',
    ['i-bem__dom', 'jquery', 'widget'],
    function(provide, BEMDOM, $, Widget) {

provide(BEMDOM.decl({block: this.name, baseBlock: Widget}, {

    onSetMod: {
        js: {
            inited: function() {

                // Если базовым классом является не `widget`,
                // нужно вызвать родительский конструктор
                //
                // this.__base.apply(this, arguments);

                this
                    .widgetAPI()
                    .configure(function(widget, settings) {
                        // Конфигурация виджета
                        // Конфигурация окна настроек
                    })
                    .onSaveSettings(function(controls) {
                        // Сработает, когда будет нажата кнопка
                        // "save" в окне настроеек.
                        //
                        // controls - значение всех элементов окна настроек
                    })
                    .onShowSettings(function() {
                        // Сработает, когда будет нажата кнопка "SET".
                    })
                    .onLoadWidget(function(controls) {
                        // Сработает, когда виджет будет загружен из хранилища
                        // "save" в окне настроеек.
                        //
                        // controls - значение всех элементов окна настроек
                    })
                    .init(); // Инициализировать базовый виджет
            }
        }
    }

}));

});
API конфигуратора
//...
.configure(function(widget, settings) {
    widget.setProps({
        width: 200,  // ширина виджета по умолчанию
        height: 260  // высота виджета по умолчанию
    });

    settings.setProps({
        width: 200, // ширина окна настроеек
        height: 260 // высота окна настроеек
    })
    .input({    // cоздать input
        placeholder: 'hint', // подсказка
        label: 'Text area',  // метка (опциональное поле)
        handler: this.handle // обработчик состояние change
    })
    .checkbox({ // cоздать checkbox
        text: 'Simple checkbox', // текст перед элементов
        handler: this.handle     // обработчик события change
    })
    .select({   // создать select
        options: [ // элементы
            {val: '1', text: 'text1'},
            {val: '2', text: 'text2', checked: true},
            {val: '3', text: 'text3'}
        ],
        handler: this.handle, // обработчик состояния change
        label: 'Foo select'   // метка (опциональное поле)
    });
    .radioGroup({   // создать radio-group
        options: [ // элементы
            {val: '1', text: 'text1'},
            {val: '2', text: 'text2', checked: true},
            {val: '3', text: 'text3'}
        ],
        handler: this.handle, // обработчик состояния change
        label: 'This is super radio-group'   // метка (опциональное поле)
    });

    // Во все обработчики приходит параметр,
    // содержащий новое состояние элемента
})
//...
Общение с сервером

Общение с сервером происходит посредством модуля server, который общается с реальным сервером через WebSocket. Достаточно добавить модуль в зависиомсти и подисаться на события для конкретного виджета.

server.on('widgets/name/event', function(e, data) {
    console.log(data);
});

В данный момент сервер не реализован. В модуле server описаны фикстурные данные для разработки.

Базовый виджет

Базовый виджет отличается от конкретного лишь тем, что в нем не выполняется инициализация (метод конфигуратора .init()). Распологаются такие виджеты в директории ./widgets.base.

Ссылки на документацию