SUPPORT-8783: add landing
This commit is contained in:
parent
6617e42343
commit
ecec2d595d
9 changed files with 268 additions and 70 deletions
|
|
@ -1,10 +1,14 @@
|
|||
<nav class="header" id="webbpm-header">
|
||||
<div class="header-logo">
|
||||
<div *ngIf="isLanding" class="header">
|
||||
<div class="header-logo"></div>
|
||||
<div class="header-title">Реестр повесток юридических лиц</div>
|
||||
</div>
|
||||
<div *ngIf="!isLanding" class="header-logo">
|
||||
<div class="logo"><a routerLink="/"></a></div>
|
||||
<div class="main-page"><a routerLink="/">Главная</a></div>
|
||||
<div class="header-menu-left"><a routerLink="/filesentlog">Журнал взаимодействий</a></div>
|
||||
</div>
|
||||
<div class="header-menu">
|
||||
<div *ngIf="!isLanding" class="header-menu">
|
||||
<div ngbDropdown class="logout" log-out></div>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
<div class="list-group lk-what">
|
||||
<div>
|
||||
<div class="title short-text"><a href=".">Личный кабинет</a> для ведения воинского учета в организациях</div>
|
||||
<div class="paragraph">
|
||||
<div class="paragraph-left">
|
||||
<div class="text icon-checklist">Кому доступен личный кабинет?</div>
|
||||
<div class="short-text">Организациям, за ĸоторыми заĸреплена обязанность по осуществлению воинсĸого учета в соответствии с <a href="https://www.consultant.ru/document/cons_doc_LAW_18260/">ФЗ от 28.03.1998 No 53-ФЗ</a></div>
|
||||
</div>
|
||||
<div class="paragraph-right">
|
||||
<div class="text icon-clock">Для чего нужен личный кабинет?</div>
|
||||
<div class="short-text">Для своевременной и оперативной передачи сведений в военĸоматы в элеĸтронном виде</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group lk-access">
|
||||
<div class="paragraph">
|
||||
<div class="paragraph-left">
|
||||
<div class="subtitle short-text">Как получить доступ к Личному кабинету?</div>
|
||||
</div>
|
||||
<div class="paragraph-right">
|
||||
<div class="list">
|
||||
<div class="esia short-text">Необходимо авторизоваться</div>
|
||||
<div class="case short-text">Потребуется подтвержденная учетная запись организации</div>
|
||||
<div class="user short-text">Доступ предоставляется тольĸо сотрудниĸу, наделенному соответствующими полномочиями (ролью) на ведения воинсĸого учета внутри организации</div>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a href="." class="btn">Войти в Личный кабинет</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group lk-info">
|
||||
<div class="subtitle">Какие виды сведений доступны для отправки?</div>
|
||||
<div class="paragraph">
|
||||
<div class="paragraph-left">
|
||||
<div class="section-group">
|
||||
<div class="icon-case">
|
||||
Сведения о приеме на работу (увольнении), зачислении в образовательную организацию (отчислении)
|
||||
<div class="muted">Срок передачи сведений: <span class="detailed">до 5 дней</span></div>
|
||||
</div>
|
||||
<div class="icon-shield">
|
||||
Изменения сведений сотрудников, необходимых для ведения воинского учета
|
||||
<div class="muted">Срок передачи сведений: <span class="detailed">до 5 дней</span></div>
|
||||
</div>
|
||||
<div class="icon-clip">
|
||||
Сообщение о гражданах, не состоящих, но обязанных состоять на воинском учете
|
||||
<div class="muted">Срок передачи сведений: <span class="detailed">до 3 дней</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph-right">
|
||||
<div class="section-group">
|
||||
<div class="icon-pers">
|
||||
Ежегодное предоставление списка граждан мужского пола, подлежащих первоначальной постановке на воинский учет в год достижения ими возраста 17 лет
|
||||
<div class="muted">Срок передачи сведений: <span class="detailed">ежегодно, в срок до 1 ноября</span></div>
|
||||
</div>
|
||||
<div class="icon-building">
|
||||
Ежегодное предоставление списка сотрудников/обучающихся в организации, подлежащих воинскому учету
|
||||
<div class="muted">Срок передачи сведений: <span class="detailed">ежегодно, по согласованию с военкоматом</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group lk-pass">
|
||||
<div class="subtitle">Как передавать сведения?</div>
|
||||
<div class="pass-list">
|
||||
<div>Войдите в личный ĸабинет организации через Госуслуги</div>
|
||||
<div>Подготовьте файл-csv с данными в соответствии с форматом в личном кабинете организации</div>
|
||||
<div>Убедитесь, что все данные в файле введены ĸорреĸтно</div>
|
||||
<div>Выберите необходимый вид сведений и загрузите файл</div>
|
||||
<div>Следите за статусом приема</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group lk-msg">
|
||||
<div class="msg-list">
|
||||
<span class="info"></span>Если в файле будут ошибĸи, данные не будут приняты Реестром и выгрузĸу сведений придется повторить
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group lk-docs">
|
||||
</div>
|
||||
|
|
@ -1,8 +1,19 @@
|
|||
<div class="wrapper">
|
||||
<app-header *ngIf="headerVisible">
|
||||
</app-header>
|
||||
|
||||
<div class="container">
|
||||
<div *ngIf="isLanding" id="browser-check-info">
|
||||
<div class="browser-check-content">
|
||||
<div class="browser-check-text">
|
||||
<p class="plain-text text-header">
|
||||
Доступ к личному кабинету для юридических лиц осуществляется исключительно через браузеры Яндекс или Chromium gost.
|
||||
</p>
|
||||
<p class="plain-text">
|
||||
Пожалуйста, попробуйте снова, выбрав один из этих браузеров.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-inside" id="webbpm-angular-application-container">
|
||||
<router-outlet></router-outlet>
|
||||
<app-footer *ngIf="footerVisible"></app-footer>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {RouterModule, Routes} from "@angular/router";
|
|||
import {AccessDeniedComponent} from "./component/access-denied.component";
|
||||
import {AuthGuard} from "../security/guard/auth.guard";
|
||||
import {ConfirmExitGuard} from "@webbpm/base-package";
|
||||
import {HomeLandingComponent} from "./component/home-landing.component";
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
|
|
@ -19,7 +20,12 @@ const appRoutes: Routes = [
|
|||
path: 'filesentlog',
|
||||
loadChildren: 'generated-sources/page-filesentlog.module#PagefilesentlogModule',
|
||||
canActivate: [AuthGuard],
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'home-landing',
|
||||
component: HomeLandingComponent,
|
||||
canActivate: [ConfirmExitGuard],
|
||||
},
|
||||
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import {ErvuFileUpload} from "../../ervu/component/fileupload/ErvuFileUpload";
|
|||
import {InMemoryStaticGrid} from "../../ervu/component/grid/InMemoryStaticGrid";
|
||||
import {ErvuDownloadFileButton} from "../../ervu/component/button/ErvuDownloadFileButton";
|
||||
import {AuthenticationService} from "../security/authentication.service";
|
||||
import {HomeLandingComponent} from "./component/home-landing.component";
|
||||
|
||||
registerLocaleData(localeRu);
|
||||
export const DIRECTIVES = [
|
||||
|
|
@ -37,7 +38,8 @@ export const DIRECTIVES = [
|
|||
forwardRef(() => AppProgressIndicationComponent),
|
||||
forwardRef(() => ErvuFileUpload),
|
||||
forwardRef(() => ErvuDownloadFileButton),
|
||||
forwardRef(() => InMemoryStaticGrid)
|
||||
forwardRef(() => InMemoryStaticGrid),
|
||||
forwardRef(() => HomeLandingComponent),
|
||||
];
|
||||
|
||||
export function checkAuthentication(authService: AuthenticationService): () => Promise<any> {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from "@angular/core";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
|
|
@ -8,7 +8,14 @@ import {Router} from "@angular/router";
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AppHeaderComponent {
|
||||
public isLanding: boolean = false;
|
||||
|
||||
constructor(protected router: Router) {
|
||||
constructor(protected router: Router,
|
||||
private cd: ChangeDetectorRef) {
|
||||
this.isLanding = window.location.href.endsWith('home-landing');
|
||||
router.events.subscribe((event) => {
|
||||
this.isLanding = window.location.href.endsWith('home-landing');
|
||||
this.cd.markForCheck();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
import {ChangeDetectorRef, Component, OnInit} from "@angular/core";
|
||||
import {CadesHelper} from "@webbpm/base-package";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "home-landing",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/home_landing.html",
|
||||
})
|
||||
export class HomeLandingComponent implements OnInit {
|
||||
|
||||
constructor(private cd: ChangeDetectorRef) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.checkCsp()
|
||||
.then((cspCheckPassed) => {
|
||||
if (this.checkBrowser() && cspCheckPassed) {
|
||||
document.getElementById("browser-check-info").hidden = true;
|
||||
}
|
||||
});
|
||||
this.cd.markForCheck();
|
||||
}
|
||||
|
||||
|
||||
private checkBrowser(): boolean {
|
||||
const userAgent = navigator.userAgent;
|
||||
return userAgent.indexOf("Chromium GOST") > -1 || userAgent.indexOf("YaBrowser") > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка работы CSP через CadesPlugin (асинхронно)
|
||||
*/
|
||||
private async checkCsp(): Promise<boolean> {
|
||||
try {
|
||||
if (!CadesHelper.plugin()) {
|
||||
console.error("Ошибка: cadesplugin не найден!");
|
||||
return false;
|
||||
}
|
||||
await CadesHelper.plugin();
|
||||
const oAbout = await CadesHelper.plugin().CreateObjectAsync("CAdESCOM.About");
|
||||
const cspVersion = await oAbout.CSPVersion();
|
||||
let cspVersionStr = (await cspVersion.MajorVersion) + "." + (await cspVersion.MinorVersion) + "." + (await cspVersion.BuildVersion);
|
||||
return !!cspVersionStr;
|
||||
} catch (error) {
|
||||
console.error("Ошибка при получении версии CSP:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import {HttpClient, HttpParams} from "@angular/common/http";
|
|||
import {MessagesService} from "@webbpm/base-package";
|
||||
import {AuthenticationService} from "../authentication.service";
|
||||
import {EsiaErrorDetail} from "../EsiaErrorDetail";
|
||||
import {CadesHelper} from "@webbpm/base-package";
|
||||
|
||||
@Injectable({providedIn:'root'})
|
||||
export abstract class AuthGuard implements CanActivate {
|
||||
|
|
@ -21,68 +22,79 @@ export abstract class AuthGuard implements CanActivate {
|
|||
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
|
||||
let url = new URL(window.location.href);
|
||||
if (!this.checkBrowser()) {
|
||||
window.open(url.origin + url.pathname + "home.html", "_self");
|
||||
this.router.navigateByUrl('/home-landing');
|
||||
return false;
|
||||
}
|
||||
let hasAccess: Promise<boolean> | boolean = this.checkAccess();
|
||||
|
||||
return Promise.resolve(hasAccess).then((isAccess) => {
|
||||
let params = new URLSearchParams(url.search);
|
||||
let code = params.get('code');
|
||||
let error = params.get('error');
|
||||
let errorDescription = params.get('error_description');
|
||||
if (isAccess) {
|
||||
return true;
|
||||
}
|
||||
if (code || error) {
|
||||
const params = new HttpParams().set('code', code).set('error', error);
|
||||
this.httpClient.get("esia/auth",
|
||||
{
|
||||
params: params, responseType: 'text', observe: 'response', headers: {
|
||||
"Error-intercept-skip": "true"
|
||||
}
|
||||
})
|
||||
.toPromise()
|
||||
.then(
|
||||
(response) => {
|
||||
window.open(url.origin + url.pathname, "_self");
|
||||
})
|
||||
.catch((reason) => {
|
||||
let errorMessage = reason.error.messages != null
|
||||
? reason.error.messages
|
||||
: reason.error.replaceAll('\\', '');
|
||||
if (error) {
|
||||
errorMessage = 'Произошла неизвестная ошибка. Обратитесь к системному администратору';
|
||||
let errorCode = this.extractCode(errorDescription);
|
||||
if (errorCode) {
|
||||
errorMessage = EsiaErrorDetail.getDescription(errorCode);
|
||||
}
|
||||
let consoleError = error + ', error description = ' + errorDescription;
|
||||
this.messageService.error(errorMessage);
|
||||
console.error(consoleError);
|
||||
}
|
||||
else {
|
||||
this.messageService.error(errorMessage);
|
||||
console.error(reason);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return this.httpClient.get<string>("esia/url")
|
||||
.toPromise()
|
||||
.then(url => {
|
||||
window.open(url, "_self");
|
||||
return true;
|
||||
}).catch((reason)=> {
|
||||
console.error(reason);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}).catch((reason) => {
|
||||
console.error(reason);
|
||||
return false
|
||||
});
|
||||
return this.checkCsp()
|
||||
.then((cspCheckPassed) => {
|
||||
if (!cspCheckPassed) {
|
||||
this.router.navigateByUrl('/home-landing');
|
||||
return Promise.reject("Navigation on /home-landing")
|
||||
}
|
||||
return Promise.resolve(this.checkAccess());
|
||||
}).then((isAccess) => {
|
||||
let params = new URLSearchParams(url.search);
|
||||
let code = params.get('code');
|
||||
let error = params.get('error');
|
||||
let errorDescription = params.get('error_description');
|
||||
if (isAccess) {
|
||||
return true;
|
||||
}
|
||||
if (code || error) {
|
||||
const params = new HttpParams().set('code', code).set('error', error);
|
||||
this.httpClient.get("esia/auth",
|
||||
{
|
||||
params: params,
|
||||
responseType: 'text',
|
||||
observe: 'response',
|
||||
headers: {
|
||||
"Error-intercept-skip": "true"
|
||||
}
|
||||
})
|
||||
.toPromise()
|
||||
.then(
|
||||
(response) => {
|
||||
window.open(url.origin + url.pathname, "_self");
|
||||
})
|
||||
.catch((reason) => {
|
||||
let errorMessage = reason.error.messages != null
|
||||
? reason.error.messages
|
||||
: reason.error.replaceAll('\\', '');
|
||||
if (error) {
|
||||
errorMessage =
|
||||
'Произошла неизвестная ошибка. Обратитесь к системному администратору';
|
||||
let errorCode = this.extractCode(errorDescription);
|
||||
if (errorCode) {
|
||||
errorMessage = EsiaErrorDetail.getDescription(errorCode);
|
||||
}
|
||||
let consoleError = error + ', error description = ' + errorDescription;
|
||||
this.messageService.error(errorMessage);
|
||||
console.error(consoleError);
|
||||
}
|
||||
else {
|
||||
this.messageService.error(errorMessage);
|
||||
console.error(reason);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return this.httpClient.get<string>("esia/url")
|
||||
.toPromise()
|
||||
.then(url => {
|
||||
window.open(url, "_self");
|
||||
return true;
|
||||
}).catch((reason) => {
|
||||
console.error(reason);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}).catch((reason) => {
|
||||
if (reason !== 'Navigation on /home-landing') {
|
||||
console.error(reason);
|
||||
}
|
||||
return false
|
||||
});
|
||||
}
|
||||
|
||||
private checkAccess(): boolean {
|
||||
|
|
@ -99,4 +111,24 @@ export abstract class AuthGuard implements CanActivate {
|
|||
const userAgent = navigator.userAgent;
|
||||
return userAgent.indexOf("Chromium GOST") > -1 || userAgent.indexOf("YaBrowser") > -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка работы CSP через CadesPlugin (асинхронно)
|
||||
*/
|
||||
private async checkCsp(): Promise<boolean> {
|
||||
try {
|
||||
if (!CadesHelper.plugin()) {
|
||||
console.error("Ошибка: cadesplugin не найден!");
|
||||
return false;
|
||||
}
|
||||
await CadesHelper.plugin();
|
||||
const oAbout = await CadesHelper.plugin().CreateObjectAsync("CAdESCOM.About");
|
||||
const cspVersion = await oAbout.CSPVersion();
|
||||
let cspVersionStr = (await cspVersion.MajorVersion) + "." + (await cspVersion.MinorVersion) + "." + (await cspVersion.BuildVersion);
|
||||
return !!cspVersionStr;
|
||||
} catch (error) {
|
||||
console.error("Ошибка при получении версии CSP:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {Component} from "@angular/core";
|
||||
import {ChangeDetectorRef, Component} from "@angular/core";
|
||||
import {
|
||||
Event,
|
||||
NavigationCancel,
|
||||
|
|
@ -17,10 +17,14 @@ import {ProgressIndicationService} from "@webbpm/base-package";
|
|||
export class WebbpmComponent {
|
||||
public headerVisible: boolean = true;
|
||||
public footerVisible: boolean = true;
|
||||
public isLanding: boolean = false;
|
||||
|
||||
constructor(private router: Router,
|
||||
private progressIndicationService: ProgressIndicationService) {
|
||||
private progressIndicationService: ProgressIndicationService,
|
||||
private cd: ChangeDetectorRef) {
|
||||
this.isLanding = window.location.href.endsWith('home-landing');
|
||||
router.events.subscribe((event: Event) => {
|
||||
this.isLanding = window.location.href.endsWith('home-landing');
|
||||
if (event instanceof NavigationStart) {
|
||||
progressIndicationService.showProgressBar();
|
||||
}
|
||||
|
|
@ -29,6 +33,7 @@ export class WebbpmComponent {
|
|||
|| event instanceof NavigationCancel) {
|
||||
progressIndicationService.hideProgressBar();
|
||||
}
|
||||
this.cd.markForCheck();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue