initial commit
1
frontend/.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
registry=https://repo.micord.ru/repository/npm-all/
|
||||
71
frontend/angular.json
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"webbpm-frontend": {
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/ts/main.ts",
|
||||
"tsConfig": "src/tsconfig.json",
|
||||
"polyfills": "src/ts/polyfills.ts",
|
||||
"assets": [
|
||||
"src/resources"
|
||||
],
|
||||
"styles": [
|
||||
],
|
||||
"scripts": [
|
||||
"node_modules/jquery/dist/jquery.min.js",
|
||||
"node_modules/moment/min/moment-with-locales.js",
|
||||
"node_modules/moment-timezone/builds/moment-timezone-with-data.min.js",
|
||||
"node_modules/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js",
|
||||
"node_modules/selectize/dist/js/standalone/selectize.min.js",
|
||||
"node_modules/downloadjs/download.min.js"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "webbpm-frontend:build"
|
||||
},
|
||||
"configurations": {}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "webbpm-frontend:build"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [],
|
||||
"exclude": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "webbpm-frontend"
|
||||
}
|
||||
23
frontend/index.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ervu-eks</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="icon" type="image/png" href="src/resources/img/logo.png"/>
|
||||
<link rel="stylesheet" href="src/resources/css/style.css"/>
|
||||
|
||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||
<script src="systemjs.config.js"></script>
|
||||
<script>
|
||||
System.import('webbpm').catch(function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body webbpm class="webbpm ervu-eks">
|
||||
<div class="progress"></div>
|
||||
</body>
|
||||
</html>
|
||||
11
frontend/index.webpack.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ervu-eks</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="icon" type="image/png" href="src/resources/img/logo.png"/>
|
||||
</head>
|
||||
<body webbpm class="webbpm ervu-eks">
|
||||
<div class="progress"></div>
|
||||
</body>
|
||||
</html>
|
||||
100
frontend/package.json
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"name": "ervu-eks",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"cleanup": "npm run cleanup-ngc && node ./node_modules/rimraf/bin ./build ./dist",
|
||||
"cleanup-ngc": "node ./node_modules/rimraf/bin ./src/ts/**/*.js ./src/ts/**/*.json ./src/ts/page.routing.ts",
|
||||
"cleanup-and-ngc": "npm run cleanup && npm run ngc",
|
||||
"ngc": "node --max-old-space-size=14336 ./node_modules/@angular/compiler-cli/src/main -p tsconfig.aot.json",
|
||||
"build-webpack": "node --max-old-space-size=14336 ./node_modules/webpack/bin/webpack --config webpack.aot.config.js --progress --profile",
|
||||
"save-ts-metadata": "node save.ts.metadata.js",
|
||||
"tsc": "node ./node_modules/typescript/bin/tsc",
|
||||
"tsc-watch": "node ./node_modules/typescript/bin/tsc --watch",
|
||||
"ts-watch": "node node_modules/cross-env/dist/bin/cross-env.js TSC_NONPOLLING_WATCHER=true npm run tsc-watch",
|
||||
"ts": "npm install && npm run tsc",
|
||||
"compile": "npm run ts-watch",
|
||||
"install-compile": "npm install && npm run ts-watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "7.2.15",
|
||||
"@angular/common": "7.2.15",
|
||||
"@angular/compiler": "7.2.15",
|
||||
"@angular/core": "7.2.15",
|
||||
"@angular/forms": "7.2.15",
|
||||
"@angular/http": "7.2.15",
|
||||
"@angular/platform-browser": "7.2.15",
|
||||
"@angular/platform-browser-dynamic": "7.2.15",
|
||||
"@angular/router": "7.2.15",
|
||||
"@ng-bootstrap/ng-bootstrap": "4.2.2-micord.1",
|
||||
"@webbpm/base-package": "3.185.0",
|
||||
"ag-grid-angular": "29.0.0-micord.4",
|
||||
"ag-grid-community": "29.0.0-micord.4",
|
||||
"angular-calendar": "0.28.28",
|
||||
"autonumeric": "4.5.10-cg",
|
||||
"bootstrap": "4.3.1",
|
||||
"bootstrap-icons": "1.10.3",
|
||||
"cadesplugin_api": "2.0.4-micord.1",
|
||||
"chart.js": "3.8.0-cg.1",
|
||||
"chartjs-adapter-moment": "1.0.0",
|
||||
"core-js": "2.4.1",
|
||||
"date-fns": "2.29.3",
|
||||
"downloadjs": "1.4.8",
|
||||
"eonasdan-bootstrap-datetimepicker": "4.17.47-micord.5",
|
||||
"esmarttokenjs": "2.2.1-cg",
|
||||
"font-awesome": "4.7.0",
|
||||
"google-libphonenumber": "3.0.9",
|
||||
"inputmask": "5.0.5-cg.2",
|
||||
"jquery": "3.7.1",
|
||||
"js-year-calendar": "1.0.0-cg.2",
|
||||
"jsgantt-improved": "2.0.10-cg",
|
||||
"moment": "2.30.1",
|
||||
"moment-timezone": "0.5.46",
|
||||
"ngx-cookie": "3.0.1",
|
||||
"ngx-international-phone-number": "1.0.6",
|
||||
"ngx-toastr": "10.2.0-cg",
|
||||
"popper.js": "1.14.7",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rxjs": "6.4.0",
|
||||
"rxjs-compat": "6.4.0",
|
||||
"selectize": "0.12.4-cg.11",
|
||||
"systemjs": "0.21.4",
|
||||
"systemjs-plugin-babel": "0.0.25",
|
||||
"tslib": "1.9.3",
|
||||
"zone.js": "0.11.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-optimizer": "0.13.9",
|
||||
"@angular-devkit/core": "7.3.9",
|
||||
"@angular/cli": "7.3.9",
|
||||
"@angular/compiler-cli": "7.2.15",
|
||||
"@angular/platform-server": "7.2.15",
|
||||
"@babel/core": "7.18.10",
|
||||
"@babel/preset-env": "7.18.10",
|
||||
"@types/bootstrap": "3.3.39",
|
||||
"@types/eslint": "7.2.5",
|
||||
"@types/jquery": "3.5.5",
|
||||
"@types/node": "7.0.5",
|
||||
"@types/selectize": "0.12.33",
|
||||
"ajv": "8.8.2",
|
||||
"angular-router-loader": "0.8.5",
|
||||
"angular2-template-loader": "0.6.2",
|
||||
"babel-loader": "9.1.2",
|
||||
"codelyzer": "5.2.1",
|
||||
"copy-webpack-plugin": "5.0.3",
|
||||
"cross-env": "5.2.1",
|
||||
"css-loader": "6.11.0",
|
||||
"del": "2.2.2",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.6.0",
|
||||
"mini-css-extract-plugin": "2.9.1",
|
||||
"mkdirp": "3.0.1",
|
||||
"raw-loader": "4.0.2",
|
||||
"style-loader": "3.3.4",
|
||||
"terser-webpack-plugin": "5.3.10",
|
||||
"tslint": "5.13.1",
|
||||
"typescript": "3.2.4",
|
||||
"typescript-parser": "2.6.1-cg.2",
|
||||
"webpack": "5.90.1",
|
||||
"webpack-cli": "5.0.2"
|
||||
}
|
||||
}
|
||||
113
frontend/pom.xml
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>ru.micord.ervu</groupId>
|
||||
<artifactId>eks</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ru.micord.ervu.eks</groupId>
|
||||
<artifactId>frontend</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.google.code.maven-replacer-plugin</groupId>
|
||||
<artifactId>replacer</artifactId>
|
||||
<version>1.5.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>replace-version-in-url</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>replace</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>${basedir}/src/resources/app-config.json</include>
|
||||
<include>${basedir}/dist/src/resources/app-config.json</include>
|
||||
<include>${basedir}/src/resources/app.version</include>
|
||||
<include>${basedir}/dist/src/resources/app.version</include>
|
||||
</includes>
|
||||
<replacements>
|
||||
<replacement>
|
||||
<token>%project.version%</token>
|
||||
<value>${project.version}</value>
|
||||
</replacement>
|
||||
<replacement>
|
||||
<token>%enable.version.in.url%</token>
|
||||
<value>${enable.version.in.url}</value>
|
||||
</replacement>
|
||||
</replacements>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>dev</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<copyWebResources>false</copyWebResources>
|
||||
<webResources>
|
||||
<resource>
|
||||
<directory>${basedir}</directory>
|
||||
<includes>
|
||||
<include>src/resources/**/*</include>
|
||||
<include>build_dev/**/*</include>
|
||||
<include>node_modules/**/*</include>
|
||||
<include>index.html</include>
|
||||
<include>systemjs.config.js</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>compile-ts</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
</activation>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>prod</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<copyWebResources>false</copyWebResources>
|
||||
<webResources>
|
||||
<resource>
|
||||
<directory>${basedir}/dist</directory>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>enable-version-in-url</id>
|
||||
<properties>
|
||||
<enable.version.in.url>true</enable.version.in.url>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
23
frontend/preview.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Web BPM</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="icon" type="image/png" href="src/resources/img/logo.png"/>
|
||||
<link rel="stylesheet" href="src/resources/css/style.css"/>
|
||||
|
||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||
<script src="systemjs.preview.config.js"></script>
|
||||
<script>
|
||||
System.import('preview').catch(function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body preview-container id="webbpm-angular-application-container ervu-eks" class="webbpm">
|
||||
<div class="progress"></div>
|
||||
</body>
|
||||
</html>
|
||||
72
frontend/save.ts.metadata.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env node
|
||||
var tsp = require("typescript-parser");
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var ts = require("typescript");
|
||||
|
||||
var parser = new tsp.TypescriptParser();
|
||||
var excludedDirs = [
|
||||
'generated-sources'
|
||||
];
|
||||
|
||||
var walkFileTree = function (dir, action) {
|
||||
if (typeof action !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.readdirSync(dir).forEach(function (file) {
|
||||
var path = dir + "/" + file;
|
||||
var stat = fs.statSync(path);
|
||||
var extension = ".ts";
|
||||
if (stat && stat.isDirectory() && excludedDirs.indexOf(file) === -1) {
|
||||
walkFileTree(path, action);
|
||||
}
|
||||
else if (path.indexOf(extension, path.length - extension.length) !== -1) {
|
||||
action(null, path);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var dateInLong = Date.now();
|
||||
var arr = [];
|
||||
|
||||
var basePath = path.resolve(__dirname, "src/ts/");
|
||||
walkFileTree(basePath, function (err, file) {
|
||||
var content = fs.readFileSync(file).toString();
|
||||
var jsonStructure = parser.parseTypescript(ts.createSourceFile(
|
||||
file,
|
||||
content,
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
ts.ScriptKind.TS
|
||||
),
|
||||
'/');
|
||||
jsonStructure['packageName'] = path.relative(path.resolve(__dirname, "src/ts/"),jsonStructure['filePath']);
|
||||
jsonStructure['imports'].forEach( function (val) {
|
||||
if (val.libraryName.startsWith(".")) {
|
||||
val['libraryName'] = path.resolve(path.dirname(jsonStructure['filePath']), val['libraryName']);
|
||||
val['libraryName'] = path.relative(path.resolve(__dirname, "src/ts/"), val['libraryName']);
|
||||
val['libraryName'] = path.dirname(val['libraryName']).split(path.sep).join(".");
|
||||
}
|
||||
});
|
||||
delete jsonStructure['filePath'];
|
||||
jsonStructure['packageName'] = path.dirname(jsonStructure['packageName']).split(path.sep).join( ".");
|
||||
arr.push(jsonStructure);
|
||||
});
|
||||
var cache = [];
|
||||
|
||||
fs.writeFileSync("./../.studio/typescript.metadata.json",
|
||||
JSON.stringify(arr, function (key, value) {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
if (cache.indexOf(value) !== -1) {
|
||||
// Circular reference found, discard key
|
||||
return;
|
||||
}
|
||||
// Store value in our collection
|
||||
cache.push(value);
|
||||
}
|
||||
return value;
|
||||
}));
|
||||
|
||||
cache = null;
|
||||
console.log("typescript parse time = " + (Date.now() - dateInLong));
|
||||
19
frontend/src/resources/app-config.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"electronic_sign.esmart_extension_url": "",
|
||||
"electronic_sign.tsp_address": "",
|
||||
"filter_cleanup_interval_hours": 720,
|
||||
"filter_cleanup_check_period_minutes": 30,
|
||||
"auth_method": "form",
|
||||
"enable.version.in.url": "false",
|
||||
"guard.confirm_exit": false,
|
||||
"message_service_error_timeout": "",
|
||||
"message_service_warning_timeout": "",
|
||||
"message_service_success_timeout": "",
|
||||
"message_service_info_timeout": "",
|
||||
"jivo_chat_widget_api_url": "https://code.jivo.ru/widget/{ID}",
|
||||
"jivo_chat_widget_enabled": false,
|
||||
"password_pattern": "^((?=(.*\\d){1,})(?=.*[a-zа-яё])(?=.*[A-ZА-ЯЁ]).{8,})$",
|
||||
"password_pattern_error": "Пароль должен содержать заглавные или прописные буквы и как минимум 1 цифру",
|
||||
"show.client.errors": false,
|
||||
"available_task.single_fetch": true
|
||||
}
|
||||
1
frontend/src/resources/app.version
Normal file
|
|
@ -0,0 +1 @@
|
|||
1.0.0-SNAPSHOT
|
||||
1584
frontend/src/resources/css/components-app.css
Normal file
342
frontend/src/resources/css/inbox-app.css
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
@font-face {
|
||||
font-family: 'Segoe';
|
||||
src: url('../fonts/Segoe.ttf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'SegoeSL';
|
||||
src: url('../fonts/SegoeSL.ttf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'SegoeSB';
|
||||
src: url('../fonts/SegoeSB.ttf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'SegoeB';
|
||||
src: url('../fonts/SegoeB.ttf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'SegoeBL';
|
||||
src: url('../fonts/SegoeBL.ttf');
|
||||
}
|
||||
|
||||
.webbpm a {
|
||||
color: var(--color-link);
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
color: var(--color-link-hover);
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
body.webbpm {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: var(--color-text-primary);
|
||||
font-family: 'Segoe';
|
||||
background-color: var(--white);
|
||||
}
|
||||
|
||||
.webbpm .container {
|
||||
padding: 70px 0 0;
|
||||
}
|
||||
|
||||
body.webbpm [id="page"],
|
||||
.webbpm .container .container-inside {
|
||||
font-family: 'Segoe';
|
||||
font-size: var(--size-text-primary);
|
||||
}
|
||||
|
||||
.webbpm .logo {
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.webbpm .header-logo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-left: 40px;
|
||||
|
||||
.logo a {
|
||||
background: url('../../../src/resources/img/logo-full.png') no-repeat 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.webbpm .header-menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-left: auto;
|
||||
margin-right: 40px;
|
||||
& > * {
|
||||
margin-right: 20px;
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
.nav-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--white);
|
||||
font-size: var(--size-text-primary);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 15px;
|
||||
background-color: var(--color-text-primary);
|
||||
outline: transparent;
|
||||
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
background-color: var(--color-link);
|
||||
}
|
||||
}
|
||||
.logout .user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: var(--black);
|
||||
padding: 4px 20px;
|
||||
background: transparent;
|
||||
cursor: default;
|
||||
|
||||
& > * {
|
||||
display: flex;
|
||||
padding-bottom: 10px;
|
||||
margin: 0 0 10px 0;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.user-fio {
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.user-department {
|
||||
color: #a0b1bc;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.webbpm .header {
|
||||
display: flex;
|
||||
font-family: 'Segoe';
|
||||
width: 100%;
|
||||
height: auto;
|
||||
min-height: 70px;
|
||||
border-bottom: 1px solid var(--bg-light);
|
||||
background: var(--white);
|
||||
box-shadow: 0px 15px 20px 0px rgb(0 0 0 / 4%);
|
||||
|
||||
& > div > * {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dropdown-menu.show {
|
||||
top: 69px !important;
|
||||
right: 0px !important;
|
||||
left: auto !important;
|
||||
transform: none !important;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
border-radius: 0 0 10px 10px;
|
||||
background-color: var(--white);
|
||||
box-shadow: 0 8px 12px rgb(77 72 91 / 5%), 0 6px 10px rgb(77 72 91 / 0%);
|
||||
|
||||
.dropdown-menu-inner {
|
||||
max-height: calc(100vh - 140px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
:is(process, admin-menu) .dropdown-menu.show {
|
||||
top: 49px !important;
|
||||
}
|
||||
|
||||
.logout .dropdown-menu.show {
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.webbpm .dropdown-menu-inner:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.webbpm .dropdown-item {
|
||||
padding: 4px 20px;
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
color: var(--color-link);
|
||||
background-color: transparent;
|
||||
outline: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.webbpm footer {
|
||||
color: var(--color-text-primary);
|
||||
font-size: var(--size-text-secondary);
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 15px 40px;
|
||||
border-top: 1px solid var(--border-light);
|
||||
a {
|
||||
color: var(--color-text-primary);
|
||||
&:hover {
|
||||
color: var(--color-link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------- Menu tasks -------------- */
|
||||
.webbpm .task-list-tree-panel {
|
||||
padding: 0 40px;
|
||||
.task-list-filter {
|
||||
font-family: 'Segoe';
|
||||
box-shadow: none;
|
||||
|
||||
li:first-of-type {
|
||||
font-family: 'SegoeSB';
|
||||
font-weight: normal;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
li.ontime label div {
|
||||
background-color: #31c980;
|
||||
}
|
||||
|
||||
li.overdue label div {
|
||||
background-color: var(--color-link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.webbpm .task-list-workplace {
|
||||
padding: 20px 40px 0 40px;
|
||||
}
|
||||
|
||||
.webbpm .task-tbl :is(.tr.task-ontime, .tr.task-overdue) > .td.task::before {
|
||||
top: 24px;
|
||||
background-color: #31c980;
|
||||
}
|
||||
|
||||
.webbpm .task-tbl .tr.task-overdue > .td.task::before {
|
||||
background-color: var(--color-link);
|
||||
}
|
||||
|
||||
.webbpm .task-tbl .thead {
|
||||
display: table-header-group;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.webbpm .task-tbl .th {
|
||||
color: var(--color-text-primary);
|
||||
font-family: 'SegoeSB';
|
||||
font-size: var(--size-text-secondary);
|
||||
font-weight: normal;
|
||||
padding: 9px 12px;
|
||||
border: 0;
|
||||
background: var(--bg-light);
|
||||
}
|
||||
.webbpm .task-tbl .th:first-child {
|
||||
border-top-left-radius: 12px;
|
||||
border-bottom-left-radius: 12px;
|
||||
}
|
||||
.webbpm .task-tbl .th:last-child {
|
||||
border-top-right-radius: 12px;
|
||||
border-bottom-right-radius: 12px;
|
||||
}
|
||||
|
||||
.webbpm .task-tbl .td {
|
||||
color: var(--color-text-primary);
|
||||
font-size: var(--size-text-primary);
|
||||
padding: 16px 12px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.webbpm .task-tbl .thead ~ .tr {
|
||||
border-color: var(--border-light);
|
||||
border-width: 1px 0 0 0;
|
||||
border-style: solid;
|
||||
}
|
||||
.webbpm .task-tbl .thead + .tr {
|
||||
border-top-color: transparent;
|
||||
}
|
||||
|
||||
.webbpm .task-tbl .thead ~ .tr:hover {
|
||||
border-top-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
.webbpm .task-tbl .thead ~ .tr:hover +.tr {
|
||||
border-top-color: transparent;
|
||||
}
|
||||
|
||||
.webbpm .task-tbl .thead ~ .tr:hover .td {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.webbpm .task-tbl .thead ~ .tr:hover .td:first-child {
|
||||
border-top-left-radius: 12px;
|
||||
border-bottom-left-radius: 12px;
|
||||
}
|
||||
.webbpm .task-tbl .thead ~ .tr:hover .td:last-child {
|
||||
border-top-right-radius: 12px;
|
||||
border-bottom-right-radius: 12px;
|
||||
}
|
||||
/*------------- end Menu tasks ----------- */
|
||||
|
||||
/*----------------- Login ---------------- */
|
||||
.webbpm :is(.form-signin, .form-signup, .confirm) {
|
||||
color: var(--color-text-primary);
|
||||
width: 560px;
|
||||
padding: 60px 80px;
|
||||
margin: 30px auto;
|
||||
border: 0;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0px 0px 30px 2px rgb(77 72 91 / 12%);
|
||||
background-color: var(--white);
|
||||
}
|
||||
|
||||
.webbpm :is(.form-signin, .form-signup) .row.title {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.webbpm .form-signin h1,
|
||||
.webbpm .form-signin h2,
|
||||
.webbpm .form-signup h2,
|
||||
.webbpm .confirm h2 {
|
||||
font-family: 'SegoeB';
|
||||
font-size: 32px;
|
||||
text-align: left;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.webbpm :is(.form-signin, .form-signup, .confirm) .logo {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: 0;
|
||||
width: 145px;
|
||||
height: 40px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.webbpm .form-signin .row.registration > * + *,
|
||||
.webbpm .form-signin .login-btn-box .password,
|
||||
.webbpm .form-signin .login-btn-box .btn + .btn {
|
||||
margin-left: 20px;
|
||||
}
|
||||
/*--------------- end Login -------------- */
|
||||
846
frontend/src/resources/css/structure.css
Normal file
|
|
@ -0,0 +1,846 @@
|
|||
:root {
|
||||
--white: #ffffff;
|
||||
--black: #000000;
|
||||
--color-text-primary: #404954;
|
||||
--color-link: #1c92ea;
|
||||
--color-link-hover: #1b84d2;
|
||||
--bg-light: #f5f7fa;
|
||||
--bg-secondary: #4c5969;
|
||||
--border-light: #e3e6ed;
|
||||
|
||||
--size-text-primary: 16px;
|
||||
--size-text-secondary: 14px;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body.webbpm .form-signin label {
|
||||
width: 160px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.webbpm .progress {
|
||||
position: absolute;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin-bottom: 0 !important;
|
||||
background: url("../img/progress.gif") no-repeat 0 0;
|
||||
}
|
||||
|
||||
.webbpm > .progress {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -30px;
|
||||
margin-left: -30px;
|
||||
}
|
||||
|
||||
.webbpm .search-task-progress-bar {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.webbpm .modal-body .progress,
|
||||
.webbpm .search-task-progress-bar .progress {
|
||||
position: relative;
|
||||
top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/*-- common class --*/
|
||||
.webbpm .fl-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.webbpm .fl-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.webbpm .anchor {
|
||||
float: none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.webbpm :is(ul, ol) li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.webbpm :is(h1, h2, h3) {
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
.webbpm h1 {
|
||||
font-size: 2.33em;
|
||||
}
|
||||
.webbpm h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
.webbpm h3 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.webbpm .table {
|
||||
display: table;
|
||||
}
|
||||
|
||||
.webbpm .tr {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.webbpm .td, .webbpm .th {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
/*-- layout --*/
|
||||
html, body.webbpm {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
body.webbpm {
|
||||
background-color: #f9f9fa;
|
||||
font-family: Arial;
|
||||
font-size: var(--size-text-secondary);
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.webbpm .wrapper {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.webbpm .container {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
padding: 67px 0 0;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 50px;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
|
||||
[ng-include="taskPageFile"] {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
.container-inside {
|
||||
font-family: Arial;
|
||||
font-size: var(--size-text-secondary);
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.webbpm footer {
|
||||
position: absolute;
|
||||
color: var(--black);
|
||||
font-size: 12px;
|
||||
bottom: 0;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
height: 50px;
|
||||
padding: 15px 0;
|
||||
border-top: 1px solid #c1c1c1;
|
||||
background: transparent;
|
||||
|
||||
span + span {
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
/*--------- TOP MENU ----------*/
|
||||
.webbpm .logo {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
float: left;
|
||||
|
||||
a {
|
||||
width: 200px;
|
||||
height: 67px;
|
||||
position: absolute;
|
||||
background: url("../img/logo.png") no-repeat 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.webbpm .header {
|
||||
position: absolute;
|
||||
color: var(--white);
|
||||
font-family: Corbel;
|
||||
font-size: var(--size-text-secondary);
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 67px;
|
||||
min-height: 67px;
|
||||
line-height: normal;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background: #b9c0ca;
|
||||
z-index: 997;
|
||||
|
||||
.nav .nav-link {
|
||||
color: var(--white);
|
||||
float: none;
|
||||
display: block;
|
||||
line-height: 60px;
|
||||
padding: 0 15px 0 60px;
|
||||
text-shadow: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav .nav-link:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.webbpm .dropdown-menu {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.webbpm .nav .nav-item .dropdown-menu:after {
|
||||
border-bottom: 6px solid #eee;
|
||||
}
|
||||
|
||||
.webbpm .inner {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.webbpm .navbar .nav > * {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.webbpm .dropdown-menu > div > button {
|
||||
color: #d1dbe5;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------- end - TOP MENU ----------*/
|
||||
.webbpm .user-department,
|
||||
.webbpm .user-info {
|
||||
color: #5a6473;
|
||||
}
|
||||
|
||||
.webbpm .user-info > * {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.webbpm [log-out] {
|
||||
max-width: 40%;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.webbpm .content {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.webbpm .inner {
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
overflow-y : scroll;
|
||||
}
|
||||
|
||||
/*--------------task-list------------------*/
|
||||
.task-list {
|
||||
font-size: 0;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.task-list > div {
|
||||
display: block;
|
||||
float: left;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
font-size: var(--size-text-secondary);
|
||||
}
|
||||
|
||||
.task-list-tree-panel {
|
||||
width: 20%;
|
||||
background: #e9edf2;
|
||||
border-right: 1px solid #b9c1ca;
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter {
|
||||
position: relative;
|
||||
margin-top: 15px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter li {
|
||||
position: relative;
|
||||
padding: 8px 10px;
|
||||
margin: 2px 10px;
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter li::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
border: 1px solid rgb(206, 212, 219);
|
||||
border-radius: 4px;
|
||||
background-color: var(--white);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter li label:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter li label {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter li label input[type="radio"] {
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter li label span {
|
||||
float: right;
|
||||
background-color: #bbb;
|
||||
padding: 0px 4px;
|
||||
border-radius: 3px;
|
||||
min-width: 25px;
|
||||
text-align: center;
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter li.ontime label span {
|
||||
background-color: #a0c367;
|
||||
}
|
||||
|
||||
.task-list-tree-panel .task-list-filter li.overdue label span {
|
||||
background-color: #fc2d2d;
|
||||
}
|
||||
|
||||
.task-list-header {
|
||||
border-bottom: 1px solid #b9c1ca;
|
||||
background-color: #ccd6e0;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
color: #565968;
|
||||
font-size: var(--size-text-secondary);
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.structure-box {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.task-list-workplace {
|
||||
width: 80%;
|
||||
padding: 15px 15px 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
/*--------------task-list end--------------*/
|
||||
|
||||
/*---------------table-list----------------*/
|
||||
.task-tbl {
|
||||
background: var(--white);
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.task-tbl .td, .task-tbl .th {
|
||||
border: 1px solid #b9c1ca;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.task-tbl .th {
|
||||
color: #565968;
|
||||
}
|
||||
|
||||
.task-tbl .td {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.task-tbl .thead {
|
||||
background: #ccd6e0;
|
||||
}
|
||||
|
||||
.task-tbl > .tr:hover {
|
||||
cursor: pointer;
|
||||
background: #e9edf2;
|
||||
}
|
||||
|
||||
.task-tbl .tr.task-ontime > .td.task,
|
||||
.task-tbl .tr.task-overdue > .td.task {
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.task-tbl .tr.task-ontime > .td.task::before,
|
||||
.task-tbl .tr.task-overdue > .td.task::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
left: 5px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: #a0c367;
|
||||
border-radius: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.task-tbl .tr.task-overdue > .td.task::before {
|
||||
background-color: #ff0000;
|
||||
}
|
||||
/*----------------table-list end----------------*/
|
||||
|
||||
/*--------------Окно сообщения об ошибке--------------*/
|
||||
.webbpm #toast-container {
|
||||
font-size: 12px;
|
||||
bottom: auto;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 95%;
|
||||
}
|
||||
|
||||
.webbpm #toast-container .toast:hover {
|
||||
box-shadow: 0 0 12px #999999;
|
||||
}
|
||||
|
||||
.webbpm #toast-container .ngx-toastr {
|
||||
min-width: 540px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.webbpm #toast-container .toast-error {
|
||||
background-color: #d9534f;
|
||||
}
|
||||
|
||||
.webbpm #toast-container .toast-close-button {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.webbpm .toast-message > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.webbpm .toast-message > .active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.webbpm .toast-message > .active::after {
|
||||
display: block;
|
||||
content: "";
|
||||
float: none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.webbpm .toast-message > .active a {
|
||||
float: right;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.webbpm .toast-message > .toast-msg-close.active ~ .toast-msg-text {
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.webbpm .toast-message a:not([href]):not([tabindex]) {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/*------------Окно сообщения об ошибке end------------*/
|
||||
|
||||
/*----------------- Ошибка 404 -------------------*/
|
||||
.webbpm .container .task-not-found-page {
|
||||
position: relative;
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.webbpm .container .task-not-found-container {
|
||||
display: table-cell;
|
||||
color: var(--black);
|
||||
font-size: 1.8em;
|
||||
background-color: #c9d4e0;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.webbpm .container .task-not-found-container > div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.webbpm .container .task-not-found-container > div:first-child {
|
||||
color: var(--white);
|
||||
font-size: 7.8em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.webbpm .container .task-not-found-container > div:last-child {
|
||||
text-align: left;
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.webbpm .container .task-not-found-container h2 {
|
||||
font-size: 2em;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
.webbpm .container .task-not-found-container a {
|
||||
cursor: pointer;
|
||||
}
|
||||
/*--------------- end Ошибка 404 -----------------*/
|
||||
|
||||
/*-------------- MOBILE --------------*/
|
||||
.webbpm.mobile .task-list-tree-panel,
|
||||
.webbpm.mobile footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.webbpm.mobile .task-list-workplace {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.webbpm.mobile .container {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.webbpm.mobile form {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.webbpm.mobile .form-signin {
|
||||
width: auto;
|
||||
padding: 20px;
|
||||
margin: 40px 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.webbpm.mobile .form-signin h1,
|
||||
.webbpm.mobile .form-signin h2 {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.webbpm.mobile .form-signin label {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.webbpm.mobile .form-signin input[type="text"],
|
||||
.webbpm.mobile .form-signin input[type="password"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.webbpm.mobile .form-signin .login-btn-box {
|
||||
width: auto;
|
||||
margin-right: 0;
|
||||
}
|
||||
/*-------------- end MOBILE --------------*/
|
||||
|
||||
|
||||
/*-------------- НОВЫЙ ДИЗАЙН --------------*/
|
||||
/*------------------ Фильтры ------------------*/
|
||||
.webbpm .task-list {
|
||||
height: auto;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.webbpm .task-list > .task-list-tree-panel {
|
||||
background: var(--white);
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.webbpm .task-list > .task-list-tree-panel,
|
||||
.webbpm .task-list > .task-list-workplace {
|
||||
font-size: var(--size-text-secondary);
|
||||
float: none;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.webbpm .task-list-tree-panel .task-list-filter {
|
||||
font-family: Corbel;
|
||||
margin: 0;
|
||||
box-shadow: 0px 4px 10px -5px rgba(40, 40, 40, 0.3);
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
padding: 12px 0px;
|
||||
margin: 0;
|
||||
|
||||
&:first-of-type {
|
||||
font-size: 1.4em;
|
||||
font-weight: bold;
|
||||
width: 197px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 1.3em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
label div {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 10px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
&.ontime label div {
|
||||
background-color: #2da6a1;
|
||||
}
|
||||
|
||||
&.overdue label div {
|
||||
background-color: #9c5d7a;
|
||||
}
|
||||
|
||||
label input[type="radio"] {
|
||||
float: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
label span {
|
||||
float: none;
|
||||
color: var(--black);
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
min-width: auto;
|
||||
padding: 5px 15px;
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
label input[type="radio"].ng-valid-parse ~ span {
|
||||
background-color: #eaedf2;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-------------- end НОВЫЙ ДИЗАЙН --------------*/
|
||||
|
||||
.webbpm .dialog-stack-trace {
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
max-height: 300px;
|
||||
}
|
||||
.webbpm .dialog-show-button {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
.webbpm .dialog-error-number {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
.webbpm .dialog-error-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/*-- login --*/
|
||||
.webbpm :is(.form-signin, .form-signup, .confirm) {
|
||||
color: #333;
|
||||
width: 580px;
|
||||
padding: 80px 100px;
|
||||
margin: 20px auto;
|
||||
border: 1px solid var(--bg-light);
|
||||
background: var(--white);
|
||||
}
|
||||
|
||||
.webbpm .form-signin.esia {
|
||||
width: 450px;
|
||||
text-align: center;
|
||||
padding: 45px 55px 35px 55px;
|
||||
}
|
||||
|
||||
.webbpm .form-signin h1,
|
||||
.webbpm .form-signin h2,
|
||||
.webbpm .form-signup h2,
|
||||
.webbpm .confirm h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.webbpm .form-signin.esia :is(h1, h2) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.webbpm .form-signin label,
|
||||
.webbpm .form-signup label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.webbpm .form-signin input {
|
||||
width: 240px;
|
||||
font-size: var(--size-text-secondary);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.webbpm .form-signin.esia input {
|
||||
width: 160px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.webbpm :is(.form-signin, .form-signup) .row {
|
||||
display: flex;
|
||||
margin: 0 0 20px;
|
||||
}
|
||||
|
||||
.webbpm .registration-link,
|
||||
.webbpm .login-link {
|
||||
margin-right: 20px;
|
||||
font-size: var(--size-text-secondary);
|
||||
}
|
||||
|
||||
.webbpm .form-signin .row.registration {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.webbpm .form-signin .login-btn-box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.webbpm .form-signin .row.registration > * + *,
|
||||
.webbpm .form-signin .login-btn-box .password,
|
||||
.webbpm .form-signin .login-btn-box .btn + .btn {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.webbpm .input-group > .input-group-append > .input-group-text {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.webbpm .form-signin .register-btn-box,
|
||||
.webbpm .form-signup .register-btn-box,
|
||||
.webbpm .form-signup .reset-password-btn-box {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.webbpm .form-signup .row international-phone-number .flagInput .btn {
|
||||
border-left: 1px solid #c6cdd3;
|
||||
}
|
||||
.webbpm .form-signup .row international-phone-number .flagInput ~ input {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.webbpm .form-signin .has-error .help-block {
|
||||
padding-left: 125px;
|
||||
font-size: var(--size-text-secondary);
|
||||
}
|
||||
|
||||
.webbpm .form-signup .has-account a {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
/*------------------ Формы регистрации и подтверждения ------------------*/
|
||||
.form-signup .has-account {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.form-signup .has-account a span,
|
||||
.confirm a span {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.form-signup .dropbtn.btn {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-signup .input-group-text {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.form-signup input.ng-invalid.ng-touched,
|
||||
.form-signup input.ng-invalid.ng-dirty {
|
||||
border-color: red !important;
|
||||
}
|
||||
|
||||
.form-signup .msg-alert {
|
||||
color: red;
|
||||
font-size: 11px;
|
||||
padding: 3px 0 0;
|
||||
}
|
||||
|
||||
.form-signup .consent {
|
||||
color: #929292;
|
||||
font-size: 13px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
/*------------------ End - Формы регистрации и подтверждения ------------------*/
|
||||
|
||||
/*------------------ Сообщения об ошибке ------------------*/
|
||||
.webbpm .error_message {
|
||||
width: 650px;
|
||||
margin: 0 auto;
|
||||
margin-top: 10%;
|
||||
}
|
||||
|
||||
.webbpm .error_title {
|
||||
position: relative;
|
||||
color: #9c5d7a;
|
||||
font-size: 5.5em;
|
||||
font-weight: bold;
|
||||
margin-left: 100px;
|
||||
line-height: 1;
|
||||
}
|
||||
.webbpm .error_title::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
left: -100px;
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
border-radius: 40px;
|
||||
background-color: #9c5d7a;
|
||||
background-image: url("../img/access_denied.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50% 50%;
|
||||
}
|
||||
|
||||
.webbpm .error_title_long {
|
||||
margin-bottom: 20px;
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
.webbpm .error_body {
|
||||
font-size: 2em;
|
||||
line-height: 1.2;
|
||||
margin: 5px 0 0 100px;
|
||||
}
|
||||
/*---------------- end Сообщения об ошибке ---------------*/
|
||||
/*-------------- Поле телефона ------------ */
|
||||
.flag {
|
||||
background-image: url('./../img/country-flags.jpg') !important;
|
||||
}
|
||||
/*-------------- end Поле телефона ------------ */
|
||||
|
||||
10
frontend/src/resources/css/style.css
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
@import "../../../node_modules/angular-calendar/css/angular-calendar.css";
|
||||
@import "../../../node_modules/bootstrap/dist/css/bootstrap-grid.css";
|
||||
@import "../../../node_modules/bootstrap/dist/css/bootstrap-reboot.css";
|
||||
@import "../../../node_modules/bootstrap/dist/css/bootstrap.css";
|
||||
@import "../../../node_modules/bootstrap-icons/font/bootstrap-icons.css";
|
||||
@import "../../../node_modules/font-awesome/css/font-awesome.css";
|
||||
@import "../../../node_modules/@webbpm/base-package/css/style.css";
|
||||
@import "structure.css";
|
||||
@import "inbox-app.css";
|
||||
@import "components-app.css";
|
||||
BIN
frontend/src/resources/fonts/Segoe.ttf
Normal file
BIN
frontend/src/resources/fonts/SegoeB.ttf
Normal file
BIN
frontend/src/resources/fonts/SegoeBL.ttf
Normal file
BIN
frontend/src/resources/fonts/SegoeSB.ttf
Normal file
BIN
frontend/src/resources/fonts/SegoeSL.ttf
Normal file
BIN
frontend/src/resources/img/access_denied.png
Normal file
|
After Width: | Height: | Size: 855 B |
BIN
frontend/src/resources/img/admin.png
Normal file
|
After Width: | Height: | Size: 811 B |
BIN
frontend/src/resources/img/country-flags.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
frontend/src/resources/img/create.png
Normal file
|
After Width: | Height: | Size: 673 B |
10
frontend/src/resources/img/icons/dots-six-vertical.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_340_5833)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.5 3.75C6.5 4.16421 6.16421 4.5 5.75 4.5C5.33579 4.5 5 4.16421 5 3.75C5 3.33579 5.33579 3 5.75 3C6.16421 3 6.5 3.33579 6.5 3.75ZM11 3.75C11 4.16421 10.6642 4.5 10.25 4.5C9.83579 4.5 9.5 4.16421 9.5 3.75C9.5 3.33579 9.83579 3 10.25 3C10.6642 3 11 3.33579 11 3.75ZM5.75 8.75C6.16421 8.75 6.5 8.41421 6.5 8C6.5 7.58579 6.16421 7.25 5.75 7.25C5.33579 7.25 5 7.58579 5 8C5 8.41421 5.33579 8.75 5.75 8.75ZM11 8C11 8.41421 10.6642 8.75 10.25 8.75C9.83579 8.75 9.5 8.41421 9.5 8C9.5 7.58579 9.83579 7.25 10.25 7.25C10.6642 7.25 11 7.58579 11 8ZM5.75 13C6.16421 13 6.5 12.6642 6.5 12.25C6.5 11.8358 6.16421 11.5 5.75 11.5C5.33579 11.5 5 11.8358 5 12.25C5 12.6642 5.33579 13 5.75 13ZM11 12.25C11 12.6642 10.6642 13 10.25 13C9.83579 13 9.5 12.6642 9.5 12.25C9.5 11.8358 9.83579 11.5 10.25 11.5C10.6642 11.5 11 11.8358 11 12.25Z" fill="#353535"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_340_5833">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
3
frontend/src/resources/img/icons/settings-sm.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4289 4.03093L14.5357 3.84641C14.7628 3.46915 15.2354 3.35853 15.5798 3.56346L15.593 3.57113L17.3235 4.56141C17.7982 4.83272 17.9624 5.4493 17.6908 5.91957C17.1401 6.8701 16.9763 7.94135 17.4902 8.83311C18.0042 9.72502 19.0132 10.12 20.11 10.12C20.656 10.12 21.11 10.5701 21.11 11.12V12.88C21.11 13.426 20.6598 13.88 20.11 13.88C19.0132 13.88 18.0042 14.275 17.4902 15.1669C16.9767 16.058 17.1399 17.1284 17.6896 18.0784C17.9642 18.5612 17.7961 19.1685 17.323 19.4389L15.593 20.4289L15.5798 20.4365C15.2354 20.6415 14.7628 20.5308 14.5357 20.1536L14.4308 19.9724L14.4297 19.9706C13.8837 19.0191 13.0383 18.3425 12.0087 18.3425C10.9799 18.3425 10.1319 19.0187 9.58109 19.9691L9.47424 20.1536C9.24711 20.5308 8.77457 20.6414 8.43014 20.4365L8.41699 20.4289L6.6865 19.4386C6.21174 19.1673 6.04759 18.5507 6.31911 18.0805C6.8698 17.1299 7.03367 16.0587 6.51976 15.1669C6.00578 14.275 4.99672 13.88 3.89998 13.88C3.35011 13.88 2.89998 13.426 2.89998 12.88V11.12C2.89998 10.574 3.35011 10.12 3.89998 10.12C4.99672 10.12 6.00578 9.72502 6.51976 8.83311C7.03367 7.94133 6.8698 6.87005 6.31911 5.9195C6.04759 5.44924 6.21222 4.83243 6.68699 4.56113L8.41699 3.57113L8.43014 3.56346C8.77458 3.35854 9.24714 3.46915 9.47426 3.8464L9.58016 4.02932C10.1262 4.98086 10.9716 5.65749 12.0012 5.65749C13.03 5.65749 13.878 4.9813 14.4289 4.03093ZM6.31911 5.9195C6.31895 5.91922 6.31879 5.91894 6.31863 5.91867L5.53998 6.36999L6.31925 5.91974C6.31921 5.91966 6.31916 5.91958 6.31911 5.9195ZM17.6896 18.0784C17.6902 18.0794 17.6908 18.0804 17.6913 18.0813L18.47 17.63L17.6886 18.0765C17.6889 18.0772 17.6893 18.0778 17.6896 18.0784ZM12.9865 2.92983C13.6989 1.73245 15.2596 1.28388 16.4929 2.01224L18.217 2.99885C19.5618 3.76765 20.0174 5.49069 19.2493 6.82024L19.2486 6.82132C18.8897 7.44056 18.9688 7.79392 19.0498 7.93437C19.1308 8.07497 19.3967 8.31999 20.11 8.31999C21.6439 8.31999 22.91 9.56986 22.91 11.12V12.88C22.91 14.414 21.6601 15.68 20.11 15.68C19.3967 15.68 19.1308 15.925 19.0498 16.0656C18.9688 16.2061 18.8897 16.5594 19.2486 17.1787L19.2514 17.1835C20.0153 18.5204 19.5627 20.2321 18.2165 21.0014L16.4929 21.9878C15.2596 22.7161 13.6989 22.2675 12.9865 21.0702L12.9811 21.0609L12.8711 20.8709L12.8692 20.8676C12.5152 20.25 12.171 20.1425 12.0087 20.1425C11.8451 20.1425 11.4977 20.252 11.1386 20.8713L11.0234 21.0702C10.3111 22.2675 8.75036 22.7161 7.51707 21.9878L5.79345 21.0014C4.4483 20.2328 3.99242 18.5095 4.7607 17.1797L4.76132 17.1787C5.12024 16.5594 5.04113 16.2061 4.96019 16.0656C4.87917 15.925 4.61323 15.68 3.89998 15.68C2.34984 15.68 1.09998 14.414 1.09998 12.88V11.12C1.09998 9.58602 2.34984 8.31999 3.89998 8.31999C4.61323 8.31999 4.87917 8.07497 4.96019 7.93437C5.04113 7.79392 5.12024 7.44056 4.76132 6.82132L4.7607 6.82024C3.99251 5.49069 4.44867 3.76737 5.79345 2.99857L7.51705 2.01224C8.75034 1.28388 10.3111 1.73245 11.0234 2.92983L11.0289 2.93906L11.1408 3.1324C11.4948 3.74995 11.8389 3.85749 12.0012 3.85749C12.1649 3.85749 12.5122 3.74829 12.8713 3.12867L12.9865 2.92983ZM9.89998 12C9.89998 10.8402 10.8402 9.89998 12 9.89998C13.1598 9.89998 14.1 10.8402 14.1 12C14.1 13.1598 13.1598 14.1 12 14.1C10.8402 14.1 9.89998 13.1598 9.89998 12ZM12 8.09998C9.84607 8.09998 8.09998 9.84607 8.09998 12C8.09998 14.1539 9.84607 15.9 12 15.9C14.1539 15.9 15.9 14.1539 15.9 12C15.9 9.84607 14.1539 8.09998 12 8.09998Z" fill="#353535"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
BIN
frontend/src/resources/img/logo-full.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
frontend/src/resources/img/logo.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
frontend/src/resources/img/progress.gif
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
frontend/src/resources/img/project.png
Normal file
|
After Width: | Height: | Size: 712 B |
BIN
frontend/src/resources/img/tasks.png
Normal file
|
After Width: | Height: | Size: 351 B |
|
|
@ -0,0 +1,9 @@
|
|||
<div>
|
||||
<button type="button"
|
||||
[disabled]="!isEnabled()"
|
||||
class="btn btn-secondary"
|
||||
[ngbTooltip]="tooltip | emptyIfNull"
|
||||
(click)="onClick()"
|
||||
(focus)="onFocus()"
|
||||
(blur)="onBlur()">{{caption}}</button>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<div class="error_message">
|
||||
<div class="error_title">403</div>
|
||||
<div class="error_body">Доступ запрещен</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<div *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.USER.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.GROUP.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.ROLE.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.ORG_UNIT.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.AUTHORITY.LIST')" ngbDropdown class="nav-item" [placement]="placement">
|
||||
<button class="nav-link bi bi-gear-fill" id="adminDropdownMenu" ngbDropdownToggle title="Администрирование"></button>
|
||||
<div ngbDropdownMenu aria-labelledby="adminDropdownMenu">
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.USER.LIST')"
|
||||
routerLink="/user-management/users" ngbDropdownItem>
|
||||
Пользователи
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.GROUP.LIST')"
|
||||
routerLink="/user-management/groups" ngbDropdownItem>
|
||||
Группы
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.ROLE.LIST')"
|
||||
routerLink="/user-management/roles" ngbDropdownItem>
|
||||
Роли
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.ORG_UNIT.LIST')"
|
||||
routerLink="/user-management/org-units" ngbDropdownItem>
|
||||
Организации
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.AUTHORITY.LIST')"
|
||||
routerLink="/user-management/authorities" ngbDropdownItem>
|
||||
Безопасность действий
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<footer>
|
||||
<div id="webbpm-footer">
|
||||
<div class="fl-left"><span>Web-BPM</span></div>
|
||||
<div class="fl-right">
|
||||
<span><a href="mailto:info@micord.ru">Поддержка</a></span>
|
||||
<span><a href="http://www.micord.ru" target="_blank">Компания "Микорд"</a></span>
|
||||
<span><application-version></application-version></span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<nav class="header" *ngIf="currentSession | async as session" id="webbpm-header">
|
||||
<div class="header-logo">
|
||||
<div class="logo"><a routerLink="/"></a></div>
|
||||
</div>
|
||||
<div class="header-menu">
|
||||
<admin-menu [placement]="'bottom'"></admin-menu>
|
||||
<div ngbDropdown class="logout" log-out></div>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<span id="version-footer">Версия: {{applicationVersion}}</span>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<div class="confirm">
|
||||
<div class="form-logo">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div>
|
||||
<h2>Подтверждение почты</h2>
|
||||
|
||||
<div *ngIf="verificationStatus.toString() === 'VERIFYING'">
|
||||
Подтверждение...
|
||||
</div>
|
||||
<div *ngIf="verificationStatus.toString() === 'VERIFIED'">
|
||||
<div class="alert alert-success">
|
||||
Адрес электронной почты успешно подтвержден
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="verificationStatus.toString() === 'FAILED'">
|
||||
<div class="alert alert-danger">{{ errorMessage }}</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="(currentSession | async) == null">
|
||||
<a href="#/login"><span class="fa fa-lock"></span>Войти</a><br/>
|
||||
<a href="#/registration">Зарегистрироваться</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<button class="nav-link bi bi-person-fill" ngbDropdownToggle title="Пользователь"></button>
|
||||
<div ngbDropdownMenu *ngIf="currentSession | async as session">
|
||||
<div class="user-info">
|
||||
<div class="user-fio">{{session.fullUserName}}</div>
|
||||
<div class="user-login">{{session.username}}</div>
|
||||
<div class="user-department">{{getOrgUnitName()}}</div>
|
||||
</div>
|
||||
<button ngbDropdownItem *ngIf="isLogoutButtonVisible()" (click)="logout()">Выход</button>
|
||||
</div>
|
||||
51
frontend/src/resources/template/app/component/login.html
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<div class="form-signin">
|
||||
<form #formComponent="ngForm">
|
||||
<div class="alert alert-success" [hidden]="!confirmationSent">На ваш почтовый адрес было
|
||||
отправлено письмо. Подтвердите почту, чтобы войти в систему
|
||||
</div>
|
||||
<div class="alert alert-danger" [hidden]="!errorMessage">{{errorMessage}}</div>
|
||||
|
||||
<h2>Вход</h2>
|
||||
<div class="row registration">
|
||||
<span>Еще нет аккаунта?</span><a href="#/registration">Зарегистрироваться</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label>Пользователь</label>
|
||||
<div class="input-group">
|
||||
<input type="text" name="username" class="form-control" placeholder="Пользователь" required autofocus
|
||||
[(ngModel)]="username" maxlength="100">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Пароль</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
[type]="passwordType ? 'text' : 'password'"
|
||||
name="password"
|
||||
class="form-control field-password-view"
|
||||
placeholder="" required
|
||||
[(ngModel)]="password"
|
||||
maxlength="100"
|
||||
>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<i
|
||||
(click)="togglePasswordType()"
|
||||
class="fa"
|
||||
[ngClass]="{
|
||||
'fa-eye': passwordType,
|
||||
'fa-eye-slash': !passwordType
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-btn-box">
|
||||
<!--<esia-login-button></esia-login-button>-->
|
||||
<button type="submit" class="btn btn-primary" (click)="formComponent.form.valid && login()">Войти</button>
|
||||
<div class="password"><a href="#/reset-password">Забыли пароль?</a></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
103
frontend/src/resources/template/app/component/new_password.html
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<div class="form-signup">
|
||||
<div class="form-logo">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="form-new-password">
|
||||
<form #formComponent="ngForm">
|
||||
<div [hidden]="!errorMessage" class="alert alert-danger">{{ errorMessage }}</div>
|
||||
<p class="has-account">Вспомнили пароль?
|
||||
<a href="#/login"><span class="fa fa-lock"></span>Войти</a></p>
|
||||
|
||||
<p class="has-account">Задайте новый пароль</p>
|
||||
|
||||
<div class="row">
|
||||
<label>Пароль</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
#passwordInput="ngModel"
|
||||
[(ngModel)]="password"
|
||||
[type]="passwordType ? 'text' : 'password'"
|
||||
class="form-control"
|
||||
maxlength="32"
|
||||
minlength="6"
|
||||
name="password"
|
||||
pattern="^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$"
|
||||
required
|
||||
(change)="validPasswords()"
|
||||
>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<i
|
||||
(click)="togglePasswordType()"
|
||||
class="fa"
|
||||
[ngClass]="{
|
||||
'fa-eye': passwordType,
|
||||
'fa-eye-slash': !passwordType
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="passwordInput.invalid && (passwordInput.dirty || passwordInput.touched)">
|
||||
<div *ngIf="passwordInput.errors.required" class="msg-alert">Поле обязательно
|
||||
</div>
|
||||
<div *ngIf="passwordInput.errors.minlength" class="msg-alert">Пароль должен
|
||||
содержать как минимум 6 символов
|
||||
</div>
|
||||
<div *ngIf="passwordInput.errors.pattern" class="msg-alert">Пароль должен
|
||||
содержать заглавные и прописные буквы и как минимум 1 цифру
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Подтверждение пароля</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
#confirmPasswordInput="ngModel"
|
||||
[(ngModel)]="confirmPassword"
|
||||
[type]="confirmPasswordType ? 'text' : 'password'"
|
||||
class="form-control"
|
||||
maxlength="32"
|
||||
minlength="6"
|
||||
name="confirmPassword"
|
||||
pattern="^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$"
|
||||
required
|
||||
(change)="validPasswords()"
|
||||
>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<i
|
||||
(click)="toggleConfirmPasswordType()"
|
||||
class="fa"
|
||||
[ngClass]="{
|
||||
'fa-eye': confirmPasswordType,
|
||||
'fa-eye-slash': !confirmPasswordType
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="confirmPasswordInput.invalid && (confirmPasswordInput.dirty || confirmPasswordInput.touched)">
|
||||
<div *ngIf="confirmPasswordInput.errors.required" class="msg-alert">Поле обязательно
|
||||
</div>
|
||||
<div *ngIf="confirmPasswordInput.errors.minlength" class="msg-alert">Пароль должен
|
||||
содержать как минимум 6 символов
|
||||
</div>
|
||||
<div *ngIf="confirmPasswordInput.errors.pattern" class="msg-alert">Пароль должен
|
||||
содержать заглавные и прописные буквы и как минимум 1 цифру
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="reset-password-btn-box">
|
||||
<button
|
||||
(click)="formComponent.form.valid && validPasswords() && changePassword()"
|
||||
[disabled]="!formComponent.form.valid && !validPasswords()"
|
||||
class="btn btn-primary"
|
||||
type="submit"
|
||||
>
|
||||
Изменить пароль
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="modal-body">
|
||||
<div class="progress"></div>
|
||||
</div>
|
||||
121
frontend/src/resources/template/app/component/register.html
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
<div class="form-signup">
|
||||
<div class="form-logo">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="form-register">
|
||||
<form #formComponent="ngForm">
|
||||
<div [hidden]="!errorMessage" class="alert alert-danger">{{ errorMessage }}</div>
|
||||
<h2>Регистрация</h2>
|
||||
<p class="has-account">Уже зарегистрированы?
|
||||
<a href="#/login"><span class="fa fa-lock"></span>Войти</a></p>
|
||||
|
||||
<div class="row">
|
||||
<label>Имя</label>
|
||||
<input
|
||||
#name="ngModel"
|
||||
[(ngModel)]="username"
|
||||
class="form-control"
|
||||
maxlength="100"
|
||||
name="username"
|
||||
required
|
||||
type="text"
|
||||
>
|
||||
<div *ngIf="name.invalid && (name.dirty || name.touched)">
|
||||
<div *ngIf="name.errors.required" class="msg-alert">Поле обязательно</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Адрес эл. почты</label>
|
||||
<input
|
||||
#emailInput="ngModel"
|
||||
[(ngModel)]="email"
|
||||
class="form-control"
|
||||
email
|
||||
maxlength="100"
|
||||
name="email"
|
||||
required
|
||||
type="email"
|
||||
>
|
||||
<div *ngIf="emailInput.invalid && (emailInput.dirty || emailInput.touched)">
|
||||
<div *ngIf="emailInput.errors.required" class="msg-alert">Поле обязательно</div>
|
||||
<div *ngIf="emailInput.errors.email" class="msg-alert">Неверный формат адреса
|
||||
эл. почты
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Номер телефона</label>
|
||||
<international-phone-number
|
||||
#phoneInput="ngModel"
|
||||
[(ngModel)]="phoneNumber"
|
||||
[defaultCountry]="'ru'"
|
||||
[pattern]="'^\\+(?!7 ?\\d{11})[0-9 ]+$'"
|
||||
maxlength="20"
|
||||
minlength="8"
|
||||
name="phoneNumber"
|
||||
placeholder="+79991112233"
|
||||
(focusout)="phoneInputFocusOut()"
|
||||
required
|
||||
></international-phone-number>
|
||||
<div *ngIf="phoneInput.invalid && (phoneInput.dirty || phoneIsTouched)">
|
||||
<div *ngIf="phone.selectedCountry">
|
||||
<div *ngIf="phoneHasOnlyDialCode()" class="msg-alert">Поле обязательно</div>
|
||||
<div *ngIf="!phoneHasOnlyDialCode()" class="msg-alert">Введите корректный номер</div>
|
||||
</div>
|
||||
<div *ngIf="!phone.selectedCountry">
|
||||
<div *ngIf="phoneInput.errors.required" class="msg-alert">Поле обязательно</div>
|
||||
<div *ngIf="!phoneInput.errors.required" class="msg-alert">Введите код страны</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Пароль</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
#passwordInput="ngModel"
|
||||
[(ngModel)]="password"
|
||||
[type]="fieldType ? 'text' : 'password'"
|
||||
class="form-control"
|
||||
maxlength="32"
|
||||
minlength="8"
|
||||
name="password"
|
||||
[pattern]="passwordPattern"
|
||||
required
|
||||
>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<i
|
||||
(click)="toggleFieldType()"
|
||||
class="fa"
|
||||
[ngClass]="{
|
||||
'fa-eye': fieldType,
|
||||
'fa-eye-slash': !fieldType
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="passwordInput.invalid && (passwordInput.dirty || passwordInput.touched)">
|
||||
<div *ngIf="passwordInput.errors.required" class="msg-alert">Поле обязательно
|
||||
</div>
|
||||
<div *ngIf="passwordInput.errors.minlength" class="msg-alert">Пароль должен
|
||||
содержать как минимум 8 символов
|
||||
</div>
|
||||
<div *ngIf="passwordInput.errors.pattern" class="msg-alert" [innerText]="passwordPatternErrorMessage">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="register-btn-box">
|
||||
<button
|
||||
(click)="formComponent.form.valid && register()"
|
||||
[disabled]="!formComponent.form.valid"
|
||||
class="btn btn-primary"
|
||||
type="submit"
|
||||
>
|
||||
Зарегистрироваться
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="consent" [innerHTML]="consent" class="consent"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<div class="form-signup">
|
||||
<div class="form-logo">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="form-reset-password">
|
||||
<form #formComponent="ngForm">
|
||||
<div [hidden]="!errorMessage" class="alert alert-danger">{{ errorMessage }}</div>
|
||||
<p class="has-account">Вспомнили пароль?
|
||||
<a href="#/login"><span class="fa fa-lock"></span>Войти</a></p>
|
||||
|
||||
<p class="has-account">Укажите адрес эл. почты, который был указан при регистрации,
|
||||
на него пришлем временный пароль. Пароль сможете поменять в личном кабинете.
|
||||
</p>
|
||||
|
||||
<div class="row">
|
||||
<label>Адрес эл. почты</label>
|
||||
<input
|
||||
#emailInput="ngModel"
|
||||
[(ngModel)]="email"
|
||||
class="form-control"
|
||||
email
|
||||
maxlength="100"
|
||||
name="email"
|
||||
required
|
||||
type="email"
|
||||
>
|
||||
<div *ngIf="emailInput.invalid && (emailInput.dirty || emailInput.touched)">
|
||||
<div *ngIf="emailInput.errors.required" class="msg-alert">Поле обязательно</div>
|
||||
<div *ngIf="emailInput.errors.email" class="msg-alert">Неверный формат адреса эл. почты
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="reset-password-btn-box">
|
||||
<button
|
||||
(click)="formComponent.form.valid && resetPassword()"
|
||||
[disabled]="!formComponent.form.valid"
|
||||
class="btn btn-primary"
|
||||
type="submit"
|
||||
>
|
||||
Восстановить
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
3
frontend/src/resources/template/preview/preview.html
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<div id="page">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<router-outlet></router-outlet>
|
||||
6
frontend/src/resources/template/webbpm/home.html
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<div id="home">
|
||||
<div class="inner">
|
||||
<div class="task-list">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
1
frontend/src/resources/template/webbpm/page.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<div #pageContent></div>
|
||||
12
frontend/src/resources/template/webbpm/webbpm.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<div class="wrapper">
|
||||
<app-header *ngIf="headerVisible">
|
||||
</app-header>
|
||||
|
||||
<div class="container">
|
||||
<div class="container-inside" id="webbpm-angular-application-container">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
<app-footer *ngIf="footerVisible">
|
||||
</app-footer>
|
||||
</div>
|
||||
47
frontend/src/ts/ervu/ConfigExecuteBtn.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef} from "@angular/core";
|
||||
import {AbstractButton, NotNull, ObjectRef, TextArea} from "@webbpm/base-package";
|
||||
import {ConfigExecutorRpcService} from "../generated/rpc/ConfigExecutorRpcService";
|
||||
|
||||
/**
|
||||
* @author: a.petrov
|
||||
*/
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'config-execute-button-component',
|
||||
templateUrl: './../../../src/resources/template/app/component/ConfigExecuteBtn.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ConfigExecuteBtn extends AbstractButton {
|
||||
|
||||
@ObjectRef()
|
||||
@NotNull()
|
||||
public ervuIdField: TextArea;
|
||||
@NotNull()
|
||||
public methodPath: string;
|
||||
private script: ConfigExecutorRpcService;
|
||||
|
||||
constructor(el: ElementRef, cd: ChangeDetectorRef) {
|
||||
super(el, cd);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
super.initialize();
|
||||
this.script = this.getScript(ConfigExecutorRpcService)
|
||||
}
|
||||
|
||||
doClickActions(): Promise<any> {
|
||||
const value = this.ervuIdField.getValue();
|
||||
if (value && this.methodPath.trim().length !== 0) {
|
||||
const ids = value.replace(/[{}]/g, '')
|
||||
.split(',')
|
||||
.map(id => id.trim().replace(/"/g, ''));
|
||||
|
||||
return this.script.callConfigExecutor(this.methodPath, ids, true)
|
||||
.catch(error => Promise.reject(error));
|
||||
}
|
||||
}
|
||||
|
||||
getFocusElement(): HTMLInputElement {
|
||||
return this.el.nativeElement.querySelector('button');
|
||||
}
|
||||
}
|
||||
69
frontend/src/ts/ervu/ExportDataBtn.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef} from "@angular/core";
|
||||
import {
|
||||
AbstractButton,
|
||||
ComboBox,
|
||||
FileModel,
|
||||
FileUtils,
|
||||
MessagesService,
|
||||
NotNull,
|
||||
ObjectRef,
|
||||
TextArea
|
||||
} from "@webbpm/base-package";
|
||||
import {ExportDataRpcService} from "../generated/rpc/ExportDataRpcService";
|
||||
import {ExportDataRequest} from "../generated/dto/ExportDataRequest";
|
||||
|
||||
/**
|
||||
* @author: kochetkov
|
||||
*/
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'export-data-button-component',
|
||||
templateUrl: './../../../src/resources/template/app/component/ConfigExecuteBtn.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ExportDataBtn extends AbstractButton {
|
||||
|
||||
@ObjectRef()
|
||||
@NotNull()
|
||||
public dataTypeField: ComboBox;
|
||||
|
||||
@ObjectRef()
|
||||
@NotNull()
|
||||
public ervuIdsField: TextArea;
|
||||
|
||||
private rpc: ExportDataRpcService;
|
||||
private messagesService: MessagesService;
|
||||
|
||||
constructor(el: ElementRef, cd: ChangeDetectorRef) {
|
||||
super(el, cd);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
super.initialize();
|
||||
this.rpc = this.getScript(ExportDataRpcService);
|
||||
this.messagesService = this.getScript(MessagesService);
|
||||
}
|
||||
|
||||
doClickActions(): Promise<any> {
|
||||
const type = this.dataTypeField.getValue();
|
||||
const value = this.ervuIdsField.getValue();
|
||||
|
||||
const ids = value == null ? value : value.replace(/[{}]/g, '')
|
||||
.split(',')
|
||||
.map(id => id.trim().replace(/"/g, ''));
|
||||
|
||||
let exportDataRequest = new ExportDataRequest();
|
||||
exportDataRequest.ids = ids;
|
||||
exportDataRequest.type = type;
|
||||
return this.rpc.exportData(exportDataRequest)
|
||||
.then((data: FileModel) => {
|
||||
FileUtils.downloadFile(data.fileName, data.fileContent);
|
||||
}).catch(reason => {
|
||||
return this.messagesService.error(reason);
|
||||
});
|
||||
}
|
||||
|
||||
getFocusElement(): HTMLInputElement {
|
||||
return this.el.nativeElement.querySelector('button');
|
||||
}
|
||||
}
|
||||
8
frontend/src/ts/main.aot.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import "../../src/resources/css/style.css";
|
||||
import {platformBrowser} from '@angular/platform-browser';
|
||||
import {enableProdMode} from "@angular/core";
|
||||
import {WebbpmModuleNgFactory} from "./modules/webbpm/webbpm.module.ngfactory";
|
||||
|
||||
window['dev_mode'] = false;
|
||||
enableProdMode();
|
||||
platformBrowser().bootstrapModuleFactory(WebbpmModuleNgFactory);
|
||||
7
frontend/src/ts/main.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
|
||||
import {enableProdMode} from "@angular/core";
|
||||
import {WebbpmModule} from "./modules/webbpm/webbpm.module";
|
||||
|
||||
window['dev_mode'] = true;
|
||||
enableProdMode();
|
||||
platformBrowserDynamic().bootstrapModule(WebbpmModule);
|
||||
47
frontend/src/ts/modules/app/app-routing.module.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {RouterModule, Routes} from "@angular/router";
|
||||
import {AccessDeniedComponent} from "./component/access-denied.component";
|
||||
import {LoginComponent} from "./component/login.component";
|
||||
import {AuthenticationGuard, ConfirmExitGuard, SignedInGuard} from "@webbpm/base-package";
|
||||
import {RegisterComponent} from "./component/register.component";
|
||||
import {ConfirmUserEmailComponent} from "./component/confirm-user-email.component";
|
||||
import {ResetPasswordComponent} from "./component/reset-password.component";
|
||||
import {NewPasswordComponent} from "./component/new-password.component";
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
path: 'login',
|
||||
component: LoginComponent,
|
||||
canActivate: [SignedInGuard]
|
||||
},
|
||||
{
|
||||
path: 'access-denied',
|
||||
component: AccessDeniedComponent,
|
||||
canActivate: [AuthenticationGuard, ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'registration',
|
||||
component: RegisterComponent,
|
||||
canActivate: [SignedInGuard]
|
||||
},
|
||||
{
|
||||
path: 'confirm',
|
||||
component: ConfirmUserEmailComponent
|
||||
},
|
||||
{
|
||||
path: 'reset-password',
|
||||
component: ResetPasswordComponent
|
||||
},
|
||||
{
|
||||
path: 'new-password',
|
||||
component: NewPasswordComponent
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(appRoutes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {
|
||||
|
||||
}
|
||||
76
frontend/src/ts/modules/app/app.module.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import {forwardRef, NgModule} from "@angular/core";
|
||||
import {NgbModule} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {CommonModule, registerLocaleData} from "@angular/common";
|
||||
import localeRu from '@angular/common/locales/ru';
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {AgGridModule} from "ag-grid-angular";
|
||||
import {
|
||||
BpmnModule,
|
||||
ComponentsModule,
|
||||
CoreModule,
|
||||
ProgressIndicationService,
|
||||
SecurityModule
|
||||
} from "@webbpm/base-package";
|
||||
import {AdminMenuComponent} from "./component/admin-menu.component";
|
||||
import {AppHeaderComponent} from "./component/app-header.component";
|
||||
import {AppFooterComponent} from "./component/app-footer.component";
|
||||
import {LogOutComponent} from "./component/logout.component";
|
||||
import {LoginComponent} from "./component/login.component";
|
||||
import {AccessDeniedComponent} from "./component/access-denied.component";
|
||||
import {ApplicationVersionComponent} from "./component/application-version.component";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {RegisterComponent} from "./component/register.component";
|
||||
import {ConfirmUserEmailComponent} from "./component/confirm-user-email.component";
|
||||
import {InternationalPhoneNumberModule} from "ngx-international-phone-number";
|
||||
import {ResetPasswordComponent} from "./component/reset-password.component";
|
||||
import {NewPasswordComponent} from "./component/new-password.component";
|
||||
import {AppProgressIndicationComponent} from "./component/app-progress-indication.component";
|
||||
import {AppProgressIndicationService} from "./service/app-progress-indication.service";
|
||||
import {ConfigExecuteBtn} from "../../ervu/ConfigExecuteBtn";
|
||||
import {ExportDataBtn} from "../../ervu/ExportDataBtn";
|
||||
|
||||
registerLocaleData(localeRu);
|
||||
export const DIRECTIVES = [
|
||||
forwardRef(() => AppHeaderComponent),
|
||||
forwardRef(() => AppFooterComponent),
|
||||
forwardRef(() => AdminMenuComponent),
|
||||
forwardRef(() => ApplicationVersionComponent),
|
||||
forwardRef(() => LogOutComponent),
|
||||
forwardRef(() => LoginComponent),
|
||||
forwardRef(() => AccessDeniedComponent),
|
||||
forwardRef(() => RegisterComponent),
|
||||
forwardRef(() => ConfirmUserEmailComponent),
|
||||
forwardRef(() => ResetPasswordComponent),
|
||||
forwardRef(() => NewPasswordComponent),
|
||||
forwardRef(() => AppProgressIndicationComponent),
|
||||
forwardRef(() => ConfigExecuteBtn),
|
||||
forwardRef(() => ExportDataBtn)
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
CoreModule,
|
||||
NgbModule,
|
||||
BpmnModule,
|
||||
SecurityModule,
|
||||
ComponentsModule,
|
||||
AgGridModule,
|
||||
RouterModule,
|
||||
InternationalPhoneNumberModule
|
||||
],
|
||||
declarations: [
|
||||
DIRECTIVES
|
||||
],
|
||||
exports: [
|
||||
DIRECTIVES
|
||||
],
|
||||
providers: [
|
||||
{ provide: ProgressIndicationService, useClass: AppProgressIndicationService }
|
||||
],
|
||||
bootstrap: [],
|
||||
entryComponents: [AppProgressIndicationComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "access-denied",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/access_denied.html",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AccessDeniedComponent {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import {ChangeDetectionStrategy, Component, Input} from "@angular/core";
|
||||
import {UserService, Session} from "@webbpm/base-package";
|
||||
import {NgbDropdownConfig, Placement} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'admin-menu',
|
||||
templateUrl: '../../../../../src/resources/template/app/component/admin_menu.html',
|
||||
providers: [NgbDropdownConfig],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AdminMenuComponent {
|
||||
|
||||
@Input()
|
||||
public placement: Placement = 'bottom';
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
constructor(protected userService: UserService, public config: NgbDropdownConfig) {
|
||||
this.config.placement = this.placement;
|
||||
this.currentSession = this.userService.getCurrentSession();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import {Component} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "app-footer",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/app_footer.html"
|
||||
})
|
||||
export class AppFooterComponent {
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
||||
import {Router} from "@angular/router";
|
||||
import {UserService, Session} from "@webbpm/base-package";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "app-header",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/app_header.html",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AppHeaderComponent {
|
||||
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
constructor(protected userService: UserService,
|
||||
protected router: Router) {
|
||||
this.currentSession = this.userService.getCurrentSession();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
selector: 'progress-indication-dialog-content',
|
||||
templateUrl: '../../../../../src/resources/template/app/component/progress-indication.html'
|
||||
})
|
||||
export class AppProgressIndicationComponent {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input} from "@angular/core";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "application-version",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/application_version.html",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ApplicationVersionComponent {
|
||||
@Input()
|
||||
public applicationVersion: string;
|
||||
|
||||
constructor(private httpClient: HttpClient, private cd: ChangeDetectorRef) {
|
||||
this.loadAppVersion(); //TODO: check version url
|
||||
}
|
||||
|
||||
private loadAppVersion() {
|
||||
this.httpClient.get("version").toPromise().then((version: any) => {
|
||||
this.applicationVersion = version.number;
|
||||
this.cd.markForCheck();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input} from "@angular/core";
|
||||
import {Session, UserService} from "@webbpm/base-package";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
enum VerificationStatus {
|
||||
VERIFYING = "VERIFYING",
|
||||
VERIFIED = "VERIFIED",
|
||||
FAILED = "FAILED"
|
||||
}
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "confirm",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: "../../../../../src/resources/template/app/component/confirm-user-email.html"
|
||||
})
|
||||
export class ConfirmUserEmailComponent {
|
||||
public verificationStatus = VerificationStatus.VERIFYING;
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
constructor(private router: Router, private userService: UserService,
|
||||
private route: ActivatedRoute, private cd: ChangeDetectorRef) {
|
||||
this.currentSession = this.userService.getCurrentSession();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const link: string = this.route.snapshot.queryParamMap.get("link");
|
||||
// remove link from url to prevent http referer leakage
|
||||
this.router.navigate([], { relativeTo: this.route, replaceUrl: true });
|
||||
this.userService.confirm(
|
||||
link,
|
||||
(reason) => {
|
||||
this.verificationStatus = VerificationStatus.FAILED;
|
||||
if (reason.status === 404) {
|
||||
this.errorMessage = 'Ссылка недействительна. Требуется повторная регистрация.';
|
||||
}
|
||||
else {
|
||||
this.errorMessage = 'Произошла ошибка, обратитесь в службу технической поддержки!';
|
||||
}
|
||||
this.cd.markForCheck();
|
||||
})
|
||||
.then(() => {
|
||||
this.verificationStatus = VerificationStatus.VERIFIED;
|
||||
this.cd.markForCheck();
|
||||
});
|
||||
}
|
||||
}
|
||||
68
frontend/src/ts/modules/app/component/login.component.ts
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import {Component, Input} from "@angular/core";
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {UserService, Credentials} from "@webbpm/base-package";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "login",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/login.html"
|
||||
})
|
||||
export class LoginComponent {
|
||||
|
||||
@Input()
|
||||
public username: string;
|
||||
|
||||
@Input()
|
||||
public password: string;
|
||||
public passwordType: boolean;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
@Input()
|
||||
public confirmationSent: boolean;
|
||||
|
||||
constructor(private router: Router, private userService: UserService,
|
||||
private route: ActivatedRoute) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.confirmationSent = this.route.snapshot.queryParamMap.get('confirmationSent') === 'true';
|
||||
this.router.navigate([], { relativeTo: this.route, replaceUrl: true });
|
||||
}
|
||||
|
||||
public login(): void {
|
||||
let credentials: Credentials = new Credentials();
|
||||
credentials.username = this.username;
|
||||
credentials.password = this.password;
|
||||
|
||||
this.userService.login(credentials, "Password")
|
||||
.then(() => this.router.navigateByUrl("/"),
|
||||
(reason: any) => {
|
||||
switch (reason.status) {
|
||||
case 401: {
|
||||
this.errorMessage = "Неправильный логин или пароль";
|
||||
break;
|
||||
}
|
||||
case 404: {
|
||||
this.errorMessage = "Приложение стартует. Пожалуйста, подождите...";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
this.errorMessage =
|
||||
"Произошла неизвестная ошибка, обратитесь в службу технической поддержки!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public goToRegister(): void {
|
||||
this.router.navigateByUrl("/register");
|
||||
}
|
||||
|
||||
togglePasswordType(): void {
|
||||
this.passwordType = !this.passwordType;
|
||||
}
|
||||
}
|
||||
37
frontend/src/ts/modules/app/component/logout.component.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import {Component} from "@angular/core";
|
||||
import {UserService, Session, AuthenticationMethodService} from "@webbpm/base-package";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "[log-out]",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/log_out.html"
|
||||
})
|
||||
export class LogOutComponent {
|
||||
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
constructor(private userService: UserService, private authenticationMethodService: AuthenticationMethodService) {
|
||||
this.currentSession = userService.getCurrentSession();
|
||||
}
|
||||
|
||||
public logout(): void {
|
||||
this.userService.logout();
|
||||
}
|
||||
|
||||
public getCurrentUserName(): string {
|
||||
return this.userService.getCurrentUserName();
|
||||
}
|
||||
|
||||
public getFullUserName(): string {
|
||||
return this.userService.getFullUserName();
|
||||
}
|
||||
|
||||
public isLogoutButtonVisible(): boolean {
|
||||
return this.authenticationMethodService.isFormAuth();
|
||||
}
|
||||
|
||||
public getOrgUnitName(): string {
|
||||
return this.userService.getOrgUnitName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {Component, Input} from "@angular/core";
|
||||
import {Session, UserPasswordResetRequestDto, UserService} from "@webbpm/base-package";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "newPassword",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/new_password.html"
|
||||
})
|
||||
export class NewPasswordComponent {
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
private token: string;
|
||||
|
||||
@Input()
|
||||
public password: string;
|
||||
public passwordType: boolean;
|
||||
|
||||
@Input()
|
||||
public confirmPassword: string;
|
||||
public confirmPasswordType: boolean;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
constructor(private router: Router, private userService: UserService,
|
||||
private route: ActivatedRoute) {
|
||||
this.currentSession = this.userService.getCurrentSession();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.token = this.route.snapshot.queryParamMap.get("token");
|
||||
|
||||
this.router.navigate([], {relativeTo: this.route, replaceUrl: true});
|
||||
|
||||
if (this.token == undefined || this.token === '') {
|
||||
this.errorMessage = 'Ссылка недействительна. Требуется повторить восстановление пароля.';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public changePassword(): void {
|
||||
let dto: UserPasswordResetRequestDto = new UserPasswordResetRequestDto();
|
||||
dto.password = this.password;
|
||||
dto.passwordConfirm = this.confirmPassword;
|
||||
this.userService.changePassword(dto, this.token)
|
||||
.then(() => this.router.navigateByUrl("/"),
|
||||
() => {
|
||||
this.errorMessage =
|
||||
'Произошла неизвестная ошибка, обратитесь в службу технической поддержки!';
|
||||
});
|
||||
}
|
||||
|
||||
togglePasswordType(): void {
|
||||
this.passwordType = !this.passwordType;
|
||||
}
|
||||
|
||||
toggleConfirmPasswordType(): void {
|
||||
this.confirmPasswordType = !this.confirmPasswordType;
|
||||
}
|
||||
|
||||
validPasswords(): boolean {
|
||||
if (this.password === undefined || this.confirmPassword === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let eq = this.password === this.confirmPassword;
|
||||
if (!eq) {
|
||||
this.errorMessage = 'Введенные пароли не совпадают. Убедитесь, что данные, ' +
|
||||
'введенные в поле "Подтверждение пароля", совпадают с теми, ' +
|
||||
'которые указаны в поле "Пароль".';
|
||||
}
|
||||
else {
|
||||
this.errorMessage = '';
|
||||
}
|
||||
return eq;
|
||||
}
|
||||
}
|
||||
71
frontend/src/ts/modules/app/component/register.component.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import {Component, Input, ViewChild} from "@angular/core";
|
||||
import {AppConfigService, UserDto, UserService} from "@webbpm/base-package";
|
||||
import {Router} from "@angular/router";
|
||||
import {PhoneNumberComponent} from "ngx-international-phone-number";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "register",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/register.html"
|
||||
})
|
||||
export class RegisterComponent {
|
||||
|
||||
public passwordPattern: string;
|
||||
public passwordPatternErrorMessage: string;
|
||||
public errorMessage: string;
|
||||
|
||||
@Input()
|
||||
public username: string;
|
||||
|
||||
@Input()
|
||||
public email: string;
|
||||
@ViewChild(PhoneNumberComponent)
|
||||
public phone: PhoneNumberComponent;
|
||||
public phoneNumber: string;
|
||||
|
||||
public phoneIsTouched: boolean = false;
|
||||
@Input()
|
||||
public password: string;
|
||||
|
||||
public fieldType: boolean;
|
||||
|
||||
@Input()
|
||||
public consent: string;
|
||||
|
||||
constructor(private router: Router, private userService: UserService,private appConfigService: AppConfigService) {
|
||||
this.passwordPattern = appConfigService.getParamValue("password_pattern");
|
||||
this.passwordPatternErrorMessage = appConfigService.getParamValue("password_pattern_error");
|
||||
}
|
||||
|
||||
public register(): void {
|
||||
let user: UserDto = new UserDto();
|
||||
user.username = this.username;
|
||||
user.email = this.email;
|
||||
user.name = this.username;
|
||||
user.phone = this.phone.value;
|
||||
user.password = this.password;
|
||||
|
||||
this.userService.register(user)
|
||||
.then(() => this.router.navigateByUrl("/login?confirmationSent=true"),
|
||||
(reason: any) => {
|
||||
if (reason.status === 409) {
|
||||
this.errorMessage = 'Пользователь с данным почтовым адресом уже существует';
|
||||
}
|
||||
else {
|
||||
this.errorMessage = 'Произошла неизвестная ошибка, обратитесь в службу технической поддержки!';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleFieldType(): void {
|
||||
this.fieldType = !this.fieldType;
|
||||
}
|
||||
|
||||
phoneHasOnlyDialCode(): boolean {
|
||||
return this.phone.phoneNumber.trim() === this.phone.getSelectedCountryDialCode().trim()
|
||||
}
|
||||
|
||||
phoneInputFocusOut(): void {
|
||||
this.phoneIsTouched = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import {Component, Input} from "@angular/core";
|
||||
import {UserService} from "@webbpm/base-package";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "resetPassword",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/reset_password.html"
|
||||
})
|
||||
export class ResetPasswordComponent {
|
||||
|
||||
@Input()
|
||||
public email: string;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
constructor(private router: Router, private userService: UserService) {
|
||||
}
|
||||
|
||||
resetPassword(): void {
|
||||
|
||||
this.userService.resetPassword(this.email)
|
||||
.then(() => this.router.navigateByUrl("/"),
|
||||
(reason: any) => {
|
||||
this.errorMessage =
|
||||
'Произошла неизвестная ошибка, обратитесь в службу технической поддержки!';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
import {Injectable} from "@angular/core";
|
||||
import {AppProgressIndicationComponent} from "../component/app-progress-indication.component";
|
||||
import {NgbModal, NgbModalOptions, NgbModalRef} from "@ng-bootstrap/ng-bootstrap";
|
||||
|
||||
@Injectable()
|
||||
export class AppProgressIndicationService {
|
||||
|
||||
private static readonly EVENT_INTERCEPTOR = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
private counter: number = 0;
|
||||
private focused: any;
|
||||
private ngbModalRef: NgbModalRef;
|
||||
private options: NgbModalOptions = {
|
||||
backdrop: 'static',
|
||||
keyboard: false,
|
||||
windowClass: 'modal-center loader'
|
||||
};
|
||||
|
||||
constructor(private ngbModal: NgbModal) {
|
||||
}
|
||||
|
||||
public showProgressBar(): boolean {
|
||||
if (this.counter == 0) {
|
||||
this.disableEvents();
|
||||
this.saveFocus();
|
||||
this.showProgressIndicator();
|
||||
}
|
||||
++this.counter;
|
||||
return this.counter == 1;
|
||||
}
|
||||
|
||||
public hideProgressBar(): boolean {
|
||||
if (this.counter == 0) {
|
||||
return false;
|
||||
}
|
||||
if (this.counter == 1) {
|
||||
this.hideProgressIndicator();
|
||||
this.restoreFocus();
|
||||
this.enableEvents();
|
||||
}
|
||||
--this.counter;
|
||||
return this.counter == 0;
|
||||
}
|
||||
|
||||
public unconditionallyHideProgressBar(): void {
|
||||
this.enableEvents();
|
||||
this.hideProgressIndicator();
|
||||
}
|
||||
|
||||
public restoreProgressBar(): void {
|
||||
|
||||
if (this.counter > 0 && this.ngbModalRef == null) {
|
||||
this.disableEvents();
|
||||
this.showProgressIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
private showProgressIndicator() {
|
||||
this.ngbModalRef = this.ngbModal.open(AppProgressIndicationComponent, this.options);
|
||||
}
|
||||
|
||||
private hideProgressIndicator() {
|
||||
this.ngbModalRef.dismiss('cancel');
|
||||
this.ngbModalRef = null;
|
||||
}
|
||||
|
||||
private saveFocus() {
|
||||
this.focused = $(':focus');
|
||||
}
|
||||
|
||||
private restoreFocus() {
|
||||
if (this.focused) {
|
||||
this.focused.focus();
|
||||
this.focused = null;
|
||||
}
|
||||
}
|
||||
|
||||
private disableEvents() {
|
||||
let body = $('body');
|
||||
body.keydown(AppProgressIndicationService.EVENT_INTERCEPTOR);
|
||||
body.keyup(AppProgressIndicationService.EVENT_INTERCEPTOR);
|
||||
body.contextmenu(AppProgressIndicationService.EVENT_INTERCEPTOR)
|
||||
}
|
||||
|
||||
private enableEvents() {
|
||||
let body = $('body');
|
||||
body.off('keydown', AppProgressIndicationService.EVENT_INTERCEPTOR);
|
||||
body.off('keyup', AppProgressIndicationService.EVENT_INTERCEPTOR);
|
||||
body.off('contextmenu', AppProgressIndicationService.EVENT_INTERCEPTOR);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import {Component} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "[preview-container]",
|
||||
templateUrl: "../../../../../src/resources/template/preview/preview_container.html"
|
||||
})
|
||||
export class PreviewContainerComponent {
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import {Component} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "[preview]",
|
||||
templateUrl: "../../../../../src/resources/template/preview/preview.html"
|
||||
})
|
||||
export class PreviewComponent {
|
||||
}
|
||||
20
frontend/src/ts/modules/preview/preview-routing.module.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {RouterModule, Routes} from "@angular/router";
|
||||
import {PreviewComponent} from "./component/preview.component";
|
||||
import {DYNAMIC_ROUTING} from "../../page.routing";
|
||||
|
||||
const previewRoutes: Routes = [
|
||||
{
|
||||
path: 'preview',
|
||||
component: PreviewComponent,
|
||||
children: DYNAMIC_ROUTING,
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(previewRoutes, {useHash: true})],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PreviewRoutingModule {
|
||||
|
||||
}
|
||||
7
frontend/src/ts/modules/preview/preview.main.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import {platformBrowserDynamic} from "@angular/platform-browser-dynamic";
|
||||
import {enableProdMode} from "@angular/core";
|
||||
import {PreviewModule} from "./preview.module";
|
||||
|
||||
window['dev_mode'] = true;
|
||||
enableProdMode();
|
||||
platformBrowserDynamic().bootstrapModule(PreviewModule);
|
||||
51
frontend/src/ts/modules/preview/preview.module.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import {NgModule, NgZone} from "@angular/core";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {BrowserModule} from "@angular/platform-browser";
|
||||
import {AgGridModule} from "ag-grid-angular";
|
||||
import {PreviewComponent} from "./component/preview.component";
|
||||
import {PreviewRoutingModule} from "./preview-routing.module";
|
||||
import {PreviewContainerComponent} from "./component/preview-container.component";
|
||||
import {NgbModule} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {ToastNoAnimationModule} from "ngx-toastr";
|
||||
import {AppModule} from "../app/app.module";
|
||||
import {ComponentsModule, CoreModule, SecurityModule} from "@webbpm/base-package";
|
||||
import {HTTP_INTERCEPTORS} from "@angular/common/http";
|
||||
import {HttpPreviewInterceptor} from "./service/http-preview-interceptor.service";
|
||||
|
||||
export const HTTP_INTERCEPTOR_PROVIDERS = [
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: HttpPreviewInterceptor, multi: true }
|
||||
];
|
||||
|
||||
let IMPORTS = [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
NgbModule,
|
||||
ToastNoAnimationModule.forRoot(),
|
||||
AgGridModule,
|
||||
CoreModule,
|
||||
ComponentsModule,
|
||||
AppModule,
|
||||
SecurityModule,
|
||||
PreviewRoutingModule
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: IMPORTS,
|
||||
declarations: [
|
||||
PreviewContainerComponent,
|
||||
PreviewComponent
|
||||
],
|
||||
exports: [],
|
||||
providers: [
|
||||
HTTP_INTERCEPTOR_PROVIDERS
|
||||
],
|
||||
bootstrap: [
|
||||
PreviewContainerComponent
|
||||
]
|
||||
})
|
||||
export class PreviewModule {
|
||||
|
||||
constructor(zone: NgZone) {
|
||||
window['zoneImpl'] = zone;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import {Injectable} from "@angular/core";
|
||||
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from "@angular/common/http";
|
||||
import {EMPTY, Observable} from "rxjs";
|
||||
import {catchError} from "rxjs/operators";
|
||||
|
||||
@Injectable()
|
||||
export class HttpPreviewInterceptor implements HttpInterceptor {
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
|
||||
return next.handle(req).pipe(catchError(() => {
|
||||
return EMPTY;
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import {Component} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "home",
|
||||
templateUrl: './../../../../../src/resources/template/webbpm/home.html'
|
||||
})
|
||||
export class HomeComponent {
|
||||
}
|
||||
34
frontend/src/ts/modules/webbpm/component/webbpm.component.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import {Component} from "@angular/core";
|
||||
import {
|
||||
Event,
|
||||
NavigationCancel,
|
||||
NavigationEnd,
|
||||
NavigationError,
|
||||
NavigationStart,
|
||||
Router
|
||||
} from "@angular/router";
|
||||
import {ProgressIndicationService} from "@webbpm/base-package";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: '[webbpm]',
|
||||
templateUrl: './../../../../../src/resources/template/webbpm/webbpm.html'
|
||||
})
|
||||
export class WebbpmComponent {
|
||||
public headerVisible: boolean = true;
|
||||
public footerVisible: boolean = true;
|
||||
|
||||
constructor(private router: Router,
|
||||
private progressIndicationService: ProgressIndicationService) {
|
||||
router.events.subscribe((event: Event) => {
|
||||
if (event instanceof NavigationStart) {
|
||||
progressIndicationService.showProgressBar();
|
||||
}
|
||||
else if (event instanceof NavigationEnd
|
||||
|| event instanceof NavigationError
|
||||
|| event instanceof NavigationCancel) {
|
||||
progressIndicationService.hideProgressBar();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import {ErrorHandler, Injectable, Injector} from '@angular/core';
|
||||
import {BaseErrorHandler} from "@webbpm/base-package";
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class GlobalErrorHandler extends BaseErrorHandler implements ErrorHandler {
|
||||
|
||||
constructor(injector: Injector) {
|
||||
super(injector);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import {ErrorHandler, Injectable, Injector} from '@angular/core';
|
||||
import {BaseErrorHandler} from "@webbpm/base-package";
|
||||
|
||||
//todo: will be used after angular update in dev mode
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class GlobalErrorHandler extends BaseErrorHandler implements ErrorHandler {
|
||||
|
||||
constructor(injector: Injector) {
|
||||
super(injector);
|
||||
}
|
||||
|
||||
handleError(error) {
|
||||
const chunkFailedMessage = /Loading chunk [\d]+ failed/;
|
||||
|
||||
if (chunkFailedMessage.test(error.message)) {
|
||||
window.location.reload();
|
||||
}
|
||||
else if (!this.isPreviewPage()) {
|
||||
super.handleError(error);
|
||||
}
|
||||
}
|
||||
|
||||
internalHandleError(error) {
|
||||
if (this.isPreviewPage()) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
super.internalHandleError(error);
|
||||
}
|
||||
}
|
||||
|
||||
private isPreviewPage() {
|
||||
return window.location.hash.includes("webbpm-preview");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import {HTTP_INTERCEPTORS} from "@angular/common/http";
|
||||
import {
|
||||
FormDirtyInterceptor,
|
||||
HttpSecurityErrorInterceptor,
|
||||
HttpSecurityInterceptor
|
||||
} from "@webbpm/base-package";
|
||||
|
||||
export const DEFAULT_HTTP_INTERCEPTOR_PROVIDERS = [
|
||||
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityErrorInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true}
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import {HTTP_INTERCEPTORS} from "@angular/common/http";
|
||||
import {FormDirtyInterceptor, HttpSecurityInterceptor} from "@webbpm/base-package";
|
||||
import {DevHttpSecurityErrorInterceptor} from "./http-security-error-interceptor.dev";
|
||||
|
||||
export const DEFAULT_HTTP_INTERCEPTOR_PROVIDERS = [
|
||||
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: DevHttpSecurityErrorInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true}
|
||||
];
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from "@angular/common/http";
|
||||
import {HttpSecurityErrorInterceptor, MessagesService, UserService} from "@webbpm/base-package";
|
||||
import {Injectable} from "@angular/core";
|
||||
import {Router} from "@angular/router";
|
||||
import {EMPTY, Observable} from "rxjs";
|
||||
import {catchError} from "rxjs/operators";
|
||||
|
||||
@Injectable()
|
||||
export class DevHttpSecurityErrorInterceptor extends HttpSecurityErrorInterceptor
|
||||
implements HttpInterceptor {
|
||||
private router: Router;
|
||||
|
||||
|
||||
constructor(router: Router, messagesService: MessagesService, userService: UserService) {
|
||||
super(router, messagesService, userService);
|
||||
this.router = router;
|
||||
}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
|
||||
if (window.location.hash.includes("webbpm-preview")) {
|
||||
return next.handle(req).pipe(catchError(() => {
|
||||
return EMPTY;
|
||||
}
|
||||
));
|
||||
}
|
||||
else {
|
||||
return super.intercept(req, next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import {RouterModule, Routes} from "@angular/router";
|
||||
import {NgModule} from "@angular/core";
|
||||
import {
|
||||
AuthenticationGuard,
|
||||
ConfirmExitGuard
|
||||
} from "@webbpm/base-package";
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'user-management',
|
||||
canActivate: [AuthenticationGuard],
|
||||
children: [
|
||||
{
|
||||
path: 'users',
|
||||
loadChildren: 'generated-sources/page-user-management-users.module#PageusermanagementusersModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'users/new',
|
||||
loadChildren: 'generated-sources/page-user-management-user-create.module#PageusermanagementusercreateModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'users/:id',
|
||||
loadChildren: 'generated-sources/page-user-management-user-edit.module#PageusermanagementusereditModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'org-units',
|
||||
loadChildren: 'generated-sources/page-user-management-org-units.module#PageusermanagementorgunitsModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'org-units/new',
|
||||
loadChildren: 'generated-sources/page-user-management-org-unit.module#PageusermanagementorgunitModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'org-units/:id',
|
||||
loadChildren: 'generated-sources/page-user-management-org-unit.module#PageusermanagementorgunitModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'roles',
|
||||
loadChildren: 'generated-sources/page-user-management-roles.module#PageusermanagementrolesModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'roles/new',
|
||||
loadChildren: 'generated-sources/page-user-management-role.module#PageusermanagementroleModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'roles/:id',
|
||||
loadChildren: 'generated-sources/page-user-management-role.module#PageusermanagementroleModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'groups',
|
||||
loadChildren: 'generated-sources/page-user-management-groups.module#PageusermanagementgroupsModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'groups/new',
|
||||
loadChildren: 'generated-sources/page-user-management-group-create.module#PageusermanagementgroupcreateModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'groups/:id',
|
||||
loadChildren: 'generated-sources/page-user-management-group-edit.module#PageusermanagementgroupeditModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'authorities',
|
||||
loadChildren: 'generated-sources/page-user-management-authorities.module#PageusermanagementauthoritiesModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class UserManagementRoutingModule {
|
||||
|
||||
}
|
||||
27
frontend/src/ts/modules/webbpm/webbpm-routing.module.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {RouterModule, Routes} from "@angular/router";
|
||||
import {AuthenticationGuard, ConfirmExitGuard} from "@webbpm/base-package";
|
||||
|
||||
const webbpmRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
loadChildren: 'generated-sources/page-main.module#PagemainModule',
|
||||
canActivate: [AuthenticationGuard, ConfirmExitGuard],
|
||||
pathMatch: 'full',
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: '',
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(webbpmRoutes, {
|
||||
useHash: true,
|
||||
onSameUrlNavigation: "reload"
|
||||
})],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class WebbpmRoutingModule {
|
||||
|
||||
}
|
||||
56
frontend/src/ts/modules/webbpm/webbpm.module.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import {ErrorHandler, NgModule} from "@angular/core";
|
||||
import {BrowserModule} from "@angular/platform-browser";
|
||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {AgGridModule} from "ag-grid-angular";
|
||||
import {WebbpmComponent} from "./component/webbpm.component";
|
||||
import {WebbpmRoutingModule} from "./webbpm-routing.module";
|
||||
import {NgbModule} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {ToastNoAnimationModule} from "ngx-toastr";
|
||||
import {AppModule} from "../app/app.module";
|
||||
import {HomeComponent} from "./component/home.component";
|
||||
import {
|
||||
BpmnModule,
|
||||
ComponentsModule,
|
||||
CoreModule,
|
||||
SecurityModule,
|
||||
} from "@webbpm/base-package";
|
||||
import {AppRoutingModule} from "../app/app-routing.module";
|
||||
import {UserManagementRoutingModule} from "./user-management-routing.module";
|
||||
import {GlobalErrorHandler} from "./handler/global-error.handler.prod";
|
||||
import {DEFAULT_HTTP_INTERCEPTOR_PROVIDERS} from "./interceptor/default-interceptors.prod";
|
||||
|
||||
let IMPORTS = [
|
||||
BrowserAnimationsModule,
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
NgbModule,
|
||||
ToastNoAnimationModule.forRoot(),
|
||||
AgGridModule,
|
||||
AppRoutingModule,
|
||||
UserManagementRoutingModule,
|
||||
BpmnModule,
|
||||
CoreModule,
|
||||
ComponentsModule,
|
||||
SecurityModule,
|
||||
AppModule,
|
||||
WebbpmRoutingModule
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: IMPORTS,
|
||||
declarations: [
|
||||
WebbpmComponent,
|
||||
HomeComponent
|
||||
],
|
||||
exports: [],
|
||||
providers: [
|
||||
{provide: ErrorHandler, useClass: GlobalErrorHandler},
|
||||
DEFAULT_HTTP_INTERCEPTOR_PROVIDERS
|
||||
],
|
||||
bootstrap: [
|
||||
WebbpmComponent
|
||||
]
|
||||
})
|
||||
export class WebbpmModule {
|
||||
}
|
||||
3
frontend/src/ts/page.routing.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import {Routes} from "@angular/router";
|
||||
|
||||
declare const DYNAMIC_ROUTING: Routes;
|
||||
59
frontend/src/ts/polyfills.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
||||
import 'core-js/es6/symbol';
|
||||
import 'core-js/es6/object';
|
||||
import 'core-js/es6/function';
|
||||
import 'core-js/es6/parse-int';
|
||||
import 'core-js/es6/parse-float';
|
||||
import 'core-js/es6/number';
|
||||
import 'core-js/es6/math';
|
||||
import 'core-js/es6/string';
|
||||
import 'core-js/es6/date';
|
||||
import 'core-js/es6/array';
|
||||
import 'core-js/es6/regexp';
|
||||
import 'core-js/es6/map';
|
||||
import 'core-js/es6/weak-map';
|
||||
import 'core-js/es6/set';
|
||||
import 'core-js/es6/promise';
|
||||
import 'core-js/es7';
|
||||
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||
|
||||
/** IE10 and IE11 requires the following for the Reflect API. */
|
||||
// import 'core-js/es6/reflect';
|
||||
|
||||
|
||||
/** Evergreen browsers require these. **/
|
||||
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Required to support Web Animations `@angular/platform-browser/animations`.
|
||||
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
|
||||
**/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
/**
|
||||
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||
*/
|
||||
|
||||
// (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
|
||||
// (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||
// (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
||||
|
||||
/*
|
||||
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||
*/
|
||||
// (window as any).__Zone_enable_cross_context_check = true;
|
||||
|
||||
/***************************************************************************************************
|
||||
* Zone JS is required by default for Angular itself.
|
||||
*/
|
||||
import 'zone.js/dist/zone';// Included with Angular CLI.
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
38
frontend/src/ts/vendor.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Angular
|
||||
import '@angular/core';
|
||||
import '@angular/common';
|
||||
import '@angular/common/http';
|
||||
import '@angular/forms';
|
||||
import '@angular/platform-browser';
|
||||
import '@angular/router';
|
||||
import '@angular/animations';
|
||||
import '@webbpm/base-package';
|
||||
// RxJS
|
||||
import 'rxjs';
|
||||
import 'rxjs-compat';
|
||||
import 'rxjs/operators';
|
||||
import 'rxjs/internal-compatibility';
|
||||
import 'rxjs/ajax';
|
||||
import 'rxjs/testing';
|
||||
import 'rxjs/webSocket';
|
||||
//jquery
|
||||
import 'jquery';
|
||||
//popper
|
||||
import 'popper.js';
|
||||
//bootstrap
|
||||
import '@ng-bootstrap/ng-bootstrap';
|
||||
import 'bootstrap';
|
||||
//mask
|
||||
import 'inputmask';
|
||||
//grid
|
||||
import 'ag-grid-community';
|
||||
import 'ag-grid-angular';
|
||||
//selectize
|
||||
import 'selectize';
|
||||
//datepicker
|
||||
import 'eonasdan-bootstrap-datetimepicker';
|
||||
import 'moment-timezone';
|
||||
//ngx-toastr
|
||||
import 'ngx-toastr';
|
||||
//ngx-cookie
|
||||
import 'ngx-cookie';
|
||||
93
frontend/systemjs.config.js
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
(function(global) {
|
||||
System.config({
|
||||
transpiler: 'plugin-babel',
|
||||
paths: {
|
||||
'npm:': 'node_modules/',
|
||||
'generated-sources': 'build_dev/js/generated-sources'
|
||||
},
|
||||
map: {
|
||||
'webbpm': 'build_dev/js',
|
||||
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
||||
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
||||
'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',
|
||||
'@angular/common/locales': 'npm:@angular/common/locales',
|
||||
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
||||
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
||||
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||
'@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
|
||||
'@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
|
||||
'@angular/platform-browser/animations':'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
|
||||
'@ng-bootstrap/ng-bootstrap': 'npm:@ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap.umd.js',
|
||||
'bootstrap': 'npm:bootstrap',
|
||||
'@webbpm/base-package': 'npm:@webbpm/base-package/bundles/webbpm-base-package.umd.js',
|
||||
'angular-calendar': 'npm:angular-calendar/bundles/angular-calendar.umd.js',
|
||||
'angular-calendar/date-adapters/date-fns': 'npm:angular-calendar/date-adapters/date-fns/index.js',
|
||||
'angular-draggable-droppable': 'npm:angular-draggable-droppable/bundles/angular-draggable-droppable.umd.js',
|
||||
'angular-resizable-element': 'npm:angular-resizable-element/bundles/angular-resizable-element.umd.js',
|
||||
'calendar-utils': 'npm:calendar-utils/bundles/calendar-utils.umd.js',
|
||||
'calendar-utils/date-adapters/date-fns': 'npm:calendar-utils/date-adapters/date-fns/index.js',
|
||||
'date-fns': 'npm:date-fns',
|
||||
'ngx-cookie': 'npm:ngx-cookie/bundles/ngx-cookie.umd.js',
|
||||
'moment': 'npm:moment',
|
||||
'moment-timezone': 'npm:moment-timezone',
|
||||
'positioning': 'npm:positioning/dist/positioning.js',
|
||||
'rxjs': 'npm:rxjs',
|
||||
'rxjs-compat': 'npm:rxjs-compat',
|
||||
'rxjs/operators': 'npm:rxjs/operators',
|
||||
'rxjs/internal-compatibility': 'npm:rxjs/internal-compatibility',
|
||||
'rxjs/ajax': 'npm:rxjs/ajax',
|
||||
'rxjs/testing': 'npm:rxjs/testing',
|
||||
'rxjs/webSocket': 'npm:rxjs/webSocket',
|
||||
'jquery': 'npm:jquery/dist/jquery.js',
|
||||
'popper.js': 'npm:popper.js/dist/umd/popper.js',
|
||||
'sifter': 'npm:sifter/sifter.min.js',
|
||||
'microplugin': 'npm:microplugin/src/microplugin.js',
|
||||
'selectize': 'npm:selectize/dist/js/selectize.min.js',
|
||||
'ngx-toastr': 'npm:ngx-toastr/bundles/ngx-toastr.umd.min.js',
|
||||
'eonasdan-bootstrap-datetimepicker': 'npm:eonasdan-bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js',
|
||||
'autonumeric': 'npm:autonumeric',
|
||||
'jsgantt-improved': 'npm:jsgantt-improved/dist/jsgantt.js',
|
||||
'js-year-calendar': 'npm:js-year-calendar/dist/js-year-calendar.js',
|
||||
'ag-grid-angular': 'npm:ag-grid-angular/bundles/ag-grid-angular.umd.js',
|
||||
'ag-grid-community': 'npm:ag-grid-community/dist/ag-grid-community.cjs.js',
|
||||
'inputmask': 'npm:inputmask',
|
||||
'downloadjs': 'npm:downloadjs/download.js',
|
||||
'esmarttokenjs': 'npm:esmarttokenjs/esmarttoken.js',
|
||||
'cadesplugin_api': 'npm:cadesplugin_api/index.js',
|
||||
'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js',
|
||||
'systemjs-babel-build': 'npm:systemjs-plugin-babel/systemjs-babel-browser.js',
|
||||
'chart.js': 'npm:chart.js/dist',
|
||||
'chartjs-adapter-moment': 'npm:chartjs-adapter-moment/dist/chartjs-adapter-moment.js',
|
||||
'tslib': 'npm:tslib/tslib.js',
|
||||
'ngx-international-phone-number': 'npm:ngx-international-phone-number/ngx-international-phone-number.umd.js',
|
||||
'google-libphonenumber': 'npm:google-libphonenumber/dist/libphonenumber.js'
|
||||
},
|
||||
packages: {
|
||||
'webbpm': { main: 'main', defaultExtension: 'js'},
|
||||
'@angular/common/locales': { defaultExtension: 'js'},
|
||||
'date-fns': { main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs': { main: 'index.js', defaultExtension: 'js' },
|
||||
'rxjs-compat': { main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/operators': { main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/internal-compatibility':{ main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/ajax': { main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/testing': { main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/webSocket': { main: "index.js", defaultExtension: 'js'},
|
||||
'moment': { main: 'min/locales.min', defaultExtension: 'js' },
|
||||
'moment-es6': { main: 'index.js', defaultExtension: 'js' },
|
||||
'moment-timezone': { main: 'builds/moment-timezone-with-data.min', defaultExtension: 'js' },
|
||||
'bootstrap': { main: 'dist/js/bootstrap', defaultExtension: 'js'},
|
||||
'lib': { format: 'register', defaultExtension: 'js' },
|
||||
'autonumeric': {
|
||||
main: 'dist/autoNumeric.js'
|
||||
},
|
||||
'chart.js': { main: 'chart.js', defaultExtension: 'js' },
|
||||
'inputmask': {
|
||||
main: 'dist/inputmask.js',
|
||||
defaultExtension: 'js'
|
||||
}
|
||||
}
|
||||
});
|
||||
})(this);
|
||||
92
frontend/systemjs.preview.config.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
(function(global) {
|
||||
System.config({
|
||||
transpiler: 'plugin-babel',
|
||||
paths: {
|
||||
'npm:': 'node_modules/',
|
||||
'generated-sources': 'build_dev/js/generated-sources'
|
||||
},
|
||||
map: {
|
||||
'preview': 'build_dev/js',
|
||||
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
||||
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
||||
'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',
|
||||
'@angular/common/locales': 'npm:@angular/common/locales',
|
||||
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
||||
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
||||
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||
'@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
|
||||
'@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
|
||||
'@angular/platform-browser/animations':'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
|
||||
'@ng-bootstrap/ng-bootstrap': 'npm:@ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap.umd.js',
|
||||
'bootstrap': 'npm:bootstrap',
|
||||
'@webbpm/base-package': 'npm:@webbpm/base-package/bundles/webbpm-base-package.umd.js',
|
||||
'angular-calendar': 'npm:angular-calendar/bundles/angular-calendar.umd.js',
|
||||
'angular-calendar/date-adapters/date-fns': 'npm:angular-calendar/date-adapters/date-fns/index.js',
|
||||
'angular-draggable-droppable': 'npm:angular-draggable-droppable/bundles/angular-draggable-droppable.umd.js',
|
||||
'angular-resizable-element': 'npm:angular-resizable-element/bundles/angular-resizable-element.umd.js',
|
||||
'calendar-utils': 'npm:calendar-utils/bundles/calendar-utils.umd.js',
|
||||
'calendar-utils/date-adapters/date-fns': 'npm:calendar-utils/date-adapters/date-fns/index.js',
|
||||
'date-fns': 'npm:date-fns',
|
||||
'ngx-cookie': 'npm:ngx-cookie/bundles/ngx-cookie.umd.js',
|
||||
'moment': 'npm:moment',
|
||||
'moment-timezone': 'npm:moment-timezone',
|
||||
'positioning': 'npm:positioning/dist/positioning.js',
|
||||
'rxjs': 'npm:rxjs',
|
||||
'rxjs-compat': 'npm:rxjs-compat',
|
||||
'rxjs/operators': 'npm:rxjs/operators',
|
||||
'rxjs/internal-compatibility': 'npm:rxjs/internal-compatibility',
|
||||
'rxjs/ajax': 'npm:rxjs/ajax',
|
||||
'rxjs/testing': 'npm:rxjs/testing',
|
||||
'rxjs/webSocket': 'npm:rxjs/webSocket',
|
||||
'jquery': 'npm:jquery/dist/jquery.js',
|
||||
'popper.js': 'npm:popper.js/dist/umd/popper.js',
|
||||
'sifter': 'npm:sifter/sifter.min.js',
|
||||
'microplugin': 'npm:microplugin/src/microplugin.js',
|
||||
'selectize': 'npm:selectize/dist/js/selectize.min.js',
|
||||
'ngx-toastr': 'npm:ngx-toastr/bundles/ngx-toastr.umd.min.js',
|
||||
'eonasdan-bootstrap-datetimepicker': 'npm:eonasdan-bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js',
|
||||
'autonumeric': 'npm:autonumeric',
|
||||
'jsgantt-improved': 'npm:jsgantt-improved/dist/jsgantt.js',
|
||||
'js-year-calendar': 'npm:js-year-calendar/dist/js-year-calendar.js',
|
||||
'ag-grid-angular': 'npm:ag-grid-angular/bundles/ag-grid-angular.umd.js',
|
||||
'ag-grid-community': 'npm:ag-grid-community/dist/ag-grid-community.cjs.js',
|
||||
'inputmask': 'npm:inputmask',
|
||||
'downloadjs': 'npm:downloadjs/download.js',
|
||||
'esmarttokenjs': 'npm:esmarttokenjs/esmarttoken.js',
|
||||
'cadesplugin_api': 'npm:cadesplugin_api/index.js',
|
||||
'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js',
|
||||
'systemjs-babel-build': 'npm:systemjs-plugin-babel/systemjs-babel-browser.js',
|
||||
'chart.js': 'npm:chart.js/dist',
|
||||
'chartjs-adapter-moment': 'npm:chartjs-adapter-moment/dist/chartjs-adapter-moment.js',
|
||||
'tslib': 'npm:tslib/tslib.js',
|
||||
'ngx-international-phone-number': 'npm:ngx-international-phone-number/ngx-international-phone-number.umd.js',
|
||||
'google-libphonenumber': 'npm:google-libphonenumber/dist/libphonenumber.js'
|
||||
},
|
||||
packages: {
|
||||
'preview': { main: './modules/preview/preview.main', defaultExtension: 'js'},
|
||||
'@angular/common/locales': { defaultExtension: 'js'},
|
||||
'date-fns': { main: 'index.js', defaultExtension: 'js'},
|
||||
'rxjs': { main: 'index.js', defaultExtension: 'js' },
|
||||
'rxjs-compat': { main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/operators': { main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/internal-compatibility':{ main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/ajax': { main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/testing': { main: "index.js", defaultExtension: 'js'},
|
||||
'rxjs/webSocket': { main: "index.js", defaultExtension: 'js'},
|
||||
'moment': { main: 'min/locales.min', defaultExtension: 'js' },
|
||||
'moment-timezone': { main: 'builds/moment-timezone-with-data.min', defaultExtension: 'js' },
|
||||
'bootstrap': { main: 'dist/js/bootstrap', defaultExtension: 'js'},
|
||||
'lib': { format: 'register', defaultExtension: 'js' },
|
||||
'autonumeric': {
|
||||
main: 'dist/autoNumeric.js'
|
||||
},
|
||||
'chart.js': { main: 'chart.js', defaultExtension: 'js' },
|
||||
'inputmask': {
|
||||
main: 'dist/inputmask.js',
|
||||
defaultExtension: 'js'
|
||||
}
|
||||
}
|
||||
});
|
||||
})(this);
|
||||
42
frontend/tsconfig.aot.json
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"declaration": false,
|
||||
"sourceMap": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"removeComments": false,
|
||||
"skipLibCheck": true,
|
||||
"noImplicitAny": false,
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
"lib": [
|
||||
"es2016",
|
||||
"dom",
|
||||
"es2017.object",
|
||||
"es2018.promise"
|
||||
]
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"buildOnSave": false,
|
||||
"include": [
|
||||
"src/ts/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"./node_modules/@types",
|
||||
"src/ts/main.ts",
|
||||
"**/*.spec.ts",
|
||||
"src/test.ts"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"skipMetadataEmit": true,
|
||||
"alwaysCompileGeneratedCode":true,
|
||||
"preserveWhitespaces": false,
|
||||
"annotationsAs": "decorators",
|
||||
"mainPath": "./src/ts"
|
||||
}
|
||||
}
|
||||
40
frontend/tsconfig.json
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"declaration": false,
|
||||
"inlineSourceMap": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"removeComments": false,
|
||||
"skipLibCheck": true,
|
||||
"noImplicitAny": false,
|
||||
"outDir": "build_dev/js",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
"lib": [
|
||||
"es2016",
|
||||
"dom",
|
||||
"es2017.object",
|
||||
"es2018.promise"
|
||||
]
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"buildOnSave": false,
|
||||
"include": [
|
||||
"src/ts/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"./node_modules/@types",
|
||||
"**/*.ngfactory.ts",
|
||||
"**/*.shim.ts",
|
||||
"src/ts/main.aot.ts",
|
||||
"src/ts/generated-sources/**/*",
|
||||
"src/ts/page.routing.ts",
|
||||
"src/ts/aot"
|
||||
]
|
||||
}
|
||||
142
frontend/webpack.aot.config.js
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
'use strict';
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
function _path(p) {
|
||||
return path.join(__dirname, p);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: {
|
||||
polyfills: './build/scripts/polyfills.js',
|
||||
vendor: './build/scripts/vendor.js',
|
||||
main: './build/scripts/main.aot.js',
|
||||
},
|
||||
|
||||
context: process.cwd(),
|
||||
|
||||
output: {
|
||||
path: path.join(process.cwd(), './dist'),
|
||||
filename: '[name].[chunkhash].bundle.js',
|
||||
chunkFilename: '[id].[chunkhash].chunk.js',
|
||||
assetModuleFilename: 'src/resources/[base]',
|
||||
publicPath: 'auto'
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: ['@babel/preset-env']
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: {
|
||||
loader: 'angular-router-loader?aot=true'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
use: {
|
||||
loader: 'raw-loader'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
// you can specify a publicPath here
|
||||
// by default it use publicPath in webpackOptions.output
|
||||
// publicPath: '../'
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: 'css-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico|otf)$/,
|
||||
type: 'asset/resource'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
parallel: true,
|
||||
terserOptions: {
|
||||
// https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions
|
||||
}
|
||||
})
|
||||
],
|
||||
splitChunks: {
|
||||
// include all types of chunks
|
||||
chunks: 'all'
|
||||
}
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'index.webpack.html',
|
||||
filename: 'index.html',
|
||||
chunksSortMode : 'none'
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
{from: 'index.webpack.html', to: 'index.html'},
|
||||
{from: 'src/resources/img/progress.gif', to: 'src/resources/img/progress.gif'},
|
||||
{from: 'src/resources/img/logo.png', to: 'src/resources/img/logo.png'},
|
||||
{from: 'src/resources/app-config.json', to: 'src/resources/app-config.json'},
|
||||
{from: 'src/resources/app.version', to: 'src/resources/app.version'}
|
||||
]),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].[fullhash].css',
|
||||
chunkFilename: '[id].[fullhash].css'
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
$: "jquery",
|
||||
jQuery: "jquery",
|
||||
"window.jQuery": "jquery",
|
||||
Popper: ['popper.js', 'default']
|
||||
})
|
||||
],
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'jquery': _path('node_modules/jquery/dist/jquery.min'),
|
||||
'inputmask': _path('node_modules/inputmask/dist/inputmask'),
|
||||
'downloadjs': _path('node_modules/downloadjs/download.min.js'),
|
||||
'esmarttokenjs': _path('node_modules/esmarttokenjs/esmarttoken.js'),
|
||||
'cadesplugin_api': _path('node_modules/cadesplugin_api/index.js'),
|
||||
'eonasdan-bootstrap-datetimepicker': _path('node_modules/eonasdan-bootstrap-datetimepicker/src/js/bootstrap-datetimepicker'),
|
||||
'autonumeric': _path('node_modules/autonumeric/dist/autoNumeric.js'),
|
||||
'jsgantt-improved': _path('node_modules/jsgantt-improved/dist/jsgantt.js'),
|
||||
'js-year-calendar': _path('node_modules/js-year-calendar/dist/js-year-calendar.js'),
|
||||
'chart.js': _path('node_modules/chart.js/dist/chart.js')
|
||||
},
|
||||
modules: [
|
||||
'node_modules',
|
||||
path.resolve(process.cwd(), './build'),
|
||||
path.resolve(process.cwd(), './build/scripts'),
|
||||
],
|
||||
extensions: ['.js']
|
||||
},
|
||||
|
||||
stats: {
|
||||
children: false
|
||||
},
|
||||
devtool: false
|
||||
};
|
||||