Initial commit

This commit is contained in:
2026-01-11 21:16:46 +00:00
commit 25051654a1
73 changed files with 30427 additions and 0 deletions

17
.browserslistrc Normal file
View File

@@ -0,0 +1,17 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.

16
.editorconfig Normal file
View File

@@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

45
.gitignore vendored Normal file
View File

@@ -0,0 +1,45 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

10
LICENSE Normal file
View File

@@ -0,0 +1,10 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# brainman-data-generator
Test data generator

113
angular.json Normal file
View File

@@ -0,0 +1,113 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"testowy": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
},
"@schematics/angular:application": {
"strict": true
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/testowy",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "testowy:build:production"
},
"development": {
"browserTarget": "testowy:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "testowy:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
],
"scripts": []
}
}
}
}
},
"defaultProject": "testowy"
}

44
karma.conf.js Normal file
View File

@@ -0,0 +1,44 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage/testowy'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

28552
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

46
package.json Normal file
View File

@@ -0,0 +1,46 @@
{
"name": "testowy",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"brainman": "ng build --base-href /szkolenie/ --output-hashing all",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "~12.2.0",
"@angular/cdk": "^12.2.6",
"@angular/common": "~12.2.0",
"@angular/compiler": "~12.2.0",
"@angular/core": "~12.2.0",
"@angular/forms": "~12.2.0",
"@angular/material": "^12.2.6",
"@angular/localize": "^12.2.6",
"@angular/platform-browser": "~12.2.0",
"@angular/platform-browser-dynamic": "~12.2.0",
"@angular/router": "~12.2.0",
"date-fns": "~2.24.0",
"rxjs": "~6.6.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~12.2.6",
"@angular/cli": "~12.2.6",
"@angular/compiler-cli": "~12.2.0",
"@angular/localize": "^12.2.6",
"@types/jasmine": "~3.8.0",
"@types/node": "^12.11.1",
"date-fns": "~2.24.0",
"jasmine-core": "~3.8.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.3.5"
}
}

41
src/app/app.module.ts Normal file
View File

@@ -0,0 +1,41 @@
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './components/app/app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatInputModule } from '@angular/material/input';
import { MatIconModule } from '@angular/material/icon';
import { MatGridListModule } from '@angular/material/grid-list';
import { ClipboardModule } from '@angular/cdk/clipboard';
import { MatSnackBarModule} from '@angular/material/snack-bar';
import { TranslatePipe } from './translate-pipe';
import { PeselComponent } from './components/pesel/pesel.component';
import { NipComponent } from './components/nip/nip.component';
import { RegonComponent } from './components/regon/regon.component';
import { IbanComponent } from './components/iban/iban.component';
@NgModule({
declarations: [
AppComponent,
TranslatePipe,
PeselComponent,
NipComponent,
RegonComponent,
IbanComponent
],
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
MatInputModule,
MatIconModule,
MatGridListModule,
ClipboardModule,
MatSnackBarModule,
ReactiveFormsModule,
],
providers: [TranslatePipe],
bootstrap: [AppComponent]
})
export class AppModule {
}

View File

@@ -0,0 +1 @@
/* No CSS *//*# sourceMappingURL=app.component.css.map */

View File

@@ -0,0 +1,9 @@
{
"version": 3,
"mappings": "",
"sources": [
"app.component.scss"
],
"names": [],
"file": "app.component.css"
}

View File

@@ -0,0 +1,7 @@
<div class="gradient"></div>
<div class="generators">
<app-regon></app-regon>
<app-nip></app-nip>
<app-pesel></app-pesel>
<app-iban></app-iban>
</div>

View File

@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor() {
}
ngOnInit(): void {
}
}

View File

@@ -0,0 +1 @@
/* No CSS *//*# sourceMappingURL=iban.component.css.map */

View File

@@ -0,0 +1,9 @@
{
"version": 3,
"mappings": "",
"sources": [
"iban.component.scss"
],
"names": [],
"file": "iban.component.css"
}

View File

@@ -0,0 +1,19 @@
<div class="generator">
<div class="title">
<span>IBAN</span>
<div class="titleButtons">
<img id="lettersPrefixButton" src="assets/format_color_text_black_24dp.svg" title="Prefiks literowy" alt="Czy umieścić prefiks literowy PL" (click)="toggleLettersPrefix()" class="smaller" [style.background] = "lettersPrefix ? 'rgba(0, 0, 0, 0.35)' : ''" />
<div style="width: 20px;"></div>
<img id="separatorButton" src="assets/space_bar_black_24dp.svg" title="Separatory między grupami cyfr" alt="Czy umieścić separatory między grupami cyfr" (click)="toggleSeparators()" [style.background] = "separators ? 'rgba(0, 0, 0, 0.35)' : ''" />
</div>
</div>
<div class="container">
<input type="text" [formControl]="valueField" style="width: 380px;"/>
<div class="buttons">
<img id="ibanGenerateButton" src="assets/autorenew_black_24dp.svg" title="Generuj numer IBAN" alt="Generuj numer IBAN" style="margin-left: 1em;" (click)="generate()"/>
<img id="ibanCopyButton" src="assets/content_copy_black_24dp.svg" title="Skopiuj numer IBAN do schowka" alt="Skopiuj numer IBAN do schowka" style="margin: auto 1em;" (click)="copyToClipboard()"/>
<img id="ibanHelpButton" src="assets/info_black_24dp.svg" title="Definicja numeru IBAN na Wikipedii" alt="Definicja numeru IBAN na Wikipedii" (click)="navigateToDocs()" />
</div>
</div>
</div>

View File

