Compare commits
27 Commits
17af0f2015
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a9b40bb9de | |||
| 6bd7377a3f | |||
| a96f742b52 | |||
| 56b359df87 | |||
| 02de90fa4a | |||
| 596c205f3d | |||
| 117c7fc1f8 | |||
| 1c9b4ce53f | |||
| 71c44f146f | |||
| 120f0cdc96 | |||
| b1db249a99 | |||
| fcf7e5e8c0 | |||
| b1c4c1b75f | |||
| 18069d883c | |||
| 5cdd313e5b | |||
| 634a5fe298 | |||
| ede1f34930 | |||
|
|
b9cbfa0d50 | ||
| 32b244a42e | |||
| 94e5973f88 | |||
| 712baefa7f | |||
| dd6dbb6236 | |||
| 170b472545 | |||
| e2232af098 | |||
| 2a1a68e969 | |||
| cf3f5b11ac | |||
| 64ca83083e |
39
.gitea/workflows/build-and-deploy.yaml
Normal file
39
.gitea/workflows/build-and-deploy.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Build and Deploy develop
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
builds:
|
||||
runs-on: host
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm install
|
||||
npm install -g @angular/cli
|
||||
|
||||
- name: Build Angular project
|
||||
run: ng build --configuration=production
|
||||
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
docker build -t 192.168.2.28:5050/tusha-fe:latest .
|
||||
|
||||
- name: Push Docker image
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
run: |
|
||||
echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
|
||||
docker push 192.168.2.28:5050/tusha-fe:latest
|
||||
|
||||
16
Dockerfile
Normal file
16
Dockerfile
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM node:20-bullseye as build
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
|
||||
RUN npm install
|
||||
RUN npm install -g @angular/cli
|
||||
|
||||
COPY . ./
|
||||
|
||||
RUN ng build --configuration=production
|
||||
|
||||
FROM nginx:latest
|
||||
COPY --from=build app/dist/aftas-angular /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
@@ -126,7 +126,10 @@
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"schematicCollections": ["@ionic/angular-toolkit"]
|
||||
"schematicCollections": [
|
||||
"@ionic/angular-toolkit"
|
||||
],
|
||||
"analytics": false
|
||||
},
|
||||
"schematics": {
|
||||
"@ionic/angular-toolkit:component": {
|
||||
|
||||
3588
package-lock.json
generated
3588
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -21,11 +21,11 @@
|
||||
"@angular/platform-browser": "^17.3.0",
|
||||
"@angular/platform-browser-dynamic": "^17.3.0",
|
||||
"@angular/router": "^17.3.0",
|
||||
"@capacitor/app": "5.0.6",
|
||||
"@capacitor/core": "5.6.0",
|
||||
"@capacitor/haptics": "5.0.6",
|
||||
"@capacitor/keyboard": "5.0.7",
|
||||
"@capacitor/status-bar": "5.0.6",
|
||||
"@capacitor/app": "5.0.8",
|
||||
"@capacitor/core": "5.7.8",
|
||||
"@capacitor/haptics": "5.0.8",
|
||||
"@capacitor/keyboard": "5.0.9",
|
||||
"@capacitor/status-bar": "5.0.8",
|
||||
"@ionic/angular": "^7.5.0",
|
||||
"chart.js": "^4.4.1",
|
||||
"ionicons": "^7.2.1",
|
||||
@@ -43,14 +43,14 @@
|
||||
"@angular/cli": "^17.3.0",
|
||||
"@angular/compiler-cli": "^17.3.0",
|
||||
"@angular/language-service": "^17.3.0",
|
||||
"@capacitor/cli": "5.6.0",
|
||||
"@capacitor/cli": "5.7.8",
|
||||
"@ionic/angular-toolkit": "^9.0.0",
|
||||
"@types/jasmine": "~5.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-plugin-import": "2.22.1",
|
||||
"eslint-plugin-jsdoc": "30.7.6",
|
||||
"eslint-plugin-jsdoc": "30.7.13",
|
||||
"eslint-plugin-prefer-arrow": "1.2.2",
|
||||
"jasmine-core": "~5.1.0",
|
||||
"jasmine-spec-reporter": "~5.0.0",
|
||||
|
||||
84
renovate.json
Normal file
84
renovate.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:recommended"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"@angular/**",
|
||||
"@angular-devkit/**",
|
||||
"@angular-eslint/**"
|
||||
],
|
||||
"allowedVersions": ">=17.0.0 <18.0.0"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"@angular/animations",
|
||||
"@angular/common",
|
||||
"@angular/compiler",
|
||||
"@angular/core",
|
||||
"@angular/forms",
|
||||
"@angular/platform-browser",
|
||||
"@angular/platform-browser-dynamic",
|
||||
"@angular/router",
|
||||
"@angular/compiler-cli",
|
||||
"@angular/language-service"
|
||||
],
|
||||
"groupName": "Angular framework"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"@angular/cli",
|
||||
"@angular-devkit/build-angular"
|
||||
],
|
||||
"groupName": "Angular CLI"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"typescript"
|
||||
],
|
||||
"allowedVersions": ">=5.2.0 <5.5.0"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"node"
|
||||
],
|
||||
"allowedVersions": "^18.13.0 || ^20.9.0"
|
||||
},
|
||||
{
|
||||
"description": [
|
||||
"Ionic requires RxJS 7.5 or newer within Angular's supported major"
|
||||
],
|
||||
"matchPackageNames": [
|
||||
"rxjs"
|
||||
],
|
||||
"allowedVersions": ">=7.5.0 <8.0.0"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"zone.js"
|
||||
],
|
||||
"allowedVersions": ">=0.14.0 <0.15.0"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"@ionic/angular"
|
||||
],
|
||||
"allowedVersions": ">=7.5.0 <8.0.0"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"@ionic/angular-toolkit"
|
||||
],
|
||||
"allowedVersions": ">=9.0.0 <10.0.0"
|
||||
},
|
||||
{
|
||||
"matchPackageNames": [
|
||||
"@capacitor/**"
|
||||
],
|
||||
"allowedVersions": ">=5.0.0 <6.0.0",
|
||||
"groupName": "Capacitor"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,29 +1,58 @@
|
||||
import {FocusState} from "./focus-state";
|
||||
import {state} from "@angular/animations";
|
||||
|
||||
export class FocusStats {
|
||||
private _focusCycles: number = 0;
|
||||
private _focusTimeInMs: number = 0;
|
||||
private _focusTime: string = '';
|
||||
private _shortBreakCycles: number = 0;
|
||||
private _longBreakCycles: number = 0;
|
||||
private _breakTimeInMs: number = 0;
|
||||
private _breakTime: string = '';
|
||||
|
||||
inc(state: FocusState, deltaInMs?: number): void {
|
||||
switch (state) {
|
||||
case FocusState.FOCUS:
|
||||
this._focusCycles++;
|
||||
this._focusTimeInMs += !!deltaInMs ? deltaInMs : 0;
|
||||
this.updateFocusTime();
|
||||
break;
|
||||
case FocusState.SHORT_BREAK:
|
||||
this._shortBreakCycles++;
|
||||
this._breakTimeInMs += !!deltaInMs ? deltaInMs : 0;
|
||||
this.updateBreakTime();
|
||||
break;
|
||||
case FocusState.LONG_BREAK:
|
||||
this._longBreakCycles++;
|
||||
this._breakTimeInMs += !!deltaInMs ? deltaInMs : 0;
|
||||
this.updateBreakTime();
|
||||
break;
|
||||
default:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private updateFocusTime() {
|
||||
this._focusTime = this.transformTime(this._focusTimeInMs);
|
||||
}
|
||||
|
||||
private updateBreakTime() {
|
||||
this._breakTime = this.transformTime(this._breakTimeInMs);
|
||||
}
|
||||
|
||||
private transformTime(ms: number): string {
|
||||
const totalSeconds = Math.floor(ms / 1000);
|
||||
const seconds = totalSeconds % 60;
|
||||
const totalMinutes = Math.floor(totalSeconds / 60);
|
||||
const minutes = totalMinutes % 60;
|
||||
const hours = Math.floor(totalMinutes / 60);
|
||||
|
||||
const pad = (n: number) => n.toString().padStart(2, "0");
|
||||
|
||||
if (hours > 0) {
|
||||
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
|
||||
} else {
|
||||
return `${pad(minutes)}:${pad(seconds)}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +60,6 @@ export class FocusStats {
|
||||
return this._focusCycles;
|
||||
}
|
||||
|
||||
get focusTimeInMs(): number {
|
||||
return this._focusTimeInMs;
|
||||
}
|
||||
|
||||
get shortBreakCycles(): number {
|
||||
return this._shortBreakCycles;
|
||||
}
|
||||
@@ -43,7 +68,12 @@ export class FocusStats {
|
||||
return this._longBreakCycles;
|
||||
}
|
||||
|
||||
get breakTimeInMs(): number {
|
||||
return this._breakTimeInMs;
|
||||
|
||||
get focusTime(): string {
|
||||
return this._focusTime;
|
||||
}
|
||||
|
||||
get breakTime(): string {
|
||||
return this._breakTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>
|
||||
<p>Focus tijd: <span>{{ ($stats | async)?.focusTimeInMs}}</span></p>
|
||||
<p>Focus tijd: <span>{{ ($stats | async)?.focusTime}}</span></p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
@@ -90,7 +90,7 @@
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>
|
||||
<p>Pauze tijd: <span>{{ ($stats | async)?.breakTimeInMs}}</span></p>
|
||||
<p>Pauze tijd: <span>{{ ($stats | async)?.breakTime}}</span></p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
@@ -32,6 +32,8 @@ export class FocusPage implements OnInit, OnDestroy {
|
||||
$stats: Observable<FocusStats> = this.focusService.$stats;
|
||||
|
||||
private endOfTimerChime: HTMLAudioElement;
|
||||
private forcedEndOfTimerChime: HTMLAudioElement;
|
||||
private windUpChime: HTMLAudioElement;
|
||||
|
||||
pathD: string = 'M100 10 A90 90 0 1 1 0 0';
|
||||
|
||||
@@ -39,6 +41,8 @@ export class FocusPage implements OnInit, OnDestroy {
|
||||
|
||||
constructor(private renderer: Renderer2, private focusService: FocusService) {
|
||||
this.endOfTimerChime = new Audio('../../../assets/race-start-beeps-125125.mp3');
|
||||
this.forcedEndOfTimerChime = new Audio('../../../assets/hardstop.mp3');
|
||||
this.windUpChime = new Audio('../../../assets/wind-up.mp3');
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -63,20 +67,24 @@ export class FocusPage implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private update() {
|
||||
const elapsed = Math.round((Date.now() - (this.timerStarted!)) / 1000); // in seconden
|
||||
const elapsed = this.timerStarted ? Math.round((Date.now() - (this.timerStarted)) / 1000) : 0; // in seconden
|
||||
let progress = elapsed / (this.duration * 60); // from 0 to 1
|
||||
|
||||
if( progress === 0) {
|
||||
progress = 0.0000001; // otherwise no graph
|
||||
}
|
||||
|
||||
if (progress >= 1) {
|
||||
if (progress >= 1 || isNaN(progress)) {
|
||||
if (this.duration === 0) {
|
||||
clearInterval(this.interval);
|
||||
this.timerStarted = null;
|
||||
}
|
||||
else if (progress === 1) {
|
||||
this.endOfTimerChime.play().catch(error => {
|
||||
console.error('Error playing audio:', error);
|
||||
});
|
||||
}
|
||||
progress = 1;
|
||||
this.endOfTimerChime.play().catch(error => {
|
||||
console.error('Error playing audio:', error);
|
||||
});
|
||||
clearInterval(this.interval);
|
||||
this.timerStarted = null;
|
||||
}
|
||||
|
||||
this.renderer.setStyle(
|
||||
@@ -95,8 +103,9 @@ export class FocusPage implements OnInit, OnDestroy {
|
||||
this.pathD = 'M100 10 A90 90 0 ' + (percentage > 0.5 ? '1' : '0') + ' 1 ' + circleEndX + ' ' + circleEndY;
|
||||
|
||||
const twoNumbers = (n: number) => n < 10 && n >= 0 ? '0' + n.toString() : n.toString();
|
||||
this.minutesText = twoNumbers(Math.max(Math.floor(timeLeft / 60), 0));
|
||||
this.secondsText = twoNumbers(Math.max(Math.floor(timeLeft % 60), 0));
|
||||
const floorPositiveCeilNegative = (n: number): number => n > 0 ? Math.floor(n) : Math.ceil(n);
|
||||
this.minutesText = twoNumbers(Math.abs(floorPositiveCeilNegative(timeLeft / 60)));
|
||||
this.secondsText = twoNumbers(Math.abs(floorPositiveCeilNegative(timeLeft % 60)));
|
||||
|
||||
this.dashOffset = elapsed;
|
||||
}
|
||||
@@ -121,27 +130,50 @@ export class FocusPage implements OnInit, OnDestroy {
|
||||
stopTimer() {
|
||||
this.focusRuns = 0;
|
||||
this.state = FocusState.STOPPED;
|
||||
this.stopStatsCounter();
|
||||
this.startTimer(0);
|
||||
this.forcedEndOfTimerChime.play().catch(error => {
|
||||
console.error('Error playing audio:', error);
|
||||
});
|
||||
}
|
||||
|
||||
private stopStatsCounter() {
|
||||
this.focusService.stopCurrent(this.timerStarted !== null);
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.windUpChime.play().catch(error => {
|
||||
console.error('Error playing audio:', error);
|
||||
});
|
||||
this.state = FocusState.FOCUS;
|
||||
this.startTimer(25);
|
||||
this.stopStatsCounter();
|
||||
this.focusService.startFocus();
|
||||
this.startTimer(0.3); // 25
|
||||
}
|
||||
|
||||
reload() {
|
||||
this.windUpChime.play().catch(error => {
|
||||
console.error('Error playing audio:', error);
|
||||
});
|
||||
if (!!this.timerStarted) {
|
||||
this.focusRuns = 0;
|
||||
}
|
||||
this.state = FocusState.SHORT_BREAK;
|
||||
this.startTimer(5);
|
||||
this.stopStatsCounter();
|
||||
this.focusService.startShortBreak();
|
||||
this.startTimer(0.1); // 5
|
||||
}
|
||||
|
||||
recharge() {
|
||||
this.windUpChime.play().catch(error => {
|
||||
console.error('Error playing audio:', error);
|
||||
});
|
||||
if (!!this.timerStarted) {
|
||||
this.focusRuns = 0;
|
||||
}
|
||||
this.state = FocusState.LONG_BREAK;
|
||||
this.startTimer(15);
|
||||
this.stopStatsCounter();
|
||||
this.focusService.startLongBreak();
|
||||
this.startTimer(0.2); // 15
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,35 +37,4 @@ export class FocusService {
|
||||
this.statsSubject.next(this.localStats);
|
||||
}
|
||||
}
|
||||
|
||||
private formatDelta(deltaInMs: number) {
|
||||
const totalSeconds = Math.floor(deltaInMs / 1000);
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
||||
const seconds = totalSeconds % 60;
|
||||
|
||||
const padZero = (num: number) => num.toString().padStart(2, '0');
|
||||
|
||||
return `${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)}`;
|
||||
}
|
||||
|
||||
getFocusCycles(): number {
|
||||
return this.localStats.focusCycles;
|
||||
}
|
||||
|
||||
getFocusTime(): string {
|
||||
return this.formatDelta(this.localStats.focusTimeInMs);
|
||||
}
|
||||
|
||||
getShortBreakCycles(): number {
|
||||
return this.localStats.shortBreakCycles;
|
||||
}
|
||||
|
||||
getLongBreakCycles(): number {
|
||||
return this.localStats.longBreakCycles;
|
||||
}
|
||||
|
||||
getBreakTime(): string {
|
||||
return this.formatDelta(this.localStats.breakTimeInMs);
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/assets/hardstop.mp3
Normal file
BIN
src/assets/hardstop.mp3
Normal file
Binary file not shown.
BIN
src/assets/wind-up.mp3
Normal file
BIN
src/assets/wind-up.mp3
Normal file
Binary file not shown.
Reference in New Issue
Block a user