Отладка в nodejs

Актуально для версии Node JS 8.9.0

Устанавливаем:
npm install —global node-inspect

Выполняем команду: node —inspect-brk [filename].js

Должен открыться chrome для начала отладки

Полезные статьи.

https://nodejs.org/en/docs/inspector

https://nodejs.org/api/debugger.html

https://github.com/nodejs/node-inspect

Sencha cmd — быстрый старт

Создание проекта:

— генерация проекта
sencha -sdk «D:\Install_new\sencha\ext-6.0.0-gpl\ext-6.0.0\» generate app App1 «E:\serp\work\_sencha\App1»
— или
sencha -sdk «D:\Install_new\sencha\ext-6.0.0-gpl\ext-6.0.0\» generate app -modern App1 «E:\serp\work\_sencha\App1»

— дальше перейти в сгенерированный проект
cd /D «E:\serp\work\_sencha\App1»

— запускаем проект, теперь он доступен по адресу http://localhost:1841/
sencha app watch

— билдим
sencha app build modern production
sencha app build modern production «d:/temp»
sencha app build modern testing

— дополнительный действия при билде(build.xml), в примере ниже копирование файла config.json



Как собрать проект под android:

— чтобы cordova была доступна из командной строки
npm install -g cordova

— подготавливаем проект, создает папку cordova и добавляет в app.json «builds»: «native», если builds не был определен

— «builds»: «native» надо будет еще подправить ручками, выбрать «platforms»
sencha cordova init com.iserv.cabinet Cabinet

«builds»: {
«native»: {
«packager»: «cordova»,
«cordova»: {
«config»: {
«platforms»: «android»,
«id»: «com.iserv.cabinet»,
«name»: «Cabinet»
}
}
}
},

— запускает приложение на android
sencha app run native

— билдит мобильную версию. Для android результат кладет в cordova\platforms\android\build\outputs\apk\android-debug.apk
sencha app build native

— установка на android
D:\android-sdk\platform-tools\adb kill-server
D:\android-sdk\platform-tools\adb install -r «cordova\platforms\android\build\outputs\apk\android-debug.apk»

— shell
D:\android-sdk\platform-tools\adb shell
D:\android-sdk\tools\ddms.bat
— какие устройства подключены к компьютеру
D:\android-sdk\platform-tools\adb devices

Запуск тестов Siesta из консоли с помощью PhantomJS

В проект добавлен скрипт run-siesta.js в папку с тестами. Он предназначен для того, чтобы с помощью PhantomJS запускать тесты Siesta. run-siesta.js использует API PhantomJS для запуска страницы c тестами и выводит в консоль и в текстовый файл siesta_log.txt логи, которые формируются на странице index.html.

Также в скрипте index.js изменен Harness.configure — в него добавлены дополнительные обработчики событий: testfinalize, testsuiteend и условие автозапуска autoRun: true.

При завершении тестов run-siesta.js парсит тестовую страницу на общее количество пройденных тестов, выводит общее затраченное время и возвращает соответствующий числовой идентификатор в консоль (0 – успех, 1 — ошибка).

Пример команды в консоли: D:\…\Omnis-ExtJS\Pir\Siesta\phantomjs run-siesta.js http://localhost:62681/Siesta/index.html

Для выполнения команды ‘phantomjs’ нужно установить сам PhantomJS — http://phantomjs.org/download.html, и прописать в PATH системы — путь к исполняемому файлу phantomjs.exe, или скопировать phantomjs.exe в папку с тестами D:\…\Omnis-ExtJS\Pir\Siesta\ и запускать команду: D:\…\Omnis-ExtJS\Pir\Siesta\phantomjs.exe run-siesta.js http://localhost:62681/Siesta/index.html На момент написания использовалась версия PhantomJS 2.0 — http://phantomjs.org/

Sencha CMD. Как правильно подключить собственные библиотеки.

Надо начать с того, что приложение, запущенное с помошью «sencha app watch», работает немного по-другому, чем приложение, собранное с помощью «sencha app build».

В случае «sencha app watch» нет никакого минификатора, загрузка библиотек идет из секции «js», определенной в файле app.json. Единственное, что собирается, это стили css, они кидаются в папку build/temp

В случае «sencha app build» есть минификатор, все библиотеки собираются в один файл. Пути для минификатора прописываюся в секции «classpath» файла app.json. При этом загрузку библиотек из секции «js» тоже никто не отменяет.