@@ -0,0 +1,112 @@
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl } from '@angular/forms';
import { ClipboardService } from '../../service/gui/clipboard.service';
import { IbanService } from '../../service/iban.service';
@Component({
selector: 'app-iban',
templateUrl: './iban.component.html',
styleUrls: ['./iban.component.scss']
})
export class IbanComponent implements OnInit {
public valueField: FormControl;
public lettersPrefix: boolean;
public separators: boolean;
constructor(private ibanService: IbanService, private clipboardService: ClipboardService) {
this.valueField = new FormControl('iban');
this.valueField.setValidators([(control: AbstractControl) => this.ibanService.validateIban(control.value)]);
this.lettersPrefix = false;
this.separators = false;
}
ngOnInit(): void {
this.generate();
}
generate(): void {
let iban: string = this.ibanService.generateIban();
let formattedIban = iban;
if (this.separators) {
formattedIban = iban.substring(0, 2);
for (let i: number = 2; i < iban.length; i+=4) {
formattedIban += " " + iban.substring(i, i + 4);
}
}
if (this.lettersPrefix) {
formattedIban = 'PL' + (this.separators ? " " : "") + formattedIban;
}
this.valueField.setValue(formattedIban);
}
toggleLettersPrefix(): void {
this.lettersPrefix = !this.lettersPrefix;
if (this.valueField.valid) {
var formattedValue: string;
if (this.lettersPrefix) {
formattedValue = this.addLetterPrefix(this.valueField.value);
} else {
formattedValue = this.removeLetterPrefix(this.valueField.value);
}
this.valueField.setValue(formattedValue);
}
}
toggleSeparators(): void {
this.separators = !this.separators;
if (this.valueField.valid) {
var formattedValue: string;
if (this.separators) {
formattedValue = this.addSeparators(this.valueField.value);
} else {
formattedValue = this.removeSeparators(this.valueField.value);
}
this.valueField.setValue(formattedValue);
}
}
addLetterPrefix(iban: string): string {
return 'PL' + (this.separators ? " " : "") + iban;
}
removeLetterPrefix(iban: string): string {
return iban.replace(/[a-zA-Z]*/g, "");
}
addSeparators(iban: string): string {
var formattedIban = iban.substring(0, 2);
for (let i: number = 2; i < iban.length; i+=4) {
formattedIban += " " + iban.substring(i, i + 4);
}
return formattedIban;
}
removeSeparators(iban: string) : string {
return iban.replace(/ /g, "");
}
copyToClipboard(): void {
this.clipboardService.copyToClipboard(this.valueField.value);
}
navigateToDocs(): void {
window.open('https://pl.wikipedia.org/wiki/Mi%C4%99dzynarodowy_numer_rachunku_bankowego', "_blank");
}
}

View File

@@ -0,0 +1 @@
/* No CSS *//*# sourceMappingURL=nip.component.css.map */

View File

@@ -0,0 +1,9 @@
{
"version": 3,
"mappings": "",
"sources": [
"nip.component.scss"
],
"names": [],
"file": "nip.component.css"
}

View File

@@ -0,0 +1,14 @@
<div class="generator">
<div class="title">
<span>NIP</span>
</div>
<div class="container">
<input type="text" [formControl]="valueField" />
<div class="buttons">
<img id="nipGenerateButton" src="assets/autorenew_black_24dp.svg" title="Generuj numer NIP" alt="Generuj numer NIP" (click)="generate()"/>
<img id="nipCopyButton" src="assets/content_copy_black_24dp.svg" title="Skopiuj numer NIP do schowka" alt="Skopiuj numer NIP do schowka" (click)="copyToClipboard()"/>
<img id="nipHelpButton" src="assets/info_black_24dp.svg" title="Szczegóły dotyczące numeru NIP" alt="Definicja numeru NIP na Wikipedii" (click)="navigateToDocs()" />
</div>
</div>
</div>

View File

@@ -0,0 +1,34 @@
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl } from '@angular/forms';
import { NipService } from 'src/app/service/nip.service';
import { ClipboardService } from 'src/app/service/gui/clipboard.service';
@Component({
selector: 'app-nip',
templateUrl: './nip.component.html',
styleUrls: ['./nip.component.scss']
})
export class NipComponent implements OnInit {
public valueField: FormControl;
constructor(private nipService: NipService, private clipboardService: ClipboardService) {
this.valueField = new FormControl('nip');
this.valueField.setValidators([(control: AbstractControl) => this.nipService.validateNip(control.value)]);
}
ngOnInit(): void {
this.generate();
}
generate(): void {
this.valueField.setValue(this.nipService.generateNip());
}
copyToClipboard(): void {
this.clipboardService.copyToClipboard(this.valueField.value);
}
navigateToDocs(): void {
window.open('https://pl.wikipedia.org/wiki/Numer_identyfikacji_podatkowej', "_blank");
}
}

View File

@@ -0,0 +1 @@
/* No CSS *//*# sourceMappingURL=pesel.component.css.map */

View File

@@ -0,0 +1,9 @@
{
"version": 3,
"mappings": "",
"sources": [
"pesel.component.scss"
],
"names": [],
"file": "pesel.component.css"
}

View File

@@ -0,0 +1,19 @@
<div class="generator">
<div class="title">
<span>PESEL</span>
<div class="titleButtons">
<img id="malePeselButton" src="assets/male_black_24dp.svg" title="Płeć męska" alt="Czy generować męskie numery PESEL" (click)="toggleMale()" [style.background] = "generateMale ? 'rgba(0, 0, 0, 0.35)' : ''" />
<div style="width: 20px;"></div>
<img id="femalePeselButton" src="assets/female_black_24dp.svg" title="Płeć żeńska" alt="Czy generować żeńskie numery PESEL" (click)="toggleFemale()" [style.background] = "generateFemale ? 'rgba(0, 0, 0, 0.35)' : ''" />
</div>
</div>
<div class="container">
<input type="text" [formControl]="valueField" />
<div class="buttons">
<img id="peselGenerateButton" src="assets/autorenew_black_24dp.svg" title="Generuj numer PESEL" alt="Generuj numer PESEL" style="margin-left: 1em;" (click)="generate()"/>
<img id="peselCopyButton" src="assets/content_copy_black_24dp.svg" title="Skopiuj numer PESEL do schowka" alt="Skopiuj numer PESEL do schowka" style="margin: auto 1em;" (click)="copyToClipboard()"/>
<img id="peselHelpButton" src="assets/info_black_24dp.svg" title="Szczegóły dotyczące numeru PESEL" alt="Definicja numeru PESEL na Wikipedii" (click)="navigateToDocs()" />
</div>
</div>
</div>

View File

@@ -0,0 +1,52 @@
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl } from '@angular/forms';
import { PeselService } from 'src/app/service/pesel.service';
import { ClipboardService } from 'src/app/service/gui/clipboard.service';
@Component({
selector: 'app-pesel',
templateUrl: './pesel.component.html',
styleUrls: ['./pesel.component.scss']
})
export class PeselComponent implements OnInit {
public valueField: FormControl;
public generateMale: boolean;
public generateFemale: boolean;
constructor(private peselService: PeselService, private clipboardService: ClipboardService) {
this.valueField = new FormControl('pesel');
this.valueField.setValidators([(control: AbstractControl) => this.peselService.validatePesel(control.value)]);
this.generateMale = true;
this.generateFemale = true;
}
ngOnInit(): void {
this.generate();
}
generate(): void {
if (this.generateMale === false && this.generateFemale === false) {
return;
}
this.valueField.setValue(this.peselService.generatePesel(this.generateMale, this.generateFemale));
}
toggleMale(): void {
this.generateMale = !this.generateMale;
}
toggleFemale(): void {
this.generateFemale = !this.generateFemale;
}
copyToClipboard(): void {
this.clipboardService.copyToClipboard(this.valueField.value);
}
navigateToDocs(): void {
window.open('https://pl.wikipedia.org/wiki/PESEL', "_blank");
}
}

View File

@@ -0,0 +1 @@
/* No CSS *//*# sourceMappingURL=regon.component.css.map */

View File

@@ -0,0 +1,9 @@
{
"version": 3,
"mappings": "",
"sources": [
"regon.component.scss"
],
"names": [],
"file": "regon.component.css"
}

View File

@@ -0,0 +1,14 @@
<div class="generator">
<div class="title">
<span>REGON</span>
</div>
<div class="container">
<input type="text" [formControl]="valueField" />
<div class="buttons">
<img id="regonGenerateButton" src="assets/autorenew_black_24dp.svg" title="Generuj numer REGON" alt="Generuj numer REGON" (click)="generate()"/>
<img id="regonCopyButton" src="assets/content_copy_black_24dp.svg" title="Skopiuj numer REGON do schowka" alt="Skopiuj numer REGON do schowka" (click)="copyToClipboard()"/>
<img id="regonHelpButton" src="assets/info_black_24dp.svg" title="Definicja numeru REGON na Wikipedii" alt="Definicja numeru REGON na Wikipedii" (click)="navigateToDocs()" />
</div>
</div>
</div>

View File

@@ -0,0 +1,34 @@
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl } from '@angular/forms';
import { RegonService } from 'src/app/service/regon.service';
import { ClipboardService } from 'src/app/service/gui/clipboard.service';
@Component({
selector: 'app-regon',
templateUrl: './regon.component.html',
styleUrls: ['./regon.component.scss']
})
export class RegonComponent implements OnInit {
public valueField: FormControl;
constructor(private regonService: RegonService, private clipboardService: ClipboardService) {
this.valueField = new FormControl('nip');
this.valueField.setValidators([(control: AbstractControl) => this.regonService.validateRegon9(control.value)]);
}
ngOnInit(): void {
this.generate();
}
generate(): void {
this.valueField.setValue(this.regonService.generateRegon9());
}
copyToClipboard(): void {
this.clipboardService.copyToClipboard(this.valueField.value);
}
navigateToDocs(): void {
window.open('https://pl.wikipedia.org/wiki/REGON', "_blank");
}
}

View File

@@ -0,0 +1,74 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class CommonService {
// numeryczny regexp
public static readonly numericRegExp: RegExp = new RegExp("^[0-9]*$");
constructor() { }
/**
* Waliduje cyfrę kontrolną dla przekazanej wartości i wag kolejnych cyfr.
*
* @param value wartość wejściowa do wyliczenia cyfry kontrolnej
* @param weights wejściowy zbiór wag
* @param lastStepFunction funkcja matematyczna finalizująca wyliczoną sumę
* @returns
*/
public validateControlDigit(value: string, weights: number[], lastStepFunction: (weight: number) => number): boolean {
const controlDigit: number = this.calculateControlDigit(value, weights, lastStepFunction);
const digits: string[] = value.split("");
return controlDigit == parseInt(digits[digits.length - 1], 10);
}
/**
* Wylicza cyfrę kontrolną dla przekazanej wartości używając przekazanej tablicy wag i końcowej operacji matematycznej
*
* @param value analizowana wartość
* @param weights tablica wag dla kolejnych cyfr
* @param lastStepFunction finalizujące działanie matematyczne
* @returns wyliczona cyfra kontrolna
*/
public calculateControlDigit(value: string, weights: number[], lastStepFunction: (weight: number) => number): number {
let digits: string[] = value.split("");
let calculatedChecksum: number = 0;
for (let i = 0; i < weights.length; i++) {
let digit: number = parseInt(digits[i], 10);
calculatedChecksum += digit * weights[i];
}
return lastStepFunction.call(this, calculatedChecksum);
}
/**
* Zwraca liczbę losową z podanego zakresu
*
* @param min minimalna zwrócona
* @param max maksymalna zwrócona wartość
* @returns
*/
public getRandomInt(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/**
* Konwertuje przekazaną wartość do tekstu i dopełnia zerami z lewej strony
*
* @param value przekazana wartość liczbowa
* @param length długość tekstu z dopełnionymi zerami
* @returns
*/
public pad(value: number, length: number): string {
let text: string = value + "";
while (text.length < length) {
text = "0" + text;
}
return text;
}
}

View File

@@ -0,0 +1,22 @@
import { Clipboard } from '@angular/cdk/clipboard';
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
@Injectable({
providedIn: 'root'
})
export class ClipboardService {
constructor(private snackBar: MatSnackBar, private clipboard: Clipboard) { }
copyToClipboard(value: string): void {
if (value == '') {
return;
}
this.clipboard.copy(value);
this.snackBar.open("Skopiowano do schowka.", "", {
duration: 1000
});
}
}

View File

@@ -0,0 +1,71 @@
import { Injectable } from '@angular/core';
import { ValidationErrors } from '@angular/forms';
import { CommonService } from './common.service';
@Injectable({
providedIn: 'root'
})
export class IbanService {
private readonly bankSortCode: number = 13201784;
private readonly magic: number = 252100;
constructor(private common: CommonService) { }
public generateIban(): string {
const part1: string = this.common.pad(this.common.getRandomInt(1, 9999), 4);
const part2: string = this.common.pad(this.common.getRandomInt(1, 9999), 4);
const part3: string = this.common.pad(this.common.getRandomInt(1, 9999), 4);
const part4: string = this.common.pad(this.common.getRandomInt(1, 9999), 4);
const ibanWithoutControlDigit = this.bankSortCode + part1 + part2 + part3 + part4;
const controlDigit: string = this.calculateControlDigit(ibanWithoutControlDigit);
return controlDigit + ibanWithoutControlDigit;
}
public validateIban(iban: string): ValidationErrors | null {
const errors: ValidationErrors = {};
iban = iban.replace(/ /g, "");
if (/[a-zA-Z]{2}\d*/g.test(iban)) {
iban = iban.substr(2);
}
if (iban.length < 26) {
errors.tooShort = true;
}
if (iban.length > 26) {
errors.tooLong = true;
}
if (!CommonService.numericRegExp.test(iban)) {
errors.invalidPattern = true;
}
if (iban.length == 26 && !errors.invalidPattern && !this.validateIbanControlDigit(iban)) {
errors.invalidControlDigit = true;
}
return errors;
}
private validateIbanControlDigit(iban: string): boolean {
const controlDigit: string = iban.substring(0, 2);
const ibanWithoutControlDigit = iban.substring(2, 26);
const calculatedControlDigit: string = this.calculateControlDigit(ibanWithoutControlDigit);
return controlDigit == calculatedControlDigit;
}
private calculateControlDigit(value: string): string {
const ibanWithoutControlDigit = BigInt(value + this.magic);
const rest: bigint = ibanWithoutControlDigit % BigInt(97);
const controlDigit: number = 98 - Number(rest);
return this.common.pad(controlDigit, 2);
}
}

View File

@@ -0,0 +1,92 @@
import { Injectable } from '@angular/core';
import { ValidationErrors } from '@angular/forms';
import { CommonService } from './common.service';
@Injectable({
providedIn: 'root'
})
export class NipService {
// wagi kolejnych cyfr numeru NIP
private readonly nipWeights: Array<number> = [6, 5, 7, 2, 3, 4, 5, 6, 7];
private readonly officeCodes: number[] = [
107, 108, 109, 111, 112, 113, 114, 115, 116, 117, 118, 119, 121, 122, 123, 124, 125, 154, 156, 157, 158, 337, 338, 339, 341, 342, 355, 356, 375, 376, 377, 378,
379, 381, 389, 392, 393, 394, 416, 417, 496, 497, 509, 511, 512, 519, 521, 522, 523, 524, 525, 526, 527, 528, 529, 531, 532, 533, 534, 535, 536, 566, 567, 568,
569, 572, 601, 701, 757, 758, 759, 761, 762, 774, 776, 796, 797, 798, 799, 811, 812, 821, 822, 823, 826, 837, 838, 931, 932, 948, 951, 952, 965, 971, 978
];
constructor(private common: CommonService) { }
public generateNip(): string {
let nipWithoutControlDigit: string;
let controlDigit: number = 0;
do {
// losowanie pierwszych 9 cyfr
const officeCode: number = this.officeCodes[this.common.getRandomInt(0, this.officeCodes.length - 1)];
const rest: number = this.common.getRandomInt(0, 999999);
// wyliczenie cyfry kontrolnej
nipWithoutControlDigit = this.common.pad(officeCode, 3) + this.common.pad(rest, 6);
controlDigit = this.common.calculateControlDigit(nipWithoutControlDigit, this.nipWeights, this.lastStepFunction);
} while (controlDigit == 10);
// ostateczna konkatenacja
return nipWithoutControlDigit + controlDigit;
}
validateNip(nip: string): ValidationErrors | null {
const errors: ValidationErrors = {};
if (nip.length < 10) {
errors.tooShort = true;
}
if (nip.length > 10) {
errors.tooLong = true;
}
// czy wszystkie znaki są cyframi
if (!this.validateNipRegExp(nip)) {
errors.invalidPattern = true;
}
// czy kod placówki jest poprawny
if (nip.length >= 3 && !this.validateNipOfficeCode(nip)) {
errors.nipInvalidOfficeCode = true;
}
// czy cyfra kontrolna jest poprawna
if (nip.length == 10 && !errors.invalidPattern && !this.validateNipControlDigit(nip)) {
errors.invalidControlDigit = true;
}
return errors;
}
/**
* Walidacja numeru PESEL przy użyciu wyrażeń regularnych
* @param pesel
* @returns
*/
private validateNipRegExp(pesel: string): boolean {
return CommonService.numericRegExp.test(pesel);
}
/**
* Pelna walidacja numeru PESEL: regexpem i weryfikacja cyfry kontrolnej
* @returns
*/
private validateNipControlDigit(pesel: string): boolean {
return this.common.validateControlDigit(pesel, this.nipWeights, this.lastStepFunction);
}
private validateNipOfficeCode(pesel: string): boolean {
const officeCode : number = parseInt(pesel.substring(0, 3), 10);
return this.officeCodes.indexOf(officeCode) != -1;
}
private lastStepFunction(sum: number): number {
return sum % 11;
}
}

View File

@@ -0,0 +1,172 @@
import { Injectable } from '@angular/core';
import { CommonService } from './common.service';
import { endOfMonth } from 'date-fns'
import { ValidationErrors } from '@angular/forms';
import { concat } from 'rxjs';
@Injectable({
providedIn: 'any'
})
export class PeselService {
// wagi kolejnych cyfr numeru PESEL
private readonly peselWeights: number[] = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
private readonly maleDigits: number[] = [1, 3, 5, 7, 9];
private readonly femaleDigits: number[] = [0, 2, 4, 6, 8];
constructor(private common: CommonService) { }
public generatePesel(male: boolean, female: boolean): string {
// losowanie pierwszych 10 cyfr
const year: number = this.common.getRandomInt(0, 99);
const month: number = this.common.getRandomInt(1, 12);
const endDayOfMonth: number = endOfMonth(new Date(year, month - 1)).getDate();
const day: number = this.common.getRandomInt(1, endDayOfMonth);
const rest: number = this.common.getRandomInt(0, 999);
const sexDigits: number[] = [... male ? this.maleDigits : [], ...female ? this.femaleDigits : []];
const sexDigitIndex: number = this.common.getRandomInt(0, sexDigits.length - 1);
const sexDigit = sexDigits[sexDigitIndex];
// wyliczenie cyfry kontrolnej
const peselWithoutControlDigit: string = this.common.pad(year, 2) + this.common.pad(month, 2) + this.common.pad(day, 2) + this.common.pad(rest, 3) + this.common.pad(sexDigit, 1);
const controlDigit: number = this.common.calculateControlDigit(peselWithoutControlDigit, this.peselWeights, this.lastStepFunction);
// ostateczna konkatenacja
return peselWithoutControlDigit + controlDigit;
}
validatePesel(pesel: string): ValidationErrors | null {
const errors: ValidationErrors = {};
if (pesel.length < 11) {
errors.tooShort = true;
}
if (pesel.length > 11) {
errors.tooLong = true;
}
// czy wszystkie znaki są cyframi
if (!this.validatePeselRegExp(pesel)) {
errors.invalidPattern = true;
}
// czy miesiac jest poprawny
if (pesel.length >= 4 && !this.validatePeselMonth(pesel)) {
errors.peselInvalidBirthMonth = true;
}
// czy dzien jest poprawny
if (pesel.length >= 6 && !this.validatePeselDay(pesel)) {
errors.peselInvalidBirthDay = true;
}
// czy cyfra kontrolna jest poprawna
if (pesel.length == 11 && !errors.invalidPattern && !this.validatePeselControlDigit(pesel)) {
errors.invalidControlDigit = true;
}
return errors;
}
/**
* Walidacja numeru PESEL przy użyciu wyrażeń regularnych
* @param pesel
* @returns
*/
private validatePeselRegExp(pesel: string): boolean {
return CommonService.numericRegExp.test(pesel);
}
/**
* Pelna walidacja numeru PESEL: regexpem i weryfikacja cyfry kontrolnej
* @returns
*/
private validatePeselControlDigit(pesel: string): boolean {
return this.common.validateControlDigit(pesel, this.peselWeights, this.lastStepFunction);
}
/**
* Waliduje datę w numerze PESEL:
* 1800-1899 - miesiąc od 81
* 1900-1999 - miesiąc od 01
* 2000-2099 - miesiąc od 21
* 2100-2199 - miesiąc od 41
* 2200-2299 - miesiąc od 61
*
* @param pesel
* @returns
*/
private validatePeselMonth(pesel: string): boolean {
const month: number = parseInt(pesel.substring(2, 4), 10);
return month > 0 && month < 13 ||
month > 20 && month < 33 ||
month > 40 && month < 53 ||
month > 60 && month < 73 ||
month > 80 && month < 93;
}
private validatePeselDay(pesel: string): boolean {
// jesli nie mamy miesiaca to sprawdzamy twardy limit na 31
if (!this.validatePeselMonth(pesel)) {
const day: number = parseInt(pesel.substring(4, 6), 10);
return day <= 31;
}
const yearDiff: number = parseInt(pesel.substring(0, 2), 10);
const month: number = parseInt(pesel.substring(2, 4), 10);
const day: number = parseInt(pesel.substring(4, 6), 10);
const year: number = this.extractYearBasedOnMonth(month);
const endDayOfMonth: number = endOfMonth(new Date(year + yearDiff, month - 1)).getDate();
return day > 0 && day <= endDayOfMonth;
}
private extractDateFromPesel(pesel: string): Date | null {
const yearDiff: number = parseInt(pesel.substring(0, 2), 10);
const month: number = parseInt(pesel.substring(2, 4), 10);
const day: number = parseInt(pesel.substring(4, 6), 10);
let year: number = this.extractYearBasedOnMonth(month) + yearDiff;
const date: Date = new Date(year, month - 1, day)
if (date.getFullYear() == year && date.getMonth() + 1 == month && date.getDate() == day) {
return date;
} else {
return null;
}
}
private extractYearBasedOnMonth(month: number): number {
if (month < 20) {
return 1900;
} else if (month < 40) {
return 2000;
} else if (month < 60) {
return 2100;
} else if (month < 80) {
return 2200;
} else {
return 1800;
}
}
private lastStepFunction(sum: number): number {
sum = sum % 10;
if (sum == 0) {
sum = 10;
}
sum = 10 - sum;
return sum;
}
}

View File

@@ -0,0 +1,123 @@
import { Injectable } from '@angular/core';
import { ValidationErrors } from '@angular/forms';
import { CommonService } from './common.service';
@Injectable({
providedIn: 'root'
})
export class RegonService {
// wagi kolejnych cyfr numeru Regon/9
private static regon9Weights: number[] = [8, 9, 2, 3, 4, 5, 6, 7];
// wagi kolejnych cyfr numeru Regon/14
private static regon14Weights: number[] = [2, 4, 8, 5, 0, 9, 7, 3, 6, 1, 2, 4, 8];
// kody województw
private static provinceCodes: number[] = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51,
53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97];
constructor(private common: CommonService) { }
public generateRegon9(): string {
const provinceIndex: number = this.common.getRandomInt(0, RegonService.provinceCodes.length - 1);
const province: number = RegonService.provinceCodes[provinceIndex];
const rest: number = this.common.getRandomInt(0, 999999);
const regonWithoutControlDigit: string = this.common.pad(province, 2) + this.common.pad(rest, 6);
const controlDigit: number = this.common.calculateControlDigit(regonWithoutControlDigit, RegonService.regon9Weights, this.lastStepFunction);
return regonWithoutControlDigit + controlDigit;
}
public generateRegon14(): string {
const provinceIndex: number = this.common.getRandomInt(0, RegonService.provinceCodes.length - 1);
const province: number = RegonService.provinceCodes[provinceIndex];
const rest: number = this.common.getRandomInt(0, 999999);
const rest2: number = this.common.getRandomInt(0, 99999);
const regonWithoutControlDigit: string = this.common.pad(province, 2) + this.common.pad(rest, 6) + this.common.pad(rest2, 5);
const controlDigit: number = this.common.calculateControlDigit(regonWithoutControlDigit, RegonService.regon14Weights, this.lastStepFunction);
return regonWithoutControlDigit + controlDigit;
}
public validateRegon9(regon: string): ValidationErrors | null {
const errors: ValidationErrors = {};
if (regon.length < 9) {
errors.tooShort = true;
}
if (regon.length > 9) {
errors.tooLong = true;
}
// czy wszystkie znaki są cyframi
if (!this.validateRegonRegExp(regon)) {
errors.invalidPattern = true;
}
// czy kod placówki jest poprawny
if (regon.length >= 2 && !this.validateProvinceCode(regon)) {
errors.regonInvalidProvinceCode = true;
}
// czy cyfra kontrolna jest poprawna
if (regon.length == 9 && !errors.invalidPattern && !this.validateRegon9ControlDigit(regon)) {
errors.invalidControlDigit = true;
}
return errors;
}
public validateRegon14(regon: string): ValidationErrors | null {
const errors: ValidationErrors = {};
if (regon.length < 14) {
errors.tooShort = true;
}
if (regon.length > 14) {
errors.tooLong = true;
}
// czy wszystkie znaki są cyframi
if (!this.validateRegonRegExp(regon)) {
errors.invalidPattern = true;
}
// czy kod placówki jest poprawny
if (regon.length >= 2 && !this.validateProvinceCode(regon)) {
errors.regonInvalidProvinceCode = true;
}
// czy cyfra kontrolna jest poprawna
if (regon.length == 14 && !errors.invalidPattern && !this.validateRegon14ControlDigit(regon)) {
errors.invalidControlDigit = true;
}
return errors;
}
private validateRegon9ControlDigit(value: string): boolean {
return this.common.validateControlDigit(value, RegonService.regon9Weights, this.lastStepFunction);
}
private validateRegon14ControlDigit(value: string): boolean {
return this.common.validateControlDigit(value, RegonService.regon14Weights, this.lastStepFunction);
}
private validateProvinceCode(value: string): boolean {
const provinceCode: number = parseInt(value.substring(0, 2), 10);
return RegonService.provinceCodes.indexOf(provinceCode) != -1;
}
private validateRegonRegExp(regon: string): boolean {
return CommonService.numericRegExp.test(regon);
}
private lastStepFunction(sum: number): number {
const modulo = sum % 11;
return modulo == 10 ? 0 : modulo;
}
}

