Template
add README.md for some configuration and building the app
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# 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
|
||||
ij_typescript_use_double_quotes = false
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"plugins": {
|
||||
"@tailwindcss/postcss": {}
|
||||
}
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
||||
"recommendations": ["angular.ng-template"]
|
||||
}
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Chrome against localhost",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: start",
|
||||
"url": "http://localhost:4200/",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
},
|
||||
{
|
||||
"name": "ng serve",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: start",
|
||||
"url": "http://localhost:4200/"
|
||||
},
|
||||
{
|
||||
"name": "ng test",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: test",
|
||||
"url": "http://localhost:9876/debug.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "(.*?)"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation complete"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "(.*?)"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation complete"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+1
-1
@@ -12,4 +12,4 @@ COPY . .
|
||||
|
||||
RUN ng build --configuration=production
|
||||
|
||||
CMD [ "ng", "serve","--port", "4240", "--host", "0.0.0.0" ]
|
||||
CMD [ "ng", "serve","--port", "4260", "--host", "0.0.0.0" ]
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Appwrite
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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 OR COPYRIGHT HOLDERS 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.
|
||||
@@ -1,26 +1,37 @@
|
||||
# Angular starter kit with Appwrite
|
||||
# Angular Template with Login and Register with Appwrite
|
||||
|
||||
Kickstart your Angular development with this ready-to-use starter project integrated with [Appwrite](https://www.appwrite.io)
|
||||
|
||||
## 🚀Getting started
|
||||
|
||||
###
|
||||
|
||||
Clone the Project
|
||||
Clone this repository to your local machine using Git:
|
||||
|
||||
`git clone https://github.com/appwrite/starter-for-angular`
|
||||
`git clone https://gitea.joshihomeserver.ipv64.net/josiadmin/appwrite-template-login`
|
||||
|
||||
## 🛠️ Development guide
|
||||
1. **Configure Appwrite**<br/>
|
||||
|
||||
1. **Configure Appwrite**
|
||||
Navigate to `/environments/environment{.development}.ts` and update the values to match your Appwrite project credentials.
|
||||
2. **Customize as needed**<br/>
|
||||
2. **Customize as needed**
|
||||
Modify the starter kit to suit your app's requirements. Adjust UI, features, or backend
|
||||
integrations as per your needs.
|
||||
3. **Install dependencies**<br/>
|
||||
3. **Install Angular/CLI**
|
||||
Run`npm install -g @angular/cli`
|
||||
4. **Install dependencies**
|
||||
Run `npm install` to install all dependencies.
|
||||
4. **Run the app**<br/>
|
||||
5. **Run the app**
|
||||
Start the project by running `ng serve`.
|
||||
6. **Run in Debug Mode in VsCode by**
|
||||
Tipping F5.
|
||||
|
||||
## 💡 Additional notes
|
||||
|
||||
- This starter project is designed to streamline your Angular development with Appwrite.
|
||||
- Refer to the [Appwrite documentation](https://appwrite.io/docs) for detailed integration guidance.
|
||||
- Images in the public/img Folder are test Images to change with yours, it will be loading in the styles.css File
|
||||
- A Dockerfile is on the root Directory to make on a Docker Server a full Web-App
|
||||
- Bevore you make a full Web-App you need to build the app for Production with `ng build --configuration=production` .
|
||||
- In the angular.json file you make a entry under server with option to your one web-address-server, in this file you find the etry by searching for `test.123server.at`.
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"$schema": "@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"angular-starter-kit-for-appwrite": {
|
||||
"projectType": "application",
|
||||
"schematics": {},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular/build:application",
|
||||
"options": {
|
||||
"outputPath": "dist/web-kegel-app-angular",
|
||||
"index": "src/index.html",
|
||||
"browser": "src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "public"
|
||||
}
|
||||
],
|
||||
"styles": ["src/styles.css"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kB",
|
||||
"maximumError": "1MB"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "4kB",
|
||||
"maximumError": "8kB"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.development.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular/build:dev-server",
|
||||
"options": {
|
||||
"allowedHosts": [
|
||||
"test.123server.at"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "angular-starter-kit-for-appwrite:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "angular-starter-kit-for-appwrite:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular/build:extract-i18n"
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular/build:karma",
|
||||
"options": {
|
||||
"polyfills": ["zone.js", "zone.js/testing"],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "public"
|
||||
}
|
||||
],
|
||||
"styles": ["src/styles.css"],
|
||||
"scripts": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"analytics": false
|
||||
},
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"type": "component"
|
||||
},
|
||||
"@schematics/angular:directive": {
|
||||
"type": "directive"
|
||||
},
|
||||
"@schematics/angular:service": {
|
||||
"type": "service"
|
||||
},
|
||||
"@schematics/angular:guard": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:interceptor": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:module": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:pipe": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:resolver": {
|
||||
"typeSeparator": "."
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+10673
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "web-kegel-app-angular",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^20.3.2",
|
||||
"@angular/common": "^20.3.2",
|
||||
"@angular/compiler": "^20.3.2",
|
||||
"@angular/core": "^20.3.2",
|
||||
"@angular/forms": "^20.3.2",
|
||||
"@angular/platform-browser": "^20.3.2",
|
||||
"@angular/platform-browser-dynamic": "^20.3.2",
|
||||
"@angular/router": "^20.3.2",
|
||||
"@fortawesome/fontawesome-free": "^7.0.1",
|
||||
"@tailwindcss/postcss": "^4.0.15",
|
||||
"appwrite": "^17.0.0",
|
||||
"postcss": "^8.5.3",
|
||||
"rxjs": "~7.8.0",
|
||||
"tailwindcss": "^4.0.15",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/build": "^20.3.3",
|
||||
"@angular/cli": "^20.3.3",
|
||||
"@angular/compiler-cli": "^20.3.2",
|
||||
"@types/jasmine": "~5.1.0",
|
||||
"jasmine-core": "~5.5.0",
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
"karma-coverage": "~2.2.0",
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.1.0",
|
||||
"postcss": "^8.5.3",
|
||||
"prettier": "^3.5.1",
|
||||
"typescript": "~5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Script used during deployment on Appwrite Sites
|
||||
|
||||
# Replace [appwriteEndpoint] with APPWRITE_ENDPOINT in environments files
|
||||
sed -i "s|\[appwriteEndpoint\]|$APPWRITE_ENDPOINT|g" src/environments/*.ts
|
||||
|
||||
# Replace [appwriteProjectId] with APPWRITE_PROJECT_ID in environments files
|
||||
sed -i "s|\[appwriteProjectId\]|$APPWRITE_PROJECT_ID|g" src/environments/*.ts
|
||||
|
||||
# Replace [appwriteProjectName] with APPWRITE_PROJECT_NAME in environments files
|
||||
sed -i "s|\[appwriteProjectName\]|$APPWRITE_PROJECT_NAME|g" src/environments/*.ts
|
||||
@@ -0,0 +1,14 @@
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 250 250" style="enable-background:new 0 0 250 250;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#DD0031;}
|
||||
.st1{fill:#C3002F;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<polygon class="st0" points="125,30 125,30 125,30 31.9,63.2 46.1,186.3 125,230 125,230 125,230 203.9,186.3 218.1,63.2 "/>
|
||||
<polygon class="st1" points="125,30 125,52.2 125,52.1 125,153.4 125,153.4 125,230 125,230 203.9,186.3 218.1,63.2 125,30 "/>
|
||||
<path class="st2" d="M125,52.1L66.8,182.6h0h21.7h0l11.7-29.2h49.4l11.7,29.2h0h21.7h0L125,52.1L125,52.1L125,52.1L125,52.1
|
||||
L125,52.1z M142,135.4H108l17-40.9L142,135.4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 762 B |
@@ -0,0 +1,8 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M24.4429 16.4322V21.9096H10.7519C6.76318 21.9096 3.28044 19.7067 1.4171 16.4322C1.14622 15.9561 0.909137 15.4567 0.710264 14.9383C0.319864 13.9225 0.0744552 12.8325 0 11.6952V10.2143C0.0161646 9.96089 0.0416361 9.70942 0.0749451 9.46095C0.143032 8.95105 0.245898 8.45211 0.381093 7.96711C1.66006 3.36909 5.81877 0 10.7519 0C15.6851 0 19.8433 3.36909 21.1223 7.96711H15.2682C14.3072 6.4683 12.6437 5.4774 10.7519 5.4774C8.86017 5.4774 7.19668 6.4683 6.23562 7.96711C5.9427 8.42274 5.71542 8.92516 5.56651 9.46095C5.43425 9.93599 5.36371 10.4369 5.36371 10.9548C5.36371 12.5248 6.01324 13.94 7.05463 14.9383C8.01961 15.865 9.32061 16.4322 10.7519 16.4322H24.4429Z"
|
||||
fill="#FD366E" />
|
||||
<path
|
||||
d="M24.4429 9.46094V14.9383H14.4492C15.4906 13.94 16.1401 12.5248 16.1401 10.9548C16.1401 10.4369 16.0696 9.93598 15.9373 9.46094H24.4429Z"
|
||||
fill="#FD366E" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 977 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -0,0 +1,5 @@
|
||||
<main>
|
||||
<!-- Hier wird der Inhalt deiner gerouteten Seiten angezeigt -->
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Component} from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: true,
|
||||
imports: [RouterOutlet],
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css'],
|
||||
})
|
||||
export class AppComponent{
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { importProvidersFrom } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms'; // <-- Wichtig!
|
||||
|
||||
import { routes } from './app.routes';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideRouter(routes),
|
||||
importProvidersFrom(ReactiveFormsModule) // <-- Bereitstellen
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { LoginComponent } from './components/login/login.component';
|
||||
import { RegisterComponent } from './components/register/register.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: '', redirectTo: '/login', pathMatch: 'full' },
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: 'register', component: RegisterComponent},
|
||||
{ path: '**', redirectTo: '/login' },
|
||||
];
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
.headerText {
|
||||
text-align: center;
|
||||
color: rgb(42, 42, 88);
|
||||
font-weight: bold;
|
||||
font-size: 1.75rem;
|
||||
font-family: "Libre Baskerville", serif;
|
||||
}
|
||||
|
||||
i{
|
||||
color: rgb(42, 42, 88);
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<div class="flex flex-row justify-between items-center bg-red-500/80 py-4 px-2">
|
||||
<h2 class="headerText pl-4 ">Kegel Spielplan</h2>
|
||||
<div>
|
||||
<i class="fa-solid fa-file-lines fa-2xl pr-10" (click)="goToSummery()"></i>
|
||||
<i class="fa-solid fa-file-circle-plus fa-2xl pr-10" (click)="goToInput()" ></i>
|
||||
<i class="fa-solid fa-right-from-bracket fa-2xl pr-10" (click)="logout()"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { AppwriteService } from '../../services/appwrite.service';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
templateUrl: './header.component.html',
|
||||
styleUrl: './header.component.css',
|
||||
})
|
||||
export class HeaderComponentComponent {
|
||||
|
||||
constructor(
|
||||
private appwriteService: AppwriteService,
|
||||
private routes: Router,
|
||||
) {}
|
||||
|
||||
goToSummery() {
|
||||
// this.routes.navigate(['/list']);
|
||||
}
|
||||
|
||||
goToInput() {
|
||||
// this.routes.navigate(['/input']);
|
||||
}
|
||||
|
||||
async logout() {
|
||||
try {
|
||||
const accountService = await this.appwriteService.accountService;
|
||||
await this.appwriteService.accountService.deleteSession(
|
||||
(await accountService.getSession('current')).$id,
|
||||
);
|
||||
// Bei erfolgreicher Abmeldung
|
||||
//this.toast.success('Logout erfolgreich!', 'Auf Wiedersehen!');
|
||||
this.routes.navigate(['/login']);
|
||||
} catch (err: any) {
|
||||
console.error('Fehler beim Abmelden:', err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<main class="login-container">
|
||||
<div class="mt-8 flex flex-col items-center justify-center rounded-lg bg-red-500/30 p-6 shadow-md">
|
||||
<h2 class="mb-4 text-4xl font-bold text-[#000000FF]">Pinin</h2>
|
||||
<form class="flex flex-col gap-4" (ngSubmit)="login()">
|
||||
<div>
|
||||
<label for="username" class="sr-only">Benutzername</label>
|
||||
<input
|
||||
id="username"
|
||||
type="email"
|
||||
[(ngModel)]="email"
|
||||
placeholder="E-Mail-Adresse"
|
||||
name="email"
|
||||
required
|
||||
class="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-[#000000] focus:outline-none focus:ring-1 focus:ring-[#030303]
|
||||
text-black
|
||||
text-xl
|
||||
bg-white"
|
||||
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="password" class="sr-only">Passwort</label>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
placeholder="Passwort"
|
||||
class="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-[#000000] focus:outline-none focus:ring-1 focus:ring-[#000000] text-black
|
||||
text-xl
|
||||
bg-white"
|
||||
[(ngModel)]="password"
|
||||
name="password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
class="text-xl cursor-pointer rounded-md bg-[#ff0048] px-4 py-2 text-white hover:bg-[#E03164] focus:outline-none focus:ring-2 focus:ring-[#FD366E] focus:ring-offset-2">
|
||||
Anmelden
|
||||
</button>
|
||||
<button (click)="logout()" type="button" class="text-xl cursor-pointer rounded-md bg-[#168B07FF] px-4 py-2 text-white hover:bg-[#034E13FF] focus:outline-none focus:ring-2 focus:ring-[#168B07FF] focus:ring-offset-2">
|
||||
Logout
|
||||
</button>
|
||||
</form>
|
||||
<p class="pt-2 text-gray-800">Or you can here <span class="text-blue-600"><button (click)="register()" type="button" class="cursor-pointer">Sign in</button></span> to the Applikation</p>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { AppwriteService } from '../../services/appwrite.service';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule],
|
||||
templateUrl: './login.component.html',
|
||||
styleUrl: './login.component.css'
|
||||
})
|
||||
export class LoginComponent {
|
||||
detailHeight: number = 0;
|
||||
|
||||
email = '';
|
||||
password = '';
|
||||
sessionId = '';
|
||||
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private appwriteService: AppwriteService
|
||||
) {}
|
||||
|
||||
|
||||
register() {
|
||||
this.router.navigate(['/register']);
|
||||
}
|
||||
|
||||
async logout() {
|
||||
try {
|
||||
await this.appwriteService.accountService.deleteSession(this.sessionId).then((response) => {
|
||||
this.sessionId = '';
|
||||
this.email = '';
|
||||
this.password = '';
|
||||
alert('Erfolgreich abgemeldet');
|
||||
}).catch((error) => {
|
||||
console.error('Fehler beim Abmelden: ' + error.message);
|
||||
});
|
||||
} catch (err: any) {
|
||||
console.error('Logout fehlgeschlagen: ' + err.message);
|
||||
}
|
||||
}
|
||||
async login() {
|
||||
try {
|
||||
await this.appwriteService.accountService.createEmailPasswordSession(
|
||||
this.email,
|
||||
this.password,
|
||||
).then((response) => {
|
||||
this.sessionId = response.$id;
|
||||
this.email = '';
|
||||
this.password = '';
|
||||
//this.router.navigate(['/input']);
|
||||
}).catch((error) => {
|
||||
console.error('Fehler beim Anmelden: ' + error.message);
|
||||
alert('Fehler beim Anmelden: ' + error.message);
|
||||
});
|
||||
} catch (err: any) {
|
||||
console.error('Anmeldung fehlgeschlagen: ' + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
summary::-webkit-details-marker {
|
||||
display: none
|
||||
}
|
||||
|
||||
.checker-background::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-image: linear-gradient(#e6e6e690 1px, transparent 1px),
|
||||
linear-gradient(90deg, #e6e6e690 1px, transparent 1px);
|
||||
background-size: 3.7em 3.7em;
|
||||
-webkit-mask-image: radial-gradient(ellipse at 50% 40%, black 0%, transparent 55%);
|
||||
mask-image: radial-gradient(ellipse at 50% 40%, black 0%, transparent 55%);
|
||||
z-index: -1;
|
||||
background-position-x: center;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<main class="login-container">
|
||||
<div class="mt-8 flex flex-col items-center justify-center rounded-lg bg-red-500/30 p-6 shadow-md">
|
||||
<h2 class="mb-4 text-4xl font-bold text-[#050505FF]">Registrieren</h2>
|
||||
<form class="flex flex-col gap-4" (ngSubmit)="registerUser()">
|
||||
<div>
|
||||
<label for="username" class="sr-only">Benutzer</label>
|
||||
<input
|
||||
id="username"
|
||||
type="text"
|
||||
[(ngModel)]="userName"
|
||||
placeholder="Benutzer Name"
|
||||
name="username"
|
||||
required
|
||||
class="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-[#000000] focus:outline-none focus:ring-1 focus:ring-[#030303]
|
||||
text-black
|
||||
text-xl
|
||||
bg-white"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="email" class="sr-only">Email</label>
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
[(ngModel)]="email"
|
||||
placeholder="E-Mail-Adresse"
|
||||
name="email"
|
||||
required
|
||||
class="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-[#000000] focus:outline-none focus:ring-1 focus:ring-[#030303]
|
||||
text-black
|
||||
text-xl
|
||||
bg-white"
|
||||
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="password" class="sr-only">Passwort</label>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
placeholder="Passwort"
|
||||
class="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-[#000000] focus:outline-none focus:ring-1 focus:ring-[#000000] text-black
|
||||
text-xl
|
||||
bg-white"
|
||||
[(ngModel)]="password"
|
||||
name="password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
class="text-xl cursor-pointer rounded-md bg-[#ff0048] px-4 py-2 text-white hover:bg-[#E03164] focus:outline-none focus:ring-2 focus:ring-[#FD366E] focus:ring-offset-2">
|
||||
Register
|
||||
</button>
|
||||
</form>
|
||||
<p class="pt-2 text-gray-800">Or you can here <span class="text-blue-600"><button (click)="goTologin()" type="button" class="cursor-pointer">Log in</button></span> to the Applikation</p>
|
||||
</div>
|
||||
</main>
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { AppwriteService } from '../../services/appwrite.service';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-register',
|
||||
imports: [CommonModule, FormsModule],
|
||||
templateUrl: './register.component.html',
|
||||
styleUrl: './register.component.css'
|
||||
})
|
||||
export class RegisterComponent {
|
||||
|
||||
email = 'ich@example.com';
|
||||
userName = 'TestUser';
|
||||
password = '123456789';
|
||||
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private appwriteService: AppwriteService
|
||||
) { }
|
||||
|
||||
async registerUser(): Promise<void>{
|
||||
try {
|
||||
const responseUserSignIn = await this.appwriteService.register(this.email, this.password, this.userName);
|
||||
this.router.navigate(['/login']);
|
||||
} catch (error) {
|
||||
console.log('Registrierung fehlgeschlagen :' + error);
|
||||
}
|
||||
}
|
||||
|
||||
goTologin() {
|
||||
this.router.navigate(['/login']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Client, Account, Databases, ID, Query, Models } from 'appwrite';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { Observable, from } from 'rxjs';
|
||||
import { tap, map } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AppwriteService {
|
||||
private client: Client;
|
||||
private account: Account;
|
||||
private databases: Databases;
|
||||
private readonly localStorageKey = 'appwriteRecords';
|
||||
|
||||
constructor() {
|
||||
this.client = new Client()
|
||||
.setEndpoint(environment.appwriteEndpoint) // Your Appwrite API endpoint
|
||||
.setProject(environment.appwriteProjectId); // Your project ID
|
||||
this.account = new Account(this.client);
|
||||
this.databases = new Databases(this.client);
|
||||
}
|
||||
|
||||
// --- Account Service ---
|
||||
|
||||
get accountService(): Account {
|
||||
return this.account;
|
||||
}
|
||||
|
||||
async register(email: string, password: string, name: string): Promise<any> {
|
||||
return await this.account.create(ID.unique(), email, password, name);
|
||||
}
|
||||
|
||||
// --- CRUD Operations for Databases ---
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new document in a specified collection.
|
||||
* @param databaseId The ID of the database.
|
||||
* @param collectionId The ID of the collection.
|
||||
* @param data The data object for the new document.
|
||||
* @returns A promise with the created document.
|
||||
*/
|
||||
async createDocument(data: any): Promise<any> {
|
||||
try {
|
||||
const result = await this.databases.createDocument(
|
||||
environment.appwriteDatabaseId,
|
||||
environment.appwriteCollectionId,
|
||||
ID.unique(),
|
||||
data,
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error creating document:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single document from a collection.
|
||||
* @param databaseId The ID of the database.
|
||||
* @param collectionId The ID of the collection.
|
||||
* @param documentId The ID of the document to retrieve.
|
||||
* @returns A promise with the retrieved document.
|
||||
*/
|
||||
async getDocument(documentId: string): Promise<any> {
|
||||
try {
|
||||
const result = await this.databases.getDocument(
|
||||
environment.appwriteDatabaseId,
|
||||
environment.appwriteCollectionId,
|
||||
documentId,
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error getting document:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists documents from a specified collection with optional queries.
|
||||
* @param databaseId The ID of the database.
|
||||
* @param collectionId The ID of the collection.
|
||||
* @param queries An array of Query objects to filter the results (e.g., [Query.equal('name', 'John')]).
|
||||
* @returns A promise with the list of documents.
|
||||
*/
|
||||
public getRecords(queries: string[] = []): Observable<any> {
|
||||
//If no Data in localStorage
|
||||
return from(
|
||||
this.databases.listDocuments(
|
||||
environment.appwriteDatabaseId,
|
||||
environment.appwriteCollectionId,
|
||||
queries,
|
||||
),
|
||||
).pipe(
|
||||
map((response: Models.DocumentList<any>) => response.documents),
|
||||
tap((documents: any) => {
|
||||
this.saveToLocalStorage(documents);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// Rest deines Codes bleibt unverändert
|
||||
private saveToLocalStorage(data: any): void {
|
||||
try {
|
||||
localStorage.setItem(this.localStorageKey, JSON.stringify(data));
|
||||
} catch (e) {
|
||||
console.error('Fehler beim Speichern im LocalStorage', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Lädt die Daten aus dem LocalStorage und parst sie als JSON
|
||||
private loadFromLocalStorage(): any | null {
|
||||
try {
|
||||
const storedData = localStorage.getItem(this.localStorageKey);
|
||||
return storedData ? JSON.parse(storedData) : null;
|
||||
} catch (e) {
|
||||
console.error('Fehler beim Laden aus LocalStorage', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// async listDocuments(
|
||||
// queries: string[] = []
|
||||
// ): Promise<any> {
|
||||
// try {
|
||||
// const result = await this.databases.listDocuments(
|
||||
// environment.appwriteDatabaseId,
|
||||
// environment.appwriteCollectionId,
|
||||
// queries
|
||||
// );
|
||||
// return result;
|
||||
// } catch (error) {
|
||||
// console.error('Error listing documents:', error);
|
||||
// throw error;
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Updates an existing document in a collection.
|
||||
* @param databaseId The ID of the database.
|
||||
* @param collectionId The ID of the collection.
|
||||
* @param documentId The ID of the document to update.
|
||||
* @param data The new data object to merge with the existing document.
|
||||
* @returns A promise with the updated document.
|
||||
*/
|
||||
async updateDocument(documentId: string, data: any): Promise<any> {
|
||||
try {
|
||||
const result = await this.databases.updateDocument(
|
||||
environment.appwriteDatabaseId,
|
||||
environment.appwriteCollectionId,
|
||||
documentId,
|
||||
data,
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error updating document:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a document from a collection.
|
||||
* @param databaseId The ID of the database.
|
||||
* @param collectionId The ID of the collection.
|
||||
* @param documentId The ID of the document to delete.
|
||||
* @returns A promise that resolves upon successful deletion.
|
||||
*/
|
||||
async deleteDocument(documentId: string): Promise<any> {
|
||||
try {
|
||||
await this.databases.deleteDocument(
|
||||
environment.appwriteDatabaseId,
|
||||
environment.appwriteCollectionId,
|
||||
documentId,
|
||||
);
|
||||
return { success: true, message: 'Document deleted successfully.' };
|
||||
} catch (error) {
|
||||
console.error('Error deleting document:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export const environment: {
|
||||
appwriteEndpoint: string;
|
||||
appwriteProjectId: string;
|
||||
appwriteProjectName: string;
|
||||
appwriteDatabaseId: string;
|
||||
appwriteCollectionId: string;
|
||||
} = {
|
||||
appwriteEndpoint: '<Your endpoint URL>', // Your Appwrite Endpoint
|
||||
appwriteProjectId: '<123456789abcdefgh>', // Your project ID
|
||||
appwriteProjectName: '<Your Project name>', // Your project name
|
||||
appwriteDatabaseId: '<123456789abcdefgh>', // Your database ID
|
||||
appwriteCollectionId: '<123456789abcdefgh>', // Your collection ID
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
export const environment: {
|
||||
appwriteEndpoint: string;
|
||||
appwriteProjectId: string;
|
||||
appwriteProjectName: string;
|
||||
appwriteDatabaseId: string;
|
||||
appwriteCollectionId: string;
|
||||
} = {
|
||||
appwriteEndpoint: '<Your endpoint URL>', // Your Appwrite Endpoint
|
||||
appwriteProjectId: '<123456789abcdefgh>', // Your project ID
|
||||
appwriteProjectName: '<Your Project name>', // Your project name
|
||||
appwriteDatabaseId: '<123456789abcdefgh>', // Your database ID
|
||||
appwriteCollectionId: '<123456789abcdefgh>', // Your collection ID
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Appwrite + Angular</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/svg+xml" href="/appwrite.svg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Inter:opsz,wght@14..32,100..900&family=Poppins:wght@300;400&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink-icons" />
|
||||
</head>
|
||||
<body class="bg-[#FAFAFB] font-[Inter] text-sm text-[#56565C]">
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,7 @@
|
||||
import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { appConfig } from './app/app.config';
|
||||
import { AppComponent } from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
@import "tailwindcss";
|
||||
@import "@fortawesome/fontawesome-free/css/all.min.css";
|
||||
|
||||
.login-container {
|
||||
/* Positioniere den Container, um den gesamten Viewport abzudecken */
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
/* Füge das Hintergrundbild hinzu */
|
||||
background-image: url('/assets/img/KegelGaudi2025.png');
|
||||
|
||||
/* Stelle sicher, dass das Bild den gesamten Container ausfüllt */
|
||||
background-size: cover;
|
||||
|
||||
/* Zentriere das Bild horizontal und vertikal */
|
||||
background-position: center;
|
||||
|
||||
/* Verhindere, dass sich das Bild wiederholt */
|
||||
background-repeat: no-repeat;
|
||||
|
||||
/* Setze ein Overlay (optional), um den Text lesbarer zu machen */
|
||||
/* background-color: rgba(0, 0, 0, 0.5); Semi-transparentes Schwarz */
|
||||
background-blend-mode: overlay;
|
||||
|
||||
/* Zentriere die Login-Karte */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.input-container{
|
||||
/* Positioniere den Container, um den gesamten Viewport abzudecken */
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
/* Füge das Hintergrundbild hinzu */
|
||||
background-image: url('/assets/img/InputKegel.png');
|
||||
|
||||
/* Stelle sicher, dass das Bild den gesamten Container ausfüllt */
|
||||
background-size: cover;
|
||||
|
||||
/* Zentriere das Bild horizontal und vertikal */
|
||||
background-position: center;
|
||||
|
||||
/* Verhindere, dass sich das Bild wiederholt */
|
||||
background-repeat: no-repeat;
|
||||
|
||||
/* Setze ein Overlay (optional), um den Text lesbarer zu machen */
|
||||
/* background-color: rgba(0, 0, 0, 0.5); Semi-transparentes Schwarz */
|
||||
background-blend-mode: overlay;
|
||||
|
||||
/* Zentriere die Login-Karte */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.kegel-container {
|
||||
max-width: 800px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 75vh;
|
||||
margin: 2rem auto;
|
||||
padding: 1rem;
|
||||
font-family: "Libre Baskerville", serif;
|
||||
}
|
||||
/* Definiert den Bereich, der scrollen soll */
|
||||
.scrollable-content {
|
||||
flex: 2; /* Nimmt den verfügbaren Platz ein */
|
||||
overflow-y: auto; /* Erlaubt vertikales Scrollen in diesem Block */
|
||||
}
|
||||
|
||||
.save-button {
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 1.1rem;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.save-button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
}
|
||||
.form-group label {
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: bold;
|
||||
font-size: 1.3em;
|
||||
color: rgb(3, 3, 3);
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #020202;
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: red;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/app",
|
||||
"types": []
|
||||
},
|
||||
"files": ["src/main.ts"],
|
||||
"include": ["src/**/*.d.ts"]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/out-tsc",
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"skipLibCheck": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "bundler",
|
||||
"importHelpers": true,
|
||||
"target": "ES2022",
|
||||
"module": "ES2022"
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/spec",
|
||||
"types": ["jasmine"]
|
||||
},
|
||||
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user