Из этого рождаются правила:
•если вы хотите подключить свою библиотеку, поместите ее в один из каталогов, определенный в «classpath», этим мы обеспечим то, что наша библиотека попадет в общий файл при работе минификатора.
•пропишите путь к этой библиотеки в секции «js», это позволит загружать ее при команде «sencha app watch».
•для прописанного пути в секции «js» поставьте «bootstrap»: true. Это нужно для того, чтобы эти пути учитывались только для «sencha app watch», но не попадали в финальный файл конфигурации после команды «sencha app build».

Если что-то сделать неправильно, то Extjs ругнется примерно такими словами: «Failed to resolve dependency It.app.Application…»
Пример подключения библиотеки it.core.js:

"classpath": [
     "app",
     "${toolkit.name}/src"
 ],
 
"js": [
     {
         "path": "app/it.core.js",
         "bootstrap": true
     },
     ...
 ],

setInterval или Ext.direct.PollingProvider

Иногда в приложениях требуется обращение к серверу по определенному интервалу времени. Стандартными средствами JavaScript’a это делается примерно так:

setInterval(function() {
     RPC.util.Format(function() {
           ...
     });
}, 5000);

Но в ExtJS есть более корректный подход, использовать Ext.direct.PollingProvider. Если кратко, то Ext.direct.PollingProvider — это провайдер, который сам запрашивает данные с сервера с помощью direct-функции по таймеру.

PN.RPC.POLLING_API = {
           type: 'itpolling',
           pollFn: 'RPC.util.Format,
           id: 'datePoller',
           interval: 2000,
           listeners: {
               data: function (provider, e, eOpts) {
                    // e.response - здесь хранится результат выполнения
                    var poll = Ext.direct.Manager.getProvider('datePoller');
                    poll.disconnect(); // если хотим завершить запросы
               }
           }
       };
       setInterval()
       // register the polling API to the PollingProvider.
       Ext.Direct.addProvider(PN.RPC.POLLING_API);

Данный способ отлично подходит если, например, нужно запрашивать какую-либо direct — функцию. В руководстве ExtJS type указан как polling, но здесь используется наши itpolling В нем переопределены некоторые методы для работы с нашим itdirect

!!!Внимание. Помните о том что большое количество запросов к серверу могут «положит» пул IIS

Код провайдера

Ext.define('It.direct.PollingProvider', {
    extend: 'Ext.direct.PollingProvider',
    alias: 'direct.itpollingprovider',
    requires: [
        'Ext.Ajax',
        'Ext.util.TaskRunner',
        'Ext.direct.ExceptionEvent'
    ],
    type: 'itpolling',
 
    /*
     * переопределен
     */
    onData: function (opt, success, response) {
        var me = this,
            i, len, events;
        if (success) {
            //events = me.createEvents(response);
            //for (i = 0, len = events.length; i < len; ++i) {
                me.fireEvent('data', me, response);
            //}
        } else {
            events = new (Ext).direct.ExceptionEvent({
                data: null,
                code: Ext.direct.Manager.exceptions.TRANSPORT,
                message: 'Unable to connect to the server.',
                xhr: response
            });
            me.fireEvent('data', me, events);
        }
    },
 
    /*
     * переопределен
     */
    onPollFn: function (result, event, success, options) {
        this.onData(null, success, {
            response: result
        });
    }
}) 

Работа с датами в ExtJS. Меняем локализацию

По умолчинию ExtJS применяет en-локализацию. Чтобы поменять ее на ru выполните следующие действия:

— в app.json добавляем следующие параметры:

"requires": [
    "font-awesome",
    "ext-locale" // пакет с локализациями
],
 
"locale": "ru" // устанавливаем культуру

Полный перечень культур можно посмотреть в папке ext\classic\local\overrides

— после этого запускаем команду app build

— открываем файл ext\classic\local\overrides и добавлем следующие параметры в объект Ext.locale.ru.form.field.Date

 ***
format: "d.m.Y",
dateFormat: "d.m.Y", // формат даты который выводиться в поле
submitFormat: 'm/d/Y H:i:s' // требуется для правильного конвертирования даты на клиенте
  ***

— далее в настройках прокси, для store, требуется указать следующий параметр

