Страницы

Поиск по вопросам

Показаны сообщения с ярлыком angular2. Показать все сообщения
Показаны сообщения с ярлыком angular2. Показать все сообщения

среда, 4 марта 2020 г.

Не работает [(ngModel)] в md-select(Angular Material)

#angular2


Вывожу в компоненте


    
        {{food.viewValue}}
    
 


Браузер выдаёт ошибку: 

В классе пишу:

selected: any = [
    {viewValue: "Элемент 1", value: "0"},
    {viewValue: "Элемент 2", value: "1"},
    {viewValue: "Элемент 3", value: "2"},
    {viewValue: "Элемент 4", value: "3"},
];
selectedOne: string = "0";


Делаю всё по доке Material Angular
Но всё равно не хочется ставить элемент по умолчанию. Кто знает в чём может быть причина?
Angular cli 4.3; material 2.0
    


Ответы

Ответ 1



Директива ngModel расположена в модуле FormsModule из @angular/forms. Поэтому для ее использования нужно импортировать этот модуль в модуль где находит указанный компонент.

пятница, 24 января 2020 г.

Как правильно csrftoken от django в angular2?

#python #django #angular2


Доброго времени суток,

Переписываю проект с angular (роутинг был на стороне backend) на angular 2
На стороне backend стоит django. Написал роутинг, аутентификацию по средством записи
в куки (использовал для этого пакет angular2-cookie).
Ранее, для того чтобы просто забрать csrftoken, чтобы спокойно писать код, использовал
своего рода небольшой костыль:

let token = document.cookie.replace(/(?:(?:^|.*;\s*)csrftoken\s*\=\s*([^;]*).*$)|^.*$/,
"$1");


Но теперь этот вариант не работает, а как правильно работать с csrftoken django -
angular2 не могу в полной мере разобраться.

Буду благодарен, если кто-нибудь поможет в этой сложившейся ситуации. Спасибо
    


Ответы

Ответ 1



Вам стоит посмотреть сюда: https://angular.io/docs/ts/latest/guide/security.html Your server may use a different cookie or header name for this purpose. An Angular application can customize cookie and header names by providing its own CookieXSRFStrategy values. { provide: XSRFStrategy, useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name') }

Реализация механизма выдачи уведомлений в Web-приложении

#javascript #angular2 #frontend #backend


Вопрос - есть веб-приложение на angular 2, каким образом можно реализовать постоянное
получение уведомления о каких-либо действиях с сервера (backend на Google Cloud Platform
- App engine). Мне приходил вариант постоянно опрашивать в вечном цикле сервер, однако
это не выход, или по крайней мере реализация будет затратной. Какие есть варианты механизмы
live-уведомлений, а именно их отдачи с сервера на фронт?
    


Ответы

Ответ 1



Если я правильно понял вопрос то возможно WebSocket и event-driven архитектура поможет Вам решить Вашу проблему. Изменения на сервере будут отправлять action на фронт, где уже слушатели будут реагировать на это должным образом.

суббота, 11 января 2020 г.

Возможно ли одним fxFlex-ом добиться нужного вида?

#angular2 #flexbox #angular #angular4 #angular5


Необходимо получить такой результат:


Но проблема вот в чем:

Если в блоке fxLayout="row wrap" fxLayoutGap="25px"
для элемента задать fxFlex="20", в строке вмещается 3 элемента, а не 4 из-за отступов
fxLayoutGap в 25px

В инспекторе смотрю для элемента задано max-width: 20%

Думал решить проблему таким образом, fxFlex="calc(20% - 25px)", но в таком случае
в инспекторе уже не максимальная ширина, а min-width: calc(20% - 25px); и вот что получается:


fxLayoutGap="25px grid" также не решает даной задачи, добавляет лишний горизонтальный
скролинг :(

Как можно решить данную задачу ?

Код тут: https://stackblitz.com/edit/angular-j3pgzp
    


Ответы

Ответ 1



Можно добиться, но для этого вам нужно использовать биндинги с медиа запросами: fxFlex.gt-md="calc(20% - 25px)" Где gt-md это screen and (min-width: 1280px), а на меньшую ширину использовать другой медиа запрос, например: fxFlex.lt-lg="calc(33% - 25px)" Где lt-lg это screen and (max-width: 1279px). Но еще проблема в том, что вы оперируете процентами и 2 блока имеющих ширину 33% растянуться, это проблема самого пакета flex-layout, потому что биндинг fxFlex компилируется в flex + min-width. Единственный workaround, который предлагает Каэрус Кару (лид flex-layout) - это вручную задавать max-width. Один из вариантов это вручную следить за изменениями медиа запросов, это за вас может сделать MediaObserver из ядра flex-layout: import { MediaObserver, MediaChange } from '@angular/flex-layout'; import { Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; @Component({ ... }) export class SomeComponent implements OnDestroy { public fxFlex: string = null; private readonly destroy$ = new Subject(); constructor(mediaObserver: MediaObserver) { mediaObserver.asObservable().pipe( map((changes: MediaChange[]) => { return changes.map(({ mediaQuery }) => mediaQuery); }), map((queries: string[]) => { const matches = queries.find((query) => query === 'screen and (min-width: 1280px)'); return !!matches; }), takeUntil(this.destroy$) ).subscribe((matches) => { if (matches) { this.fxFlex = 'calc(25% - 25px)'; } else { this.fxFlex = 'calc(33% - 25px)'; } }); } public ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } } Дабы поиграться и понять, что представляет из себя поток mediaObserver - вы можете просто добавить console.log(changes). Тогда в самом шаблоне вы можете уже биндить саму переменную: [fxFlex]="fxFlex" [style.max-width]="fxFlex" Добавлю от себя - не полагайтесь полностью на этот пакет. Проще писать стили , используя обычный CSS. Этот пакет - убийца производительности.

четверг, 2 января 2020 г.

Как сделать компонент с настраиваемым required?

#angular2 #angular


Допустим, компонент А представляет собой блок input-ов.

Этот компонент я добавляю внутрь другого компонента.

В компоненте Б заполняемость input'ов может быть обязательная, а в компоненте С нет.

В обычном случае, если бы не было компонента А и я добавлял бы поля напрямую в Б
и С я бы пометил бы необходимые поля required, а затем повесил бы на кнопку условие,
что поля валидны.

На ум приходит только передача через @Input() компонента А массива с названием необходимых
полей и какое-нибудь булево @Output() свойство, которое может читать компонент Б при
изменении компонента А, показывающие валидность.

Это правильное решение или есть другие более простые варианты?
    


Ответы

Ответ 1



Необязательно это делать через входные параметры, я часто предпочитаю взаимодействие через сервисы, изолируя бизнес логику, а также сервисы позволяют добавить щепотку производительности. К тому же я бы предпочел оперировать константами. Angular построен таким образом, что он будет каждый раз проверять не изменилось ли входное свойство: [requiredFields]="['name', 'surname']" Хотя с другой стороны этот список должен быть константой. Поэтому здесь 2 варианта - использовать сервисы либо константные атрибуты. Компонент A должен находиться в отдельное папке, если это какой-то переиспользуемый компонент и структура должна выглядеть следующим образом: Еще если подключите TS paths, то получится мед, будут понятные и читабельные импорты. Компонент вы добавляете в declarations и exports, тем самым мы получаем так называемый "small&dumb" модуль. Сервис мы не объявляем в провайдерах этого модуля, сервис будет использоваться родительскими компонентами B и C, которые будут проджектить этот компонент A. Сервис будет представлять из себя нечто подобное: interface RequiredFieldsState { allFieldsRequired: boolean; requiredFields?: string[]; } @Injectable() export class RequiredFieldsService implements OnDestroy { private state$ = new BehaviorSubject(null); public ngOnDestroy(): void { this.state$.complete(); } public setState(state: RequiredFieldsState): void { this.state$.next(state); } public getSnapshot(): RequiredFieldsState { return this.state$.getValue(); } } Сервис мы будем добавлять в провайдеры компонентов B и C: import { RequiredFieldsService } from '@app/shared/A'; @Component({ selector: 'app-b', template: ` `, providers: [RequiredFieldsService] }) export class BComponent {} У компонента A также должен быть доступ к инстансу сервиса RequiredFieldsService, также я еще хотел бы, чтоб Angular начал поиск зависимости с родительского инжектора и пропустил текущий: import { SkipSelf } from '@angular/core'; export class AComponent { constructor( @SkipSelf() private requiredFieldsService: RequiredFieldsService ) {} } В родительском компоненте вы просто вызываете метод setState сервиса с нужными параметрами: import { RequiredFieldsService } from '@app/shared/A'; @Component({ selector: 'app-b', template: ` `, providers: [RequiredFieldsService] }) export class BComponent { constructor( @Self() requiredFieldsService: RequiredFieldsService ) { requiredFieldsService.setState({ allFieldsRequired: false }); } } Декоратор @Self говорит Angular получить зависимость для BComponent только из его собственного инжектора. В AComponent вы получаете текущее состояние, проводите некоторые инициализации и сеттите атрибуты required: @Component({ selector: 'app-a', template: `
` }) export class AComponent { public required = this.requiredFieldsService.getSnapshot().allFieldsRequired; constructor( @SkipSelf() private requiredFieldsService: RequiredFieldsService ) {} } Если же мы хотим, чтобы 1 инпут был required, а второй нет, то соответственно сеттим состояние следующим образом: requireFieldsService.setState({ allFieldsRequired: false, requiredFields: ['name'] }); В самом сервисе RequiredFieldsService я бы создал такой хелпер метод: public inputShouldBeRequired({ name }: HTMLInputElement): boolean { const { requiredFields } = this.getSnapshot(); if (Array.isArray(requiredFields)) { return requiredFields.includes(name); } return false; } Использовал бы его в шаблоне следующим образом: Как быть с константными атрибутами? Декоратор @Attribute позволяет получить доступ к строковому атрибуту, который биндится к элементу. Angular сеттит его 1 раз и забывает про него. Как использовать? import { Attribute } from '@angular/core'; export class AComponent { constructor( @Attribute('requiredFields') requiredFields: string | null ) {} } Биндинг один в один как и входного свойства: Квадратные скобки использовать нельзя, все что внутри кавычек - строка!. Разница в том, что доступ в входным параметрам мы можем получить только в ngOnChanges, в отличии от атрибутов, которые доступны уже в конструкторе на этапе инициализации, потому что на этапе компиляции уже известно значение. Как нам превратить строку ['name'] в массив required инпутов - распарсить: @Component({ selector: 'app-a', template: `
` }) export class AComponent { public requiredFields: string[] = []; constructor( @Attribute('requiredFields') requiredFields: string | null ) { this.setRequireFields(requiredFields); } private setRequireFields(requiredFields: string | null): void { if (requiredFields === null) { return; } this.requiredFields = JSON.parse(requiredFields.replace(/\'/g, "\"")); } public inputShouldBeRequired({ name }: HTMLInputElement): boolean { return this.requiredFields.includes(name); } } И кстати во втором варианте нам не нужен сервис, мы засеттили requiredFields 1 раз на этапе инициализации и забыли про него, тем самым Angular не будет производить какие либо проверки.

пятница, 27 декабря 2019 г.

Построение эффективной CI/CD инфраструктуры с нуля начинающему devops инженеру

#c_sharp #angular2 #docker #непрерывная_интеграция #devops


Предыстория.

На работе встала задача, наше новое приложение, разработанное на asp.net core и Angular
по серьёзному развернуть на серверах компании. Инженеров devops нет и не предвидится,
поэтому мне как старшему разработчику придётся осваивать и это направление т.к. команда
и так не большая - всего 4 человека. В общем, проблема возникла на стадии планирования. 

Сейчас в компании используются две независимые гальванически не связанные сети для
интернета и для внутренней подсети. Вся инфраструктура (1с и прочее) находятся именно
в локальной сети без доступа из вне. Разработчики напротив сидят именно в интернетовском
сегменте. 

Обдумывая инфраструктуру серверов для публикации и тестирования проекта я обдумывал
использовать Docker.(Само приложение будет использовать linux в качестве серверной
платформы(nginx для angular, postgresql - db, api на .net core). 

Небольшая выжимка информации.


Windows; Visual studio 2017 для разработки API; Visual studio code для Angular; GitLab
на внутренем интернет сервере;
API написано с использованием ASP.NET Core 2; Клиент на Angular 4; DB - postgresql;
Разработчики находятся в отдельной сети от места развертывания приложения;
Сервера с приложением будут в локальной сети без доступа к интернету;
В качестве базовой платформы будет использоваться ProxMox в локальной сети;


Структура получившаяся на мой взгляд.



Вот только есть несколько проблем (собственно вопросов):


Обновление пакетов NPM(в качестве пакетного менеджера используется Yarn) и NuGet.
Добавление новых пакетов.  Вроде, как и для nuget и для Yarn можно делать offline зеркала,
но как поддерживать в них актуальность? И есть ли возможность обновлять/добавлять пакеты
используя Git? м.б. кто-то сталкивался с этим?
Есть ли вообще смысл от Гипервизора и виртуальных машин? Или в данной ситуации лучше
на одной физической машине развернуть всё? Есть ли плюс поддержки виртуальных машин
(в будущем планировалось объединить несколько серверов в кластер и добавить репликацию
с резервированием)?
Возможно ли что я иду в неправильном направлении и все мои идеи и мысли в корне не
верны? Будет ли мне потом мучительно больно при работе со всем этим? :)
Где вообще можно почитать об организации такой структуры с нуля?  


Возможно кто-то подскажет как лучше организовать весь этот процесс CI/CD. Для меня
это первый опыт в этом направлении и всё хочется сделать правильно (на сколько это
возможно)) ведь мне самому придётся работать со всей этой структурой и как разработчику
и как devops.
    


Ответы

Ответ 1



Обновление пакетов NPM(в качестве пакетного менеджера используется Yarn) и NuGet. Добавление новых пакетов. Вроде, как и для nuget и для Yarn можно делать offline зеркала, но как поддерживать в них актуальность? И есть ли возможность обновлять/добавлять пакеты используя Git? м.б. кто-то сталкивался с этим? Большинство пакетных менеджеров могу скачивать репозитории по ssh / git. yarn install git+ssh://git@github.com//.git. С nuget видимо только репозитории. Пока это не проблема, а будущая возможная оптимизация, по уменьшению трафика и увеличению скорости билдов. Спокойно игнорируем на этом этапе. Есть ли вообще смысл от Гипервизора и виртуальных машин? Или в данной ситуации лучше на одной физической машине развернуть всё? Есть ли плюс поддержки виртуальных машин (в будущем планировалось объединить несколько серверов в кластер и добавить репликацию с резервированием)? Смысл есть - изоляция, но и overhead. Как плюс gold image, в котором уже все готово, нужно только залить весь стек (docker stack deploy). Вполне можно ужиться и на одном, более рисковый путь. Для кластера - docker-swarm + glusterfs / edge fs / etc (для overlay volumes). Возможно ли что я иду в неправильном направлении и все мои идеи и мысли в корне не верны? Будет ли мне потом мучительно больно при работе со всем этим? :) Направление верное. Мучительно ли? - Да, как и всё новое. Мой пример - docker-swarm около месяца (две из них auto letsencrypt + nginx). Просто потому что выбрал инструмент, который знал. После на Traefik сделал за два дня. Автоматизировать, нужно постепенно. Сделать CI. Deploy ручной, но c одной командой. По началу даже так ускорится процесс (Fail Fast). Ни слова не упомянули о конфигурационной менеджменте. Тут Ansible в помощь. По ссылке мой опыт автоматизации деплоя на swarm cluster, а так же структура, которая позволит быстро добавить новые сервисы и задеплоить. Конечно есть нюансы, типа нельзя воспользоваться deploy script, пока нету registry. Или workflow c множеством docker-compose.*.yml файлов. Плюс полная докеризация (как пример) или DevSecOps. Где вообще можно почитать об организации такой структуры с нуля? Подписаться на DevOps рассылки, настроить google alerts по темам (docker, container, etc). Повышать кругозор. Накладывать свои знания на свою реальность. И много экспериментировать.

Angular 2 thinking and way

#typescript #angular2


Ситуация: 
Есть два очень похожих компонента: превью статьи на главной странице, и сама статья,
при переходе на "читать дальше". У компонента превью свой сервис, который тянет данные
через http. В роутере, при переходе на полноую статью (другой компонент) указан компонент
статьи, непосредственно. 

Вопрос: 
Создавать копмоненту свой собственный сервис, который будет дублировать код сервиса
превьюхи, либо же использовать один компонент, просто с отдельным шаблоном целой статьи
(//не нашел, как юзать несколько шаблонов в одном компоненте), либо же ваш вариант.
Интересует именно правильный подход с точки зрения angular way и TS.
Заранее благодарю.
    


Ответы

Ответ 1



Для обоих компонентов можно сделать через один сервис

Как правильно собирать проект на Angular2?

#javascript #angularjs #gulp #angular2 #webpack


Более двух лет я писал приложения на Angular 1 - 1.5 и использовал для собрки gulp.
Сейчас я решил изучить Angular 2 и распространенный сегодня webpack. В процессе изучения
узнал о cli для генерации приложений на Angular 2 и автоматизации создания компонентов,
сервисов и т. д. Мне показалось это безумно удобным, но в то же время появилось два
вопроса. 


Означает ли использование cli, что мне не нужен ни gulp, ни webpack? Или есть смысл
каким-то образом комбинировать эти инструменты? Если да, то как это делаете вы? 
Допустим, я сгенерировал каркас приложения при помощи cli, создал какие-то компоненты,
написал некоторое кол-во кода, и тут я понимаю, что хочу использовать другой препроцессор
css, переименовать ряд компонентов и директив, создать новые модули и таким образом
изменить файловую структуру проекта. Не станет ли это проблемой? И смогу ли я после
этого продолжать использовать cli?


PS: Я понимаю, что cli работает на основе webpack, поэтому странно говорить, что
использовать cli, значит отказаться от webpack. Но где искать конфигурационный файл
webpack? Что, если я хочу автоматизировать заливку файлов по ftp, компиляцию jade или
делать что-то еще, чего нет по умолчанию в cli?
    


Ответы

Ответ 1



По первому вопросу: Если вы создали каркас проекта при помощи cli, то использовать gulp и webpack уже не нужно. Порядок сборки и развёртывания таков: Переходим в корневой каталог проекта npm install - устанавливаем пакеты ng build --prod --aot - собираем проект В папке /dist корневого каталога будет лежать собранный проект. При желании миницифицируем полученные файлы Заливаем содержимое папки /dist на веб-сервер Вуаля По второму вопросу: Для того, чтобы вытащить webpack.config, в корневом каталоге проекта, сгенерированного при помощи cli, выполните: ng eject В результате в консоли выведется сообщение о том, что извлечение проведено успешно, и что теперь для запуска проекта нужно использовать npm run build... etc а в корневом каталоге получите сгенерированный webpack.config, который можете конфигурировать как вам угодно. Следует отметить, что ng serve и прочие подобные команды использовать уже не сможете, а после извлечения в package.json добавится ряд новых пакетов, следовательно, перед запуском приложения после проведения извлечения, необходимо будет запустить npm install. Следовательно, алгоритм таков: Переходим в корневой каталог проекта ng eject Проверяем наличие webpack.config Вносим необходимые изменения npm install npm run build Вуаля :)

воскресенье, 22 декабря 2019 г.

Конфликт bootstrap 4 и angular 4 - некорректно вычисляется высота блоков

#css #bootstrap #angular2 #angular4


Как сделать страницу аналогично https://startbootstrap.com/template-overviews/3-col-portfolio/
с boostrap 4 и angular 4?

Изначально использовались boostrap 3 и angular 4, 
пытался сделать страницу по примеру, в котором используется bootstrap 4 https://startbootstrap.com/template-overviews/3-col-portfolio/
https://blackrockdigital.github.io/startbootstrap-3-col-portfolio/

вот мои попытки с моей версией boostrap 3
http://jsfiddle.net/96thessa/4/
здесь вроде бы все работает аналогично, но если добавляется angular, место под изображение
растягивается на высоту всего блока, а текст съезжает.
при использовании angular происходит следующее https://imgur.com/9IZ1Jvx размеры
пустой картинки: https://imgur.com/z3sqNoe
вначале блоки отображаются аналогично http://jsfiddle.net/96thessa/4/ 
но через мгновение пустая картинка занимает всю высоту блока и выталкивает текст
ниже границы блока.
С bootstrap 4 ситуация аналогичная.

Страница - компонент angular, соответственно, boostrap скрипт и стили подгружаются
в индексе, а стиль самого компонента содержит правила для классов card, card-img-top
и т.д. На jsfiddle.net не знаю, как эти все нюансы воспроизвести с учетом angular.
Возможно, angular вносит смуту? Влияет ли порядок загрузки стилей на расчет размера
картинки? Или boostrap не стоит подключать через link и script в html файле, а лучше
каким-то другим способом? Влияет ли angular на отображение изображений таким образом?
В стилях в инспекторе браузера не увидел ничего дополнительного, что бы могло исказить
отображение. Пробовал использовать изображение, не обрамленное ссылкой a, результат тот же.

Update: архив тестовые исходники 

Update: пока костыльное решение - не показывать несуществующие изображения (display:
none), но блоки все равно почему-то растягиваются больше, чем нужно, в высоту. Пытался
заменить margin-ы на padding-и, эффект не особо изменился, автоматический расчет высоты
блока происходит неверно, я полагаю, проблема не в изображениях, а в самих блоках.

Update: пытаюсь устранить конфликт angular и bootstrap, используя ng-bootstrap. Выполнил
установку npm install --save @ng-bootstrap/ng-bootstrap, убрал подключение bootstrap.min.js
и jquery.min.js, оставив только подключение bootstrap.min.js (4.0.0-beta.2). В app.module.ts
внес изменения:

import {NgbModule} from '@ng-bootstrap/ng-bootstrap';    
...

@NgModule({
  ...
  imports: [
    ...
    NgbModule.forRoot(),
    ...
  ],
  providers: [
   ...
  ],
  bootstrap: [AppComponent]
})
...


Высота блоков по-прежнему рассчитывается некорректно.

Ссылка на страницу 

Update:
добавил стили 

.h-100[_ngcontent-c3] { height: auto !important; }
.h-100 { height: auto!important; }
.h-100[_ngcontent-c4] { height: auto !important; }
.container[_ngcontent-c3] .card[_ngcontent-c3] { height: auto !important; }


и убрал 

.h-100 { height: 100%!important; }


результат:
https://i.imgur.com/ULzNpFK.png
Внешние дивы для блоков имеют корректную высоту, но .card сжимается по контенту по
высоте, и соседние колонки не выравниваются в итоге по высоте, хотя стиль height: auto
!important; применяется. Проверял в chrome, firefox. Искомая страница, с которой сделан
скриншот Ссылка на страницу 
    


Ответы

Ответ 1



Вы не указали стили к классу .row .row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -15px; margin-left: -15px; } Результат: Обновление 0.0.1: На предоставленном ресурсе возможно поправить верстку внеся вот такие изменения: Удалите css код: .h-100[_ngcontent-c3] { height: 100% !important; } .h-100 { height: 100%!important; } Если нет возможности удалить, замените на height: auto important; После для выравнивания вы можете написать: .portfolio-item[_ngcontent-c3] { margin-bottom: 30px; display: flex; } И если размер картинок будет всегда один сделать вот так: .card.h-100 img { max-height: 200px; } В итоге вы получите вот такой результат: Вариант №1 С картинкой но битой ссылкой Вариант №2 Полностью без картинки(без тега < img >)

суббота, 21 декабря 2019 г.

Как выбрать option в select по значению?

#html #html5 #angular2 #typescript #html_select


Возможно ли указать значение option, которое будет выбираться по умолчанию при загрузке
страницы? Пробовал через selected и  selected="selected". Результат нулевой.





    


Ответы

Ответ 1



Судя по разметке - используется Angular. При связывании через ngModel выбирается option чье значение совпадает со значением typeSearch. Таким образом достаточно просто присвоить этой переменной или свойству нужное значение.

Ответ 2



Можешь обойти циклом все значения select и применить порядковый номер соответствующего option (значение option совпадает с нужным значением) к select через selectedIndex. Пример: var defaultValue = "Расширению"; var yourSelect = document.querySelector('.form-control'); for (let i, j = 0; i = yourSelect.options[j]; j++) { if (i.value == defaultValue) { yourSelect.selectedIndex = j; break; } } Если нужного значения в select нет, то будет выбрано значение selected или же самое первое (при отсутствии selected).

воскресенье, 15 декабря 2019 г.

Rails + Devise + Angular2: аутентификация

#ruby_on_rails #безопасность #devise #csrf #angular2


У меня просто огромное количество вопросов... Но перед этим нужно описать, что собственно
происходит.

Преамбула

Я пытаюсь научить Angular2 авторизироваться в Rails 5 beta 3 приложении. При этом
Rails работает в режиме API. Как я понимаю, для того, чтобы Devise работал в режиме
API, нужен gem devise_token_auth. Гем я установил и настроил, но вот после этого начались
проблемы:

Unpermitted parameters: user, session

Первое, что я попробовал сделать после настройки, послать простой POST запрос и посмотреть,
что произойдёт. А произошло следующее: 

Processing by DeviseTokenAuth::SessionsController#create as *json*
  Parameters: {"user"=>{"username"=>"demo", "password"=>"[FILTERED]"}, "session"=>{"user"=>{"username"=>"demo",
"password"=>"[FILTERED]"}}}
Unpermitted parameters: user, session
  Rendered devise_token_auth/sessions/create.json (0.2ms)
Completed 401 Unauthorized in 18ms (Views: 3.2ms | ActiveRecord: 0.0ms)


И вот с этого момента я немного не понимаю, с каких это пор я должен прописывать
permit для параметров, которые ActionController::ParamsWrapper создаёт динамически
в качестве обёртки? Более того:

devise_parameter_sanitizer.permit(:sign_in) do |user_params|
  user_params.permit(:user, :session)
end


ничего не меняет. Кто-нибудь сталкивался с подобным ранее?

Authentication header

Покопавшись в документации в поисках решения проблемы я нашёл другую:


  The authentication information should be included by the client in the headers
of each request. The headers follow the RFC 6750 Bearer Token format


Т.е. в заголовке запроса должны быть следующие данные:

"access-token": "wwwww",
"token-type":   "Bearer",
"client":       "xxxxx",
"expiry":       "yyyyy",
"uid":          "zzzzz"


В AngularJS они генерировались модулем ng-token-auth, но как мне сгенерировать их
посредством Angular2, у которого данного модуля нет?



Подводя промежуточный итог (потому что чувствую я, после этих проблем я наткнусь
на их ещё большее количество), вот список моих вопросов:


Как исправить unpermitted parameters: user, session в devise_token_auth?
Как сгенерировать access-token?
Как высчитать expiry и есть ли "rails-way" для времени жизни токена?
Что следует писать в client? Раз уж этот идентификатор позволяет пользователю одновременно
авторизироваться с нескольких устройств, то как он должен выглядить? Что туда следует
записать?





Какие данные следует возвращать клиенту после авторизации (помимо 200)?
Какие ещё подводные камни могут меня ждать при попытке авторизироваться через Rails API?




UPD

Вот запрос, который я шлю:

private _user_session_url = 'auth/sign_in';

login (username: string, password: string) : Observable {
    let body = JSON.stringify({ username: username, password: password });
    // TODO: generate header data.
    let headers = new Headers({
        'Content-Type': 'application/json',
        'accept': 'json'
    });
    let options = new RequestOptions({ headers: headers});

    return this.http.post(this._user_session_url, body, options)
        .map((data: any) => data.json())
        .catch(this.handleError)
}


Как видите, session в теле запроса нет. Его создаёт ActionController::ParamsWrapper

В подтверждение привожу Request Payload:

{"username":"demo","password":"123"}    

    


Ответы

Ответ 1



Согласно краткой документации к devise_token_auth (DTA) POST /sign_in принимает только параметры email и password прямо в корне. То есть, параметры должны выглядеть так: { "email": "foo@example.com", "password": "bar" } Никакой вложенности. Не надо дополнительно настраивать санитайзер и придумывать ненужные ключи. А теперь ответ разом на все оставшиеся вопросы: Token-Type, Access-Token, Client и Expiry. В AngularJS они генерировались модулем ng-token-auth Нет, они генерируются сервером, клиент ничем умным не занимается. Хранятся они в БД (в частично искажённом, но проверяемом виде, как пароли), а обмен ими происходит с помощью заголовков. /sign_in возвращает все интересующие заголовки. Все эти значения вы просто будете передавать туда-сюда (и обновлять, ведь по умолчанию после каждого отдельного запроса токен меняется). Кроме, разве что, Expiry, значением которого можно следить, "когда токен отвалится и потребует обновления", что можно использовать для выкидывания на форму входа. Пользоваться DTA без ng-token-auth можно, но прежде чем за это браться, стоит прочесть документацию к используемым методам. Я пользовался этим гемом ранее и не рекомендую его для случаев, где важна настраиваемость принимаемых и отдаваемых этой системой данных, потому что расширяемость гема близка к нулю.

четверг, 5 декабря 2019 г.

Angular2 минимизация приложения. Оптимизация времени загрузки

#angular2 #минификация


Помогите, пожалуйста, разобраться с оптимизацией приложения. Есть приложения на Angular2.
Минимизацию делал по этой статье. Без webpack. 
Командами 

 browserify -s main dist/main.js > dist/bundle.js


и 

uglifyjs dist/bundle.js --screw-ie8 --compress --mangle --output dist/bundle.min.js


получилось минимизировать бандл, но он занимает 1.7 метра. 
Структура app.module.ts проекта очень большая на мой взгляд.  

@NgModule({
  imports: [
    BrowserModule,
    CommonModule,
    FormsModule,
    Ng2PaginationModule,
    HttpModule,
    FormsModule,
    DatePickerModule,
    Ng2GoogleChartsModule,
    routing,
    AgmCoreModule.forRoot({
      apiKey: 'AIzaSyAqIBAiCeLH9A5I5lqEK3iK1j3gAmL3yIg',
      libraries:['geometry', 'places']
    })
  ],
  declarations: [
    MainComponent,
    AuthComponent,
    RecoveryComponent,
    BaseComponent,
    IndexComponent,
    UsersComponent,
    ActiveDriversComponent,
    AdminsComponent,
    ClientComponent,
    DriversApplicationsComponent,
    ActiveDriverComponent,
    ActivationComponent,
    OrdersCanceledComponent,
    AllOrderForDriverComponent,
    NewUserComponent,
    DriverRateComponent,
    DeterminationErrors,
    HttpPopupErrors,
    TranslatePipe,
    CKEditorComponent,
    OrdersComponent,
    SelectLanguageComponent,
    SelectRoleComponent,
    SelectNoticeComponent,
    CurrentOrdersComponent,
    NotConfirmedComponent,
    DeferredOrdersComponent,
    CompletedOrdersComponent,
    AbolishedOrdersComponent,
    DriversOffersComponent,
    EvaluationEditorComponent,
    NewOrderComponent,
    OrderInfoComponent,
    PermissionDeniedComponent,
    SelectBoxComponent,
    NewsComponent,
    CreateNewsComponent,
    EditNewsComponent,
    PublishedNewsComponent,
    SelectFilterComponent,
    ChangeStatusComponent,
    PaymentsTemplatesComponent,
    PaymentsComponent,
    NewTemplateComponent,
    NewTemplateComponent,
    ChangePasswordComponent,
    EditTemplateComponent,
    SupportComponent,
    TemplatesComponent,
    DraftsComponent,
    AppealsMessagesComponent,
    NotificationsComponent,
    NotificationComponent,
    CountriesComponent,
    AddCountryComponent,
    AddCityComponent,
    EditCountryComponent,
    EditCityComponent,
    CurrentBalanceComponent,
    MarkerClusterDirective,
    DriverMapDirective,
    PersonalDirective,
    AllInfoDirective,
    StatisticDirective,
    SearchDirective,
    DateRangePickerDirective,
    PersonalAutoDirective,
    DocumentsDirective,
    PaginationDirective,
    HelpersDirective,
    SimpleRateDirective,
    FilterPipe,
    PluralPipe
  ],
  providers: [
    Urls,
    User,
    SearchModel,
    HttpService,
    CurrencyService,
    Md5,
    DeterminationErrorService,
    TRANSLATION_PROVIDERS,
    TranslateService,
    LocationService
  ],
  schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
  bootstrap:    [ MainComponent ]
})


В связи с этим есть вопросы. Поможет ли в данной ситуации ленивая загрузка модулей,
и если поможет то как разбить на отдельные модули данную структуру (не понятен сам
принцип)?
Возможно ли как то ещё оптимизировать приложение?
    


Ответы

Ответ 1



Проблему решил так. Сначала решил костылём, а потом создал новый проект с angular-cli и добавил в него свои модули Обходное решение (костыль) Так как скомпилировать проект без angular-cli не получилось - пришлось сделать html костяк с лоудером и вставить в index.html. index.html ..... ... $(document).ready(function() {$('#auth_').show();)} // Показывает html блок с лоудер В файле скрывал блок auth.component.ts ngOnInit() { $('#auth_').hide(); } Это решение быстрое и не требует большого количества времени. Второй путь более сложный и трудоёмкий. Создание приложения с помощью angular-cli Устанавливаем локально angular-cli. Для этого выполнить в консоли. npm install -g @angular/cli Второй шаг перенос кода. Это самый сложный и рутинный этап, так как на проекте была версия 2.0.0, а версия с которой создаётся проект - 2.3. Поэтому пришлось переписывать импорты некоторых компонентов. Но в результате что бы релизнуть Создаём билд AOT ng build --prod --aot ng serve --prod --aot

понедельник, 8 июля 2019 г.

Сравнение группы надписей кнопок

Привет, в общем хочу сделать следующее, есть 2 группы баттонов(angular material "md-radio-button"), если какое-то из значений первой группы совпадает с любым из второй, сделать баттон неактивным и добавить какой-то текст. К примеру в 1 группе есть :
-Москва -СПБ -Воронеж
Во второй есть:
-Краснодар -Чебаркуль -Воронеж
Тогда в 1 группе сделать баттон Воронеж неактивным и добавить текст. Здесь код: https://plnkr.co/edit/3QdQtu4kWCQjL5uO2kJt?p=preview
Мои мысли ведут меня в сторону - [disabled] = "selectedcountry === selectedcopycountry", такой же *ngIf c текстом к баттону, но ведь тогда считаются значения только с выбранного ... В общем прошу помощи


Ответ

Должно было быть что-то такое
[disabled]="countries.includes(country)"
но т. к. там лежат объекты, то функцию для поиска надо вынести в компонент
hasCountry(country) { return this.countries && this.countries.some(c => c.name === country.name); }
и вызывать её
[disabled]="hasCountry(country)"
https://plnkr.co/edit/ufz70Kx89YtWLglFPfck?p=preview

вторник, 21 мая 2019 г.

Не работает [(ngModel)] в md-select(Angular Material)

Вывожу в компоненте
{{food.viewValue}}
Браузер выдаёт ошибку:
В классе пишу:
selected: any = [ {viewValue: "Элемент 1", value: "0"}, {viewValue: "Элемент 2", value: "1"}, {viewValue: "Элемент 3", value: "2"}, {viewValue: "Элемент 4", value: "3"}, ]; selectedOne: string = "0";
Делаю всё по доке Material Angular Но всё равно не хочется ставить элемент по умолчанию. Кто знает в чём может быть причина? Angular cli 4.3; material 2.0


Ответ

Директива ngModel расположена в модуле FormsModule из @angular/forms
Поэтому для ее использования нужно импортировать этот модуль в модуль где находит указанный компонент.

понедельник, 18 марта 2019 г.

Как правильно csrftoken от django в angular2?

Доброго времени суток,
Переписываю проект с angular (роутинг был на стороне backend) на angular 2 На стороне backend стоит django. Написал роутинг, аутентификацию по средством записи в куки (использовал для этого пакет angular2-cookie). Ранее, для того чтобы просто забрать csrftoken, чтобы спокойно писать код, использовал своего рода небольшой костыль:
let token = document.cookie.replace(/(?:(?:^|.*;\s*)csrftoken\s*\=\s*([^;]*).*$)|^.*$/, "$1");
Но теперь этот вариант не работает, а как правильно работать с csrftoken django - angular2 не могу в полной мере разобраться.
Буду благодарен, если кто-нибудь поможет в этой сложившейся ситуации. Спасибо


Ответ

Вам стоит посмотреть сюда: https://angular.io/docs/ts/latest/guide/security.html
Your server may use a different cookie or header name for this purpose. An Angular application can customize cookie and header names by providing its own CookieXSRFStrategy values.
{ provide: XSRFStrategy, useValue: new CookieXSRFStrategy('myCookieName', 'My-Header-Name') }

понедельник, 3 декабря 2018 г.

Angular 2 thinking and way

Ситуация: Есть два очень похожих компонента: превью статьи на главной странице, и сама статья, при переходе на "читать дальше". У компонента превью свой сервис, который тянет данные через http. В роутере, при переходе на полноую статью (другой компонент) указан компонент статьи, непосредственно.
Вопрос: Создавать копмоненту свой собственный сервис, который будет дублировать код сервиса превьюхи, либо же использовать один компонент, просто с отдельным шаблоном целой статьи (//не нашел, как юзать несколько шаблонов в одном компоненте), либо же ваш вариант. Интересует именно правильный подход с точки зрения angular way и TS. Заранее благодарю.


Ответ

Для обоих компонентов можно сделать через один сервис

вторник, 13 ноября 2018 г.

Конфликт bootstrap 4 и angular 4 - некорректно вычисляется высота блоков

Как сделать страницу аналогично https://startbootstrap.com/template-overviews/3-col-portfolio/ с boostrap 4 и angular 4?
Изначально использовались boostrap 3 и angular 4, пытался сделать страницу по примеру, в котором используется bootstrap 4 https://startbootstrap.com/template-overviews/3-col-portfolio/ https://blackrockdigital.github.io/startbootstrap-3-col-portfolio/
вот мои попытки с моей версией boostrap 3 http://jsfiddle.net/96thessa/4/ здесь вроде бы все работает аналогично, но если добавляется angular, место под изображение растягивается на высоту всего блока, а текст съезжает. при использовании angular происходит следующее https://imgur.com/9IZ1Jvx размеры пустой картинки: https://imgur.com/z3sqNoe вначале блоки отображаются аналогично http://jsfiddle.net/96thessa/4/ но через мгновение пустая картинка занимает всю высоту блока и выталкивает текст ниже границы блока. С bootstrap 4 ситуация аналогичная.
Страница - компонент angular, соответственно, boostrap скрипт и стили подгружаются в индексе, а стиль самого компонента содержит правила для классов card, card-img-top и т.д. На jsfiddle.net не знаю, как эти все нюансы воспроизвести с учетом angular. Возможно, angular вносит смуту? Влияет ли порядок загрузки стилей на расчет размера картинки? Или boostrap не стоит подключать через link и script в html файле, а лучше каким-то другим способом? Влияет ли angular на отображение изображений таким образом? В стилях в инспекторе браузера не увидел ничего дополнительного, что бы могло исказить отображение. Пробовал использовать изображение, не обрамленное ссылкой a, результат тот же.
Update: архив тестовые исходники
Update: пока костыльное решение - не показывать несуществующие изображения (display: none), но блоки все равно почему-то растягиваются больше, чем нужно, в высоту. Пытался заменить margin-ы на padding-и, эффект не особо изменился, автоматический расчет высоты блока происходит неверно, я полагаю, проблема не в изображениях, а в самих блоках.
Update: пытаюсь устранить конфликт angular и bootstrap, используя ng-bootstrap. Выполнил установку npm install --save @ng-bootstrap/ng-bootstrap, убрал подключение bootstrap.min.js и jquery.min.js, оставив только подключение bootstrap.min.js (4.0.0-beta.2). В app.module.ts внес изменения:
import {NgbModule} from '@ng-bootstrap/ng-bootstrap'; ...
@NgModule({ ... imports: [ ... NgbModule.forRoot(), ... ], providers: [ ... ], bootstrap: [AppComponent] }) ...
Высота блоков по-прежнему рассчитывается некорректно.
Ссылка на страницу
Update: добавил стили
.h-100[_ngcontent-c3] { height: auto !important; } .h-100 { height: auto!important; } .h-100[_ngcontent-c4] { height: auto !important; } .container[_ngcontent-c3] .card[_ngcontent-c3] { height: auto !important; }
и убрал
.h-100 { height: 100%!important; }
результат: https://i.imgur.com/ULzNpFK.png Внешние дивы для блоков имеют корректную высоту, но .card сжимается по контенту по высоте, и соседние колонки не выравниваются в итоге по высоте, хотя стиль height: auto !important; применяется. Проверял в chrome, firefox. Искомая страница, с которой сделан скриншот Ссылка на страницу


Ответ

Вы не указали стили к классу .row
.row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -15px; margin-left: -15px; }
Результат:

Обновление 0.0.1:
На предоставленном ресурсе возможно поправить верстку внеся вот такие изменения:
Удалите css код:
.h-100[_ngcontent-c3] { height: 100% !important; } .h-100 { height: 100%!important; }
Если нет возможности удалить, замените на height: auto important;
После для выравнивания вы можете написать:
.portfolio-item[_ngcontent-c3] { margin-bottom: 30px; display: flex; }
И если размер картинок будет всегда один сделать вот так:
.card.h-100 img { max-height: 200px; }
В итоге вы получите вот такой результат:
Вариант №1 С картинкой но битой ссылкой
Вариант №2 Полностью без картинки(без тега < img >)

суббота, 27 октября 2018 г.

Rails + Devise + Angular2: аутентификация

У меня просто огромное количество вопросов... Но перед этим нужно описать, что собственно происходит.
Преамбула
Я пытаюсь научить Angular2 авторизироваться в Rails 5 beta 3 приложении. При этом Rails работает в режиме API. Как я понимаю, для того, чтобы Devise работал в режиме API, нужен gem devise_token_auth. Гем я установил и настроил, но вот после этого начались проблемы:
Unpermitted parameters: user, session
Первое, что я попробовал сделать после настройки, послать простой POST запрос и посмотреть, что произойдёт. А произошло следующее:
Processing by DeviseTokenAuth::SessionsController#create as *json* Parameters: {"user"=>{"username"=>"demo", "password"=>"[FILTERED]"}, "session"=>{"user"=>{"username"=>"demo", "password"=>"[FILTERED]"}}} Unpermitted parameters: user, session Rendered devise_token_auth/sessions/create.json (0.2ms) Completed 401 Unauthorized in 18ms (Views: 3.2ms | ActiveRecord: 0.0ms)
И вот с этого момента я немного не понимаю, с каких это пор я должен прописывать permit для параметров, которые ActionController::ParamsWrapper создаёт динамически в качестве обёртки? Более того:
devise_parameter_sanitizer.permit(:sign_in) do |user_params| user_params.permit(:user, :session) end
ничего не меняет. Кто-нибудь сталкивался с подобным ранее?
Authentication header
Покопавшись в документации в поисках решения проблемы я нашёл другую:
The authentication information should be included by the client in the headers of each request. The headers follow the RFC 6750 Bearer Token format
Т.е. в заголовке запроса должны быть следующие данные:
"access-token": "wwwww", "token-type": "Bearer", "client": "xxxxx", "expiry": "yyyyy", "uid": "zzzzz"
В AngularJS они генерировались модулем ng-token-auth, но как мне сгенерировать их посредством Angular2, у которого данного модуля нет?

Подводя промежуточный итог (потому что чувствую я, после этих проблем я наткнусь на их ещё большее количество), вот список моих вопросов:
Как исправить unpermitted parameters: user, session в devise_token_auth? Как сгенерировать access-token? Как высчитать expiry и есть ли "rails-way" для времени жизни токена? Что следует писать в client? Раз уж этот идентификатор позволяет пользователю одновременно авторизироваться с нескольких устройств, то как он должен выглядить? Что туда следует записать?

Какие данные следует возвращать клиенту после авторизации (помимо 200)? Какие ещё подводные камни могут меня ждать при попытке авторизироваться через Rails API?

UPD
Вот запрос, который я шлю:
private _user_session_url = 'auth/sign_in';
login (username: string, password: string) : Observable { let body = JSON.stringify({ username: username, password: password }); // TODO: generate header data. let headers = new Headers({ 'Content-Type': 'application/json', 'accept': 'json' }); let options = new RequestOptions({ headers: headers});
return this.http.post(this._user_session_url, body, options) .map((data: any) => data.json()) .catch(this.handleError) }
Как видите, session в теле запроса нет. Его создаёт ActionController::ParamsWrapper
В подтверждение привожу Request Payload:
{"username":"demo","password":"123"}


Ответ

Согласно краткой документации к devise_token_auth (DTA) POST /sign_in принимает только параметры email и password прямо в корне. То есть, параметры должны выглядеть так:
{ "email": "foo@example.com", "password": "bar" }
Никакой вложенности. Не надо дополнительно настраивать санитайзер и придумывать ненужные ключи.

А теперь ответ разом на все оставшиеся вопросы:
Token-Type, Access-Token, Client и Expiry
В AngularJS они генерировались модулем ng-token-auth
Нет, они генерируются сервером, клиент ничем умным не занимается. Хранятся они в БД (в частично искажённом, но проверяемом виде, как пароли), а обмен ими происходит с помощью заголовков. /sign_in возвращает все интересующие заголовки. Все эти значения вы просто будете передавать туда-сюда (и обновлять, ведь по умолчанию после каждого отдельного запроса токен меняется).
Кроме, разве что, Expiry, значением которого можно следить, "когда токен отвалится и потребует обновления", что можно использовать для выкидывания на форму входа.
Пользоваться DTA без ng-token-auth можно, но прежде чем за это браться, стоит прочесть документацию к используемым методам.

Я пользовался этим гемом ранее и не рекомендую его для случаев, где важна настраиваемость принимаемых и отдаваемых этой системой данных, потому что расширяемость гема близка к нулю.

вторник, 9 октября 2018 г.

Angular2 минимизация приложения. Оптимизация времени загрузки

Помогите, пожалуйста, разобраться с оптимизацией приложения. Есть приложения на Angular2. Минимизацию делал по этой статье. Без webpack. Командами
browserify -s main dist/main.js > dist/bundle.js
и
uglifyjs dist/bundle.js --screw-ie8 --compress --mangle --output dist/bundle.min.js
получилось минимизировать бандл, но он занимает 1.7 метра. Структура app.module.ts проекта очень большая на мой взгляд.
@NgModule({ imports: [ BrowserModule, CommonModule, FormsModule, Ng2PaginationModule, HttpModule, FormsModule, DatePickerModule, Ng2GoogleChartsModule, routing, AgmCoreModule.forRoot({ apiKey: 'AIzaSyAqIBAiCeLH9A5I5lqEK3iK1j3gAmL3yIg', libraries:['geometry', 'places'] }) ], declarations: [ MainComponent, AuthComponent, RecoveryComponent, BaseComponent, IndexComponent, UsersComponent, ActiveDriversComponent, AdminsComponent, ClientComponent, DriversApplicationsComponent, ActiveDriverComponent, ActivationComponent, OrdersCanceledComponent, AllOrderForDriverComponent, NewUserComponent, DriverRateComponent, DeterminationErrors, HttpPopupErrors, TranslatePipe, CKEditorComponent, OrdersComponent, SelectLanguageComponent, SelectRoleComponent, SelectNoticeComponent, CurrentOrdersComponent, NotConfirmedComponent, DeferredOrdersComponent, CompletedOrdersComponent, AbolishedOrdersComponent, DriversOffersComponent, EvaluationEditorComponent, NewOrderComponent, OrderInfoComponent, PermissionDeniedComponent, SelectBoxComponent, NewsComponent, CreateNewsComponent, EditNewsComponent, PublishedNewsComponent, SelectFilterComponent, ChangeStatusComponent, PaymentsTemplatesComponent, PaymentsComponent, NewTemplateComponent, NewTemplateComponent, ChangePasswordComponent, EditTemplateComponent, SupportComponent, TemplatesComponent, DraftsComponent, AppealsMessagesComponent, NotificationsComponent, NotificationComponent, CountriesComponent, AddCountryComponent, AddCityComponent, EditCountryComponent, EditCityComponent, CurrentBalanceComponent, MarkerClusterDirective, DriverMapDirective, PersonalDirective, AllInfoDirective, StatisticDirective, SearchDirective, DateRangePickerDirective, PersonalAutoDirective, DocumentsDirective, PaginationDirective, HelpersDirective, SimpleRateDirective, FilterPipe, PluralPipe ], providers: [ Urls, User, SearchModel, HttpService, CurrencyService, Md5, DeterminationErrorService, TRANSLATION_PROVIDERS, TranslateService, LocationService ], schemas: [ CUSTOM_ELEMENTS_SCHEMA ], bootstrap: [ MainComponent ] })
В связи с этим есть вопросы. Поможет ли в данной ситуации ленивая загрузка модулей, и если поможет то как разбить на отдельные модули данную структуру (не понятен сам принцип)? Возможно ли как то ещё оптимизировать приложение?


Ответ

Проблему решил так. Сначала решил костылём, а потом создал новый проект с angular-cli и добавил в него свои модули
Обходное решение (костыль)
Так как скомпилировать проект без angular-cli не получилось - пришлось сделать html костяк с лоудером и вставить в index.html.
index.html

..... ...
$(document).ready(function() {$('#auth_').show();)} // Показывает html блок с лоудер
В файле скрывал блок auth.component.ts
ngOnInit() { $('#auth_').hide(); }
Это решение быстрое и не требует большого количества времени.
Второй путь более сложный и трудоёмкий.
Создание приложения с помощью angular-cli
Устанавливаем локально angular-cli. Для этого выполнить в консоли.
npm install -g @angular/cli
Второй шаг перенос кода. Это самый сложный и рутинный этап, так как на проекте была версия 2.0.0, а версия с которой создаётся проект - 2.3. Поэтому пришлось переписывать импорты некоторых компонентов. Но в результате что бы релизнуть
Создаём билд AOT
ng build --prod --aot ng serve --prod --aot