removing friendly pages
This commit is contained in:
parent
797863008d
commit
444ee0481d
|
|
@ -0,0 +1 @@
|
|||
python3 compress-with-structure.py
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import os
|
||||
from PIL import Image, UnidentifiedImageError
|
||||
from shutil import copy2
|
||||
|
||||
# Ścieżki katalogów
|
||||
input_folder = "src/main/resources/static/zaklik-public-images" # Folder źródłowy
|
||||
output_folder = "src/main/resources/static/zaklik-public-images" # Folder docelowy
|
||||
|
||||
# Funkcja kompresująca obrazy
|
||||
def compress_image(input_path, output_path):
|
||||
try:
|
||||
with Image.open(input_path) as img:
|
||||
img_format = img.format # Zachowaj format pliku
|
||||
if img_format in ["JPEG", "PNG"]:
|
||||
img.save(output_path, optimize=True, quality=15)
|
||||
else:
|
||||
copy2(input_path, output_path) # Kopiuj bez zmian, jeśli format nie jest obsługiwany
|
||||
except UnidentifiedImageError:
|
||||
print(f"Nie rozpoznano formatu obrazu: {input_path}")
|
||||
|
||||
# Funkcja do przetwarzania plików w folderze
|
||||
def process_folder(input_folder, output_folder):
|
||||
for root, _, files in os.walk(input_folder):
|
||||
for file in files:
|
||||
# Ścieżka do pliku wejściowego
|
||||
input_path = os.path.join(root, file)
|
||||
|
||||
# Tworzenie ścieżki docelowej z odpowiednią strukturą katalogów
|
||||
relative_path = os.path.relpath(root, input_folder)
|
||||
target_dir = os.path.join(output_folder, relative_path)
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
|
||||
# Obsługa plików już skompresowanych
|
||||
if "(compressed)" in file:
|
||||
continue
|
||||
if "properties" in file:
|
||||
continue
|
||||
# Generowanie nazwy pliku wyjściowego
|
||||
name, ext = os.path.splitext(file)
|
||||
output_file = f"{name}(compressed){ext}"
|
||||
output_path = os.path.join(target_dir, output_file)
|
||||
# Sprawdzenie, czy skompresowany plik już istnieje
|
||||
if os.path.exists(output_path):
|
||||
print(f"Pominięto, plik już istnieje: {output_path}")
|
||||
continue
|
||||
# Kompresja pliku
|
||||
print(f"Kompresowanie: {input_path} -> {output_path}")
|
||||
compress_image(input_path, output_path)
|
||||
|
||||
# Wykonanie skryptu
|
||||
process_folder(input_folder, output_folder)
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
INPUT_DIR="./src/main/resources/static/zaklik-public-images" # Folder z oryginalnymi obrazami
|
||||
OUTPUT_DIR="./src/main/resources/static/zaklik-public-images-generated" # Główny folder do zapisu obrazów w nowych formatach
|
||||
|
||||
# Iteracja po wszystkich plikach w katalogu wejściowym i jego podkatalogach
|
||||
find "$INPUT_DIR" -type f | while read -r file; do
|
||||
# Relatywna ścieżka pliku w katalogu wejściowym
|
||||
relative_path="${file#$INPUT_DIR/}"
|
||||
|
||||
# Ścieżka do katalogu docelowego
|
||||
target_dir="$OUTPUT_DIR/$(dirname "$relative_path")"
|
||||
|
||||
# Nazwa pliku bez rozszerzenia
|
||||
filename=$(basename "$file" | cut -f 1 -d '.')
|
||||
|
||||
# Ścieżki docelowych plików w formatach WebP i AVIF
|
||||
webp_file="$target_dir/$filename.webp"
|
||||
avif_file="$target_dir/$filename.avif"
|
||||
|
||||
# Sprawdzenie, czy oba pliki już istnieją
|
||||
if [ -f "$webp_file" ] && [ -f "$avif_file" ]; then
|
||||
echo "Pomijam plik: $file (już skompresowany)"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Tworzenie podkatalogu w katalogu docelowym
|
||||
mkdir -p "$target_dir"
|
||||
|
||||
# Konwersja do WebP (jeśli plik nie istnieje)
|
||||
if [ ! -f "$webp_file" ]; then
|
||||
convert "$file" -quality 80 "$webp_file"
|
||||
echo "Skompresowano do WebP: $webp_file"
|
||||
fi
|
||||
|
||||
# Konwersja do AVIF (jeśli plik nie istnieje)
|
||||
if [ ! -f "$avif_file" ]; then
|
||||
convert "$file" -quality 80 "$avif_file"
|
||||
echo "Skompresowano do AVIF: $avif_file"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Konwersja zakończona."
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
const sharp = require('sharp');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const inputDir = './src/main/resources/static/zaklik-public-images'; // Folder z oryginalnymi obrazami
|
||||
const outputDir = './src/main/resources/static/main-images/optimized-by-sharp'; // Folder do zapisu obrazów w nowych formatach
|
||||
|
||||
const formats = ['webp', 'avif'];
|
||||
|
||||
fs.readdir(inputDir, (err, files) => {
|
||||
if (err) {
|
||||
console.error('Error reading input directory:', err);
|
||||
return;
|
||||
}
|
||||
|
||||
files.forEach(file => {
|
||||
const inputFile = path.join(inputDir, file);
|
||||
const fileName = path.parse(file).name;
|
||||
|
||||
formats.forEach(format => {
|
||||
const outputFile = path.join(outputDir, `${fileName}.${format}`);
|
||||
sharp(inputFile)
|
||||
.toFormat(format, { quality: 80 })
|
||||
.toFile(outputFile, (err, info) => {
|
||||
if (err) {
|
||||
console.error(`Error converting ${file} to ${format}:`, err);
|
||||
} else {
|
||||
console.log(`Converted ${file} to ${format} format.`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
"@ngx-translate/core": "^16.0.3",
|
||||
"@ngx-translate/http-loader": "^16.0.0",
|
||||
"bootstrap": "^5.3.3",
|
||||
"date-fns": "^4.1.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.14.10"
|
||||
|
|
@ -9423,6 +9424,15 @@
|
|||
"integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/date-format": {
|
||||
"version": "4.0.14",
|
||||
"resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
"@ngx-translate/core": "^16.0.3",
|
||||
"@ngx-translate/http-loader": "^16.0.0",
|
||||
"bootstrap": "^5.3.3",
|
||||
"date-fns": "^4.1.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.14.10"
|
||||
|
|
@ -47,4 +48,4 @@
|
|||
"typescript-eslint": "8.10.0",
|
||||
"vite": "^5.4.10"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,19 +8,19 @@
|
|||
<h5 class="card-title">Wrocław</h5>
|
||||
<div class="col-auto">
|
||||
<a href="mailto:kusartur@gmail.com">
|
||||
<img width="30" height="20" src="icons/envelope.svg" />
|
||||
<img width="30" height="20" src="icons/envelope.svg" alt="envelope" >
|
||||
kusartur@gmail.com
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<a href="tel:+48512558222"> <img width="30" height="20"
|
||||
src="icons/telephone.svg" /> +48 511 116 016</a>
|
||||
<a href="tel:+48511116016"> <img width="30" height="20"
|
||||
src="icons/telephone.svg" alt="telephone" > +48 511 116 016</a>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<a href="https://www.linkedin.com/in/artur-ku%C5%9B-99a7b02/"> <img
|
||||
width="30" height="20" src="icons/linkedin.svg" />Linkedin
|
||||
width="30" height="20" src="icons/linkedin.svg" alt="linkedin" >Linkedin
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@
|
|||
<a class="navbar-brand" [routerLink]="'/about-me'">{{ 'topBar.aboutMe' | translate }}</a>
|
||||
<a class="navbar-brand" [routerLink]="'/asset-calculator'">{{ 'topBar.depreciationCalculator' | translate }}</a>
|
||||
<a class="navbar-brand" [routerLink]="'/quotes'">{{ 'topBar.courses' | translate }}</a>
|
||||
<a class="navbar-brand" [routerLink]="'/friendly-pages'">{{ 'topBar.friendlyPages' | translate }}</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,11 +36,6 @@ export const routes: Routes = [
|
|||
path: "fixed-asset",
|
||||
title:"Środki trwałe",
|
||||
component: FixedAssetComponent
|
||||
},
|
||||
{
|
||||
path: "friendly-pages",
|
||||
title:"Zaprzyjaznione strony",
|
||||
component: FriendlyPagesComponent
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
.month-picker .mat-calendar-body-cell-content {
|
||||
display: none; /* Ukrywa dni */
|
||||
}
|
||||
.month-picker .mat-calendar-body-cell-content:not(.mat-calendar-body-disabled) {
|
||||
display: flex;
|
||||
}
|
||||
|
|
@ -44,12 +44,18 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group row align-items-center ">
|
||||
|
||||
<div class="col-5 col-lg-6 text-start ">
|
||||
<label class="form-label" for="startDepreciation" >{{ 'asset-calculator.startOfDepreciation' | translate }} </label>
|
||||
</div>
|
||||
|
||||
<div class="col-7 col-lg-6">
|
||||
<input type="month" lang="pl" class="form-control" [(ngModel)]="startDepreciation" id="startDepreciation" placeholder="2024" />
|
||||
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>{{ 'asset-calculator.startOfDepreciation' | translate }}</mat-label>
|
||||
<input matInput [(ngModel)]="startDepreciation" [matDatepicker]="picker" readonly>
|
||||
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker startView="multi-year" (monthSelected)="onMonthSelected($event, picker)" panelClass="month-picker"></mat-datepicker>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,11 +4,16 @@ import { Asset, AssetPlanPosition, TypeDepreciation, YearMonth, AssetLifeChange,
|
|||
import { AssetService } from '../assets/service/asset.service';
|
||||
import { TranslateModule, TranslateService } from "@ngx-translate/core";
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatDatepicker, MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { format, parse, addMonths, isAfter } from 'date-fns';
|
||||
|
||||
|
||||
interface FormValues {
|
||||
initialValueAsset:number;
|
||||
rate: number;
|
||||
startDepreciation: string;
|
||||
startDepreciation: Date;
|
||||
typeDepreciation: TypeDepreciation;
|
||||
factor: number;
|
||||
}
|
||||
|
|
@ -17,7 +22,6 @@ class AssetLifeChangeWrapper{
|
|||
when = signal<string> ( YearMonth.todayTxt());
|
||||
initial = signal<number>( 0 );
|
||||
|
||||
|
||||
constructor( assetLifeChange : AssetLifeChange ){
|
||||
this.set(assetLifeChange);
|
||||
}
|
||||
|
|
@ -38,7 +42,11 @@ const NAME_IN_STORAGE = 'assetForCalculator';
|
|||
@Component({
|
||||
selector: 'app-asset-calculator',
|
||||
standalone: true,
|
||||
imports: [DecimalPipe, TranslateModule, FormsModule],
|
||||
imports: [DecimalPipe, TranslateModule, FormsModule, MatDatepickerModule, MatNativeDateModule, MatInputModule],
|
||||
providers: [
|
||||
MatDatepickerModule,
|
||||
MatNativeDateModule
|
||||
],
|
||||
templateUrl: "asset-calculator.component.html",
|
||||
styleUrls: ['asset-calculator.component.css']
|
||||
})
|
||||
|
|
@ -50,7 +58,7 @@ export class AssetCalculatorComponent {
|
|||
|
||||
initialValueAsset = signal <number> ( 6000 );
|
||||
rate = signal <number> ( 20 );
|
||||
startDepreciation = signal <string> ( YearMonth.today().toString() );
|
||||
startDepreciation = signal <Date> ( new Date() );
|
||||
typeDepreciation = signal <TypeDepreciation>( TypeDepreciation.linear );
|
||||
factor = signal <number>( 2 );
|
||||
|
||||
|
|
@ -74,6 +82,8 @@ export class AssetCalculatorComponent {
|
|||
effect( () => this.reCalculate( ) )
|
||||
|
||||
}
|
||||
|
||||
|
||||
private storage = {
|
||||
load: (key: string) => {
|
||||
try {
|
||||
|
|
@ -97,7 +107,6 @@ export class AssetCalculatorComponent {
|
|||
this.restoreState();
|
||||
}
|
||||
|
||||
|
||||
ngOnDestroy(): void {
|
||||
const asset = this.controlsToAsset( );
|
||||
if( null != asset){
|
||||
|
|
@ -114,7 +123,6 @@ export class AssetCalculatorComponent {
|
|||
this.storage.save(NAME_IN_STORAGE, asset);
|
||||
}
|
||||
|
||||
|
||||
private assetToControls( asset : Asset ) {
|
||||
if( asset.life.length > 0 ){
|
||||
this.updateBatch(asset);
|
||||
|
|
@ -126,7 +134,7 @@ private updateBatch(asset: Asset) {
|
|||
const method0 = asset.depreciationMethods[0];
|
||||
|
||||
this.initialValueAsset.set(firstLife.initial);
|
||||
this.startDepreciation.set(YearMonth.toTxt(firstLife.when));
|
||||
this.startDepreciation.set(YearMonth.toDate(firstLife.when));
|
||||
this.rate.set(method0.rate);
|
||||
this.typeDepreciation.set(method0.type);
|
||||
this.factor.set(method0.factor);
|
||||
|
|
@ -137,13 +145,12 @@ private updateBatch(asset: Asset) {
|
|||
this.lifeChangesSignal.set(lifeChanges);
|
||||
}
|
||||
|
||||
|
||||
private controlsToAsset(): Asset {
|
||||
|
||||
const formValues = this.formValues();
|
||||
const lifeChanges = this.lifeChangesSignal();
|
||||
|
||||
const when = YearMonth.from( formValues.startDepreciation );
|
||||
const when = YearMonth.fromDate( formValues.startDepreciation );
|
||||
const asset = new Asset( when );
|
||||
|
||||
const method = new AssetDepreciationMethod( when.year, formValues.rate, formValues.typeDepreciation, formValues.factor );
|
||||
|
|
@ -200,7 +207,7 @@ private controlsToAsset(): Asset {
|
|||
// Method to add a life change
|
||||
addLifeChange( ) {
|
||||
const assetLifeChange2 : AssetLifeChange
|
||||
= new AssetLifeChange( YearMonth.from( this.formValues().startDepreciation ), 1000, 0, 0 );
|
||||
= new AssetLifeChange( YearMonth.fromDate( this.formValues().startDepreciation ), 1000, 0, 0 );
|
||||
return this.addLifeChange2( assetLifeChange2 );
|
||||
|
||||
}
|
||||
|
|
@ -218,6 +225,15 @@ private controlsToAsset(): Asset {
|
|||
);
|
||||
}
|
||||
|
||||
updateDateFromInput(inputValue: string) {
|
||||
// Konwersja stringa 'YYYY-MM' na Date
|
||||
const parsedDate = parse(inputValue, 'yyyy-MM', new Date());
|
||||
this.startDepreciation.set(parsedDate);
|
||||
}
|
||||
onMonthSelected(event: Date, datepicker: MatDatepicker<Date>) {
|
||||
this.startDepreciation.set(event); // Aktualizacja pola w formularzu
|
||||
datepicker.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,14 +10,22 @@ export class YearMonth{
|
|||
return new YearMonth( year, month );
|
||||
}
|
||||
|
||||
static fromDate( date: Date) {
|
||||
|
||||
return new YearMonth( date.getFullYear(), date.getMonth()+1 );
|
||||
}
|
||||
|
||||
readonly year : number ;
|
||||
readonly month : number ;
|
||||
|
||||
constructor( year:number, month : number ){
|
||||
this.year = year;
|
||||
this.month = month;
|
||||
}
|
||||
}
|
||||
|
||||
toDate(){
|
||||
return new Date(this.year, this.month-1, 1);
|
||||
}
|
||||
|
||||
static today( ):YearMonth{
|
||||
const today = new Date();
|
||||
|
|
@ -31,6 +39,9 @@ export class YearMonth{
|
|||
static toTxt( ym : YearMonth ):string{
|
||||
return ym.year + '-' + String(ym.month).padStart(2, '0');;
|
||||
}
|
||||
static toDate( ym : YearMonth) : Date{
|
||||
return new Date(ym.year, ym.month-1, 1);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return { year: this.year, month: this.month };
|
||||
|
|
|
|||
Loading…
Reference in New Issue