32
src/app/translate-pipe.ts Normal file
View File

@@ -0,0 +1,32 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'translate' })
export class TranslatePipe implements PipeTransform {
private readonly translations: Map<string, string> = new Map([
// wspólne
["tooLong", "Numer jest zbyt długi."],
["tooShort", "Numer jest zbyt krótki."],
["invalidPattern", "Wprowadzono znak niebędący cyfrą."],
["invalidControlDigit", "Cyfra kontrolna jest niepoprawna."],
// PESEL
["peselInvalidBirthMonth", "Miesiąc w dacie urodzenia jest niepoprawny."],
["peselInvalidBirthDay", "Dzień w dacie urodzenia jest niepoprawny."],
// NIP
["nipInvalidOfficeCode", "Kod urzędu skarbowego jest niepoprawny."],
// REGON
["regonInvalidProvinceCode", "Kod województwa jest nieprawidłowy."]
]);
transform(code: string): string {
const translated: string | undefined = this.translations.get(code);
if (translated === undefined) {
return 'Translation undefined for code: ' + code;
}
return translated;
}
}

0
src/assets/.gitkeep Normal file
View File

Binary file not shown.

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 6v1.79c0 .45.54.67.85.35l2.79-2.79c.2-.2.2-.51 0-.71l-2.79-2.79c-.31-.31-.85-.09-.85.36V4c-4.42 0-8 3.58-8 8 0 1.04.2 2.04.57 2.95.27.67 1.13.85 1.64.34.27-.27.38-.68.23-1.04C6.15 13.56 6 12.79 6 12c0-3.31 2.69-6 6-6zm5.79 2.71c-.27.27-.38.69-.23 1.04.28.7.44 1.46.44 2.25 0 3.31-2.69 6-6 6v-1.79c0-.45-.54-.67-.85-.35l-2.79 2.79c-.2.2-.2.51 0 .71l2.79 2.79c.31.31.85.09.85-.35V20c4.42 0 8-3.58 8-8 0-1.04-.2-2.04-.57-2.95-.27-.67-1.13-.85-1.64-.34z"/></svg>

