mirror of
https://github.com/Mueller-Patrick/Betterzon.git
synced 2024-12-23 12:15:11 +00:00
Merge remote-tracking branch 'origin/develop' into BETTERZON-31
# Conflicts: # Frontend/src/app/app.module.ts
This commit is contained in:
commit
64074b48e8
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -26,6 +26,7 @@ speed-measure-plugin*.json
|
||||||
!Frontend.iml
|
!Frontend.iml
|
||||||
!Backend.iml
|
!Backend.iml
|
||||||
!CucumberTests.iml
|
!CucumberTests.iml
|
||||||
|
!Crawler.iml
|
||||||
|
|
||||||
# Include IntelliJ modules
|
# Include IntelliJ modules
|
||||||
!/.idea/modules.xml
|
!/.idea/modules.xml
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/Backend/Backend.iml" filepath="$PROJECT_DIR$/Backend/Backend.iml" />
|
<module fileurl="file://$PROJECT_DIR$/Backend/Backend.iml" filepath="$PROJECT_DIR$/Backend/Backend.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/Betterzon.iml" filepath="$PROJECT_DIR$/Betterzon.iml" />
|
<module fileurl="file://$PROJECT_DIR$/Betterzon.iml" filepath="$PROJECT_DIR$/Betterzon.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/Crawler/Crawler.iml" filepath="$PROJECT_DIR$/Crawler/Crawler.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/CucumberTests/CucumberTests.iml" filepath="$PROJECT_DIR$/CucumberTests/CucumberTests.iml" />
|
<module fileurl="file://$PROJECT_DIR$/CucumberTests/CucumberTests.iml" filepath="$PROJECT_DIR$/CucumberTests/CucumberTests.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/Frontend/Frontend.iml" filepath="$PROJECT_DIR$/Frontend/Frontend.iml" />
|
<module fileurl="file://$PROJECT_DIR$/Frontend/Frontend.iml" filepath="$PROJECT_DIR$/Frontend/Frontend.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const categoriesRouter = express.Router();
|
||||||
* Controller Definitions
|
* Controller Definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// GET items/
|
// GET categories/
|
||||||
|
|
||||||
categoriesRouter.get('/', async (req: Request, res: Response) => {
|
categoriesRouter.get('/', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
|
@ -31,7 +31,7 @@ categoriesRouter.get('/', async (req: Request, res: Response) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// GET items/:id
|
// GET categories/:id
|
||||||
|
|
||||||
categoriesRouter.get('/:id', async (req: Request, res: Response) => {
|
categoriesRouter.get('/:id', async (req: Request, res: Response) => {
|
||||||
const id: number = parseInt(req.params.id, 10);
|
const id: number = parseInt(req.params.id, 10);
|
||||||
|
@ -50,7 +50,7 @@ categoriesRouter.get('/:id', async (req: Request, res: Response) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// GET items/:name
|
// GET categories/search/:term
|
||||||
|
|
||||||
categoriesRouter.get('/search/:term', async (req: Request, res: Response) => {
|
categoriesRouter.get('/search/:term', async (req: Request, res: Response) => {
|
||||||
const term: string = req.params.term;
|
const term: string = req.params.term;
|
||||||
|
|
|
@ -4,4 +4,7 @@ export interface Price {
|
||||||
vendor_id: number;
|
vendor_id: number;
|
||||||
price_in_cents: number;
|
price_in_cents: number;
|
||||||
timestamp: Date;
|
timestamp: Date;
|
||||||
|
// Only for deals
|
||||||
|
amazonDifference?: number;
|
||||||
|
amazonDifferencePercent?: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const pricesRouter = express.Router();
|
||||||
* Controller Definitions
|
* Controller Definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// GET items/
|
// GET prices/
|
||||||
|
|
||||||
pricesRouter.get('/', async (req: Request, res: Response) => {
|
pricesRouter.get('/', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
|
@ -44,7 +44,7 @@ pricesRouter.get('/', async (req: Request, res: Response) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// GET items/:id
|
// GET prices/:id
|
||||||
|
|
||||||
pricesRouter.get('/:id', async (req: Request, res: Response) => {
|
pricesRouter.get('/:id', async (req: Request, res: Response) => {
|
||||||
const id: number = parseInt(req.params.id, 10);
|
const id: number = parseInt(req.params.id, 10);
|
||||||
|
@ -63,6 +63,25 @@ pricesRouter.get('/:id', async (req: Request, res: Response) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// GET prices/bestDeals
|
||||||
|
|
||||||
|
pricesRouter.get('/bestDeals/:amount', async (req: Request, res: Response) => {
|
||||||
|
const amount: number = parseInt(req.params.amount, 10);
|
||||||
|
|
||||||
|
if (!amount) {
|
||||||
|
res.status(400).send('Missing parameters.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const prices: Prices = await PriceService.getBestDeals(amount);
|
||||||
|
|
||||||
|
res.status(200).send(prices);
|
||||||
|
} catch (e) {
|
||||||
|
res.status(404).send(e.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// POST items/
|
// POST items/
|
||||||
|
|
||||||
// pricesRouter.post('/', async (req: Request, res: Response) => {
|
// pricesRouter.post('/', async (req: Request, res: Response) => {
|
||||||
|
|
|
@ -186,6 +186,100 @@ export const findByVendor = async (product: string, vendor: string, type: string
|
||||||
return priceRows;
|
return priceRows;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBestDeals = async (amount: number): Promise<Prices> => {
|
||||||
|
let conn;
|
||||||
|
let priceRows = [];
|
||||||
|
try {
|
||||||
|
conn = await pool.getConnection();
|
||||||
|
|
||||||
|
let allPrices: Record<number, Price[]> = {};
|
||||||
|
|
||||||
|
// Get newest prices for every product at every vendor
|
||||||
|
|
||||||
|
const rows = await conn.query(
|
||||||
|
'WITH summary AS (\n' +
|
||||||
|
' SELECT p.product_id,\n' +
|
||||||
|
' p.vendor_id,\n' +
|
||||||
|
' p.price_in_cents,\n' +
|
||||||
|
' p.timestamp,\n' +
|
||||||
|
' ROW_NUMBER() OVER(\n' +
|
||||||
|
' PARTITION BY p.product_id, p.vendor_id\n' +
|
||||||
|
' ORDER BY p.timestamp DESC) AS rk\n' +
|
||||||
|
' FROM prices p)\n' +
|
||||||
|
'SELECT s.*\n' +
|
||||||
|
'FROM summary s\n' +
|
||||||
|
'WHERE s.rk = 1');
|
||||||
|
|
||||||
|
// Write returned values to allPrices map with product id as key and a list of prices as value
|
||||||
|
for (let row in rows) {
|
||||||
|
if (row !== 'meta') {
|
||||||
|
if (!allPrices[parseInt(rows[row].product_id)]) {
|
||||||
|
allPrices[parseInt(rows[row].product_id)] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
allPrices[parseInt(rows[row].product_id)].push(rows[row]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over all prices to find the products with the biggest difference between amazon and other vendor
|
||||||
|
let deals = [];
|
||||||
|
for (let productId in Object.keys(allPrices)) {
|
||||||
|
if (allPrices[productId]) {
|
||||||
|
let pricesForProd = allPrices[productId];
|
||||||
|
|
||||||
|
// Get amazon price and lowest price from other vendor
|
||||||
|
let amazonPrice = {} as Price;
|
||||||
|
let lowestPrice = {} as Price;
|
||||||
|
pricesForProd.forEach(function(price, priceIndex) {
|
||||||
|
if (price.vendor_id === 1) {
|
||||||
|
amazonPrice = price;
|
||||||
|
} else {
|
||||||
|
if (!lowestPrice.price_in_cents || lowestPrice.price_in_cents > price.price_in_cents) {
|
||||||
|
lowestPrice = price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create deal object and add it to list
|
||||||
|
let deal = {
|
||||||
|
'product_id': lowestPrice.product_id,
|
||||||
|
'vendor_id': lowestPrice.vendor_id,
|
||||||
|
'price_in_cents': lowestPrice.price_in_cents,
|
||||||
|
'timestamp' :lowestPrice.timestamp,
|
||||||
|
'amazonDifference': (amazonPrice.price_in_cents - lowestPrice.price_in_cents),
|
||||||
|
'amazonDifferencePercent': ((1 - (lowestPrice.price_in_cents / amazonPrice.price_in_cents)) * 100),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Push only deals were the amazon price is actually higher
|
||||||
|
if(deal.amazonDifferencePercent > 0) {
|
||||||
|
deals.push(deal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort to have the best deals on the top
|
||||||
|
deals.sort((a, b) => a.amazonDifferencePercent < b.amazonDifferencePercent ? 1 : -1);
|
||||||
|
|
||||||
|
// Return only as many records as requested or the maximum amount of found deals, whatever is less
|
||||||
|
let maxAmt = Math.min(amount, deals.length);
|
||||||
|
|
||||||
|
for (let dealIndex = 0; dealIndex < maxAmt; dealIndex++){
|
||||||
|
//console.log(deals[dealIndex]);
|
||||||
|
priceRows.push(deals[dealIndex] as Price);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
throw err;
|
||||||
|
} finally {
|
||||||
|
if (conn) {
|
||||||
|
conn.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return priceRows;
|
||||||
|
};
|
||||||
|
|
||||||
// export const create = async (newItem: Product): Promise<void> => {
|
// export const create = async (newItem: Product): Promise<void> => {
|
||||||
// let conn;
|
// let conn;
|
||||||
// try {
|
// try {
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const productsRouter = express.Router();
|
||||||
* Controller Definitions
|
* Controller Definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// GET items/
|
// GET products/
|
||||||
|
|
||||||
productsRouter.get('/', async (req: Request, res: Response) => {
|
productsRouter.get('/', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
|
@ -31,7 +31,7 @@ productsRouter.get('/', async (req: Request, res: Response) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// GET items/:id
|
// GET products/:id
|
||||||
|
|
||||||
productsRouter.get('/:id', async (req: Request, res: Response) => {
|
productsRouter.get('/:id', async (req: Request, res: Response) => {
|
||||||
const id: number = parseInt(req.params.id, 10);
|
const id: number = parseInt(req.params.id, 10);
|
||||||
|
@ -50,7 +50,7 @@ productsRouter.get('/:id', async (req: Request, res: Response) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// GET items/:name
|
// GET products/search/:term
|
||||||
|
|
||||||
productsRouter.get('/search/:term', async (req: Request, res: Response) => {
|
productsRouter.get('/search/:term', async (req: Request, res: Response) => {
|
||||||
const term: string = req.params.term;
|
const term: string = req.params.term;
|
||||||
|
@ -69,6 +69,8 @@ productsRouter.get('/search/:term', async (req: Request, res: Response) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// GET products/bestDeals
|
||||||
|
|
||||||
|
|
||||||
// POST items/
|
// POST items/
|
||||||
|
|
||||||
|
|
8
Crawler/Crawler.iml
Normal file
8
Crawler/Crawler.iml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
1
Crawler/requirements.txt
Normal file
1
Crawler/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pymysql
|
|
@ -17,6 +17,8 @@ import {FormsModule} from '@angular/forms';
|
||||||
import {PageNotFoundPageComponent} from './pages/page-not-found-page/page-not-found-page.component';
|
import {PageNotFoundPageComponent} from './pages/page-not-found-page/page-not-found-page.component';
|
||||||
import {MatMenuModule} from '@angular/material/menu';
|
import {MatMenuModule} from '@angular/material/menu';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { ImprintComponent } from './pages/imprint/imprint.component';
|
||||||
|
import { PrivacyComponent } from './pages/privacy/privacy.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -29,7 +31,9 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
ProductSearchPageComponent,
|
ProductSearchPageComponent,
|
||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
NewestPricesListComponent,
|
NewestPricesListComponent,
|
||||||
PageNotFoundPageComponent
|
PageNotFoundPageComponent,
|
||||||
|
ImprintComponent,
|
||||||
|
PrivacyComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|
|
@ -7,11 +7,15 @@ import {LandingpageComponent} from './pages/landingpage/landingpage.component';
|
||||||
import {ProductDetailPageComponent} from './pages/product-detail-page/product-detail-page.component';
|
import {ProductDetailPageComponent} from './pages/product-detail-page/product-detail-page.component';
|
||||||
import {ProductSearchPageComponent} from './pages/product-search-page/product-search-page.component';
|
import {ProductSearchPageComponent} from './pages/product-search-page/product-search-page.component';
|
||||||
import {PageNotFoundPageComponent} from './pages/page-not-found-page/page-not-found-page.component';
|
import {PageNotFoundPageComponent} from './pages/page-not-found-page/page-not-found-page.component';
|
||||||
|
import {ImprintComponent} from './pages/imprint/imprint.component';
|
||||||
|
import {PrivacyComponent} from './pages/privacy/privacy.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: '', component: LandingpageComponent},
|
{path: '', component: LandingpageComponent},
|
||||||
{path: 'search', component: ProductSearchPageComponent},
|
{path: 'search', component: ProductSearchPageComponent},
|
||||||
{path: 'product/:id', component: ProductDetailPageComponent},
|
{path: 'product/:id', component: ProductDetailPageComponent},
|
||||||
|
{path: 'impressum', component: ImprintComponent},
|
||||||
|
{path: 'datenschutz', component: PrivacyComponent},
|
||||||
{path: '**', component: PageNotFoundPageComponent}
|
{path: '**', component: PageNotFoundPageComponent}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: dimgrey;
|
background-color: dimgrey;
|
||||||
color: white;
|
color: white;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-3d {
|
.icon-3d {
|
||||||
|
@ -13,5 +12,23 @@
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#footer-icons {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#imprintSection {
|
||||||
|
position: fixed;
|
||||||
|
right: 1em;
|
||||||
|
bottom: 1em;
|
||||||
|
width: 100%;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#imprintSection a {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
|
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class='wrap'>
|
<div class='wrap' id="footer-icons">
|
||||||
<div class="icons">
|
<div class="icons">
|
||||||
<a href="https://github.com/Mueller-Patrick/Betterzon" class="fa fa-github fa-4x icon-3d"></a>
|
<a href="https://github.com/Mueller-Patrick/Betterzon" class="fa fa-github fa-4x icon-3d"></a>
|
||||||
<a href="https://twitter.com/elonmusk" class="fa fa-twitter fa-4x icon-3d"></a>
|
<a href="https://twitter.com/elonmusk" class="fa fa-twitter fa-4x icon-3d"></a>
|
||||||
|
@ -11,4 +11,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class = "blocks" id="copyright">© COPYRIGHT 2020</div>
|
<div class = "blocks" id="copyright">© COPYRIGHT 2020</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="imprintSection">
|
||||||
|
<a href="/impressum" >Imprint</a><br>
|
||||||
|
<a href="/datenschutz">Privacy Policy</a>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-footer',
|
selector: 'app-footer',
|
||||||
|
@ -7,9 +8,16 @@ import { Component, OnInit } from '@angular/core';
|
||||||
})
|
})
|
||||||
export class FooterComponent implements OnInit {
|
export class FooterComponent implements OnInit {
|
||||||
|
|
||||||
constructor() { }
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
private route: ActivatedRoute
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
navigateImprint(): void {
|
||||||
|
this.router.navigate([('/impressum/')]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
margin-left: 50%;
|
margin-left: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logo:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.searchBox {
|
.searchBox {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
@ -36,6 +40,10 @@
|
||||||
margin-left: 10%;
|
margin-left: 10%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.profileIcon:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-3d {
|
.icon-3d {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
|
@ -81,3 +81,8 @@
|
||||||
margin-top: .5em;
|
margin-top: .5em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.priceAlarm:hover {
|
||||||
|
background-color: lightgray;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
|
@ -53,3 +53,8 @@
|
||||||
.productDescription {
|
.productDescription {
|
||||||
grid-area: description;
|
grid-area: description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.productItem:hover {
|
||||||
|
background-color: lightgray;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
4
Frontend/src/app/pages/imprint/imprint.component.css
Normal file
4
Frontend/src/app/pages/imprint/imprint.component.css
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#imprint {
|
||||||
|
padding-left: 5em;
|
||||||
|
padding-right: 5em;
|
||||||
|
}
|
59
Frontend/src/app/pages/imprint/imprint.component.html
Normal file
59
Frontend/src/app/pages/imprint/imprint.component.html
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<app-header [showSearch]="true"></app-header>
|
||||||
|
<div id="imprint">
|
||||||
|
<h1>Impressum</h1>
|
||||||
|
|
||||||
|
<h2>Angaben gemäß § 5 TMG</h2>
|
||||||
|
<p>
|
||||||
|
Patrick Müller<br/>
|
||||||
|
Schachtstraße 8<br/>
|
||||||
|
75031 Eppingen
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Kontakt</h2>
|
||||||
|
<p>
|
||||||
|
E-Mail: betterzon-contact@mueller-patrick.tech
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Haftung für Inhalte</h3>
|
||||||
|
<p>
|
||||||
|
Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene
|
||||||
|
Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als
|
||||||
|
Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen
|
||||||
|
oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben
|
||||||
|
hiervon unberührt.
|
||||||
|
Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich.
|
||||||
|
Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Haftung für Links</h3>
|
||||||
|
<p>
|
||||||
|
Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir keinen
|
||||||
|
Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für
|
||||||
|
die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die
|
||||||
|
verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft.
|
||||||
|
Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer
|
||||||
|
Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend
|
||||||
|
entfernen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Urheberrecht</h3>
|
||||||
|
<p>
|
||||||
|
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht.
|
||||||
|
Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des
|
||||||
|
Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und
|
||||||
|
Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet.
|
||||||
|
Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung
|
||||||
|
aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir
|
||||||
|
derartige Inhalte umgehend entfernen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<app-footer></app-footer>
|
25
Frontend/src/app/pages/imprint/imprint.component.spec.ts
Normal file
25
Frontend/src/app/pages/imprint/imprint.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ImprintComponent } from './imprint.component';
|
||||||
|
|
||||||
|
describe('ImprintComponent', () => {
|
||||||
|
let component: ImprintComponent;
|
||||||
|
let fixture: ComponentFixture<ImprintComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ ImprintComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ImprintComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
15
Frontend/src/app/pages/imprint/imprint.component.ts
Normal file
15
Frontend/src/app/pages/imprint/imprint.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-imprint',
|
||||||
|
templateUrl: './imprint.component.html',
|
||||||
|
styleUrls: ['./imprint.component.css']
|
||||||
|
})
|
||||||
|
export class ImprintComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
4
Frontend/src/app/pages/privacy/privacy.component.css
Normal file
4
Frontend/src/app/pages/privacy/privacy.component.css
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#privacy {
|
||||||
|
padding-left: 5em;
|
||||||
|
padding-right: 5em;
|
||||||
|
}
|
408
Frontend/src/app/pages/privacy/privacy.component.html
Normal file
408
Frontend/src/app/pages/privacy/privacy.component.html
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
<app-header [showSearch]="true"></app-header>
|
||||||
|
<div id="privacy">
|
||||||
|
<h1>Datenschutz­erklärung</h1>
|
||||||
|
<h2>1. Datenschutz auf einen Blick</h2>
|
||||||
|
<h3>Allgemeine Hinweise</h3>
|
||||||
|
<p>
|
||||||
|
Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren
|
||||||
|
personenbezogenen Daten passiert, wenn Sie diese Website besuchen. Personenbezogene Daten sind alle Daten, mit denen
|
||||||
|
Sie persönlich identifiziert werden können. Ausführliche Informationen zum Thema Datenschutz
|
||||||
|
entnehmen Sie unserer unter diesem Text aufgeführten Datenschutzerklärung.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Datenerfassung auf dieser Website</h3>
|
||||||
|
<h4>Wer ist verantwortlich für die Datenerfassung auf dieser Website?</h4>
|
||||||
|
<p>
|
||||||
|
Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen Kontaktdaten können
|
||||||
|
Sie dem Abschnitt „Hinweis zur Verantwortlichen Stelle“ in dieser Datenschutzerklärung
|
||||||
|
entnehmen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4>Wie erfassen wir Ihre Daten?</h4>
|
||||||
|
<p>
|
||||||
|
Ihre Daten werden zum einen dadurch erhoben, dass Sie uns
|
||||||
|
diese mitteilen. Hierbei kann es sich z. B. um Daten handeln, die Sie in ein Kontaktformular eingeben.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Andere Daten werden automatisch oder nach Ihrer Einwilligung beim Besuch der Website durch unsere IT-Systeme
|
||||||
|
erfasst. Das sind vor allem technische Daten (z. B. Internetbrowser, Betriebssystem oder Uhrzeit des
|
||||||
|
Seitenaufrufs). Die Erfassung dieser Daten erfolgt automatisch, sobald Sie diese Website betreten.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4>Wofür nutzen wir Ihre Daten?</h4>
|
||||||
|
<p>
|
||||||
|
Ein Teil der Daten wird erhoben, um eine fehlerfreie Bereitstellung der Website zu
|
||||||
|
gewährleisten. Andere Daten können zur Analyse Ihres Nutzerverhaltens verwendet werden.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4>Welche Rechte haben Sie bezüglich Ihrer Daten?</h4>
|
||||||
|
<p>
|
||||||
|
Sie haben jederzeit das Recht, unentgeltlich Auskunft über
|
||||||
|
Herkunft, Empfänger und Zweck Ihrer gespeicherten personenbezogenen Daten zu erhalten. Sie haben außerdem
|
||||||
|
ein Recht, die Berichtigung oder Löschung dieser Daten zu verlangen. Wenn Sie eine Einwilligung zur
|
||||||
|
Datenverarbeitung erteilt haben, können Sie diese Einwilligung jederzeit für die Zukunft widerrufen. Außerdem
|
||||||
|
haben Sie das Recht, unter bestimmten Umständen die Einschränkung der Verarbeitung Ihrer personenbezogenen
|
||||||
|
Daten zu verlangen. Des Weiteren steht Ihnen ein Beschwerderecht bei der zuständigen Aufsichtsbehörde
|
||||||
|
zu.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Hierzu sowie zu weiteren Fragen zum Thema Datenschutz können Sie sich jederzeit an uns wenden.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>2. Hosting und Content Delivery Networks (CDN)</h2>
|
||||||
|
<h3>Externes Hosting</h3>
|
||||||
|
<p>
|
||||||
|
Diese Website wird bei einem externen Dienstleister gehostet (Hoster). Die
|
||||||
|
personenbezogenen Daten, die auf dieser Website erfasst werden, werden auf den Servern des Hosters gespeichert.
|
||||||
|
Hierbei kann es sich v. a. um IP-Adressen, Kontaktanfragen, Meta- und Kommunikationsdaten, Vertragsdaten,
|
||||||
|
Kontaktdaten, Namen, Websitezugriffe und sonstige Daten, die über eine Website generiert werden, handeln.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Der Einsatz des Hosters erfolgt zum Zwecke der Vertragserfüllung gegenüber unseren potenziellen und
|
||||||
|
bestehenden Kunden (Art. 6 Abs. 1 lit. b DSGVO) und im Interesse einer sicheren, schnellen und effizienten
|
||||||
|
Bereitstellung unseres Online-Angebots durch einen professionellen Anbieter (Art. 6 Abs. 1 lit. f DSGVO).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Unser Hoster wird Ihre Daten nur insoweit verarbeiten, wie dies zur Erfüllung seiner Leistungspflichten
|
||||||
|
erforderlich ist und unsere Weisungen in Bezug auf diese Daten befolgen.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wir setzen folgenden Hoster ein:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
netcup GmbH<br/>
|
||||||
|
Daimlerstraße 25<br/>
|
||||||
|
76185 Karlsruhe
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4>Abschluss eines Vertrages über Auftragsverarbeitung</h4>
|
||||||
|
<p>
|
||||||
|
Um die datenschutzkonforme Verarbeitung zu gewährleisten,
|
||||||
|
haben wir einen Vertrag über Auftragsverarbeitung mit unserem Hoster geschlossen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>3. Allgemeine Hinweise und Pflicht­informationen</h2>
|
||||||
|
<h3>Datenschutz</h3>
|
||||||
|
<p>
|
||||||
|
Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir
|
||||||
|
behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie
|
||||||
|
dieser Datenschutzerklärung.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wenn Sie diese Website benutzen, werden verschiedene personenbezogene Daten
|
||||||
|
erhoben. Personenbezogene Daten sind Daten, mit denen Sie persönlich identifiziert werden können. Die
|
||||||
|
vorliegende Datenschutzerklärung erläutert, welche Daten wir erheben und wofür wir sie nutzen. Sie
|
||||||
|
erläutert auch, wie und zu welchem Zweck das geschieht.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wir weisen darauf hin, dass die Datenübertragung
|
||||||
|
im Internet (z. B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser
|
||||||
|
Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Hinweis zur verantwortlichen Stelle</h3>
|
||||||
|
<p>
|
||||||
|
Die verantwortliche Stelle für die Datenverarbeitung auf dieser
|
||||||
|
Website ist:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Patrick Müller<br/>
|
||||||
|
Schachtstraße 8<br/>
|
||||||
|
75031 Eppingen
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
E-Mail: betterzon-privacy@mueller-patrick.tech
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Verantwortliche Stelle ist die natürliche oder juristische Person, die allein oder gemeinsam mit anderen über
|
||||||
|
die Zwecke und Mittel der Verarbeitung von personenbezogenen Daten (z. B. Namen, E-Mail-Adressen o. Ä.)
|
||||||
|
entscheidet.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Speicherdauer</h3>
|
||||||
|
<p>
|
||||||
|
Soweit innerhalb dieser Datenschutzerklärung keine speziellere Speicherdauer genannt
|
||||||
|
wurde, verbleiben Ihre personenbezogenen Daten bei uns, bis der Zweck für die Datenverarbeitung entfällt.
|
||||||
|
Wenn Sie ein berechtigtes Löschersuchen geltend machen oder eine Einwilligung zur Datenverarbeitung widerrufen,
|
||||||
|
werden Ihre Daten gelöscht, sofern wir keine anderen rechtlich zulässigen Gründe für die
|
||||||
|
Speicherung Ihrer personenbezogenen Daten haben (z.B. steuer- oder handelsrechtliche Aufbewahrungsfristen); im
|
||||||
|
letztgenannten Fall erfolgt die Löschung nach Fortfall dieser Gründe.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Hinweis zur Datenweitergabe in die USA und sonstige Drittstaaten</h3>
|
||||||
|
<p>
|
||||||
|
Auf unserer Website sind unter anderem
|
||||||
|
Tools von Unternehmen mit Sitz in den USA oder sonstigen datenschutzrechtlich nicht sicheren Drittstaaten
|
||||||
|
eingebunden. Wenn diese Tools aktiv sind, können Ihre personenbezogene Daten in diese Drittstaaten übertragen
|
||||||
|
und dort verarbeitet werden. Wir weisen darauf hin, dass in diesen Ländern kein mit der EU vergleichbares
|
||||||
|
Datenschutzniveau garantiert werden kann. Beispielsweise sind US-Unternehmen dazu verpflichtet, personenbezogene
|
||||||
|
Daten an Sicherheitsbehörden herauszugeben, ohne dass Sie als Betroffener hiergegen gerichtlich vorgehen könnten.
|
||||||
|
Es kann daher nicht ausgeschlossen werden, dass US-Behörden (z.B. Geheimdienste) Ihre auf US-Servern
|
||||||
|
befindlichen Daten zu Überwachungszwecken verarbeiten, auswerten und dauerhaft speichern. Wir haben auf diese
|
||||||
|
Verarbeitungstätigkeiten keinen Einfluss.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Widerruf Ihrer Einwilligung zur Datenverarbeitung</h3>
|
||||||
|
<p>
|
||||||
|
Viele Datenverarbeitungsvorgänge sind nur mit Ihrer ausdrücklichen Einwilligung möglich. Sie können
|
||||||
|
eine bereits erteilte Einwilligung jederzeit widerrufen. Die Rechtmäßigkeit der bis zum Widerruf
|
||||||
|
erfolgten Datenverarbeitung bleibt vom Widerruf unberührt.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Widerspruchsrecht gegen die Datenerhebung in besonderen Fällen sowie gegen Direktwerbung (Art. 21 DSGVO)</h3>
|
||||||
|
<p>
|
||||||
|
WENN DIE DATENVERARBEITUNG AUF GRUNDLAGE VON ART. 6 ABS. 1 LIT. E ODER F DSGVO ERFOLGT, HABEN SIE JEDERZEIT DAS
|
||||||
|
RECHT, AUS GRÜNDEN, DIE SICH AUS IHRER BESONDEREN SITUATION ERGEBEN, GEGEN DIE VERARBEITUNG IHRER
|
||||||
|
PERSONENBEZOGENEN DATEN WIDERSPRUCH EINZULEGEN; DIES GILT AUCH FÜR EIN AUF DIESE BESTIMMUNGEN GESTÜTZTES
|
||||||
|
PROFILING. DIE JEWEILIGE RECHTSGRUNDLAGE, AUF DENEN EINE VERARBEITUNG BERUHT, ENTNEHMEN SIE DIESER DATENSCHUTZERKLÄRUNG.
|
||||||
|
WENN SIE WIDERSPRUCH EINLEGEN, WERDEN WIR IHRE BETROFFENEN PERSONENBEZOGENEN DATEN NICHT MEHR VERARBEITEN, ES SEI
|
||||||
|
DENN, WIR KÖNNEN ZWINGENDE SCHUTZWÜRDIGE GRÜNDE FÜR DIE VERARBEITUNG NACHWEISEN, DIE IHRE
|
||||||
|
INTERESSEN, RECHTE UND FREIHEITEN ÜBERWIEGEN ODER DIE VERARBEITUNG DIENT DER GELTENDMACHUNG, AUSÜBUNG ODER
|
||||||
|
VERTEIDIGUNG VON RECHTSANSPRÜCHEN (WIDERSPRUCH NACH ART. 21 ABS. 1 DSGVO).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
WERDEN IHRE PERSONENBEZOGENEN
|
||||||
|
DATEN VERARBEITET, UM DIREKTWERBUNG ZU BETREIBEN, SO HABEN SIE DAS RECHT, JEDERZEIT WIDERSPRUCH GEGEN DIE
|
||||||
|
VERARBEITUNG SIE BETREFFENDER PERSONENBEZOGENER DATEN ZUM ZWECKE DERARTIGER WERBUNG EINZULEGEN; DIES GILT AUCH FÜR
|
||||||
|
DAS PROFILING, SOWEIT ES MIT SOLCHER DIREKTWERBUNG IN VERBINDUNG STEHT. WENN SIE WIDERSPRECHEN, WERDEN IHRE
|
||||||
|
PERSONENBEZOGENEN DATEN ANSCHLIESSEND NICHT MEHR ZUM ZWECKE DER DIREKTWERBUNG VERWENDET (WIDERSPRUCH NACH ART. 21
|
||||||
|
ABS. 2 DSGVO).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Beschwerde­recht bei der zuständigen Aufsichts­behörde</h3>
|
||||||
|
<p>
|
||||||
|
Im Falle von Verstößen
|
||||||
|
gegen die DSGVO steht den Betroffenen ein Beschwerderecht bei einer Aufsichtsbehörde, insbesondere in dem
|
||||||
|
Mitgliedstaat ihres gewöhnlichen Aufenthalts, ihres Arbeitsplatzes oder des Orts des mutmaßlichen Verstoßes
|
||||||
|
zu. Das Beschwerderecht besteht unbeschadet anderweitiger verwaltungsrechtlicher oder gerichtlicher
|
||||||
|
Rechtsbehelfe.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Recht auf Daten­übertrag­barkeit</h3>
|
||||||
|
<p>
|
||||||
|
Sie haben das Recht, Daten, die wir auf Grundlage Ihrer
|
||||||
|
Einwilligung oder in Erfüllung eines Vertrags automatisiert verarbeiten, an sich oder an einen Dritten in einem
|
||||||
|
gängigen, maschinenlesbaren Format aushändigen zu lassen. Sofern Sie die direkte Übertragung der
|
||||||
|
Daten an einen anderen Verantwortlichen verlangen, erfolgt dies nur, soweit es technisch machbar ist.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>SSL- bzw. TLS-Verschlüsselung</h3>
|
||||||
|
<p>
|
||||||
|
Diese Seite nutzt aus Sicherheitsgründen und zum Schutz der Übertragung
|
||||||
|
vertraulicher Inhalte, wie zum Beispiel Bestellungen oder Anfragen, die Sie an uns als Seitenbetreiber senden, eine
|
||||||
|
SSL- bzw. TLS-Verschlüsselung. Eine verschlüsselte Verbindung erkennen Sie daran, dass die Adresszeile des
|
||||||
|
Browsers von „http://“ auf „https://“ wechselt und an dem Schloss-Symbol in Ihrer
|
||||||
|
Browserzeile.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wenn die SSL- bzw. TLS-Verschlüsselung aktiviert ist, können die Daten, die Sie an
|
||||||
|
uns übermitteln, nicht von Dritten mitgelesen werden.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Auskunft, Löschung und Berichtigung</h3>
|
||||||
|
<p>
|
||||||
|
Sie haben im Rahmen der geltenden gesetzlichen Bestimmungen
|
||||||
|
jederzeit das Recht auf unentgeltliche Auskunft über Ihre gespeicherten personenbezogenen Daten, deren Herkunft
|
||||||
|
und Empfänger und den Zweck der Datenverarbeitung und ggf. ein Recht auf Berichtigung oder Löschung dieser
|
||||||
|
Daten. Hierzu sowie zu weiteren Fragen zum Thema personenbezogene Daten können Sie sich jederzeit an uns
|
||||||
|
wenden.
|
||||||
|
</p>
|
||||||
|
<h3>Recht auf Einschränkung der Verarbeitung</h3>
|
||||||
|
<p>
|
||||||
|
Sie haben das Recht, die Einschränkung der Verarbeitung
|
||||||
|
Ihrer personenbezogenen Daten zu verlangen. Hierzu können Sie sich jederzeit an uns wenden. Das Recht auf
|
||||||
|
Einschränkung der Verarbeitung besteht in folgenden Fällen:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Wenn Sie die Richtigkeit Ihrer bei uns gespeicherten personenbezogenen Daten bestreiten, benötigen wir in
|
||||||
|
der Regel Zeit, um dies zu überprüfen. Für die Dauer der Prüfung haben Sie das Recht, die
|
||||||
|
Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Wenn die Verarbeitung Ihrer personenbezogenen Daten unrechtmäßig geschah/geschieht, können Sie
|
||||||
|
statt der Löschung die Einschränkung der Datenverarbeitung verlangen.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Wenn wir Ihre personenbezogenen Daten nicht mehr benötigen, Sie sie jedoch zur Ausübung, Verteidigung
|
||||||
|
oder Geltendmachung von Rechtsansprüchen benötigen, haben Sie das Recht, statt der Löschung die
|
||||||
|
Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Wenn Sie einen Widerspruch nach Art. 21 Abs. 1 DSGVO eingelegt haben, muss eine Abwägung zwischen Ihren und
|
||||||
|
unseren Interessen vorgenommen werden. Solange noch nicht feststeht, wessen Interessen überwiegen, haben
|
||||||
|
Sie das Recht, die Einschränkung der Verarbeitung Ihrer personenbezogenen Daten zu verlangen.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Wenn Sie die Verarbeitung Ihrer personenbezogenen Daten eingeschränkt haben, dürfen diese Daten
|
||||||
|
– von ihrer Speicherung abgesehen – nur mit Ihrer Einwilligung oder zur Geltendmachung, Ausübung
|
||||||
|
oder Verteidigung von Rechtsansprüchen oder zum Schutz der Rechte einer anderen natürlichen oder
|
||||||
|
juristischen Person oder aus Gründen eines wichtigen öffentlichen Interesses der Europäischen Union
|
||||||
|
oder eines Mitgliedstaats verarbeitet werden.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>4. Datenerfassung auf dieser Website</h2>
|
||||||
|
<h3>Cookies</h3>
|
||||||
|
<p>
|
||||||
|
Unsere Internetseiten verwenden so genannte „Cookies“. Cookies sind kleine Textdateien
|
||||||
|
und richten auf Ihrem Endgerät keinen Schaden an. Sie werden entweder vorübergehend für die Dauer
|
||||||
|
einer Sitzung (Session-Cookies) oder dauerhaft (permanente Cookies) auf Ihrem Endgerät gespeichert.
|
||||||
|
Session-Cookies werden nach Ende Ihres Besuchs automatisch gelöscht. Permanente Cookies bleiben auf Ihrem
|
||||||
|
Endgerät gespeichert, bis Sie diese selbst löschen oder eine automatische Löschung durch Ihren
|
||||||
|
Webbrowser erfolgt.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Teilweise können auch Cookies von Drittunternehmen auf Ihrem Endgerät
|
||||||
|
gespeichert werden, wenn Sie unsere Seite betreten (Third-Party-Cookies). Diese ermöglichen uns oder Ihnen die
|
||||||
|
Nutzung bestimmter Dienstleistungen des Drittunternehmens (z.B. Cookies zur Abwicklung von
|
||||||
|
Zahlungsdienstleistungen).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Cookies haben verschiedene Funktionen. Zahlreiche Cookies sind technisch
|
||||||
|
notwendig, da bestimmte Websitefunktionen ohne diese nicht funktionieren würden (z.B. die Warenkorbfunktion
|
||||||
|
oder die Anzeige von Videos). Andere Cookies dienen dazu, das Nutzerverhalten auszuwerten oder Werbung
|
||||||
|
anzuzeigen.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Cookies, die zur Durchführung des elektronischen Kommunikationsvorgangs (notwendige Cookies)
|
||||||
|
oder zur Bereitstellung bestimmter, von Ihnen erwünschter Funktionen (funktionale Cookies, z. B. für die
|
||||||
|
Warenkorbfunktion) oder zur Optimierung der Website (z.B. Cookies zur Messung des Webpublikums) erforderlich sind,
|
||||||
|
werden auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO gespeichert, sofern keine andere Rechtsgrundlage angegeben wird.
|
||||||
|
Der Websitebetreiber hat ein berechtigtes Interesse an der Speicherung von Cookies zur technisch fehlerfreien und
|
||||||
|
optimierten Bereitstellung seiner Dienste. Sofern eine Einwilligung zur Speicherung von Cookies abgefragt wurde,
|
||||||
|
erfolgt die Speicherung der betreffenden Cookies ausschließlich auf Grundlage dieser Einwilligung (Art. 6 Abs.
|
||||||
|
1 lit. a DSGVO); die Einwilligung ist jederzeit widerrufbar.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Sie können Ihren Browser so einstellen,
|
||||||
|
dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von
|
||||||
|
Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der
|
||||||
|
Cookies beim Schließen des Browsers aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität
|
||||||
|
dieser Website eingeschränkt sein.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Soweit Cookies von Drittunternehmen oder zu Analysezwecken eingesetzt
|
||||||
|
werden, werden wir Sie hierüber im Rahmen dieser Datenschutzerklärung gesondert informieren und ggf. eine
|
||||||
|
Einwilligung abfragen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Server-Log-Dateien</h3>
|
||||||
|
<p>
|
||||||
|
Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten
|
||||||
|
Server-Log-Dateien, die Ihr Browser automatisch an uns übermittelt. Dies sind:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Browsertyp und Browserversion</li>
|
||||||
|
<li>verwendetes Betriebssystem</li>
|
||||||
|
<li>Referrer URL</li>
|
||||||
|
<li>Hostname des zugreifenden Rechners</li>
|
||||||
|
<li>Uhrzeit der Serveranfrage</li>
|
||||||
|
<li>IP-Adresse</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Eine Zusammenführung dieser Daten mit anderen Datenquellen wird nicht vorgenommen.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die Erfassung
|
||||||
|
dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO. Der Websitebetreiber hat ein berechtigtes
|
||||||
|
Interesse an der technisch fehlerfreien Darstellung und der Optimierung seiner Website – hierzu müssen
|
||||||
|
die Server-Log-Files erfasst werden.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Kontaktformular</h3>
|
||||||
|
<p>
|
||||||
|
Wenn Sie uns per Kontaktformular Anfragen zukommen lassen, werden Ihre Angaben aus dem
|
||||||
|
Anfrageformular inklusive der von Ihnen dort angegebenen Kontaktdaten zwecks Bearbeitung der Anfrage und für
|
||||||
|
den Fall von Anschlussfragen bei uns gespeichert. Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO, sofern Ihre Anfrage mit der Erfüllung
|
||||||
|
eines Vertrags zusammenhängt oder zur Durchführung vorvertraglicher Maßnahmen erforderlich ist. In
|
||||||
|
allen übrigen Fällen beruht die Verarbeitung auf unserem berechtigten Interesse an der effektiven
|
||||||
|
Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf Ihrer Einwilligung (Art. 6 Abs. 1
|
||||||
|
lit. a DSGVO) sofern diese abgefragt wurde.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die von Ihnen im Kontaktformular eingegebenen Daten verbleiben
|
||||||
|
bei uns, bis Sie uns zur Löschung auffordern, Ihre Einwilligung zur Speicherung widerrufen oder der Zweck für
|
||||||
|
die Datenspeicherung entfällt (z. B. nach abgeschlossener Bearbeitung Ihrer Anfrage). Zwingende
|
||||||
|
gesetzliche Bestimmungen – insbesondere Aufbewahrungsfristen – bleiben unberührt.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Anfrage per E-Mail, Telefon oder Telefax</h3>
|
||||||
|
<p>
|
||||||
|
Wenn Sie uns per E-Mail, Telefon oder Telefax kontaktieren, wird
|
||||||
|
Ihre Anfrage inklusive aller daraus hervorgehenden personenbezogenen Daten (Name, Anfrage) zum Zwecke der
|
||||||
|
Bearbeitung Ihres Anliegens bei uns gespeichert und verarbeitet. Diese Daten geben wir nicht ohne Ihre Einwilligung
|
||||||
|
weiter.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO, sofern Ihre
|
||||||
|
Anfrage mit der Erfüllung eines Vertrags zusammenhängt oder zur Durchführung vorvertraglicher Maßnahmen
|
||||||
|
erforderlich ist. In allen übrigen Fällen beruht die Verarbeitung auf unserem berechtigten Interesse an
|
||||||
|
der effektiven Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf Ihrer Einwilligung
|
||||||
|
(Art. 6 Abs. 1 lit. a DSGVO) sofern diese abgefragt wurde.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die von Ihnen an uns per Kontaktanfragen übersandten
|
||||||
|
Daten verbleiben bei uns, bis Sie uns zur Löschung auffordern, Ihre Einwilligung zur Speicherung widerrufen
|
||||||
|
oder der Zweck für die Datenspeicherung entfällt (z. B. nach abgeschlossener Bearbeitung Ihres
|
||||||
|
Anliegens). Zwingende gesetzliche Bestimmungen – insbesondere gesetzliche Aufbewahrungsfristen – bleiben
|
||||||
|
unberührt.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>5. Plugins und Tools</h2>
|
||||||
|
<h3>Google Web Fonts</h3>
|
||||||
|
<p>
|
||||||
|
Diese Seite nutzt zur einheitlichen Darstellung von Schriftarten so genannte Web Fonts, die
|
||||||
|
von Google bereitgestellt werden. Beim Aufruf einer Seite lädt Ihr Browser die benötigten Web Fonts in
|
||||||
|
ihren Browsercache, um Texte und Schriftarten korrekt anzuzeigen.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Zu diesem Zweck muss der von Ihnen
|
||||||
|
verwendete Browser Verbindung zu den Servern von Google aufnehmen. Hierdurch erlangt Google Kenntnis darüber,
|
||||||
|
dass über Ihre IP-Adresse diese Website aufgerufen wurde. Die Nutzung von Google WebFonts erfolgt auf Grundlage
|
||||||
|
von Art. 6 Abs. 1 lit. f DSGVO. Der Websitebetreiber hat ein berechtigtes Interesse an der einheitlichen Darstellung
|
||||||
|
des Schriftbildes auf seiner Website. Sofern eine entsprechende Einwilligung abgefragt wurde (z. B. eine
|
||||||
|
Einwilligung zur Speicherung von Cookies), erfolgt die Verarbeitung ausschließlich auf Grundlage von Art. 6
|
||||||
|
Abs. 1 lit. a DSGVO; die Einwilligung ist jederzeit widerrufbar.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wenn Ihr Browser Web Fonts nicht unterstützt,
|
||||||
|
wird eine Standardschrift von Ihrem Computer genutzt.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Weitere Informationen zu Google Web Fonts finden Sie
|
||||||
|
unter <a href="https://developers.google.com/fonts/faq" target="_blank" rel="noopener noreferrer">https://developers.google.com/fonts/faq</a>
|
||||||
|
und in der Datenschutzerklärung von Google: <a href="https://policies.google.com/privacy?hl=de" target="_blank"
|
||||||
|
rel="noopener noreferrer">https://policies.google.com/privacy?hl=de</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Font Awesome</h3>
|
||||||
|
<p>
|
||||||
|
Diese Seite nutzt zur einheitlichen Darstellung von Schriftarten und Symbolen Font Awesome.
|
||||||
|
Anbieter ist die Fonticons, Inc., 6 Porter Road Apartment 3R, Cambridge, Massachusetts, USA.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Beim Aufruf
|
||||||
|
einer Seite lädt Ihr Browser die benötigten Fonts in ihren Browsercache, um Texte, Schriftarten und
|
||||||
|
Symbole korrekt anzuzeigen. Zu diesem Zweck muss der von Ihnen verwendete Browser Verbindung zu den Servern von Font
|
||||||
|
Awesome aufnehmen. Hierdurch erlangt Font Awesome Kenntnis darüber, dass über Ihre IP-Adresse diese
|
||||||
|
Website aufgerufen wurde. Die Nutzung von Font Awesome erfolgt auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO. Wir
|
||||||
|
haben ein berechtigtes Interesse an der einheitlichen Darstellung des Schriftbildes auf unserer Website. Sofern eine
|
||||||
|
entsprechende Einwilligung abgefragt wurde (z. B. eine Einwilligung zur Speicherung von Cookies), erfolgt die
|
||||||
|
Verarbeitung ausschließlich auf Grundlage von Art. 6 Abs. 1 lit. a DSGVO; die Einwilligung ist jederzeit
|
||||||
|
widerrufbar.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wenn Ihr Browser Font Awesome nicht unterstützt, wird eine Standardschrift von Ihrem
|
||||||
|
Computer genutzt.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Weitere Informationen zu Font Awesome finden Sie und in der Datenschutzerklärung
|
||||||
|
von Font Awesome unter: <a href="https://fontawesome.com/privacy" target="_blank" rel="noopener noreferrer">https://fontawesome.com/privacy</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<app-footer></app-footer>
|
25
Frontend/src/app/pages/privacy/privacy.component.spec.ts
Normal file
25
Frontend/src/app/pages/privacy/privacy.component.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PrivacyComponent } from './privacy.component';
|
||||||
|
|
||||||
|
describe('PrivacyComponent', () => {
|
||||||
|
let component: PrivacyComponent;
|
||||||
|
let fixture: ComponentFixture<PrivacyComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ PrivacyComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PrivacyComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
15
Frontend/src/app/pages/privacy/privacy.component.ts
Normal file
15
Frontend/src/app/pages/privacy/privacy.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-privacy',
|
||||||
|
templateUrl: './privacy.component.html',
|
||||||
|
styleUrls: ['./privacy.component.css']
|
||||||
|
})
|
||||||
|
export class PrivacyComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user