Ext.define('PN.store.FS_Service_Groups_FS_ServicesCollection_ListView',
{
    extend: 'Ext.data.Store',
    model: 'PN.model.FS_Service_Groups_FS_ServicesCollection_ListView',
    //autoLoad: true,
 
    remoteFilter: true,
    remoteSort: true,
    remoteGroup: true,
 
    proxy: {
        type: 'itdirect',
        api: {
            read:       PN.Domain.FS_Services.Query,
            create:     PN.Domain.FS_Services.Add,
            update:     PN.Domain.FS_Services.Update,
            destroy:    PN.Domain.FS_Services.Delete
        },
        reader: {
                successProperty: 'success',
                rootProperty: 'records',
            } ,
        writer : {
        dateFormat: "d.m.Y H:i:s" // даты на сервер будут возвращаться именно в этом формате
        }
    }
});

Splash screen для ExtJS приложения

Чтобы вывести сообщение об ожидании, при старте приложения ExtJS, требуется выполнить следующие действия.

Находим index.html файл добавляем в него следующий код

Загрузка ExtJS…

Данное сообщение будет выводиться да начала готовности Ext.Application.

!!! Внимание. Требуется наследоваться от It.app.Application

В файле app.js указать следующий параметр:

Ext.application({
    name: 'ImportSubstitution',
    ***
    splashscreen: true,
    ***

Ну вот и все!
Как это реализовано?

В базовом классе произведены следующие изменения:

/*
 * Объект для хранения splashscreen переменной
 */
splashscreen: null,
constructor: function () {
       var startExtJSMessage = Ext.get('start-extjs');
       if (startExtJSMessage)
           startExtJSMessage.hide();
 
       if (this.splashscreen == true) {
           // start the mask on the body and get a reference to the mask
           this.splashscreen = Ext.getBody().mask('Загрузка приложения...', 'splashscreen');
       }
       this.callParent(arguments);
   },

/*
 * Инициализация splashscreen
 */
initSplashScreen: function () {
    if (typeof this.splashscreen == 'object') {
        this.splashscreen.destroy();
    }
},

onProfilesReady: function () {
    var me = this;
    me.loadRemotingApi(() => {
        me.initControllers();
        me.onBeforeLaunch();
        me.initSplashScreen();
        me.finishInitControllers();
    });
},

Динамическое дерево в ExtJS modern

В данной статье пойдет речь о том, как создать динамическое дерево (TreeList) в ExtJS Modern. Возможно данная реализация есть в «коробке», но я ее не нашел.

Стандарный компонент treelist отлично работает, если в хранилище находится например 100 записей, но если их будет тысяча или более? У меня получилось так, что мобильный телефон стал заметно тормозить. И после долгих поисков решения в интернете, решил доработать компонент.

Первое что я сделал — это создал наследник от treelist

Ext.define('MobileService.view.routeList.items.MobileTreeList', {
    extend: 'Ext.list.Tree',
    xtype: 'mobiletreelist',
 
    privates: {
// expand - стоит строить дочернии элементы или нет. По умолчанию null createItem: function (node, parent, expand) { var isRootItem = node.get('isRootItem'); // требуется для определения корневого элемента (те записи которые видит пользователь на первом уровне) if (!isRootItem && !expand) return null; return this.callParent(arguments); }, // переопределен. Основной метод для добавления дочерних элементов onNodeExpand: function (node) { var item = this.getItem(node); var childNodes = node.childNodes; for (i = 0, len = childNodes.length; i < len; ++i) { child = childNodes[i]; if (!this.itemMap[child.internalId]) { var _item = item.getOwner().createItem(child, item, true); if (_item) { this.itemMap[child.internalId] = _item; item.insertItem(_item, null); } } } this.callParent(arguments); } } });

Второе, создаем наследник от Ext.list.TreeItem

/*
 * для вывода дерево документов и строк я создал собственный класс для TreeItem
 */
Ext.define('MobileService.view.routeList.items.RouteListItem', {
    extend: 'Ext.list.TreeItem',
    xtype: 'routelistitem',
 
    privates: {
        updateNode: function (node) {
            if (node) {
                var me = this,
                    map = me.itemMap,
                    childNodes, owner, len, i, item, child;
                me.element.dom.setAttribute('data-recordId', node.internalId);
                if (!map) {
                    childNodes = node.childNodes;
                    owner = me.getOwner();
                    me.itemMap = map = {};
                    for (i = 0, len = childNodes.length; i < len; ++i) {
                        child = childNodes[i];
                        item = owner.createItem(child, me);
                        if (item) { // добавили проверку на возможность создания ветки
                            map[child.internalId] = item;
                            me.insertItem(item, null);
                        }
                    }
                }
                me.setExpanded(node.isExpanded());
                me.doNodeUpdate(node);
            }
        }
    }
});

Третье, создаем данные для хранилища

var root = {
    expanded: true,
    children: [
        {
            text: 'item1',
            isRootItem: true,
            children: [
                ....
            ]
        },
        {
            text: 'item1',
            isRootItem: true,
            children: [
                ....
            ]
        }
    ]
};
var store = Ext.create('Ext.data.TreeStore', {
            root: root
});

Наконец и сам компонент

                xtype: 'mobiletreelist',
                height: '100%',
                defaults: {
                    xtype: 'routelistitem'
                }

Вроде все, должно работать. Все дочернии элементы будут отрисовывать динамически

Ext JS 6.0.0.640

Выводим Дочерние Страницы На Родительской

Для того, чтобы отобразить список дочерних страниц под родительской, вам понадобится добавить следующий код в файл functions.php темы:

function devise_list_child_pages() {

global $post;

if ( is_page() && $post->post_parent )

$childpages = wp_list_pages( ‘sort_column=menu_order&title_li=&child_of=’ . $post->post_parent . ‘&echo=0’ );
else
$childpages = wp_list_pages( ‘sort_column=menu_order&title_li=&child_of=’ . $post->ID . ‘&echo=0’ );

if ( $childpages ) {

$string = ‘

    ‘ . $childpages . ‘

‘;
}

return $string;

}

add_shortcode(‘devise_childpages’, ‘devise_list_child_pages’);

Оригинал статьи.

Настройка и установка git на собственном сервере

Устанавливаем следующие компоненты:

apt-get install git

apt-get install fcgiwrap spawn-fcgi — нужно для nginx

apt-get install gitweb — web сайт для git. Настройки можно изменить в /etc/gitweb.conf (обычно здесь меняет параметр $projectroot)

Настраиваем nginx для GitWeb

server
{
  access_log /var/log/nginx/gitweb.access.log;

  error_log /var/log/nginx/gitweb.error.log info;

  server_name gitweb.developernote.com;

  location /index.cgi {
    root /usr/share/gitweb/;
    include fastcgi_params;
    gzip off;
    fastcgi_param SCRIPT_NAME $uri;
    fastcgi_param GITWEB_CONFIG /etc/gitweb.conf;
    fastcgi_pass  unix:/var/run/fcgiwrap.socket;
  }
  location / {
    root /usr/share/gitweb/;
    index index.cgi;
  }
}

Далее создаем директорию для хранения репозиториев

cd /var/www
mkdir git
cd /var/www/git
git init --bare project.git
cd project.git
touch readme
git add .
git commit -m "first"
chown -R www-data:www-data . 
chmod -R 777 .
service fcgiwrap restart # возможно это не нужно выполнять

После этого можно спокойно открыть сайт по адресу gitweb.developernote.com

Теперь настраиваем сам git. В Nginx добавляем еще один сайт

server
{
  access_log /var/log/nginx/git.access.log;

  error_log /var/log/nginx/git.error.log info;

  server_name git.developernote.com;

  gzip off;

  location / {
        root /home/git/repositories;

        fastcgi_pass unix:/var/run/fcgiwrap.socket;
        fastcgi_param SCRIPT_FILENAME   /usr/lib/git-core/git-http-backend;
        fastcgi_param PATH_INFO         $uri;
        fastcgi_param GIT_PROJECT_ROOT  /home/git/repositories;
        fastcgi_param GIT_HTTP_EXPORT_ALL "";
        fastcgi_param REMOTE_USER $remote_user;
        include fastcgi_params;
  }
}

И если все правильно настроить, то гит должен заработать

Чтобы использовать авторизацию нужно установить

apt-get install apache2-utils

sudo htpasswd /var/www/git/htpasswd hitesh , где
/var/www/git/htpasswd путь где содержится файл, каталог которого должен быть заблокирован
hitesh — имя пользователя для доступа

И в Настройках nginx сайтов прописываем

server
{
 ...
  auth_basic "GitWeb requires authorization";
  auth_basic_user_file /home/git/.gitpasswd;
  
  ...
}

Оригинал статьи: https://developernote.com/2015/01/installing-git-on-ubuntu-12-04-and-enabling-http-access-with-nginx/