After

Width:  |  Height:  |  Size: 612 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M18.65 8.35l-2.79 2.79c-.32.32-.1.86.35.86H18c0 3.31-2.69 6-6 6-.79 0-1.56-.15-2.25-.44-.36-.15-.77-.04-1.04.23-.51.51-.33 1.37.34 1.64.91.37 1.91.57 2.95.57 4.42 0 8-3.58 8-8h1.79c.45 0 .67-.54.35-.85l-2.79-2.79c-.19-.2-.51-.2-.7-.01zM6 12c0-3.31 2.69-6 6-6 .79 0 1.56.15 2.25.44.36.15.77.04 1.04-.23.51-.51.33-1.37-.34-1.64C14.04 4.2 13.04 4 12 4c-4.42 0-8 3.58-8 8H2.21c-.45 0-.67.54-.35.85l2.79 2.79c.2.2.51.2.71 0l2.79-2.79c.31-.31.09-.85-.36-.85H6z"/></svg>

After

Width:  |  Height:  |  Size: 613 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 23.59v-3.6c-5.01-.26-9-4.42-9-9.49C2 5.26 6.26 1 11.5 1S21 5.26 21 10.5c0 4.95-3.44 9.93-8.57 12.4l-1.43.69zM11.5 3C7.36 3 4 6.36 4 10.5S7.36 18 11.5 18H13v2.3c3.64-2.3 6-6.08 6-9.8C19 6.36 15.64 3 11.5 3zm-1 11.5h2v2h-2zm2-1.5h-2c0-3.25 3-3 3-5 0-1.1-.9-2-2-2s-2 .9-2 2h-2c0-2.21 1.79-4 4-4s4 1.79 4 4c0 2.5-3 2.75-3 5z"/></svg>

After

Width:  |  Height:  |  Size: 483 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M15,20H5V7c0-0.55-0.45-1-1-1h0C3.45,6,3,6.45,3,7v13c0,1.1,0.9,2,2,2h10c0.55,0,1-0.45,1-1v0C16,20.45,15.55,20,15,20z M20,16V4c0-1.1-0.9-2-2-2H9C7.9,2,7,2.9,7,4v12c0,1.1,0.9,2,2,2h9C19.1,18,20,17.1,20,16z M18,16H9V4h9V16z"/></g></svg>

After

Width:  |  Height:  |  Size: 429 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><rect fill="none" height="24" width="24"/><path d="M18,2H9C7.9,2,7,2.9,7,4v12c0,1.1,0.9,2,2,2h9c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M18,16H9V4h9V16z M3,15v-2h2v2H3z M3,9.5h2v2H3V9.5z M10,20h2v2h-2V20z M3,18.5v-2h2v2H3z M5,22c-1.1,0-2-0.9-2-2h2V22z M8.5,22h-2v-2h2V22z M13.5,22L13.5,22l0-2h2 v0C15.5,21.1,14.6,22,13.5,22z M5,6L5,6l0,2H3v0C3,6.9,3.9,6,5,6z"/></svg>

After

Width:  |  Height:  |  Size: 501 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><rect fill="none" height="24" width="24"/><path d="M17.5,9.5C17.5,6.46,15.04,4,12,4S6.5,6.46,6.5,9.5c0,2.7,1.94,4.93,4.5,5.4V17H9v2h2v2h2v-2h2v-2h-2v-2.1 C15.56,14.43,17.5,12.2,17.5,9.5z M8.5,9.5C8.5,7.57,10.07,6,12,6s3.5,1.57,3.5,3.5S13.93,13,12,13S8.5,11.43,8.5,9.5z"/></svg>

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M2 5c-.55 0-1 .45-1 1v15c0 1.1.9 2 2 2h15c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1-.45-1-1V6c0-.55-.45-1-1-1zm19-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm-1 16H8c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1z"/></svg>

After

Width:  |  Height:  |  Size: 422 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M2,20h20v4H2V20z M5.49,17h2.42l1.27-3.58h5.65L16.09,17h2.42L13.25,3h-2.5L5.49,17z M9.91,11.39l2.03-5.79h0.12l2.03,5.79 H9.91z"/></g></svg>

After

Width:  |  Height:  |  Size: 335 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/><path d="M13.25,16.74c0,0.69-0.53,1.26-1.25,1.26c-0.7,0-1.26-0.56-1.26-1.26c0-0.71,0.56-1.25,1.26-1.25 C12.71,15.49,13.25,16.04,13.25,16.74z M11.99,6c-1.77,0-2.98,1.15-3.43,2.49l1.64,0.69c0.22-0.67,0.74-1.48,1.8-1.48 c1.62,0,1.94,1.52,1.37,2.33c-0.54,0.77-1.47,1.29-1.96,2.16c-0.39,0.69-0.31,1.49-0.31,1.98h1.82c0-0.93,0.07-1.12,0.22-1.41 c0.39-0.72,1.11-1.06,1.87-2.17c0.68-1,0.42-2.36-0.02-3.08C14.48,6.67,13.47,6,11.99,6z M19,5H5v14h14V5 M19,3c1.1,0,2,0.9,2,2v14 c0,1.1-0.9,2-2,2H5c-1.1,0-2-0.9-2-2V5c0-1.1,0.9-2,2-2H19L19,3z"/></g></svg>

After

Width:  |  Height:  |  Size: 722 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-4h2v2h-2zm1.61-9.96c-2.06-.3-3.88.97-4.43 2.79-.18.58.26 1.17.87 1.17h.2c.41 0 .74-.29.88-.67.32-.89 1.27-1.5 2.3-1.28.95.2 1.65 1.13 1.57 2.1-.1 1.34-1.62 1.63-2.45 2.88 0 .01-.01.01-.01.02-.01.02-.02.03-.03.05-.09.15-.18.32-.25.5-.01.03-.03.05-.04.08-.01.02-.01.04-.02.07-.12.34-.2.75-.2 1.25h2c0-.42.11-.77.28-1.07.02-.03.03-.06.05-.09.08-.14.18-.27.28-.39.01-.01.02-.03.03-.04.1-.12.21-.23.33-.34.96-.91 2.26-1.65 1.99-3.56-.24-1.74-1.61-3.21-3.35-3.47z"/></svg>

After

Width:  |  Height:  |  Size: 744 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g fill="none"><path d="M0 0h24v24H0V0z"/><path d="M0 0h24v24H0V0z" opacity=".87"/></g><path d="M21 3.01H3c-1.1 0-2 .9-2 2V8c0 .55.45 1 1 1s1-.45 1-1V5.99c0-.55.45-1 1-1h16c.55 0 1 .45 1 1v12.03c0 .55-.45 1-1 1H4c-.55 0-1-.45-1-1V16c0-.55-.45-1-1-1s-1 .45-1 1v3.01c0 1.09.89 1.98 1.98 1.98H21c1.1 0 2-.9 2-2V5.01c0-1.1-.9-2-2-2zm-9.15 12.14l2.79-2.79c.2-.2.2-.51 0-.71l-2.79-2.79c-.31-.32-.85-.1-.85.35V11H2c-.55 0-1 .45-1 1s.45 1 1 1h9v1.79c0 .45.54.67.85.36z"/></svg>

After

Width:  |  Height:  |  Size: 571 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><rect fill="none" height="24" width="24"/><path d="M9.5,11c1.93,0,3.5,1.57,3.5,3.5S11.43,18,9.5,18S6,16.43,6,14.5S7.57,11,9.5,11z M9.5,9C6.46,9,4,11.46,4,14.5 S6.46,20,9.5,20s5.5-2.46,5.5-5.5c0-1.16-0.36-2.23-0.97-3.12L18,7.42V10h2V4h-6v2h2.58l-3.97,3.97C11.73,9.36,10.66,9,9.5,9z"/></svg>

After

Width:  |  Height:  |  Size: 425 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17.65 6.35c-1.63-1.63-3.94-2.57-6.48-2.31-3.67.37-6.69 3.35-7.1 7.02C3.52 15.91 7.27 20 12 20c3.19 0 5.93-1.87 7.21-4.56.32-.67-.16-1.44-.9-1.44-.37 0-.72.2-.88.53-1.13 2.43-3.84 3.97-6.8 3.31-2.22-.49-4.01-2.3-4.48-4.52C5.31 9.44 8.26 6 12 6c1.66 0 3.14.69 4.22 1.78l-1.51 1.51c-.63.63-.19 1.71.7 1.71H19c.55 0 1-.45 1-1V6.41c0-.89-1.08-1.34-1.71-.71l-.64.65z"/></svg>

After

Width:  |  Height:  |  Size: 520 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17.59 3.59c-.38-.38-.89-.59-1.42-.59H5c-1.11 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7.83c0-.53-.21-1.04-.59-1.41l-2.82-2.83zM12 19c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm1-10H7c-1.1 0-2-.9-2-2s.9-2 2-2h6c1.1 0 2 .9 2 2s-.9 2-2 2z"/></svg>

After

Width:  |  Height:  |  Size: 410 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M18 9v4H6V9H4v6h16V9h-2z"/></svg>

After

Width:  |  Height:  |  Size: 183 B

View File

@@ -0,0 +1,3 @@
export const environment = {
production: true
};

View File

@@ -0,0 +1,16 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false
};
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.

BIN
src/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

16
src/index.html Normal file
View File

@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Generator i walidator identyfikatorów</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<app-root></app-root>
</body>
</html>

12
src/main.ts Normal file
View File

@@ -0,0 +1,12 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));

69
src/polyfills.ts Normal file
View File

@@ -0,0 +1,69 @@
/***************************************************************************************************
* Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
*/
import '@angular/localize/init';
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/**
* IE11 requires the following for NgClass support on SVG elements
*/
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// 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
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (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__UNPATCHED_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'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/

194
src/styles.css Normal file
View File

@@ -0,0 +1,194 @@
@font-face {
font-family: 'Comfortaa';
src: url("assets/Comfortaa-VariableFont_wght.ttf");
}
body {
padding: 0;
margin: 0;
text-decoration: none;
border: none;
font-size: 150%;
font-family: 'Comfortaa', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.gradient {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
background-image: -webkit-gradient(linear, left top, left bottom, from(#3362bc), color-stop(#3d6cc7), color-stop(#4776d1), color-stop(#5181dc), color-stop(#5a8be7), color-stop(#5a8be7), color-stop(#5b8ae7), color-stop(#5b8ae7), color-stop(#527fdc), color-stop(#4975d1), color-stop(#406ac7), to(#3760bc));
background-image: linear-gradient(to bottom, #3362bc, #3d6cc7, #4776d1, #5181dc, #5a8be7, #5a8be7, #5b8ae7, #5b8ae7, #527fdc, #4975d1, #406ac7, #3760bc);
}
.generators {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
-ms-flex-negative: 1;
flex-shrink: 1;
-webkit-box-pack: space-evenly;
-ms-flex-pack: space-evenly;
justify-content: space-evenly;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.generator {
margin: 1em;
background: rgba(255, 255, 255, 0.15);
-webkit-box-shadow: 0 8px 32px 0 rgba(0, 38, 135, 0.37);
box-shadow: 0 8px 32px 0 rgba(0, 38, 135, 0.37);
border-radius: 3px;
border: 1px solid rgba(255, 255, 255, 0.18);
}
.container {
margin: 0 1em 1em 1em;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
place-content: space-between;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.container .buttons {
margin-top: 1em;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
place-content: space-between;
margin-left: auto;
}
.container .buttons img {
padding: .2em;
width: 25px;
height: 25px;
}
.container .buttons img:hover {
background: rgba(0, 0, 0, 0.3);
}
.container .buttons :nth-child(1) {
margin: auto 0 auto 1em;
}
.container .buttons :nth-child(2) {
margin: auto 1em;
}
.title {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
margin: 0;
padding: 0;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border-bottom: 1px solid rgba(255, 255, 255, 0.7);
background: rgba(255, 255, 255, 0.2);
}
.title span {
margin-left: 1em;
padding: 0.4em 0;
color: white;
text-align: center;
font-weight: bold;
letter-spacing: 2px;
}
.title .titleButtons {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-ms-flex-pack: distribute;
justify-content: space-around;
-ms-flex-line-pack: center;
align-content: center;
margin: 0 1em;
padding: 0;
}
.title .titleButtons img {
padding: .1em;
width: 25px;
height: 25px;
}
.title .titleButtons img:hover {
background: rgba(0, 0, 0, 0.3);
}
.title .titleButtons .smaller {
padding: 0.2em;
width: 20px;
height: 20px;
}
input[type="text"] {
margin-top: 1em;
width: 210px;
min-width: 0px;
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
-ms-flex-negative: 1;
flex-shrink: 1;
padding: 0 0.7em;
letter-spacing: 1px;
font-size: 1em;
height: 2em;
color: white;
background: rgba(255, 255, 255, 0.15);
-webkit-box-shadow: 0 8px 32px 0 rgba(0, 38, 135, 0.37);
box-shadow: 0 8px 32px 0 rgba(0, 38, 135, 0.37);
border-radius: 3px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
input[type="text"].ng-valid {
border-bottom: 3px solid #87e17a;
}
input[type="text"].ng-invalid {
border-bottom: 3px solid #fb8686;
}
img {
cursor: pointer;
-webkit-filter: invert(100%);
filter: invert(100%);
margin: auto 0;
background: rgba(0, 0, 0, 0.15);
-webkit-box-shadow: 0 8px 32px 0 rgba(255, 217, 120, 0.37);
box-shadow: 0 8px 32px 0 rgba(255, 217, 120, 0.37);
border-radius: 3px;
border: 1px solid rgba(0, 0, 0, 0.1);
}
/*# sourceMappingURL=styles.css.map */

9
src/styles.css.map Normal file
View File

@@ -0,0 +1,9 @@
{
"version": 3,
"mappings": "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",
"sources": [
"styles.scss"
],
"names": [],
"file": "styles.css"
}

159
src/styles.scss Normal file
View File

@@ -0,0 +1,159 @@
@font-face {
font-family: 'Comfortaa';
src: url('assets/Comfortaa-VariableFont_wght.ttf');
}
body {
padding: 0;
margin: 0;
text-decoration: none;
border: none;
font-size: 150%;
font-family: 'Comfortaa', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.gradient {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
background-image: linear-gradient(to bottom, #3362bc, #3d6cc7, #4776d1, #5181dc, #5a8be7, #5a8be7, #5b8ae7, #5b8ae7, #527fdc, #4975d1, #406ac7, #3760bc);
}
.generators {
display: flex;
flex-direction: row;
flex-grow: 1;
flex-shrink: 1;
justify-content: space-evenly;
flex-wrap: wrap;
}
.generator {
margin: 1em;
background: rgba( 255, 255, 255, 0.15 );
box-shadow: 0 8px 32px 0 rgba( 0, 38, 135, 0.37 );
border-radius: 3px;
border: 1px solid rgba( 255, 255, 255, 0.18 );
}
.container {
margin: 0 1em 1em 1em;
display: flex;
place-content: space-between;
flex-wrap: wrap;
.buttons {
margin-top: 1em;
display: flex;
flex-wrap: nowrap;
place-content: space-between;
margin-left: auto;
img {
padding: .2em;
width: 25px;
height: 25px;
&:hover {
background: rgba( 0, 0, 0, 0.30 );
}
}
:nth-child(1) {
margin: auto 0 auto 1em;
}
:nth-child(2) {
margin: auto 1em;
}
}
}
.title {
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 0;
padding: 0;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border-bottom: 1px solid rgba(255, 255, 255, 0.7);
background: rgba(255, 255, 255, 0.20);
span {
margin-left: 1em;
padding: 0.4em 0;
color: white;
text-align: center;
font-weight: bold;
letter-spacing: 2px;
}
.titleButtons {
display: flex;
flex-direction: row;
justify-content: space-around;
align-content: center;
margin: 0 1em;
padding: 0;
img {
padding: .1em;
width: 25px;
height: 25px;
&:hover {
background: rgba( 0, 0, 0, 0.30 );
}
}
.smaller {
padding: 0.2em;
width: 20px;
height: 20px;
}
}
}
input[type="text"] {
margin-top: 1em;
width: 210px;
min-width: 0px;
flex-grow: 1;
flex-shrink: 1;
padding: 0 0.7em;
letter-spacing: 1px;
font-size: 1em;
height: 2em;
color: white;
background: rgba(255, 255, 255, 0.15);
box-shadow: 0 8px 32px 0 rgba( 0, 38, 135, 0.37 );
border-radius: 3px;
border: 1px solid rgba( 255, 255, 255, 0.20 );
&.ng-valid {
border-bottom: 3px solid #87e17a
}
&.ng-invalid {
border-bottom: 3px solid #fb8686;
}
}
img {
cursor: pointer;
filter: invert(100%);
margin: auto 0;
background: rgba( 0, 0, 0, 0.15 );
box-shadow: 0 8px 32px 0 rgba(255, 217, 120, 0.37);
border-radius: 3px;
border: 1px solid rgba(0, 0, 0, 0.10);
}

27
src/test.ts Normal file
View File

@@ -0,0 +1,27 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
{ teardown: { destroyAfterEach: true }},
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

15
tsconfig.app.json Normal file
View File

@@ -0,0 +1,15 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.d.ts"
]
}

30
tsconfig.json Normal file
View File

@@ -0,0 +1,30 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2020",
"module": "es2020",
"lib": [
"es2020",
"dom"
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}

18
tsconfig.spec.json Normal file
View File

@@ -0,0 +1,18 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"files": [
"src/test.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}