From 24708e94ea191121163d6cfa6d45577cfa561616 Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Tue, 6 Aug 2024 22:49:06 +0200 Subject: [PATCH 01/19] #762 - First grab of api to test the data from the meticulous, and read + generate data to import --- .../meticulous/meticulousDevice.ts | 50 ++++++++++- ...ew-brewing-preparation-device.component.ts | 84 ++++++++++++++++++- 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/src/classes/preparationDevice/meticulous/meticulousDevice.ts b/src/classes/preparationDevice/meticulous/meticulousDevice.ts index ee5022de..93dbd744 100644 --- a/src/classes/preparationDevice/meticulous/meticulousDevice.ts +++ b/src/classes/preparationDevice/meticulous/meticulousDevice.ts @@ -1,5 +1,5 @@ import { PreparationDevice } from '../preparationDevice'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Preparation } from '../../preparation/preparation'; import { MeticulousShotData } from './meticulousShotData'; import Api, { @@ -10,6 +10,9 @@ import Api, { import { IMeticulousParams } from '../../../interfaces/preparationDevices/meticulous/iMeticulousParams'; import { Profile } from 'meticulous-typescript-profile'; +import { UILog } from '../../../services/uiLog'; +import { catchError, timeout } from 'rxjs/operators'; +import { of } from 'rxjs'; declare var cordova; declare var io; @@ -22,6 +25,8 @@ export class MeticulousDevice extends PreparationDevice { private _profiles: Array = []; + private serverURL: string = ''; + constructor(protected httpClient: HttpClient, _preparation: Preparation) { super(httpClient, _preparation); this.meticulousShotData = undefined; @@ -29,10 +34,53 @@ export class MeticulousDevice extends PreparationDevice { undefined, _preparation.connectedPreparationDevice.url ); + this.serverURL = _preparation.connectedPreparationDevice.url; if (typeof cordova !== 'undefined') { } } + public getHistory() { + const promise = new Promise((resolve, reject) => { + const httpOptions = { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + }), + }; + this.httpClient + .post( + this.serverURL + 'api/v1/history', + { + sort: 'desc', + max_results: 20, + }, + httpOptions + ) + .pipe( + timeout(10000), + catchError((e) => { + return of(null); + }) + ) + .toPromise() + .then( + (data: any) => { + console.log(data); + if (data && data.history) { + resolve(data.history); + } + }, + (error) => { + console.log(error); + reject(); + } + ) + .catch((error) => { + console.log(error); + reject(); + }); + }); + return promise; + } public getActualShotData() { return this.meticulousShotData; diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts index 34998a4d..a420664f 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts @@ -29,6 +29,14 @@ import { UISettingsStorage } from '../../../services/uiSettingsStorage'; import { Settings } from '../../../classes/settings/settings'; import { Preparation } from '../../../classes/preparation/preparation'; import { UIPreparationStorage } from '../../../services/uiPreparationStorage'; +import moment from 'moment'; +import { + BrewFlow, + IBrewPressureFlow, + IBrewRealtimeWaterFlow, + IBrewTemperatureFlow, + IBrewWeightFlow, +} from '../../../classes/brew/brewFlow'; @Component({ selector: 'brew-brewing-preparation-device', templateUrl: './brew-brewing-preparation-device.component.html', @@ -270,10 +278,13 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { this.data.preparationDeviceBrew.params = new MeticulousParams(); await connectedDevice.connectToSocket().then( - (_connected) => { + async (_connected) => { if (_connected) { this.preparationDevice = connectedDevice as MeticulousDevice; this.preparationDevice.loadProfiles(); + + const history = await this.preparationDevice.getHistory(); + this.readShot(history[0]); } }, () => { @@ -282,6 +293,77 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { ); } + private readShot(_historyData) { + const newMoment = moment(new Date()).startOf('day'); + + let firstDripTimeSet: boolean = false; + const newBrewFlow = new BrewFlow(); + + let seconds: number = 0; + let milliseconds: number = 0; + for (const entry of _historyData.data as any) { + const shotEntry: any = entry.shot; + const shotEntryTime = newMoment.clone().add('milliseconds', entry.time); + const timestamp = shotEntryTime.format('HH:mm:ss.SSS'); + + seconds = shotEntryTime.diff(newMoment, 'seconds'); + milliseconds = shotEntryTime.get('milliseconds'); + + const realtimeWaterFlow: IBrewRealtimeWaterFlow = + {} as IBrewRealtimeWaterFlow; + + realtimeWaterFlow.brew_time = ''; + realtimeWaterFlow.timestamp = timestamp; + realtimeWaterFlow.smoothed_weight = 0; + realtimeWaterFlow.flow_value = shotEntry.flow; + realtimeWaterFlow.timestampdelta = 0; + + newBrewFlow.realtimeFlow.push(realtimeWaterFlow); + + const brewFlow: IBrewWeightFlow = {} as IBrewWeightFlow; + brewFlow.timestamp = timestamp; + brewFlow.brew_time = ''; + brewFlow.actual_weight = shotEntry.weight; + brewFlow.old_weight = 0; + brewFlow.actual_smoothed_weight = 0; + brewFlow.old_smoothed_weight = 0; + brewFlow.not_mutated_weight = 0; + newBrewFlow.weight.push(brewFlow); + + if (shotEntry.weight > 0 && firstDripTimeSet === false) { + firstDripTimeSet = true; + + this.brewComponent.brewFirstDripTime.setTime(seconds, milliseconds); + this.brewComponent.brewFirstDripTime.changeEvent(); + } + + const pressureFlow: IBrewPressureFlow = {} as IBrewPressureFlow; + pressureFlow.timestamp = timestamp; + pressureFlow.brew_time = ''; + pressureFlow.actual_pressure = shotEntry.pressure; + pressureFlow.old_pressure = 0; + newBrewFlow.pressureFlow.push(pressureFlow); + + const temperatureFlow: IBrewTemperatureFlow = {} as IBrewTemperatureFlow; + temperatureFlow.timestamp = timestamp; + temperatureFlow.brew_time = ''; + temperatureFlow.actual_temperature = shotEntry.temperature; + temperatureFlow.old_temperature = 0; + newBrewFlow.temperatureFlow.push(temperatureFlow); + } + + const lastEntry = newBrewFlow.weight[newBrewFlow.weight.length - 1]; + const lastShotEntryTime = moment(lastEntry.timestamp); + + this.brewComponent.data.brew_beverage_quantity = lastEntry.actual_weight; + + this.brewComponent.timer.setTime(seconds, milliseconds); + this.brewComponent.timer.changeEvent(); + + this.brewComponent.brewBrewingGraphEl.flow_profile_raw = newBrewFlow; + this.brewComponent.brewBrewingGraphEl.initializeFlowChart(true); + } + public getPreparationDeviceType() { if (this.preparationDevice instanceof XeniaDevice) { return PreparationDeviceType.XENIA; From 81d2f8c14da566cebb0fed75f11528cb63dbd2a4 Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Wed, 7 Aug 2024 20:22:56 +0200 Subject: [PATCH 02/19] #762 - First grab of api to test the data from the meticulous, and read + generate data to import --- .../brew-brewing-preparation-device.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts index a420664f..355f0b64 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts @@ -353,7 +353,6 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { } const lastEntry = newBrewFlow.weight[newBrewFlow.weight.length - 1]; - const lastShotEntryTime = moment(lastEntry.timestamp); this.brewComponent.data.brew_beverage_quantity = lastEntry.actual_weight; From abca8da598a035caaf4b83e2d9e0b7b385376f56 Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Wed, 7 Aug 2024 21:55:55 +0200 Subject: [PATCH 03/19] #762 - Make shothistory readable and let them be selected --- ...odal-import-shot-meticulous.component.html | 38 ++++++ ...odal-import-shot-meticulous.component.scss | 11 ++ ...l-import-shot-meticulous.component.spec.ts | 24 ++++ ...-modal-import-shot-meticulous.component.ts | 118 ++++++++++++++++++ src/app/shared/shared.module.ts | 3 + ...-brewing-preparation-device.component.html | 5 + ...ew-brewing-preparation-device.component.ts | 87 +++---------- 7 files changed, 214 insertions(+), 72 deletions(-) create mode 100644 src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.html create mode 100644 src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.scss create mode 100644 src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.spec.ts create mode 100644 src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts diff --git a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.html b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.html new file mode 100644 index 00000000..0d9e1902 --- /dev/null +++ b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.html @@ -0,0 +1,38 @@ + + + {{"CHOOSE_REFERENCE_GRAPH" | translate}} + + + + + + + + + + + + + + + + {{entry.profile.name}} + + + + + + + + + + + {{"RESET" | translate}} + + + {{"CHOOSE" | translate}} + + + diff --git a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.scss b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.scss new file mode 100644 index 00000000..cbdca414 --- /dev/null +++ b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.scss @@ -0,0 +1,11 @@ +:host { + ion-item { + margin-left: 16px; + margin-right: 0px; + line-height: 12px; + font-size: 12px; + } + ion-card-content { + background:#FFFFFF; + } +} diff --git a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.spec.ts b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.spec.ts new file mode 100644 index 00000000..b42746a1 --- /dev/null +++ b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { IonicModule } from '@ionic/angular'; + +import { BrewModalImportShotMeticulousComponent } from './brew-modal-import-shot-meticulous.component'; + +describe('BrewModalImportShotMeticulousComponent', () => { + let component: BrewModalImportShotMeticulousComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [BrewModalImportShotMeticulousComponent], + imports: [IonicModule.forRoot()], + }).compileComponents(); + + fixture = TestBed.createComponent(BrewModalImportShotMeticulousComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts new file mode 100644 index 00000000..cc14aa86 --- /dev/null +++ b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts @@ -0,0 +1,118 @@ +import { Component, Input, OnInit } from '@angular/core'; + +import { MeticulousDevice } from '../../../classes/preparationDevice/meticulous/meticulousDevice'; +import moment from 'moment/moment'; +import { + BrewFlow, + IBrewPressureFlow, + IBrewRealtimeWaterFlow, + IBrewTemperatureFlow, + IBrewWeightFlow, +} from '../../../classes/brew/brewFlow'; +import { ModalController } from '@ionic/angular'; + +@Component({ + selector: 'app-brew-modal-import-shot-meticulous', + templateUrl: './brew-modal-import-shot-meticulous.component.html', + styleUrls: ['./brew-modal-import-shot-meticulous.component.scss'], +}) +export class BrewModalImportShotMeticulousComponent implements OnInit { + public static COMPONENT_ID: string = 'brew-modal-import-shot-meticulous'; + + @Input() public meticulousDevice: MeticulousDevice; + public radioSelection: string; + public history: Array = []; + constructor(private readonly modalController: ModalController) {} + + public ngOnInit() { + this.readHistory(); + } + + private async readHistory() { + this.history = await this.meticulousDevice.getHistory(); + //this.readShot(history[0]); + } + + private readShot(_historyData) { + const newMoment = moment(new Date()).startOf('day'); + + let firstDripTimeSet: boolean = false; + const newBrewFlow = new BrewFlow(); + + let seconds: number = 0; + let milliseconds: number = 0; + for (const entry of _historyData.data as any) { + const shotEntry: any = entry.shot; + const shotEntryTime = newMoment.clone().add('milliseconds', entry.time); + const timestamp = shotEntryTime.format('HH:mm:ss.SSS'); + + seconds = shotEntryTime.diff(newMoment, 'seconds'); + milliseconds = shotEntryTime.get('milliseconds'); + + const realtimeWaterFlow: IBrewRealtimeWaterFlow = + {} as IBrewRealtimeWaterFlow; + + realtimeWaterFlow.brew_time = ''; + realtimeWaterFlow.timestamp = timestamp; + realtimeWaterFlow.smoothed_weight = 0; + realtimeWaterFlow.flow_value = shotEntry.flow; + realtimeWaterFlow.timestampdelta = 0; + + newBrewFlow.realtimeFlow.push(realtimeWaterFlow); + + const brewFlow: IBrewWeightFlow = {} as IBrewWeightFlow; + brewFlow.timestamp = timestamp; + brewFlow.brew_time = ''; + brewFlow.actual_weight = shotEntry.weight; + brewFlow.old_weight = 0; + brewFlow.actual_smoothed_weight = 0; + brewFlow.old_smoothed_weight = 0; + brewFlow.not_mutated_weight = 0; + newBrewFlow.weight.push(brewFlow); + + if (shotEntry.weight > 0 && firstDripTimeSet === false) { + firstDripTimeSet = true; + + //this.brewComponent.brewFirstDripTime.setTime(seconds, milliseconds); + //this.brewComponent.brewFirstDripTime.changeEvent(); + } + + const pressureFlow: IBrewPressureFlow = {} as IBrewPressureFlow; + pressureFlow.timestamp = timestamp; + pressureFlow.brew_time = ''; + pressureFlow.actual_pressure = shotEntry.pressure; + pressureFlow.old_pressure = 0; + newBrewFlow.pressureFlow.push(pressureFlow); + + const temperatureFlow: IBrewTemperatureFlow = {} as IBrewTemperatureFlow; + temperatureFlow.timestamp = timestamp; + temperatureFlow.brew_time = ''; + temperatureFlow.actual_temperature = shotEntry.temperature; + temperatureFlow.old_temperature = 0; + newBrewFlow.temperatureFlow.push(temperatureFlow); + } + + const lastEntry = newBrewFlow.weight[newBrewFlow.weight.length - 1]; + + console.log(newBrewFlow); + } + + public dismiss(): void { + this.modalController.dismiss( + { + dismissed: true, + }, + undefined, + BrewModalImportShotMeticulousComponent.COMPONENT_ID + ); + } + public choose(): void { + this.modalController.dismiss( + { + dismissed: true, + }, + undefined, + BrewModalImportShotMeticulousComponent.COMPONENT_ID + ); + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 79005eab..267d1887 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -191,6 +191,7 @@ import { MeticulousHelpPopoverComponent } from '../../popover/meticulous-help-po import { BeanPopoverFreezeComponent } from '../beans/bean-popover-freeze/bean-popover-freeze.component'; import { BeanFreezeInformationComponent } from '../../components/beans/bean-freeze-information/bean-freeze-information.component'; import { BeanPopoverFrozenListComponent } from '../beans/bean-popover-frozen-list/bean-popover-frozen-list.component'; +import { BrewModalImportShotMeticulousComponent } from '../brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component'; @NgModule({ declarations: [ @@ -216,6 +217,7 @@ import { BeanPopoverFrozenListComponent } from '../beans/bean-popover-frozen-lis BeansAddComponent, BrewFlowComponent, BrewChooseGraphReferenceComponent, + BrewModalImportShotMeticulousComponent, BrewMaximizeControlsComponent, BeansEditComponent, BeansDetailComponent, @@ -427,6 +429,7 @@ import { BeanPopoverFrozenListComponent } from '../beans/bean-popover-frozen-lis BeansAddComponent, BrewFlowComponent, BrewChooseGraphReferenceComponent, + BrewModalImportShotMeticulousComponent, BrewMaximizeControlsComponent, BeansEditComponent, BrewRatingComponent, diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html index 3e04427a..e052d021 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html @@ -73,6 +73,11 @@ +
+ + + {{"IMPORT_SHOT_FROM_METICULOUS" | translate}} + diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts index 355f0b64..c1346992 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts @@ -37,6 +37,9 @@ import { IBrewTemperatureFlow, IBrewWeightFlow, } from '../../../classes/brew/brewFlow'; +import { BrewChooseGraphReferenceComponent } from '../../../app/brew/brew-choose-graph-reference/brew-choose-graph-reference.component'; +import { BrewModalImportShotMeticulousComponent } from '../../../app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component'; +import { ModalController } from '@ionic/angular'; @Component({ selector: 'brew-brewing-preparation-device', templateUrl: './brew-brewing-preparation-device.component.html', @@ -63,10 +66,10 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { private readonly uiBrewStorage: UIBrewStorage, private readonly uiHelper: UIHelper, private readonly uiToast: UIToast, - private readonly uiBrewHelper: UIBrewHelper, private readonly uiSettingsStorage: UISettingsStorage, private readonly uiPreparationStorage: UIPreparationStorage, - private readonly changeDetectorRef: ChangeDetectorRef + private readonly changeDetectorRef: ChangeDetectorRef, + private readonly modalController: ModalController ) {} public ngOnInit() { @@ -282,9 +285,6 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { if (_connected) { this.preparationDevice = connectedDevice as MeticulousDevice; this.preparationDevice.loadProfiles(); - - const history = await this.preparationDevice.getHistory(); - this.readShot(history[0]); } }, () => { @@ -293,74 +293,17 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { ); } - private readShot(_historyData) { - const newMoment = moment(new Date()).startOf('day'); - - let firstDripTimeSet: boolean = false; - const newBrewFlow = new BrewFlow(); - - let seconds: number = 0; - let milliseconds: number = 0; - for (const entry of _historyData.data as any) { - const shotEntry: any = entry.shot; - const shotEntryTime = newMoment.clone().add('milliseconds', entry.time); - const timestamp = shotEntryTime.format('HH:mm:ss.SSS'); - - seconds = shotEntryTime.diff(newMoment, 'seconds'); - milliseconds = shotEntryTime.get('milliseconds'); - - const realtimeWaterFlow: IBrewRealtimeWaterFlow = - {} as IBrewRealtimeWaterFlow; - - realtimeWaterFlow.brew_time = ''; - realtimeWaterFlow.timestamp = timestamp; - realtimeWaterFlow.smoothed_weight = 0; - realtimeWaterFlow.flow_value = shotEntry.flow; - realtimeWaterFlow.timestampdelta = 0; - - newBrewFlow.realtimeFlow.push(realtimeWaterFlow); - - const brewFlow: IBrewWeightFlow = {} as IBrewWeightFlow; - brewFlow.timestamp = timestamp; - brewFlow.brew_time = ''; - brewFlow.actual_weight = shotEntry.weight; - brewFlow.old_weight = 0; - brewFlow.actual_smoothed_weight = 0; - brewFlow.old_smoothed_weight = 0; - brewFlow.not_mutated_weight = 0; - newBrewFlow.weight.push(brewFlow); - - if (shotEntry.weight > 0 && firstDripTimeSet === false) { - firstDripTimeSet = true; - - this.brewComponent.brewFirstDripTime.setTime(seconds, milliseconds); - this.brewComponent.brewFirstDripTime.changeEvent(); - } - - const pressureFlow: IBrewPressureFlow = {} as IBrewPressureFlow; - pressureFlow.timestamp = timestamp; - pressureFlow.brew_time = ''; - pressureFlow.actual_pressure = shotEntry.pressure; - pressureFlow.old_pressure = 0; - newBrewFlow.pressureFlow.push(pressureFlow); - - const temperatureFlow: IBrewTemperatureFlow = {} as IBrewTemperatureFlow; - temperatureFlow.timestamp = timestamp; - temperatureFlow.brew_time = ''; - temperatureFlow.actual_temperature = shotEntry.temperature; - temperatureFlow.old_temperature = 0; - newBrewFlow.temperatureFlow.push(temperatureFlow); - } - - const lastEntry = newBrewFlow.weight[newBrewFlow.weight.length - 1]; - - this.brewComponent.data.brew_beverage_quantity = lastEntry.actual_weight; - - this.brewComponent.timer.setTime(seconds, milliseconds); - this.brewComponent.timer.changeEvent(); + public async importShotFromMeticulous() { + const modal = await this.modalController.create({ + component: BrewModalImportShotMeticulousComponent, + id: BrewModalImportShotMeticulousComponent.COMPONENT_ID, + componentProps: { + meticulousDevice: this.preparationDevice as MeticulousDevice, + }, + }); - this.brewComponent.brewBrewingGraphEl.flow_profile_raw = newBrewFlow; - this.brewComponent.brewBrewingGraphEl.initializeFlowChart(true); + await modal.present(); + const rData = await modal.onWillDismiss(); } public getPreparationDeviceType() { From 96b9bf789bf214d7195f38999aac54bbfab01b4b Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Tue, 13 Aug 2024 17:40:29 +0200 Subject: [PATCH 04/19] #765 - First implementation for backup check --- src/services/uiExportImportHelper.ts | 165 ++++++++++++++------------- src/services/uiStorage.ts | 46 +++++--- 2 files changed, 118 insertions(+), 93 deletions(-) diff --git a/src/services/uiExportImportHelper.ts b/src/services/uiExportImportHelper.ts index 07a6a274..964f5ac9 100644 --- a/src/services/uiExportImportHelper.ts +++ b/src/services/uiExportImportHelper.ts @@ -248,90 +248,36 @@ export class UIExportImportHelper { this.uiLog.log('Check Backup'); const hasData = await this.uiStorage.hasData(); - let hasCorruptedData: boolean = false; + let corruptedDataObjCheck: any; if (hasData) { - hasCorruptedData = await this.uiStorage.hasCorruptedData(); + corruptedDataObjCheck = await this.uiStorage.hasCorruptedData(); } this.uiLog.log('Check Backup - Has data ' + hasData); - if (!hasData || hasCorruptedData) { - this.uiLog.log( - 'Check Backup - No data are stored yet inside the app, so we try to find a backup file' - ); - // If we don't got any data, we check now if there is a Beanconqueror.zip saved. - this.uiFileHelper.getZIPFile('Beanconqueror.zip').then( - async (_arrayBuffer) => { - await this.uiAlert.showLoadingSpinner(); - try { - this.uiLog.log(' We found a backup, try to import'); - const parsedJSON = - await this.getJSONFromZIPArrayBufferContent(_arrayBuffer); - this.uiStorage.import(parsedJSON).then( - async () => { - this.uiLog.log('Sucessfully imported Backup'); - setTimeout(() => { - this.uiAlert.hideLoadingSpinner(); - }, 150); - resolve(null); - }, - () => { - this.uiLog.error('Could not import Backup'); - setTimeout(() => { - this.uiAlert.hideLoadingSpinner(); - }, 150); - resolve(null); - } - ); - } catch (ex) { - setTimeout(() => { - this.uiAlert.hideLoadingSpinner(); - }, 150); - } - }, - () => { - this.uiLog.log( - 'Check Backup - We couldnt retrieve any zip file - try the old JSON Way.' - ); + if (!hasData || corruptedDataObjCheck.CORRUPTED) { + if (!hasData) { + this.uiLog.log( + 'Check Backup - We didnt found any data inside the app, so try to find a backup and import it' + ); + } else { + this.uiLog.log( + 'Check Backup - We found data but they where corrupted, so try to import a backup' + ); + } - this.uiFileHelper.getJSONFile('Beanconqueror.json').then( - async (_json) => { - await this.uiAlert.showLoadingSpinner(); - try { - this.uiLog.log('We found an backup, try to import'); - this.uiStorage.import(_json).then( - async () => { - this.uiLog.log('Sucessfully imported Backup'); - setTimeout(() => { - this.uiAlert.hideLoadingSpinner(); - }, 150); - resolve(null); - }, - () => { - this.uiLog.error('Could not import Backup'); - setTimeout(() => { - this.uiAlert.hideLoadingSpinner(); - }, 150); - resolve(null); - } - ); - } catch (ex) { - setTimeout(() => { - this.uiAlert.hideLoadingSpinner(); - }, 150); - } - }, - () => { - setTimeout(() => { - this.uiAlert.hideLoadingSpinner(); - }, 150); - this.uiLog.log( - 'Check Backup - We couldnt retrieve any JSON file' - ); - resolve(null); - } - ); - } - ); + const parsedJSON = await this.readBackupZIPFile(); + if (parsedJSON) { + await this.importBackupJSON(parsedJSON); + } } else { + /** + * BREWS: number, + * MILL: number, + * PREPARATION: number, + * BEANS: number, + */ + const parsedJSON = await this.readBackupZIPFile(); + console.log('BLAAA'); + console.log(parsedJSON); resolve(null); } } else { @@ -345,6 +291,67 @@ export class UIExportImportHelper { } catch (ex) {} } + private importBackupJSON(_parsedJSON) { + const promise = new Promise(async (resolve, reject) => { + await this.uiAlert.showLoadingSpinner(); + + this.uiStorage.import(_parsedJSON).then( + async () => { + this.uiLog.log('Sucessfully imported Backup'); + setTimeout(() => { + this.uiAlert.hideLoadingSpinner(); + }, 150); + resolve(null); + }, + () => { + this.uiLog.error('Could not import Backup'); + setTimeout(() => { + this.uiAlert.hideLoadingSpinner(); + }, 150); + resolve(null); + } + ); + }); + return promise; + } + + private readBackupZIPFile() { + // If we don't got any data, we check now if there is a Beanconqueror.zip saved. + const promise = new Promise(async (resolve, reject) => { + this.uiFileHelper.getZIPFile('Beanconqueror.zip').then( + async (_arrayBuffer) => { + try { + this.uiLog.log('Read ZIP-File, we found an zip-file'); + const parsedJSON = await this.getJSONFromZIPArrayBufferContent( + _arrayBuffer + ); + resolve(parsedJSON); + } catch (ex) { + resolve(null); + } + }, + () => { + this.uiLog.log( + 'Read ZIP-FILE failed, try to read an old Beanconqueror.json' + ); + this.uiFileHelper.getJSONFile('Beanconqueror.json').then( + async (_json) => { + this.uiLog.log('Read ZIP-File, we found an json-file'); + resolve(_json); + }, + () => { + this.uiLog.log( + 'Check Backup - We couldnt retrieve any JSON file' + ); + resolve(null); + } + ); + } + ); + }); + return promise; + } + private getAutomatedBackupFilename(): string { return moment().format('DD_MM_YYYY').toString(); } diff --git a/src/services/uiStorage.ts b/src/services/uiStorage.ts index 92eb75fd..9bea4e0b 100755 --- a/src/services/uiStorage.ts +++ b/src/services/uiStorage.ts @@ -240,13 +240,29 @@ export class UIStorage { return promise; } - public async hasCorruptedData(): Promise { - const promise: Promise = new Promise((resolve, reject) => { + public async hasCorruptedData(): Promise<{ + CORRUPTED: boolean; + DATA: { + BREWS: number; + MILL: number; + PREPARATION: number; + BEANS: number; + }; + }> { + const promise: Promise<{ + CORRUPTED: boolean; + DATA: { + BREWS: number; + MILL: number; + PREPARATION: number; + BEANS: number; + }; + }> = new Promise((resolve, reject) => { const hasDataObj = { - BREWS: false, - MILL: false, - PREPARATION: false, - BEANS: false, + BREWS: 0, + MILL: 0, + PREPARATION: 0, + BEANS: 0, }; this._storage .forEach((_value, _key, _index) => { @@ -258,7 +274,9 @@ export class UIStorage { ) { try { if (_value?.length > 0) { - hasDataObj[_key] = true; + hasDataObj[_key] = _value?.length; + } else { + hasDataObj[_key] = 0; } } catch (ex) {} } @@ -266,22 +284,22 @@ export class UIStorage { .then( () => { if ( - hasDataObj.BREWS === true && - (hasDataObj.MILL === false || - hasDataObj.PREPARATION === false || - hasDataObj.BEANS === false) + hasDataObj.BREWS > 0 && + (hasDataObj.MILL <= 0 || + hasDataObj.PREPARATION <= 0 || + hasDataObj.BEANS <= 0) ) { /** * If we got brews but not a mill / preparation / or bean something broke hard. * We saw this issue on android that a user got brews but no beans anymore, they where lost */ - resolve(true); + resolve({ CORRUPTED: true, DATA: hasDataObj }); } else { - resolve(false); + resolve({ CORRUPTED: false, DATA: hasDataObj }); } }, () => { - resolve(false); + resolve({ CORRUPTED: false, DATA: hasDataObj }); } ); }); From a44424e19e8d019ee4997838058601458700f6e0 Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Tue, 27 Aug 2024 20:56:23 +0200 Subject: [PATCH 05/19] #767 - Frozen beans sort order is now saved #765 - Show popup if data base is corrupted #762 - Read a history shot of the meticulous to import #768 - Add ean search article number #769 - Make brew/bean toggleable #438 - Import beans via excel #772 - Display best brew / favorite / frozen etc. #773 - Show frozen icon for beans on brew-list #775 - Fixing wrong labels #776 - Sorting bean for bean age #629 - Import green beans via excel #777 - grow plausible var from 5 to 6 #778 - Showing bean images on selection #623 - Showing a popup that more informations are there but not visible. --- config.xml | 2 +- package-lock.json | 52 +- package.json | 23 +- src/app/app.component.ts | 4 + src/app/app.scss | 1 + .../bean-modal-select.component.html | 32 +- .../bean-modal-select.component.ts | 3 +- .../bean-popover-freeze.component.html | 4 +- .../bean-popover-freeze.component.ts | 45 +- .../bean-popover-frozen-list.component.ts | 2 - .../bean-popover-list.component.html | 19 + .../bean-popover-list.component.scss | 0 .../bean-popover-list.component.spec.ts | 32 + .../bean-popover-list.component.ts | 65 ++ .../beans/bean-sort/bean-sort.component.html | 4 + .../beans/beans-add/beans-add.component.ts | 79 +- src/app/beans/beans.page.html | 24 +- src/app/beans/beans.page.ts | 57 +- src/app/brew/brew-add/brew-add.component.html | 10 + ...-choose-preparation-to-brew.component.html | 3 +- .../brew/brew-edit/brew-edit.component.html | 10 + ...odal-import-shot-meticulous.component.html | 26 +- ...l-import-shot-meticulous.component.spec.ts | 19 +- ...-modal-import-shot-meticulous.component.ts | 123 ++- src/app/brew/brew.page.html | 18 +- src/app/brew/brew.page.ts | 39 +- .../preparation-add-type.component.ts | 11 +- .../preparation-add.component.html | 39 +- .../preparation-add.component.ts | 13 + ...reparation-connected-device.component.html | 61 +- .../preparation-connected-device.component.ts | 53 +- .../preparation-modal-select.component.html | 12 +- src/app/settings/settings.page.html | 12 +- src/app/settings/settings.page.ts | 23 +- src/app/shared/shared.module.ts | 6 + .../beanconqueror-expand-active.svg | 1 + .../beanconqueror-expand-inactive.svg | 1 + .../beanconqueror-sanremo-you-logo.svg | 35 + src/assets/i18n/en.json | 24 +- src/classes/bean/bean.ts | 7 + src/classes/devices/argosThermometer.ts | 72 ++ src/classes/devices/index.ts | 4 + src/classes/preparation/preparation.ts | 12 + src/classes/preparationDevice/index.ts | 4 + .../meticulous/meticulousDevice.ts | 114 ++- .../sanremo/sanremoYOUDevice.ts | 187 ++++ .../preparationDevice/xenia/xeniaDevice.ts | 1 + src/classes/settings/settings.ts | 44 +- .../bean-information.component.html | 7 +- .../bean-information.component.ts | 4 +- .../bean-freeze-information.component.html | 4 +- .../brew-information.component.html | 493 ++++++----- .../brew-information.component.ts | 4 +- .../brew-brewing-graph.component.ts | 815 +++++++++++------- ...-brewing-preparation-device.component.html | 9 + ...ew-brewing-preparation-device.component.ts | 106 ++- .../graph-display-card.component.ts | 8 +- .../photo-add/photo-add.component.ts | 10 +- .../preparation-information-card.component.ts | 12 +- src/enums/beans/beanSortAfter.ts | 4 +- src/enums/preparations/preparationTypes.ts | 4 +- src/environments/environment.prod.ts | 5 +- src/environments/environment.ts | 3 + .../sanremoYOU/iSanremoYOUParams.ts | 5 + src/interfaces/settings/iSettings.ts | 10 + .../data-corruption-found.component.html | 69 ++ .../data-corruption-found.component.scss | 6 + .../data-corruption-found.component.spec.ts | 24 + .../data-corruption-found.component.ts | 68 ++ .../coffee-bluetooth-devices.service.ts | 25 +- src/services/uiBeanHelper.ts | 12 + src/services/uiExcel.ts | 504 ++++++++++- src/services/uiExportImportHelper.ts | 83 +- src/services/uiFileHelper.ts | 9 +- src/services/uiHelper.ts | 10 + src/services/uiPreparationHelper.ts | 25 +- src/services/uiUpdate.ts | 9 + 77 files changed, 2933 insertions(+), 846 deletions(-) create mode 100644 src/app/beans/bean-popover-list/bean-popover-list.component.html create mode 100644 src/app/beans/bean-popover-list/bean-popover-list.component.scss create mode 100644 src/app/beans/bean-popover-list/bean-popover-list.component.spec.ts create mode 100644 src/app/beans/bean-popover-list/bean-popover-list.component.ts create mode 100644 src/assets/custom-ion-icons/beanconqueror-expand-active.svg create mode 100644 src/assets/custom-ion-icons/beanconqueror-expand-inactive.svg create mode 100644 src/assets/custom-ion-icons/beanconqueror-sanremo-you-logo.svg create mode 100644 src/classes/devices/argosThermometer.ts create mode 100644 src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts create mode 100644 src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts create mode 100644 src/popover/data-corruption-found/data-corruption-found.component.html create mode 100644 src/popover/data-corruption-found/data-corruption-found.component.scss create mode 100644 src/popover/data-corruption-found/data-corruption-found.component.spec.ts create mode 100644 src/popover/data-corruption-found/data-corruption-found.component.ts diff --git a/config.xml b/config.xml index ce93948c..cbc79bf9 100644 --- a/config.xml +++ b/config.xml @@ -1,5 +1,5 @@ - + Beanconqueror Lars Saalbach diff --git a/package-lock.json b/package-lock.json index 280f8555..7ba5d102 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,8 @@ "@ionic/cordova-builders": "^8.0.0", "@ionic/storage": "^4.0.0", "@ionic/storage-angular": "^4.0.0", + "@meticulous-home/espresso-api": "^0.3.1", + "@meticulous-home/espresso-profile": "^0.4.0", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^4.0.0", "@zip.js/zip.js": "^2.7.14", @@ -61,7 +63,6 @@ "lodash": "^4.17.21", "long": "^5.2.0", "luxon": "^2.3.0", - "meticulous-api": "github:FFFuego/meticulous-typescript-api#dist", "moment": "^2.29.4", "ngx-stars": "^1.6.4", "postcss": "^8.3.5", @@ -91,7 +92,7 @@ "@wisdomgarden/cordova-plugin-filepath": "git+https://github.com/wisdom-garden/cordova-plugin-filepath.git", "cordova-android": "^13.0.0", "cordova-clipboard": "^1.3.0", - "cordova-ios": "^7.1.0", + "cordova-ios": "^7.1.1", "cordova-plugin-add-swift-support": "^2.0.2", "cordova-plugin-advanced-http": "^3.3.1", "cordova-plugin-android-permissions": "^1.1.5", @@ -6294,6 +6295,23 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@meticulous-home/espresso-api": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@meticulous-home/espresso-api/-/espresso-api-0.3.1.tgz", + "integrity": "sha512-KeZuK0RDDc9HhMNxyYj0BRfEgGvNOUKu5zyn8RYI4ezUCnn61PP4FbykiB7YxzBvsr8PT+5BOPyXSvqkDaC1FA==", + "license": "GPLv3", + "dependencies": { + "axios": "^1.6.8", + "meticulous-typescript-profile": "github:MeticulousHome/meticulous-typescript-profile#dist", + "socket.io-client": "^4.7.5" + } + }, + "node_modules/@meticulous-home/espresso-profile": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@meticulous-home/espresso-profile/-/espresso-profile-0.4.0.tgz", + "integrity": "sha512-jHG2y6F6mi5YTFE0nmyc5NKUGmyDxorLiix1h8CB5ch/Plae+fvD7RsxetA6nh3lAn8Zfz9U9am2kolokY0Zyg==", + "license": "GPL-3.0" + }, "node_modules/@netflix/nerror": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@netflix/nerror/-/nerror-1.1.3.tgz", @@ -9262,10 +9280,11 @@ } }, "node_modules/cordova-ios": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cordova-ios/-/cordova-ios-7.1.0.tgz", - "integrity": "sha512-9/vPU+GWRdfxNIkAc9Gq6yejMIgpy59ycP8WyVJJ7HfuPSTBUQT8AS2h5ZJOeN4Y/URyEwxQCrAqSADDBVCESA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/cordova-ios/-/cordova-ios-7.1.1.tgz", + "integrity": "sha512-JwTyPxWcAZlbIOR5QO6TaJzkoSzfrp7jrlX01bWZ7Sxp0PYXejAJbA6J0W4u11M+atrQRNimNltZDyAlSBW2tw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "cordova-common": "^5.0.0", "elementtree": "^0.1.7", @@ -9286,6 +9305,7 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=16" } @@ -9295,6 +9315,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -12750,6 +12771,7 @@ "resolved": "https://registry.npmjs.org/ios-sim/-/ios-sim-8.0.2.tgz", "integrity": "sha512-P7nEG771bfd+JoMRjnis1gpZOkjTUUxu+4Ek1Z+eoaEEoT9byllU9pxfQ8Df7hL3gSkIQxNwTSLhos2I8tWUQA==", "dev": true, + "license": "MIT", "dependencies": { "bplist-parser": "^0.0.6", "nopt": "1.0.9", @@ -12767,13 +12789,15 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.0.6.tgz", "integrity": "sha512-fGeghPEH4Eytvf+Mi446aKcDqvkA/+eh6r7QGiZWMQG6TzqrnsToLP379XFfqRSZ41+676hhGIm++maNST1Apw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ios-sim/node_modules/nopt": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.9.tgz", "integrity": "sha512-CmUZ3rzN0/4kRHum5pGRiGkhmBMzgtEDxrZVHqRJDSv8qK6s+wzaig/xeyB22Due5aZQeTiEZg/nrmMH2tapDQ==", "dev": true, + "license": "MIT", "dependencies": { "abbrev": "1" }, @@ -15075,16 +15099,6 @@ "node": ">= 0.6" } }, - "node_modules/meticulous-api": { - "version": "0.0.2", - "resolved": "git+ssh://git@github.com/FFFuego/meticulous-typescript-api.git#c1ae8038e22db7ff9547f88038b9566b4f1f9718", - "license": "GPLv3", - "dependencies": { - "axios": "^1.6.8", - "meticulous-typescript-profile": "github:MeticulousHome/meticulous-typescript-profile#dist", - "socket.io-client": "^4.7.5" - } - }, "node_modules/meticulous-typescript-profile": { "version": "0.1.0", "resolved": "git+ssh://git@github.com/MeticulousHome/meticulous-typescript-profile.git#c4520f2238770d8432272e2fbc5d29f90a78720d", @@ -18915,6 +18929,7 @@ "resolved": "https://registry.npmjs.org/simctl/-/simctl-2.0.3.tgz", "integrity": "sha512-kKCak0yszxHae5eVWcmrjV3ouUGac3sjlhjdLWpyPu4eiQcWoHsCrqS34kkgzHN8Ystqkh/LFjzrldk/g3BYJg==", "dev": true, + "license": "MIT", "dependencies": { "shelljs": "^0.8.5", "tail": "^0.4.0" @@ -21824,6 +21839,7 @@ "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "simple-plist": "^1.1.0", "uuid": "^7.0.3" @@ -21837,6 +21853,7 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -21865,7 +21882,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/xml-escape/-/xml-escape-1.1.0.tgz", "integrity": "sha512-B/T4sDK8Z6aUh/qNr7mjKAwwncIljFuUP+DO/D5hloYFj+90O88z8Wf7oSucZTHxBAsC1/CTP4rtx/x1Uf72Mg==", - "dev": true + "dev": true, + "license": "MIT License" }, "node_modules/xml-name-validator": { "version": "3.0.0", diff --git a/package.json b/package.json index 316b14af..457cd34b 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,8 @@ "@ionic/cordova-builders": "^8.0.0", "@ionic/storage": "^4.0.0", "@ionic/storage-angular": "^4.0.0", + "@meticulous-home/espresso-api": "^0.3.1", + "@meticulous-home/espresso-profile": "^0.4.0", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^4.0.0", "@zip.js/zip.js": "^2.7.14", @@ -68,7 +70,6 @@ "lodash": "^4.17.21", "long": "^5.2.0", "luxon": "^2.3.0", - "meticulous-api": "github:FFFuego/meticulous-typescript-api#dist", "moment": "^2.29.4", "ngx-stars": "^1.6.4", "postcss": "^8.3.5", @@ -98,7 +99,7 @@ "@wisdomgarden/cordova-plugin-filepath": "git+https://github.com/wisdom-garden/cordova-plugin-filepath.git", "cordova-android": "^13.0.0", "cordova-clipboard": "^1.3.0", - "cordova-ios": "^7.1.0", + "cordova-ios": "^7.1.1", "cordova-plugin-add-swift-support": "^2.0.2", "cordova-plugin-advanced-http": "^3.3.1", "cordova-plugin-android-permissions": "^1.1.5", @@ -210,22 +211,22 @@ "cordova-plugin-nativestorage": {}, "cordova-plugin-androidx": {}, "cordova-plugin-androidx-adapter": {}, - "cordova-plugin-ble-central": { - "BLUETOOTH_USAGE_DESCRIPTION": "Bluetooth access needed to connect smartscales", - "IOS_INIT_ON_LOAD": "false", - "ACCESS_BACKGROUND_LOCATION": "false", - "BLUETOOTH_RESTORE_STATE": "false" - }, "cordova-plugin-inappbrowser": {}, "skwas-cordova-plugin-datetimepicker": {}, "cordova-plugin-statusbar": {}, "cordova-plugin-file": { "ANDROIDX_WEBKIT_VERSION": "1.4.0" + }, + "cordova-plugin-ble-central": { + "BLUETOOTH_USAGE_DESCRIPTION": "Bluetooth access needed to connect smartscales", + "IOS_INIT_ON_LOAD": "false", + "ACCESS_BACKGROUND_LOCATION": "false", + "BLUETOOTH_RESTORE_STATE": "false" } }, "platforms": [ - "ios", - "android" + "android", + "ios" ] }, "platforms": [ @@ -240,4 +241,4 @@ "*.css": "stylelint --fix", "*.{ts,js,css,md}": "prettier --write" } -} +} \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5c9e5762..891080a4 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -324,6 +324,7 @@ export class AppComponent implements AfterViewInit { }); } catch (ex) {} + // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. // #7 @@ -366,6 +367,7 @@ export class AppComponent implements AfterViewInit { }); } + if (this.platform.is('cordova')) { // Just support deeplinks on devices. this.intentHandlerService.attachOnHandleOpenUrl(); @@ -374,6 +376,8 @@ export class AppComponent implements AfterViewInit { this._translate.setDefaultLang('en'); await this._translate.use('en').toPromise(); + + if (this.platform.is('cordova')) { try { await this.uiExportImportHelper.checkBackup(); diff --git a/src/app/app.scss b/src/app/app.scss index 5888a116..a2c6f01c 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -739,6 +739,7 @@ ion-menu:host .menu-inner { font-weight: bold; } + .button-top-absolute { position: absolute; top: -20px; diff --git a/src/app/beans/bean-modal-select/bean-modal-select.component.html b/src/app/beans/bean-modal-select/bean-modal-select.component.html index 28499557..45fa1b39 100644 --- a/src/app/beans/bean-modal-select/bean-modal-select.component.html +++ b/src/app/beans/bean-modal-select/bean-modal-select.component.html @@ -101,6 +101,11 @@
+
+ +
+
@@ -178,6 +183,11 @@
+
+ +
+ @@ -260,6 +270,11 @@
( +
+ +
+
@@ -348,7 +363,11 @@
( +
+ +
+
@@ -430,6 +449,11 @@
+
+ +
+
@@ -511,7 +535,11 @@
( +
+ +
+
diff --git a/src/app/beans/bean-modal-select/bean-modal-select.component.ts b/src/app/beans/bean-modal-select/bean-modal-select.component.ts index a862ad99..f04058ae 100644 --- a/src/app/beans/bean-modal-select/bean-modal-select.component.ts +++ b/src/app/beans/bean-modal-select/bean-modal-select.component.ts @@ -409,7 +409,8 @@ export class BeanModalSelectComponent implements OnInit { e.name?.toLowerCase().includes(searchText) || e.roaster?.toLowerCase().includes(searchText) || e.aromatics?.toLowerCase().includes(searchText) || - e.frozenId?.toLowerCase().includes(searchText) + e.frozenId?.toLowerCase().includes(searchText) || + e.ean_article_number?.toLowerCase().includes(searchText) ); } if (_type === 'open') { diff --git a/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.html b/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.html index 3d977ecb..773cd6f8 100644 --- a/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.html +++ b/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.html @@ -43,11 +43,11 @@ prevent-characters remove-empty-number spellcheck="false" type="text" tabIndex="2"> - - diff --git a/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.ts b/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.ts index d7a006e2..9b429b3a 100644 --- a/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.ts +++ b/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.ts @@ -59,7 +59,7 @@ export class BeanPopoverFreezeComponent implements OnInit { public ngOnInit() { // cant be done in constructor, else the bean object is not known - this.leftOverBeanBagWeight = this.bean.weight - this.getUsedWeightCount(); + this.leftOverBeanBagWeight = this.uiHelper.toFixedIfNecessary(this.bean.weight - this.getUsedWeightCount(),1); } public getUsedWeightCount(): number { @@ -87,7 +87,7 @@ export class BeanPopoverFreezeComponent implements OnInit { public async save() { const spillOver = - this.leftOverBeanBagWeight - this.getActualFreezingQuantity(); + this.uiHelper.toFixedIfNecessary(this.leftOverBeanBagWeight - this.getActualFreezingQuantity(),1); let index = 1; @@ -109,10 +109,10 @@ export class BeanPopoverFreezeComponent implements OnInit { this.bean.config.uuid ); if (brews.length > 0) { - const oldWeight = this.bean.weight; - this.bean.weight = this.bean.weight - this.getActualFreezingQuantity(); + const oldWeight = this.uiHelper.toFixedIfNecessary(this.bean.weight,1) + this.bean.weight = this.uiHelper.toFixedIfNecessary(this.bean.weight - this.getActualFreezingQuantity(),1); try { - const newCost = (this.bean.cost * this.bean.weight) / oldWeight; + const newCost = this.uiHelper.toFixedIfNecessary((this.bean.cost * this.bean.weight) / oldWeight,2) this.bean.cost = newCost; } catch (ex) { this.bean.cost = 0; @@ -148,10 +148,10 @@ export class BeanPopoverFreezeComponent implements OnInit { /** * Because we had already maybe some brews, we take the bean weight, and subtract it with the spill over, because just using the spill over would not take previus brews into account */ - const oldWeight = this.bean.weight; - this.bean.weight = this.bean.weight - this.getActualFreezingQuantity(); + const oldWeight = this.uiHelper.toFixedIfNecessary(this.bean.weight,1); + this.bean.weight = this.uiHelper.toFixedIfNecessary(this.bean.weight - this.getActualFreezingQuantity(),1); try { - const newCost = (this.bean.cost * this.bean.weight) / oldWeight; + const newCost = this.uiHelper.toFixedIfNecessary((this.bean.cost * this.bean.weight) / oldWeight,2); this.bean.cost = newCost; } catch (ex) { this.bean.cost = 0; @@ -189,13 +189,13 @@ export class BeanPopoverFreezeComponent implements OnInit { if (this.bean.cost !== 0) { try { - const newCost = (this.bean.cost * _freezingWeight) / this.bean.weight; + const newCost = this.uiHelper.toFixedIfNecessary((this.bean.cost * _freezingWeight) / this.bean.weight,2); clonedBean.cost = newCost; } catch (ex) { clonedBean.cost = 0; } } - clonedBean.weight = _freezingWeight; + clonedBean.weight = this.uiHelper.toFixedIfNecessary(_freezingWeight,1); clonedBean.config = new Config(); const newClonedBean = await this.uiBeanStorage.add(clonedBean); const newBean: Bean = new Bean(); @@ -244,18 +244,29 @@ export class BeanPopoverFreezeComponent implements OnInit { return quantity; } + public isAddingBagDisabled() { + + if (this.freezePartialBagGrams <=0) { + return true; + } + if (this.uiHelper.toFixedIfNecessary(Number(this.freezePartialBagGrams) + this.getActualFreezingQuantity(),1) > this.leftOverBeanBagWeight) { + return true; + } + return false; + } + public addOnePartialBag() { this.addedBags.push({ - weight: this.freezePartialBagGrams, + weight: Number(this.freezePartialBagGrams), type: this.frozenStorage, }); const leftFreezingCount = - this.leftOverBeanBagWeight - this.getActualFreezingQuantity(); + this.uiHelper.toFixedIfNecessary(this.leftOverBeanBagWeight - this.getActualFreezingQuantity(),1); if (leftFreezingCount < this.freezePartialBagGrams) { this.freezePartialBagGrams = this.uiHelper.toFixedIfNecessary( leftFreezingCount, - 2 + 1 ); } } @@ -263,16 +274,16 @@ export class BeanPopoverFreezeComponent implements OnInit { public addMaxPartialBags() { while (true) { this.addedBags.push({ - weight: this.freezePartialBagGrams, + weight: Number(this.freezePartialBagGrams), type: this.frozenStorage, }); const leftFreezingCount = - this.leftOverBeanBagWeight - this.getActualFreezingQuantity(); + this.uiHelper.toFixedIfNecessary(this.leftOverBeanBagWeight - this.getActualFreezingQuantity(),1); if (leftFreezingCount < this.freezePartialBagGrams) { this.freezePartialBagGrams = this.uiHelper.toFixedIfNecessary( leftFreezingCount, - 2 + 1 ); break; } @@ -282,7 +293,7 @@ export class BeanPopoverFreezeComponent implements OnInit { public deleteBag(_index) { this.addedBags.splice(_index, 1); const leftFreezingCount = - this.leftOverBeanBagWeight - this.getActualFreezingQuantity(); + this.uiHelper.toFixedIfNecessary(this.leftOverBeanBagWeight - this.getActualFreezingQuantity(),1); if (leftFreezingCount < this.freezePartialBagGrams) { this.freezePartialBagGrams = leftFreezingCount; } diff --git a/src/app/beans/bean-popover-frozen-list/bean-popover-frozen-list.component.ts b/src/app/beans/bean-popover-frozen-list/bean-popover-frozen-list.component.ts index 29c022e9..ebd9e99e 100644 --- a/src/app/beans/bean-popover-frozen-list/bean-popover-frozen-list.component.ts +++ b/src/app/beans/bean-popover-frozen-list/bean-popover-frozen-list.component.ts @@ -7,11 +7,9 @@ import { ViewChild, } from '@angular/core'; import { Bean } from '../../../classes/bean/bean'; -import { Brew } from '../../../classes/brew/brew'; import { AgVirtualSrollComponent } from 'ag-virtual-scroll'; import { ModalController } from '@ionic/angular'; import { UIBeanHelper } from '../../../services/uiBeanHelper'; -import { UIBrewHelper } from '../../../services/uiBrewHelper'; @Component({ selector: 'app-bean-popover-frozen-list', diff --git a/src/app/beans/bean-popover-list/bean-popover-list.component.html b/src/app/beans/bean-popover-list/bean-popover-list.component.html new file mode 100644 index 00000000..08d289c2 --- /dev/null +++ b/src/app/beans/bean-popover-list/bean-popover-list.component.html @@ -0,0 +1,19 @@ + + + {{"BEAN_LIST" | translate}} + + + + + + + + + + + + + + + diff --git a/src/app/beans/bean-popover-list/bean-popover-list.component.scss b/src/app/beans/bean-popover-list/bean-popover-list.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/beans/bean-popover-list/bean-popover-list.component.spec.ts b/src/app/beans/bean-popover-list/bean-popover-list.component.spec.ts new file mode 100644 index 00000000..34d578e6 --- /dev/null +++ b/src/app/beans/bean-popover-list/bean-popover-list.component.spec.ts @@ -0,0 +1,32 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { IonicModule } from '@ionic/angular'; + +import { BeanPopoverListComponent } from './bean-popover-list.component'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { TranslateServiceMock } from '../../../classes/mock'; + +describe('BeanPopoverListComponent', () => { + let component: BeanPopoverListComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ BeanPopoverListComponent ], + imports: [IonicModule.forRoot(), TranslateModule.forRoot()], + providers: [ + { + provide: TranslateService, + useValue: TranslateServiceMock, + }, + ] + }).compileComponents(); + + fixture = TestBed.createComponent(BeanPopoverListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/beans/bean-popover-list/bean-popover-list.component.ts b/src/app/beans/bean-popover-list/bean-popover-list.component.ts new file mode 100644 index 00000000..6ae0948d --- /dev/null +++ b/src/app/beans/bean-popover-list/bean-popover-list.component.ts @@ -0,0 +1,65 @@ +import { Component, ElementRef, HostListener, Input, OnInit, ViewChild } from '@angular/core'; +import { Bean } from '../../../classes/bean/bean'; +import { AgVirtualSrollComponent } from 'ag-virtual-scroll'; +import { ModalController } from '@ionic/angular'; + +@Component({ + selector: 'app-bean-popover-list', + templateUrl: './bean-popover-list.component.html', + styleUrls: ['./bean-popover-list.component.scss'], +}) +export class BeanPopoverListComponent { + + public static readonly COMPONENT_ID = 'bean-popover-list'; + + @Input() public beansList: Array = undefined; + + @ViewChild('openScroll', { read: AgVirtualSrollComponent, static: false }) + public openScroll: AgVirtualSrollComponent; + + @ViewChild('beanContent', { read: ElementRef }) + public beanContent: ElementRef; + + constructor( + private readonly modalController: ModalController, + ) {} + + public async ionViewWillEnter() { + this.loadBrews(); + } + + @HostListener('window:resize') + @HostListener('window:orientationchange', ['$event']) + public onOrientationChange(_event: any) { + this.retriggerScroll(); + } + + private retriggerScroll() { + setTimeout(async () => { + const el = this.beanContent.nativeElement; + let scrollComponent: AgVirtualSrollComponent; + scrollComponent = this.openScroll; + scrollComponent.el.style.height = + el.offsetHeight - scrollComponent.el.offsetTop + 'px'; + }, 150); + } + + public loadBrews() { + this.retriggerScroll(); + } + + public async brewAction(): Promise { + this.loadBrews(); + } + + public dismiss(): void { + this.modalController.dismiss( + { + dismissed: true, + }, + undefined, + BeanPopoverListComponent.COMPONENT_ID + ); + } + +} diff --git a/src/app/beans/bean-sort/bean-sort.component.html b/src/app/beans/bean-sort/bean-sort.component.html index a5db09b4..d7c7ed4d 100644 --- a/src/app/beans/bean-sort/bean-sort.component.html +++ b/src/app/beans/bean-sort/bean-sort.component.html @@ -43,6 +43,10 @@ {{"BREW_DATA_RATING" | translate}} + + + {{"BEAN_SORT_BEAN_AGE" | translate}} + diff --git a/src/app/beans/beans-add/beans-add.component.ts b/src/app/beans/beans-add/beans-add.component.ts index 83094636..fbad06f2 100644 --- a/src/app/beans/beans-add/beans-add.component.ts +++ b/src/app/beans/beans-add/beans-add.component.ts @@ -20,7 +20,7 @@ import { Settings } from '../../../classes/settings/settings'; @Component({ selector: 'beans-add', templateUrl: './beans-add.component.html', - styleUrls: ['./beans-add.component.scss'], + styleUrls: ['./beans-add.component.scss'] }) export class BeansAddComponent implements OnInit { public static readonly COMPONENT_ID = 'bean-add'; @@ -49,7 +49,8 @@ export class BeansAddComponent implements OnInit { private readonly platform: Platform, public readonly uiBeanHelper: UIBeanHelper, private readonly uiSettingsStorage: UISettingsStorage - ) {} + ) { + } public ngOnInit() { this.settings = this.uiSettingsStorage.getSettings(); @@ -64,6 +65,71 @@ export class BeansAddComponent implements OnInit { } } + private async checkIfInformationAreSetButNotDisplayed() { + try { + + + const params = this.settings.bean_manage_parameters; + if (this.data.bean_information.length > 0) { + const info: IBeanInformation = this.data.bean_information[0]; + let hasDataSet: boolean = false; + if (info.country && info.country !== '') { + hasDataSet = true; + } + if (info.region && info.region !== '') { + hasDataSet = true; + } + if (info.farm && info.farm !== '') { + hasDataSet = true; + } + if (info.farmer && info.farmer !== '') { + hasDataSet = true; + } + if (info.elevation && info.elevation !== '') { + hasDataSet = true; + } + if (info.harvest_time && info.harvest_time !== '') { + hasDataSet = true; + } + if (info.variety && info.variety !== '') { + hasDataSet = true; + } + if (info.processing && info.processing !== '') { + hasDataSet = true; + } + if (info.certification && info.certification !== '') { + hasDataSet = true; + } + if (info.percentage && info.percentage > 0) { + hasDataSet = true; + } + if (info.purchasing_price && info.purchasing_price > 0) { + hasDataSet = true; + } + if (info.fob_price && info.fob_price > 0) { + hasDataSet = true; + } + + if (params.bean_information === false && hasDataSet === true) { + //Woopsi doopsi, user hasn't enabled the bean_information, lets display him a popover + //#623 + try { + const yes = await this.uiAlert.showConfirm('BEAN_POPUP_YOU_DONT_SEE_EVERYTHING_DESCRIPTION', 'INFORMATION', true); + this.settings.bean_manage_parameters.bean_information = true; + await this.uiSettingsStorage.update(this.settings); + //Activate + } catch (ex) { + // Don't activate + } + + } + + } + } catch (ex) { + + } + } + public async ionViewWillEnter() { this.uiAnalytics.trackEvent(BEAN_TRACKING.TITLE, BEAN_TRACKING.ACTIONS.ADD); @@ -71,6 +137,7 @@ export class BeansAddComponent implements OnInit { // TODO how to handle roasting beans which wil be repeated? if (this.bean_template) { await this.__loadBean(this.bean_template); + await this.checkIfInformationAreSetButNotDisplayed(); } // Download images after loading the bean, else they would be copied :O @@ -161,10 +228,11 @@ export class BeansAddComponent implements OnInit { if (this.settings.security_check_when_going_back === true) { this.disableHardwareBack.unsubscribe(); } - } catch (ex) {} + } catch (ex) { + } this.modalController.dismiss( { - dismissed: true, + dismissed: true }, undefined, BeansAddComponent.COMPONENT_ID @@ -202,7 +270,8 @@ export class BeansAddComponent implements OnInit { try { const newPath: string = await this.uiFileHelper.copyFile(attachment); copyAttachments.push(newPath); - } catch (ex) {} + } catch (ex) { + } } this.data.attachments = copyAttachments; if (_bean.cupped_flavor) { diff --git a/src/app/beans/beans.page.html b/src/app/beans/beans.page.html index 73bb7d49..97fb274c 100644 --- a/src/app/beans/beans.page.html +++ b/src/app/beans/beans.page.html @@ -74,6 +74,10 @@ + + + +
@@ -85,8 +89,8 @@
- - + @@ -109,6 +113,10 @@ + + + +
@@ -118,8 +126,8 @@ {{"PAGE_BEANS_LIST_YOU_GOT_NO_FROZEN_BEANS" | translate}}
- - + @@ -142,6 +150,10 @@ + + + +
@@ -151,8 +163,8 @@ {{"PAGE_BEANS_LIST_YOU_GOT_NO_FINISHED_BEANS" | translate}}
- - + diff --git a/src/app/beans/beans.page.ts b/src/app/beans/beans.page.ts index c47a41e5..a9331db4 100644 --- a/src/app/beans/beans.page.ts +++ b/src/app/beans/beans.page.ts @@ -74,6 +74,10 @@ export class BeansPage implements OnDestroy { sort_order: BEAN_SORT_ORDER.UNKOWN, }; + public openBeansCollapsed: boolean = false; + public archivedBeansCollapsed: boolean = false; + public frozenBeansCollapsed: boolean = false; + public archivedBeansFilterText: string = ''; public openBeansFilterText: string = ''; public frozenBeansFilterText: string = ''; @@ -100,10 +104,15 @@ export class BeansPage implements OnDestroy { this.settings = this.uiSettingsStorage.getSettings(); this.archivedBeansSort = this.settings.bean_sort.ARCHIVED; this.openBeansSort = this.settings.bean_sort.OPEN; + this.frozenBeansSort = this.settings.bean_sort.FROZEN; this.archivedBeansFilter = this.settings.bean_filter.ARCHIVED; this.frozenBeansFilter = this.settings.bean_filter.FROZEN; this.openBeansFilter = this.settings.bean_filter.OPEN; + + this.openBeansCollapsed = this.settings.bean_collapsed.OPEN; + this.archivedBeansCollapsed = this.settings.bean_collapsed.ARCHIVED; + this.frozenBeansCollapsed = this.settings.bean_collapsed.FROZEN; this.loadBeans(); this.beanStorageChangeSubscription = this.uiBeanStorage @@ -119,6 +128,37 @@ export class BeansPage implements OnDestroy { this.beanStorageChangeSubscription = undefined; } } + public isCollapseActive() { + let collapsed: boolean =false; + if (this.bean_segment === 'open') { + collapsed = this.openBeansCollapsed; + } else if (this.bean_segment === 'archive') { + collapsed = this.archivedBeansCollapsed; + } else if (this.bean_segment === 'frozen') { + collapsed = this.frozenBeansCollapsed; + } + return collapsed; + } + + public toggleCollapseBeans() { + if (this.bean_segment === 'open') { + this.openBeansCollapsed = !this.openBeansCollapsed; + } else if (this.bean_segment === 'archive') { + this.archivedBeansCollapsed = !this.archivedBeansCollapsed; + } else if (this.bean_segment === 'frozen') { + this.frozenBeansCollapsed = !this.frozenBeansCollapsed; + } + this.__saveCollapseFilter(); + this.research(); + } + private async __saveCollapseFilter() { + this.settings.bean_collapsed.OPEN = this.openBeansCollapsed; + this.settings.bean_collapsed.ARCHIVED = this.archivedBeansCollapsed; + this.settings.bean_collapsed.FROZEN = this.frozenBeansCollapsed; + await this.uiSettingsStorage.saveSettings(this.settings); + } + + public loadBeans(): void { this.__initializeBeans(); this.changeDetectorRef.detectChanges(); @@ -495,10 +535,10 @@ export class BeansPage implements OnDestroy { break; case BEAN_SORT_AFTER.ROASTING_DATE: filterBeans = filterBeans.sort((a, b) => { - if (a.roastingDate > b.roastingDate) { + if (a.roastingDate < b.roastingDate) { return -1; } - if (a.roastingDate < b.roastingDate) { + if (a.roastingDate > b.roastingDate) { return 1; } return 0; @@ -506,10 +546,21 @@ export class BeansPage implements OnDestroy { break; case BEAN_SORT_AFTER.RATING: filterBeans = filterBeans.sort((a, b) => { + if (a.rating < b.rating) { + return -1; + } if (a.rating > b.rating) { + return 1; + } + return 0; + }); + break; + case BEAN_SORT_AFTER.BEAN_AGE: + filterBeans = filterBeans.sort((a, b) => { + if (a.beanAgeInDays() < b.beanAgeInDays()) { return -1; } - if (a.rating < b.rating) { + if (a.beanAgeInDays() > b.beanAgeInDays()) { return 1; } return 0; diff --git a/src/app/brew/brew-add/brew-add.component.html b/src/app/brew/brew-add/brew-add.component.html index 879e5da1..b74ee3c5 100644 --- a/src/app/brew/brew-add/brew-add.component.html +++ b/src/app/brew/brew-add/brew-add.component.html @@ -18,6 +18,16 @@ + + + + + + + + + + diff --git a/src/app/brew/brew-choose-preparation-to-brew/brew-choose-preparation-to-brew.component.html b/src/app/brew/brew-choose-preparation-to-brew/brew-choose-preparation-to-brew.component.html index f7715077..b2f76929 100644 --- a/src/app/brew/brew-choose-preparation-to-brew/brew-choose-preparation-to-brew.component.html +++ b/src/app/brew/brew-choose-preparation-to-brew/brew-choose-preparation-to-brew.component.html @@ -8,7 +8,8 @@ - {{prep.name}} ({{"LAST_USE" | translate}}: + {{prep.name}} ({{"LAST_USE" | translate}}: {{lastUsed(prep) | formatDate:[settings?.date_format]}} -) diff --git a/src/app/brew/brew-edit/brew-edit.component.html b/src/app/brew/brew-edit/brew-edit.component.html index 72bb081f..462b5e87 100644 --- a/src/app/brew/brew-edit/brew-edit.component.html +++ b/src/app/brew/brew-edit/brew-edit.component.html @@ -18,6 +18,16 @@ + + + + + + + + + + diff --git a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.html b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.html index 0d9e1902..9025f316 100644 --- a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.html +++ b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.html @@ -1,6 +1,6 @@ - {{"CHOOSE_REFERENCE_GRAPH" | translate}} + {{"IMPORT_SHOT_FROM_METICULOUS" | translate}} @@ -9,16 +9,20 @@ - + - - - - - {{entry.profile.name}} - - + + + + +

{{entry.profile.name}}

+
{{this.uiHelper.formatTimeNumber(entry.time * 1000)}}
+
+ +
+
+
@@ -27,8 +31,8 @@ - {{"RESET" | translate}} + {{"CANCEL" | translate}} { let component: BrewModalImportShotMeticulousComponent; let fixture: ComponentFixture; @@ -10,7 +15,17 @@ describe('BrewModalImportShotMeticulousComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [BrewModalImportShotMeticulousComponent], - imports: [IonicModule.forRoot()], + imports: [IonicModule.forRoot(), TranslateModule.forRoot()], + providers: [ + { provide: InAppBrowser }, + { provide: File }, + { provide: SocialSharing }, + { provide: FileTransfer }, + { + provide: TranslateService, + useValue: TranslateServiceMock, + }, + ] }).compileComponents(); fixture = TestBed.createComponent(BrewModalImportShotMeticulousComponent); diff --git a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts index cc14aa86..c98b7487 100644 --- a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts +++ b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts @@ -1,15 +1,10 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, ElementRef, HostListener, Input, OnInit, ViewChild } from '@angular/core'; import { MeticulousDevice } from '../../../classes/preparationDevice/meticulous/meticulousDevice'; -import moment from 'moment/moment'; -import { - BrewFlow, - IBrewPressureFlow, - IBrewRealtimeWaterFlow, - IBrewTemperatureFlow, - IBrewWeightFlow, -} from '../../../classes/brew/brewFlow'; import { ModalController } from '@ionic/angular'; +import { HistoryListingEntry } from '@meticulous-home/espresso-api/dist/types'; +import { UIHelper } from '../../../services/uiHelper'; +import { AgVirtualSrollComponent } from 'ag-virtual-scroll'; @Component({ selector: 'app-brew-modal-import-shot-meticulous', @@ -21,81 +16,64 @@ export class BrewModalImportShotMeticulousComponent implements OnInit { @Input() public meticulousDevice: MeticulousDevice; public radioSelection: string; - public history: Array = []; - constructor(private readonly modalController: ModalController) {} + public history: Array = []; - public ngOnInit() { - this.readHistory(); - } + @ViewChild('ionItemEl', { read: ElementRef, static: false }) + public ionItemEl: ElementRef; - private async readHistory() { - this.history = await this.meticulousDevice.getHistory(); - //this.readShot(history[0]); - } + @ViewChild('historyShotContent', { read: ElementRef }) + public historyShotContent: ElementRef; - private readShot(_historyData) { - const newMoment = moment(new Date()).startOf('day'); + @ViewChild('shotDataScroll', { + read: AgVirtualSrollComponent, + static: false, + }) + public shotDataScroll: AgVirtualSrollComponent; - let firstDripTimeSet: boolean = false; - const newBrewFlow = new BrewFlow(); + @ViewChild('footerContent', { read: ElementRef }) + public footerContent: ElementRef; - let seconds: number = 0; - let milliseconds: number = 0; - for (const entry of _historyData.data as any) { - const shotEntry: any = entry.shot; - const shotEntryTime = newMoment.clone().add('milliseconds', entry.time); - const timestamp = shotEntryTime.format('HH:mm:ss.SSS'); + constructor(private readonly modalController: ModalController, + public readonly uiHelper: UIHelper) {} - seconds = shotEntryTime.diff(newMoment, 'seconds'); - milliseconds = shotEntryTime.get('milliseconds'); - - const realtimeWaterFlow: IBrewRealtimeWaterFlow = - {} as IBrewRealtimeWaterFlow; + public ngOnInit() { + this.readHistory(); + } - realtimeWaterFlow.brew_time = ''; - realtimeWaterFlow.timestamp = timestamp; - realtimeWaterFlow.smoothed_weight = 0; - realtimeWaterFlow.flow_value = shotEntry.flow; - realtimeWaterFlow.timestampdelta = 0; + private async readHistory() { + this.history = await this.meticulousDevice?.getHistory(); + this.retriggerScroll(); - newBrewFlow.realtimeFlow.push(realtimeWaterFlow); + } + @HostListener('window:resize') + @HostListener('window:orientationchange', ['$event']) + public onOrientationChange(event) { + this.retriggerScroll(); + } - const brewFlow: IBrewWeightFlow = {} as IBrewWeightFlow; - brewFlow.timestamp = timestamp; - brewFlow.brew_time = ''; - brewFlow.actual_weight = shotEntry.weight; - brewFlow.old_weight = 0; - brewFlow.actual_smoothed_weight = 0; - brewFlow.old_smoothed_weight = 0; - brewFlow.not_mutated_weight = 0; - newBrewFlow.weight.push(brewFlow); - if (shotEntry.weight > 0 && firstDripTimeSet === false) { - firstDripTimeSet = true; + private retriggerScroll() { + setTimeout(async () => { + const el = this.historyShotContent.nativeElement; + const scrollComponent: AgVirtualSrollComponent = this.shotDataScroll; - //this.brewComponent.brewFirstDripTime.setTime(seconds, milliseconds); - //this.brewComponent.brewFirstDripTime.changeEvent(); + if (scrollComponent) { + scrollComponent.el.style.height = + (el.offsetHeight - + 20) + + 'px'; } + }, 150); + } - const pressureFlow: IBrewPressureFlow = {} as IBrewPressureFlow; - pressureFlow.timestamp = timestamp; - pressureFlow.brew_time = ''; - pressureFlow.actual_pressure = shotEntry.pressure; - pressureFlow.old_pressure = 0; - newBrewFlow.pressureFlow.push(pressureFlow); - - const temperatureFlow: IBrewTemperatureFlow = {} as IBrewTemperatureFlow; - temperatureFlow.timestamp = timestamp; - temperatureFlow.brew_time = ''; - temperatureFlow.actual_temperature = shotEntry.temperature; - temperatureFlow.old_temperature = 0; - newBrewFlow.temperatureFlow.push(temperatureFlow); + public getElementOffsetWidth() { + if (this.ionItemEl?.nativeElement?.offsetWidth) { + return this.ionItemEl?.nativeElement?.offsetWidth - 50; } + return 0; + } - const lastEntry = newBrewFlow.weight[newBrewFlow.weight.length - 1]; - console.log(newBrewFlow); - } public dismiss(): void { this.modalController.dismiss( @@ -107,8 +85,17 @@ export class BrewModalImportShotMeticulousComponent implements OnInit { ); } public choose(): void { + let returningData; + + for (const entry of this.history) { + if (entry.id === this.radioSelection) { + returningData = entry; + break; + } + } this.modalController.dismiss( { + choosenHistory: returningData, dismissed: true, }, undefined, diff --git a/src/app/brew/brew.page.html b/src/app/brew/brew.page.html index 6bdb6ffd..776ca7fd 100644 --- a/src/app/brew/brew.page.html +++ b/src/app/brew/brew.page.html @@ -55,6 +55,12 @@ + + + + + +
@@ -65,8 +71,8 @@
- - + @@ -84,6 +90,10 @@ + + + +
@@ -94,8 +104,8 @@
- - + diff --git a/src/app/brew/brew.page.ts b/src/app/brew/brew.page.ts index dfb6e618..4b291ebb 100644 --- a/src/app/brew/brew.page.ts +++ b/src/app/brew/brew.page.ts @@ -6,8 +6,7 @@ import { OnInit, ViewChild, } from '@angular/core'; -import { ModalController, Platform } from '@ionic/angular'; -import { UIAlert } from '../../services/uiAlert'; +import { ModalController } from '@ionic/angular'; import { UIHelper } from '../../services/uiHelper'; import { UIBrewStorage } from '../../services/uiBrewStorage'; import { UISettingsStorage } from '../../services/uiSettingsStorage'; @@ -19,7 +18,6 @@ import { Bean } from '../../classes/bean/bean'; import { BrewFilterComponent } from './brew-filter/brew-filter.component'; import { Settings } from '../../classes/settings/settings'; import { AgVirtualSrollComponent } from 'ag-virtual-scroll'; -import { UIAnalytics } from '../../services/uiAnalytics'; @Component({ selector: 'brew', @@ -49,18 +47,18 @@ export class BrewPage implements OnInit { public archivedBrewsFilter: IBrewPageFilter; public openBrewsFilter: IBrewPageFilter; + public openBrewsCollapsed: boolean = false; + public archivedBrewsCollapsed: boolean = false; + public settings: Settings; constructor( private readonly modalCtrl: ModalController, - private readonly platform: Platform, private readonly uiBrewStorage: UIBrewStorage, private readonly changeDetectorRef: ChangeDetectorRef, - private readonly uiAlert: UIAlert, public uiHelper: UIHelper, public uiBrewHelper: UIBrewHelper, private readonly uiSettingsStorage: UISettingsStorage, - private readonly uiAnalytics: UIAnalytics ) { this.settings = this.uiSettingsStorage.getSettings(); this.archivedBrewsFilter = this.settings.GET_BREW_FILTER(); @@ -70,6 +68,8 @@ export class BrewPage implements OnInit { public ionViewWillEnter(): void { this.archivedBrewsFilter = this.settings.brew_filter.ARCHIVED; this.openBrewsFilter = this.settings.brew_filter.OPEN; + this.openBrewsCollapsed = this.settings.brew_collapsed.OPEN; + this.archivedBrewsCollapsed = this.settings.brew_collapsed.ARCHIVED; this.loadBrews(); this.retriggerScroll(); @@ -123,6 +123,26 @@ export class BrewPage implements OnInit { this.__initializeBrewView('archiv'); } + public isCollapseActive() { + let collapsed: boolean =false; + if (this.brew_segment === 'open') { + collapsed = this.openBrewsCollapsed; + } else { + collapsed = this.archivedBrewsCollapsed; + } + return collapsed; + } + + public toggleCollapseBrews() { + if (this.brew_segment === 'open') { + this.openBrewsCollapsed = !this.openBrewsCollapsed; + } else { + this.archivedBrewsCollapsed = !this.archivedBrewsCollapsed; + } + this.__saveCollapseFilter(); + this.research(); + } + public isFilterActive(): boolean { let checkingFilter: IBrewPageFilter; let checkingFilterText: string = ''; @@ -198,6 +218,8 @@ export class BrewPage implements OnInit { return instructor.config.uuid; } + + public async showFilter() { let brewFilter: IBrewPageFilter; if (this.brew_segment === 'open') { @@ -237,6 +259,11 @@ export class BrewPage implements OnInit { this.settings.brew_filter.ARCHIVED = this.archivedBrewsFilter; await this.uiSettingsStorage.saveSettings(this.settings); } + private async __saveCollapseFilter() { + this.settings.brew_collapsed.OPEN = this.openBrewsCollapsed; + this.settings.brew_collapsed.ARCHIVED = this.archivedBrewsCollapsed; + await this.uiSettingsStorage.saveSettings(this.settings); + } public research() { this.__initializeBrewView(this.brew_segment); diff --git a/src/app/preparation/preparation-add-type/preparation-add-type.component.ts b/src/app/preparation/preparation-add-type/preparation-add-type.component.ts index 4d2a4a22..db570736 100644 --- a/src/app/preparation/preparation-add-type/preparation-add-type.component.ts +++ b/src/app/preparation/preparation-add-type/preparation-add-type.component.ts @@ -11,6 +11,7 @@ import { PREPARATION_STYLE_TYPE } from '../../../enums/preparations/preparationS import { PreparationTool } from '../../../classes/preparation/preparationTool'; import PREPARATION_TRACKING from '../../../data/tracking/preparationTracking'; import { UIAnalytics } from '../../../services/uiAnalytics'; +import { UIPreparationHelper } from '../../../services/uiPreparationHelper'; @Component({ selector: 'preparation-add-type', @@ -34,9 +35,11 @@ export class PreparationAddTypeComponent implements OnInit { private readonly navParams: NavParams, private readonly uiToast: UIToast, private readonly translate: TranslateService, - private readonly uiAnalytics: UIAnalytics + private readonly uiAnalytics: UIAnalytics, + private readonly uiPreparationHelper: UIPreparationHelper ) { this.data.type = this.navParams.get('type'); + if (this.data.type !== PREPARATION_TYPES.CUSTOM_PREPARATION) { this.data.name = this.translate.instant( 'PREPARATION_TYPE_' + this.data.type @@ -69,11 +72,15 @@ export class PreparationAddTypeComponent implements OnInit { this.data.manage_parameters.coffee_first_drip_time = false; this.data.default_last_coffee_parameters.coffee_first_drip_time = false; } - await this.uiPreparationStorage.add(this.data); + const newPreparation = await this.uiPreparationStorage.add(this.data); this.dismiss(true); if (!this.hide_toast_message) { this.uiToast.showInfoToast('TOAST_PREPARATION_ADDED_SUCCESSFULLY'); } + + if (this.data.type === PREPARATION_TYPES.METICULOUS || this.data.type === PREPARATION_TYPES.XENIA || this.data.type === PREPARATION_TYPES.SANREMO_YOU) { + await this.uiPreparationHelper.connectDevice(newPreparation); + } } public async dismiss(_added: boolean) { diff --git a/src/app/preparation/preparation-add/preparation-add.component.html b/src/app/preparation/preparation-add/preparation-add.component.html index 590de67e..7a6d4394 100644 --- a/src/app/preparation/preparation-add/preparation-add.component.html +++ b/src/app/preparation/preparation-add/preparation-add.component.html @@ -12,28 +12,31 @@ - - - + -
- -
+ + + + +
+ +
-
- {{'PREPARATION_TYPE_' + key | translate}} -
-
-
- + {{'PREPARATION_TYPE_' + key | translate}} +
+
+ +
+ +
+
+ {{'PREPARATION_TYPE_ADD_CUSTOM' | translate}}
-
- {{'PREPARATION_TYPE_ADD_CUSTOM' | translate}} -
-
-
-
+
+
+
+
diff --git a/src/app/preparation/preparation-add/preparation-add.component.ts b/src/app/preparation/preparation-add/preparation-add.component.ts index 47f68849..ada8b095 100644 --- a/src/app/preparation/preparation-add/preparation-add.component.ts +++ b/src/app/preparation/preparation-add/preparation-add.component.ts @@ -7,6 +7,7 @@ import { NgForm } from '@angular/forms'; import { PreparationAddTypeComponent } from '../preparation-add-type/preparation-add-type.component'; import PREPARATION_TRACKING from '../../../data/tracking/preparationTracking'; import { UIAnalytics } from '../../../services/uiAnalytics'; +import { environment } from '../../../environments/environment'; @Component({ selector: 'preparation-add', templateUrl: './preparation-add.component.html', @@ -18,6 +19,8 @@ export class PreparationAddComponent implements OnInit { public preparation_types_enum = PREPARATION_TYPES; + public ENVIRONMENT = environment; + @ViewChild('addPreparationForm', { static: false }) public preparationForm: NgForm; @@ -35,6 +38,16 @@ export class PreparationAddComponent implements OnInit { ); } + public individualPreparationVisible(_key) { + if (_key ==='SANREMO_YOU') { + if (this.ENVIRONMENT.FEATURES_ACTIVE.SANREMO_YOU === true) { + return true; + } + return false; + } + return true; + } + public async choosePreparation(_prepType: PREPARATION_TYPES) { //Animated false, else backdrop would sometimes not disappear and stay until user touches again. const modal = await this.modalController.create({ diff --git a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.html b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.html index 42bf7062..071f6557 100644 --- a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.html +++ b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.html @@ -12,18 +12,19 @@ - {{"PREPARATION_DEVICE.TYPE.NONE" | translate}} {{"PREPARATION_DEVICE.TYPE.XENIA" | translate}} {{"PREPARATION_DEVICE.TYPE.METICULOUS" | translate}} + {{"PREPARATION_DEVICE.TYPE.SANREMO_YOU" | translate}} - + {{"PREPARATION_DEVICE.URL" | translate}} - @@ -31,7 +32,7 @@ - V1 V2 @@ -40,7 +41,7 @@

{{"PREPARATION_DEVICE.RESIDUAL_LAG_TIME" | translate }} {{uiHelper.toFixedIfNecessary(preparation.connectedPreparationDevice.customParams.residualLagTime,2)}}

+ style="vertical-align: top;">{{uiHelper.toFixedIfNecessary(data.connectedPreparationDevice.customParams.residualLagTime,2)}}
@@ -49,33 +50,59 @@

{{"PREPARATION_DEVICE.RESIDUAL_LAG_TIME" | translate }}  - - +
{{"SAVE_LOGFILES_TO_NOTES_FROM_MACHINE" | translate}}
- - + + + {{"PREPARATION_DEVICE.URL" | translate}} + + + + + + + + {{"PREPARATION_DEVICE.URL" | translate}} - + + + + + +

{{"PREPARATION_DEVICE.RESIDUAL_LAG_TIME" | translate }} {{uiHelper.toFixedIfNecessary(data.connectedPreparationDevice.customParams.residualLagTime,2)}}

+
+
+ + +

{{"PREPARATION_DEVICE.RESIDUAL_LAG_TIME_DESCRIPTION" | translate }}

+
+
+ + + + +
- - - - + diff --git a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts index e4425e92..8e9d18f1 100644 --- a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts +++ b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts @@ -12,6 +12,8 @@ import { UIAlert } from '../../../services/uiAlert'; import { UIHelper } from '../../../services/uiHelper'; import { UISettingsStorage } from '../../../services/uiSettingsStorage'; import { Settings } from '../../../classes/settings/settings'; +import { environment } from '../../../environments/environment'; +import { PREPARATION_TYPES } from '../../../enums/preparations/preparationTypes'; @Component({ selector: 'app-preparation-connected-device', @@ -26,6 +28,8 @@ export class PreparationConnectedDeviceComponent { public PREPARATION_DEVICE_TYPE = PreparationDeviceType; @Input() public preparation: IPreparation; + public ENVIRONMENT_PARAMS = environment; + public pinFormatter(value: any) { const parsedFloat = parseFloat(value); if (isNaN(parsedFloat)) { @@ -48,6 +52,18 @@ export class PreparationConnectedDeviceComponent { if (this.preparation !== undefined) { this.data.initializeByObject(this.preparation); } + if (this.data.connectedPreparationDevice.type === PreparationDeviceType.NONE) { + if (this.data.type === PREPARATION_TYPES.METICULOUS) { + this.data.connectedPreparationDevice.type = PreparationDeviceType.METICULOUS; + } + if (this.data.type === PREPARATION_TYPES.XENIA) { + this.data.connectedPreparationDevice.type = PreparationDeviceType.XENIA; + } + if (this.data.type === PREPARATION_TYPES.SANREMO_YOU) { + this.data.connectedPreparationDevice.type = PreparationDeviceType.SANREMO_YOU; + } + } + } public dismiss(): void { @@ -98,7 +114,40 @@ export class PreparationConnectedDeviceComponent { this.data.connectedPreparationDevice.customParams.residualLagTime = 1.35; } } - + if ( + this.data.connectedPreparationDevice.type === + PreparationDeviceType.METICULOUS + ) + { + if (this.data.connectedPreparationDevice.url.endsWith('/') === true) { + this.data.connectedPreparationDevice.url = + this.data.connectedPreparationDevice.url.slice(0, -1); + } + if ( + this.data.connectedPreparationDevice.url.startsWith('http') === + false + ) { + this.data.connectedPreparationDevice.url = + 'http://' + this.data.connectedPreparationDevice.url; + } + } + if ( + this.data.connectedPreparationDevice.type === + PreparationDeviceType.SANREMO_YOU + ) + { + if (this.data.connectedPreparationDevice.url.endsWith('/') === true) { + this.data.connectedPreparationDevice.url = + this.data.connectedPreparationDevice.url.slice(0, -1); + } + if ( + this.data.connectedPreparationDevice.url.startsWith('http') === + false + ) { + this.data.connectedPreparationDevice.url = + 'http://' + this.data.connectedPreparationDevice.url; + } + } if ( this.data.connectedPreparationDevice.type !== PreparationDeviceType.NONE ) { @@ -136,4 +185,6 @@ export class PreparationConnectedDeviceComponent { } public ngOnInit() {} + + } diff --git a/src/app/preparation/preparation-modal-select/preparation-modal-select.component.html b/src/app/preparation/preparation-modal-select/preparation-modal-select.component.html index 5d775696..3151de2b 100644 --- a/src/app/preparation/preparation-modal-select/preparation-modal-select.component.html +++ b/src/app/preparation/preparation-modal-select/preparation-modal-select.component.html @@ -28,7 +28,8 @@ -
{{prep.name}}
+
{{prep.name}}

{{"LAST_USE" | translate}}: {{lastUsed(prep) | formatDate:[settings?.date_format]}} - @@ -47,7 +48,8 @@ -

{{prep.name}}
+
{{prep.name}}

{{"LAST_USE" | translate}}: {{lastUsed(prep) | formatDate:[settings?.date_format]}} - @@ -72,7 +74,8 @@

{{prep.name}}
-
{{prep.name}}
+
{{prep.name}}

{{"LAST_USE" | translate}}: {{lastUsed(prep) | formatDate:[settings?.date_format]}} - @@ -91,7 +94,8 @@

{{prep.name}}
-
{{prep.name}}
+
{{prep.name}}

{{"LAST_USE" | translate}}: {{lastUsed(prep) | formatDate:[settings?.date_format]}} - diff --git a/src/app/settings/settings.page.html b/src/app/settings/settings.page.html index 33306782..9ead758f 100644 --- a/src/app/settings/settings.page.html +++ b/src/app/settings/settings.page.html @@ -55,12 +55,16 @@

{{"EXPORT" | translate}}

Temp: Export Brew By Weight - Xenia
- + {{"EXCEL_EXPORT" | translate}} - - {{"IMPORT_BEANS_EXCEL" | translate}} + + {{"IMPORT_ROASTED_BEANS_EXCEL" | translate}} + + + + {{"IMPORT_GREEN_BEANS_EXCEL" | translate}} @@ -361,7 +365,7 @@

{{"PAGE_SETTINGS_BREW_TIMER_START_DELAY_ACTIVE" | translate}}

{{"PAGE_SETTINGS_MANAGE_FEATURES" | translate}} -
{{"ACTIVE_BEAN_FREEZING_FEATURE" | translate}}
diff --git a/src/app/settings/settings.page.ts b/src/app/settings/settings.page.ts index 46b8bd9b..c5047fb9 100644 --- a/src/app/settings/settings.page.ts +++ b/src/app/settings/settings.page.ts @@ -14,7 +14,6 @@ import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { DirectoryEntry, FileEntry } from '@awesome-cordova-plugins/file'; import { FileChooser } from '@awesome-cordova-plugins/file-chooser/ngx'; import { File } from '@awesome-cordova-plugins/file/ngx'; -import { FilePath } from '@awesome-cordova-plugins/file-path/ngx'; import { IBean } from '../../interfaces/bean/iBean'; import { IBrew } from '../../interfaces/brew/iBrew'; import { ISettings } from '../../interfaces/settings/iSettings'; @@ -918,6 +917,9 @@ export class SettingsPage { public async resetFilter() { this.settings.resetFilter(); } + public async resetBeanSort() { + this.settings.resetBeanSort(); + } public async fixWeightChangeMinFlowNumber() { //We need to trigger this, because the slider sometimes procudes values like 0.60000001, and we need to fix this before saving @@ -1223,7 +1225,9 @@ export class SettingsPage { await this.uiAlert.showLoadingSpinner(); try { const allXeniaPreps = []; - const allPreparations = this.uiPreparationStorage.getAllEntries(); + let allPreparations = this.uiPreparationStorage.getAllEntries(); + // Just take 60, else the excel will be exploding. + allPreparations = allPreparations.reverse().slice(0,60); for (const prep of allPreparations) { if ( prep.connectedPreparationDevice.type === PreparationDeviceType.XENIA @@ -1274,7 +1278,7 @@ export class SettingsPage { } } - public importBeansExcel(): void { + public importBeansExcel(_type: string='roasted'): void { if (this.platform.is('cordova')) { this.uiAnalytics.trackEvent( SETTINGS_TRACKING.TITLE, @@ -1291,7 +1295,12 @@ export class SettingsPage { this.uiFileHelper.readFileEntryAsArrayBuffer(fileEntry).then( async (_arrayBuffer) => { - this.uiExcel.importBeansByExcel(_arrayBuffer); + if (_type ==='roasted') { + this.uiExcel.importBeansByExcel(_arrayBuffer); + }else { + this.uiExcel.importGreenBeansByExcel(_arrayBuffer); + } + }, () => { // Backup, maybe it was a .JSON? @@ -1317,7 +1326,11 @@ export class SettingsPage { } this.uiFileHelper.readFileAsArrayBuffer(path, file).then( async (_arrayBuffer) => { - this.uiExcel.importBeansByExcel(_arrayBuffer); + if (_type ==='roasted') { + this.uiExcel.importBeansByExcel(_arrayBuffer); + } else { + this.uiExcel.importGreenBeansByExcel(_arrayBuffer); + } }, () => { // Backup, maybe it was a .JSON? diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index a34ce5ec..731d7b0f 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -190,6 +190,8 @@ import { BeanFreezeInformationComponent } from '../../components/beans/bean-free import { BeanPopoverFrozenListComponent } from '../beans/bean-popover-frozen-list/bean-popover-frozen-list.component'; import { PipesModule } from 'src/pipes/pipes.module'; import { BrewModalImportShotMeticulousComponent } from '../brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component'; +import { DataCorruptionFoundComponent } from '../../popover/data-corruption-found/data-corruption-found.component'; +import { BeanPopoverListComponent } from '../beans/bean-popover-list/bean-popover-list.component'; @NgModule({ declarations: [ @@ -232,6 +234,7 @@ import { BrewModalImportShotMeticulousComponent } from '../brew/brew-modal-impor WelcomePopoverComponent, AnalyticsPopoverComponent, MeticulousHelpPopoverComponent, + DataCorruptionFoundComponent, QrCodeScannerPopoverComponent, UpdatePopoverComponent, DatetimePopoverComponent, @@ -317,6 +320,7 @@ import { BrewModalImportShotMeticulousComponent } from '../brew/brew-modal-impor BeanPopoverAddComponent, BeanPopoverFreezeComponent, BeanPopoverFrozenListComponent, + BeanPopoverListComponent, BeanArchivePopoverComponent, MillPopoverActionsComponent, BeanModalSelectComponent, @@ -444,6 +448,7 @@ import { BrewModalImportShotMeticulousComponent } from '../brew/brew-modal-impor WelcomePopoverComponent, AnalyticsPopoverComponent, MeticulousHelpPopoverComponent, + DataCorruptionFoundComponent, QrCodeScannerPopoverComponent, UpdatePopoverComponent, DatetimePopoverComponent, @@ -526,6 +531,7 @@ import { BrewModalImportShotMeticulousComponent } from '../brew/brew-modal-impor BeanPopoverAddComponent, BeanPopoverFreezeComponent, BeanPopoverFrozenListComponent, + BeanPopoverListComponent, BeanArchivePopoverComponent, BeanModalSelectComponent, AssociatedBrewsComponent, diff --git a/src/assets/custom-ion-icons/beanconqueror-expand-active.svg b/src/assets/custom-ion-icons/beanconqueror-expand-active.svg new file mode 100644 index 00000000..c7db982c --- /dev/null +++ b/src/assets/custom-ion-icons/beanconqueror-expand-active.svg @@ -0,0 +1 @@ + diff --git a/src/assets/custom-ion-icons/beanconqueror-expand-inactive.svg b/src/assets/custom-ion-icons/beanconqueror-expand-inactive.svg new file mode 100644 index 00000000..a4b978e8 --- /dev/null +++ b/src/assets/custom-ion-icons/beanconqueror-expand-inactive.svg @@ -0,0 +1 @@ + diff --git a/src/assets/custom-ion-icons/beanconqueror-sanremo-you-logo.svg b/src/assets/custom-ion-icons/beanconqueror-sanremo-you-logo.svg new file mode 100644 index 00000000..076d07b5 --- /dev/null +++ b/src/assets/custom-ion-icons/beanconqueror-sanremo-you-logo.svg @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index b73e2994..5990d359 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1030,7 +1030,8 @@ "TYPE": { "NONE": "None", "XENIA": "Xenia", - "METICULOUS": "Meticulous" + "METICULOUS": "Meticulous", + "SANREMO_YOU": "Sanremo YOU" }, "URL": "Url", "CHOOSE_DEVICE": "Choose device", @@ -1063,6 +1064,10 @@ "CHOOSE_PROFILE": "Choose profile", "SHOT_STARTED": "Shot started", "SHOT_ENDED": "Shot ended" + }, + "TYPE_SANREMO_YOU": { + "TITLE": "Sanremo YOU Machine", + "STOP_AT_WEIGHT": "Stop at weight" } }, "DEVICE_CONNECTION": "Device connection", @@ -1352,5 +1357,18 @@ "BEAN_DATA_FROZEN_NOTE": "Frozen notes", "IGNORE_NEGATIVE_VALUES_DESCRIPTION": "Activating this, results into a graph which will be one second behind", "IGNORE_ANOMALY_VALUES_DESCRIPTION": "Activating this, results into a graph which will be one second behind", - "SAVE_LOGFILES_TO_NOTES_FROM_MACHINE": "Save the machine logs when saving a brew" -} \ No newline at end of file + "SAVE_LOGFILES_TO_NOTES_FROM_MACHINE": "Save the machine logs when saving a brew", + "IMPORT_SHOT_FROM_METICULOUS": "Import a shot", + "BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION": "All found entries in the excel list, have been transformed into new beans, enjoy a tasty brew!", + "IMPORT_UNSUCCESSFULLY": "Import not successful", + "BEAN_LIST": "Bean list", + "IMPORT_ROASTED_BEANS_EXCEL": "Import roasted beans via excel", + "IMPORT_GREEN_BEANS_EXCEL": "Import green beans via excel", + "BEANS_IMPORTED_UNSUCCESSFULLY_WRONG_EXCELFILE": "It looks like that the chosen excel file is corrupted, has wrong data, is wrong structured, or was wrongly chosen. Because of this no beans could be imported.", + "OK": "Ok", + "BEAN_SORT_BEAN_AGE": "Bean age", + "GREEN_BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION": "All found entries in the excel list, have been transformed into new green beans, have great roasts!", + "PREPARATION_TYPE_SANREMO_YOU": "Sanremo YOU", + "PREPARATION_TYPE_XENIA": "Xenia", + "BEAN_POPUP_YOU_DONT_SEE_EVERYTHING_DESCRIPTION": "You're adding a bean which has variety information in it, but those parameters are not activated. Do you want to activate them now?" +} diff --git a/src/classes/bean/bean.ts b/src/classes/bean/bean.ts index 8c0b28a6..633b48a3 100755 --- a/src/classes/bean/bean.ts +++ b/src/classes/bean/bean.ts @@ -156,6 +156,13 @@ export class Bean implements IBean { return false; } } + public isUnfrozen() { + if (this.frozenDate && this.unfrozenDate) { + return true; + } else { + return false; + } + } public initializeByObject(beanObj: IBean): void { Object.assign(this, beanObj); diff --git a/src/classes/devices/argosThermometer.ts b/src/classes/devices/argosThermometer.ts new file mode 100644 index 00000000..5b04c434 --- /dev/null +++ b/src/classes/devices/argosThermometer.ts @@ -0,0 +1,72 @@ +import { PeripheralData } from './ble.types'; +import { Logger } from './common/logger'; + +import { TemperatureDevice } from './temperatureBluetoothDevice'; + +declare var ble: any; + +export class ArgosThermometer extends TemperatureDevice { + public static DEVICE_NAME = 'ARGOS'; + public static TEMPERATURE_SERVICE_UUID = + '6a521c59-55b5-4384-85c0-6534e63fb09e'; + public static TEMPERATURE_CHAR_UUID = '6a521c62-55b5-4384-85c0-6534e63fb09e'; + + private logger: Logger; + + constructor(data: PeripheralData) { + super(data); + this.connect(); + this.logger = new Logger('ArgosTemperatureSensor'); + } + + public static test(device: any): boolean { + return ( + device && + device.name && + device.name.toLowerCase().startsWith(ArgosThermometer.DEVICE_NAME.toLowerCase()) + ); + } + + public connect() { + this.attachNotification(); + } + + public disconnect() { + this.deattachNotification(); + } + + private attachNotification() { + ble.startNotification( + this.device_id, + ArgosThermometer.TEMPERATURE_SERVICE_UUID, + ArgosThermometer.TEMPERATURE_CHAR_UUID, + + async (_data: any) => { + let newData = new Uint8Array(_data.slice(0,-1)); + this.parseStatusUpdate(newData); + }, + + (_data: any) => {} + ); + } + + private parseStatusUpdate(temperatureRawStatus: Uint8Array) { + this.logger.log( + 'temperatureRawStatus received is: ' + temperatureRawStatus + ); + + const temperature_in_f = temperatureRawStatus[-1] << 8 + temperatureRawStatus[-2]; +console.log("New temperature inc" + temperature_in_f); + this.setTemperature(temperature_in_f, temperatureRawStatus); + } + + private deattachNotification() { + ble.stopNotification( + this.device_id, + ArgosThermometer.TEMPERATURE_SERVICE_UUID, + ArgosThermometer.TEMPERATURE_CHAR_UUID, + (e: any) => {}, + (e: any) => {} + ); + } +} diff --git a/src/classes/devices/index.ts b/src/classes/devices/index.ts index b18f3a7e..c6657b1c 100644 --- a/src/classes/devices/index.ts +++ b/src/classes/devices/index.ts @@ -25,6 +25,7 @@ import { BookooScale } from './bokooScale'; import { BasicGrillThermometer } from './basicGrillThermometer'; import { MeaterThermometer } from './meaterThermometer'; import { CombustionThermometer } from './combustionThermometer'; +import { ArgosThermometer } from './argosThermometer'; export { BluetoothScale, SCALE_TIMER_COMMAND } from './bluetoothDevice'; export * from './common'; @@ -56,6 +57,7 @@ export enum TemperatureType { BASICGRILL = 'BASICGRILL', MEATER = 'MEATER', COMBUSTION = 'COMBUSTION', + ARGOS = 'ARGOS' } export enum RefractometerType { @@ -129,6 +131,8 @@ export function makeTemperatureDevice( return new MeaterThermometer(data); case TemperatureType.COMBUSTION: return new CombustionThermometer(data); + case TemperatureType.ARGOS: + return new ArgosThermometer(data); default: return null; } diff --git a/src/classes/preparation/preparation.ts b/src/classes/preparation/preparation.ts index d18e4639..d163ddfb 100755 --- a/src/classes/preparation/preparation.ts +++ b/src/classes/preparation/preparation.ts @@ -12,6 +12,7 @@ import { UIHelper } from '../../services/uiHelper'; import { ListViewBrewParameter } from '../parameter/listViewBrewParameter'; import { RepeatBrewParameter } from '../parameter/repeatBrewParameter'; import { ConnectedPreparationDevice } from '../preparationDevice/connectedPreparationDevice'; +import { PreparationDeviceType } from '../preparationDevice'; export class Preparation implements IPreparation { public name: string; @@ -163,6 +164,10 @@ export class Preparation implements IPreparation { return PREPARATION_STYLE_TYPE.POUR_OVER; case PREPARATION_TYPES.METICULOUS: return PREPARATION_STYLE_TYPE.ESPRESSO; + case PREPARATION_TYPES.XENIA: + return PREPARATION_STYLE_TYPE.ESPRESSO; + case PREPARATION_TYPES.SANREMO_YOU: + return PREPARATION_STYLE_TYPE.ESPRESSO; default: return PREPARATION_STYLE_TYPE.POUR_OVER; } @@ -305,4 +310,11 @@ export class Preparation implements IPreparation { public hasPhotos(): boolean { return this.attachments && this.attachments.length > 0; } + public hasDeviceConnection(): boolean { + return ( + this.connectedPreparationDevice?.type !== + PreparationDeviceType.NONE + ); + } + } diff --git a/src/classes/preparationDevice/index.ts b/src/classes/preparationDevice/index.ts index ad1960ce..729697c2 100644 --- a/src/classes/preparationDevice/index.ts +++ b/src/classes/preparationDevice/index.ts @@ -3,11 +3,13 @@ import { PreparationDevice } from './preparationDevice'; import { HttpClient } from '@angular/common/http'; import { Preparation } from '../preparation/preparation'; import { MeticulousDevice } from './meticulous/meticulousDevice'; +import { SanremoYOUDevice } from './sanremo/sanremoYOUDevice'; export enum PreparationDeviceType { NONE = 'NONE', XENIA = 'XENIA', METICULOUS = 'METICULOUS', + SANREMO_YOU = 'SANREMO_YOU', } export function makePreparationDevice( @@ -20,6 +22,8 @@ export function makePreparationDevice( return new XeniaDevice(_http, _preparation); case PreparationDeviceType.METICULOUS: return new MeticulousDevice(_http, _preparation); + case PreparationDeviceType.SANREMO_YOU: + return new SanremoYOUDevice(_http, _preparation); default: return null; } diff --git a/src/classes/preparationDevice/meticulous/meticulousDevice.ts b/src/classes/preparationDevice/meticulous/meticulousDevice.ts index 93dbd744..5dae48b3 100644 --- a/src/classes/preparationDevice/meticulous/meticulousDevice.ts +++ b/src/classes/preparationDevice/meticulous/meticulousDevice.ts @@ -2,17 +2,15 @@ import { PreparationDevice } from '../preparationDevice'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Preparation } from '../../preparation/preparation'; import { MeticulousShotData } from './meticulousShotData'; -import Api, { - ApiResponseError, - ProfileIdent, - ActionType, -} from 'meticulous-api'; +import Api, { ActionType, ProfileIdent } from '@meticulous-home/espresso-api'; import { IMeticulousParams } from '../../../interfaces/preparationDevices/meticulous/iMeticulousParams'; import { Profile } from 'meticulous-typescript-profile'; -import { UILog } from '../../../services/uiLog'; import { catchError, timeout } from 'rxjs/operators'; import { of } from 'rxjs'; +import { HistoryListingEntry } from '@meticulous-home/espresso-api/dist/types'; +import moment from 'moment'; +import { BrewFlow, IBrewPressureFlow, IBrewRealtimeWaterFlow, IBrewTemperatureFlow, IBrewWeightFlow } from '../../brew/brewFlow'; declare var cordova; declare var io; @@ -25,8 +23,56 @@ export class MeticulousDevice extends PreparationDevice { private _profiles: Array = []; + private serverURL: string = ''; + public static returnBrewFlowForShotData(_shotData) { + const newMoment = moment(new Date()).startOf('day'); + const newBrewFlow = new BrewFlow(); + + for (const entry of _shotData as any) { + const shotEntry: any = entry.shot; + const shotEntryTime = newMoment.clone().add('milliseconds', entry.time); + const timestamp = shotEntryTime.format('HH:mm:ss.SSS'); + + const realtimeWaterFlow: IBrewRealtimeWaterFlow = + {} as IBrewRealtimeWaterFlow; + + realtimeWaterFlow.brew_time = ''; + realtimeWaterFlow.timestamp = timestamp; + realtimeWaterFlow.smoothed_weight = 0; + realtimeWaterFlow.flow_value = shotEntry.flow; + realtimeWaterFlow.timestampdelta = 0; + + newBrewFlow.realtimeFlow.push(realtimeWaterFlow); + + const brewFlow: IBrewWeightFlow = {} as IBrewWeightFlow; + brewFlow.timestamp = timestamp; + brewFlow.brew_time = ''; + brewFlow.actual_weight = shotEntry.weight; + brewFlow.old_weight = 0; + brewFlow.actual_smoothed_weight = 0; + brewFlow.old_smoothed_weight = 0; + brewFlow.not_mutated_weight = 0; + newBrewFlow.weight.push(brewFlow); + + const pressureFlow: IBrewPressureFlow = {} as IBrewPressureFlow; + pressureFlow.timestamp = timestamp; + pressureFlow.brew_time = ''; + pressureFlow.actual_pressure = shotEntry.pressure; + pressureFlow.old_pressure = 0; + newBrewFlow.pressureFlow.push(pressureFlow); + + const temperatureFlow: IBrewTemperatureFlow = {} as IBrewTemperatureFlow; + temperatureFlow.timestamp = timestamp; + temperatureFlow.brew_time = ''; + temperatureFlow.actual_temperature = shotEntry.temperature; + temperatureFlow.old_temperature = 0; + newBrewFlow.temperatureFlow.push(temperatureFlow); + } + return newBrewFlow; + } + constructor(protected httpClient: HttpClient, _preparation: Preparation) { super(httpClient, _preparation); this.meticulousShotData = undefined; @@ -48,7 +94,7 @@ export class MeticulousDevice extends PreparationDevice { }; this.httpClient .post( - this.serverURL + 'api/v1/history', + this.serverURL + '/api/v1/history', { sort: 'desc', max_results: 20, @@ -93,24 +139,50 @@ export class MeticulousDevice extends PreparationDevice { try { const profileResponse = await this.metApi.getProfile(_profileId); - if (profileResponse instanceof ApiResponseError) { + const profile = profileResponse.data as unknown as Profile; + return profile; + /* if (profileResponse instanceof Profile) { } else { - const profile = profileResponse.data as unknown as Profile; - return profile; - } + + }*/ } catch (ex) {} return undefined; } + public async getHistoryShortListing() { + + const response = await this.metApi.getHistoryShortListing(); + if (response && response.data && response.data.history) + { + return response.data.history as Array; + } + } + + + + public async searchHistory() { + const response = await this.metApi.searchHistory({ + query: '', + ids: [], + start_date: '', + end_date: '', + order_by: ['date'], + sort: 'desc', + max_results: 10, + dump_data: true + } ); + if (response && response.data && response.data.history) + { + return response.data.history as Array; + } + } + public async loadProfileByID(_profileId: string) { try { const loadProfile = await this.metApi.loadProfileByID(_profileId); + const profile = loadProfile.data as unknown as Profile; + return profile; - if (loadProfile instanceof ApiResponseError) { - } else { - const profile = loadProfile.data as unknown as Profile; - return profile; - } } catch (ex) { console.log(ex.message); } @@ -135,11 +207,8 @@ export class MeticulousDevice extends PreparationDevice { try { if (this._profiles.length <= 0) { const profiles = await this.metApi.listProfiles(); + this._profiles = profiles.data as Array; - if (profiles instanceof ApiResponseError) { - } else { - this._profiles = profiles.data as Array; - } } } catch (ex) {} } @@ -149,8 +218,9 @@ export class MeticulousDevice extends PreparationDevice { } public override async deviceConnected(): Promise { - const promise = new Promise((resolve, reject) => { - if (this.socket !== undefined) { + const promise = new Promise(async(resolve, reject) => { + const settings: any = await this.metApi.getSettings(); + if (settings?.data?.config) { resolve(true); } else { resolve(false); diff --git a/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts b/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts new file mode 100644 index 00000000..d110aa9d --- /dev/null +++ b/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts @@ -0,0 +1,187 @@ +import { PreparationDevice } from '../preparationDevice'; +import { HttpClient } from '@angular/common/http'; +import { Preparation } from '../../preparation/preparation'; + +import { ISanremoYOUParams } from '../../../interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams'; +declare var cordova; +export class SanremoYOUDevice extends PreparationDevice { + public scriptList: Array<{ INDEX: number; TITLE: string }> = []; + + + private connectionURL: string =''; + constructor(protected httpClient: HttpClient, _preparation: Preparation) { + super(httpClient, _preparation); + + this.connectionURL =this.getPreparation().connectedPreparationDevice.url; + } + + public async deviceConnected(): Promise { + const promise = new Promise((resolve, reject) => { + const options = { + method: 'get', + }; + let urlAdding = '/api/runtime'; + + cordova.plugin.http.sendRequest( + this.connectionURL + urlAdding, + options, + (response) => { + try { + const parsedJSON = JSON.parse(response.data); + resolve(true); + return; + + if (parsedJSON && 'id' in parsedJSON) { + resolve(true); + } else { + reject(''); + } + } catch (e) { + // alert("Error in Resolve " + JSON.stringify(e)); + reject(JSON.stringify(e)); + } + }, + (response) => { + // prints 403 + // alert("Error " + JSON.stringify(response)); + reject(JSON.stringify(response)); + } + ); + }); + return promise; + } + + public getPressure() { + return this.pressure; + } + + public getResidualLagTime() { + const connectedPreparationDevice = + this.getPreparation().connectedPreparationDevice; + if ( + connectedPreparationDevice.customParams && + connectedPreparationDevice.customParams.residualLagTime + ) { + return connectedPreparationDevice.customParams.residualLagTime; + } else { + // Fixed value. + return 1.35; + } + } + + public getSaveLogfilesFromMachine(): boolean { + const connectedPreparationDevice = + this.getPreparation().connectedPreparationDevice; + if ( + connectedPreparationDevice.customParams && + connectedPreparationDevice.customParams.saveLogfilesFromMachine + ) { + return connectedPreparationDevice.customParams.saveLogfilesFromMachine; + } else { + // Fixed value. + return false; + } + } + + public getTemperature() { + return this.temperature; + } + public getDevicetemperature() { + return this.deviceTemperature; + } + + public fetchRuntimeData(_callback: any = null) { + const options = { + method: 'get', + }; + const urlAdding = '/api/runtime'; + + cordova.plugin.http.sendRequest( + this.connectionURL + urlAdding, + options, + (response) => { + try { + /**{"status":1,"description":"ON","statusPhase":0,"alarms":0,"warnings":2,"tempBoilerCoffe":82.1,"tempBolierServices":100.2,"pumpServicesPress":0.2,"pumpPress":0.0,"counterVol":0,"realtimeFlow":0,"setPressPaddle":0.0}**/ + const parsedJSON = JSON.parse(response.data); + const temp = parsedJSON.tempBoilerCoffe; + const press = parsedJSON.pumpPress*10; + + this.temperature = temp; + this.pressure = press; + if (_callback) { + _callback(); + } + } catch (e) {} + }, + (response) => { + // prints 403 + } + ); + } + + + + + public startShot() { + const promise = new Promise((resolve, reject) => { + const options = { + method: 'get', + }; + + let urlAdding = '/api/action/man'; + + cordova.plugin.http.sendRequest( + this.getPreparation().connectedPreparationDevice.url + urlAdding, + options, + (response) => { + try { + const parsedJSON = JSON.parse(response.data); + resolve(parsedJSON); + } catch (e) { + reject(JSON.stringify(e)); + } + }, + (response) => { + // prints 403 + reject(JSON.stringify(response)); + } + ); + }); + return promise; + } + public stopShot() { + const promise = new Promise((resolve, reject) => { + const options = { + method: 'get', + }; + + let urlAdding = '/api/action/man'; + + cordova.plugin.http.sendRequest( + this.getPreparation().connectedPreparationDevice.url + urlAdding, + options, + (response) => { + try { + const parsedJSON = JSON.parse(response.data); + resolve(parsedJSON); + } catch (e) { + reject(JSON.stringify(e)); + } + }, + (response) => { + // prints 403 + reject(JSON.stringify(response)); + } + ); + }); + return promise; + } +} + +export class SanremoYOUParams implements ISanremoYOUParams { + public stopAtWeight: number = 0; + public residualLagTime: number = 1.35; + constructor() { + this.residualLagTime = 1.35; + } +} diff --git a/src/classes/preparationDevice/xenia/xeniaDevice.ts b/src/classes/preparationDevice/xenia/xeniaDevice.ts index ef5d9578..2b699b24 100644 --- a/src/classes/preparationDevice/xenia/xeniaDevice.ts +++ b/src/classes/preparationDevice/xenia/xeniaDevice.ts @@ -337,6 +337,7 @@ export class XeniaParams implements IXeniaParams { public scriptAtFirstDripId: number = 0; public scriptAtWeightReachedId: number = 0; public scriptAtWeightReachedNumber: number = 0; + public residualLagTime: number = 0; constructor() {} } diff --git a/src/classes/settings/settings.ts b/src/classes/settings/settings.ts index fdb5c42c..6ff1711d 100755 --- a/src/classes/settings/settings.ts +++ b/src/classes/settings/settings.ts @@ -88,6 +88,16 @@ export class Settings implements ISettings { ARCHIVED: IBeanPageSort; FROZEN: IBeanPageSort; }; + public bean_collapsed: { + OPEN: boolean; + ARCHIVED: boolean; + FROZEN: boolean; + }; + public brew_collapsed: { + OPEN: boolean; + ARCHIVED: boolean; + }; + public green_bean_sort: { OPEN: IBeanPageSort; @@ -317,6 +327,15 @@ export class Settings implements ISettings { FROZEN: {} as IBeanPageSort, }; + this.bean_collapsed = { + OPEN: false, + ARCHIVED: false, + FROZEN: false, + }; + this.brew_collapsed = { + OPEN: false, + ARCHIVED: false, + }; this.green_bean_sort = { OPEN: {} as IBeanPageSort, ARCHIVED: {} as IBeanPageSort, @@ -505,14 +524,7 @@ export class Settings implements ISettings { ); } - public resetFilter() { - this.brew_filter = { - OPEN: {} as IBrewPageFilter, - ARCHIVED: {} as IBrewPageFilter, - }; - this.brew_filter.OPEN = this.GET_BREW_FILTER(); - this.brew_filter.ARCHIVED = this.GET_BREW_FILTER(); - + public resetBeanFilter() { this.bean_filter = { OPEN: {} as IBeanPageFilter, ARCHIVED: {} as IBeanPageFilter, @@ -521,7 +533,23 @@ export class Settings implements ISettings { this.bean_filter.OPEN = this.GET_BEAN_FILTER(); this.bean_filter.ARCHIVED = this.GET_BEAN_FILTER(); this.bean_filter.FROZEN = this.GET_BEAN_FILTER(); + } + + public resetBrewFilter() { + this.brew_filter = { + OPEN: {} as IBrewPageFilter, + ARCHIVED: {} as IBrewPageFilter, + }; + this.brew_filter.OPEN = this.GET_BREW_FILTER(); + this.brew_filter.ARCHIVED = this.GET_BREW_FILTER(); + } + + public resetFilter() { + this.resetBrewFilter(); + this.resetBeanFilter(); + } + public resetBeanSort() { this.bean_sort = { OPEN: {} as IBeanPageSort, ARCHIVED: {} as IBeanPageSort, diff --git a/src/components/bean-information/bean-information.component.html b/src/components/bean-information/bean-information.component.html index a4831a2f..8b4a5cd3 100644 --- a/src/components/bean-information/bean-information.component.html +++ b/src/components/bean-information/bean-information.component.html @@ -43,14 +43,15 @@ - +
+
- + @@ -144,7 +145,7 @@ {{"BEANS_AMOUNT_USED" | translate}}
- {{daysOld()}}
diff --git a/src/components/bean-information/bean-information.component.ts b/src/components/bean-information/bean-information.component.ts index ecc2130f..3f3617cd 100644 --- a/src/components/bean-information/bean-information.component.ts +++ b/src/components/bean-information/bean-information.component.ts @@ -51,7 +51,7 @@ export class BeanInformationComponent implements OnInit { @Input() public bean: Bean; @Input() public showActions: boolean = true; @Input() public disabled: boolean = false; - + @Input() public collapsed: boolean = false; @ViewChild('card', { read: ElementRef }) public cardEl: ElementRef; @ViewChild('beanStars', { read: NgxStarsComponent, static: false }) @@ -498,7 +498,7 @@ export class BeanInformationComponent implements OnInit { private async resetSettings() { const settings: Settings = this.uiSettingsStorage.getSettings(); - settings.resetFilter(); + settings.resetBeanFilter(); await this.uiSettingsStorage.saveSettings(settings); } diff --git a/src/components/beans/bean-freeze-information/bean-freeze-information.component.html b/src/components/beans/bean-freeze-information/bean-freeze-information.component.html index 4238b14a..175b0079 100644 --- a/src/components/beans/bean-freeze-information/bean-freeze-information.component.html +++ b/src/components/beans/bean-freeze-information/bean-freeze-information.component.html @@ -1,10 +1,10 @@ - + - + - - - - - - - - -
- -
-
- -
- -
-
- - - - - {{brew.config.unix_timestamp | formatDate:[settings?.date_format]}}{{brew.config.unix_timestamp | formatDate:["HH:mm"]}} - - - - - - - - -
{{bean?.name}} ({{bean?.roaster}})
- + + + + + + + + +
+ +
+
+ +
+ +
+
+ + + + + + + + + {{ brew.config.unix_timestamp | formatDate:[settings?.date_format] }}{{ brew.config.unix_timestamp | formatDate:["HH:mm"] }} + + + + + + + + + +
+ + () + + {{ bean?.name }} ({{ bean?.roaster }}) +
+
+ - - - + + + + {{ this.uiHelper.toFixedIfNecessary(brew.rating, 2) }} + +
+
+
+
+
+ + +
+
+
+
+ + + + {{ "BREW_DATA_PREPARATION_METHOD" | translate }} +
+ {{ preparation?.name }} +
+ - - {{brew?.grind_weight | number : '.0-2'}}gr / {{brew.brew_beverage_quantity | number : '.0-2'}}{{brewQuantityEnum[brew?.brew_beverage_quantity_type]}} ({{brew?.getBrewRatio()}}) - - - +
+ {{ mill?.name }} +
+ + {{ "BREW_DATA_IN_OUT_BR" | translate }} +
+ + {{ brew?.grind_weight | number : '.0-2' }}gr + / {{ brew.brew_quantity | number : '.0-2' }}{{ brewQuantityEnum[brew?.brew_quantity_type] }} ({{ brew?.getBrewRatio() }} + ) + + + {{ brew?.grind_weight | number : '.0-2' }}gr + / {{ brew.brew_beverage_quantity | number : '.0-2' }}{{ brewQuantityEnum[brew?.brew_beverage_quantity_type] }} ({{ brew?.getBrewRatio() }} + ) + +
+
- {{brew?.getFormattedTotalCoffeeBrewTime()}} -
- 0 && uiBrewHelper.fieldVisible(settings.visible_list_view_parameters.mill_speed, preparation?.visible_list_view_parameters.mill_speed, - preparation?.use_custom_parameters))" size="6"> - {{'BREW_DATA_GRIND_SIZE' | translate}}
- + {{ 'BREW_DATA_GRIND_SIZE' | translate }} +
+ {{brew?.grind_size}}{{ brew?.grind_size }}
- {{brew?.tds}}, %{{brew?.getExtractionYield()}} -
- - {{'BREW_DATA_BREW_TEMPERATURE' | translate}}
- {{brew?.brew_temperature}} -
- - {{'BREW_DATA_PRESSURE_PROFILE' | translate}}
- {{brew?.pressure_profile}} -
- - {{"BREW_DATA_BEAN_WEIGHT_IN" | translate}}
- {{brew?.bean_weight_in}} -
- +
+ {{ brew?.bean_weight_in }} +
+ + {{ "BREW_DATA_MILL_TIMER" | translate }} +
+ {{ brew?.mill_timer }} +
+ - {{"BREW_DATA_VESSEL_NAME_WEIGHT" | translate}}
- {{brew?.vessel_name}} / {{brew?.vessel_weight}} -
- +
+ {{ brew?.vessel_name }} / {{ brew?.vessel_weight }} +
+ + {{ "BREW_DATA_TEMPERATURE_TIME" | translate }} +
+ {{ brew?.getFormattedTotalCoffeeTemperatureTime() }} +
+ + {{ "BREW_DATA_COFFEE_BLOOMING_TIME" | translate }} +
+ {{ brew?.getFormattedTotalCoffeeBloomingTime() }} +
+ 0)'> + {{ "BREW_DATA_COFFEE_FIRST_DRIP_TIME" | translate }} +
+ {{ brew?.getFormattedTotalCoffeeFirstDripTime() }} +
+ - {{"BREW_DATA_WATER" | translate}}
- {{brew?.getWater().name}} -
- +
+ {{ brew?.getWater().name }} +
+ - {{"BREW_DATA_COFFEE_TYPE" | translate}}
- {{brew?.coffee_type}} -
- +
+ {{ brew?.coffee_type }} +
+ - {{"BREW_DATA_COFFEE_CONCENTRATION" | translate}}
- {{brew?.coffee_concentration}} -
- +
+ {{ brew?.coffee_concentration }} +
+ + {{ "BREW_INFORMATION_BEAN_AGE" | translate }} +
+ {{ brew?.getCalculatedBeanAge() }} +
+
- {{getCuppedBrewFlavors()}} -
- +
+ {{ brew?.getPreparationToolName(uuid) }} + +
+
+ + {{ 'BREW_DATA_FLAVOR' | translate }} +
+ {{ getCuppedBrewFlavors() }} +
+ - {{"BREW_DATA_NOTES" | translate}}
-
{{brew?.note}}
-
+ {{ "BREW_DATA_NOTES" | translate }} +
+ +
{{ brew?.note }}
+
+
-
-
-
-
-
+
+
+
+
+
- - - - - + + + + + -
-
- {{brew.config.unix_timestamp | formatDate:["DD"]}}.
- - {{brew.config.unix_timestamp | formatDate:["MMMM"]}}
{{brew.config.unix_timestamp | formatDate:["YYYY"]}} +
+
+ {{ brew.config.unix_timestamp | formatDate:["DD"] }}.
+ + {{ brew.config.unix_timestamp | formatDate:["MMMM"] }} +
{{ brew.config.unix_timestamp | formatDate:["YYYY"] }}
-
+
-
-
- - -
- - - - - - - {{bean?.name}} - - - - {{preparation?.name}} - - - - - {{mill?.name}} - - - - - - - - - - - - - -
-
- - +
+
+
+ +
+ + + + + + + + + + + () + + {{ bean?.name }} + + + + + {{ preparation?.name }} + + + + + {{ mill?.name }} + + + + + + + + + + + + + + +
+
+
+
diff --git a/src/components/brew-information/brew-information.component.ts b/src/components/brew-information/brew-information.component.ts index e333a98f..28d1a2b5 100644 --- a/src/components/brew-information/brew-information.component.ts +++ b/src/components/brew-information/brew-information.component.ts @@ -33,7 +33,7 @@ import { TranslateService } from '@ngx-translate/core'; import { BrewTrackingService } from '../../services/brewTracking/brew-tracking.service'; import { UIHealthKit } from '../../services/uiHealthKit'; import * as htmlToImage from 'html-to-image'; -import { Visualizer } from '../../classes/visualizer/visualizer'; + import { UIFileHelper } from '../../services/uiFileHelper'; import { BrewFlow } from '../../classes/brew/brewFlow'; @@ -48,6 +48,7 @@ declare var window; }) export class BrewInformationComponent implements OnInit { @Input() public brew: Brew; + @Input() public collapsed: boolean = false; @Input() public layout: string = 'brew'; @ViewChild('card', { read: ElementRef }) public cardEl: ElementRef; @@ -80,7 +81,6 @@ export class BrewInformationComponent implements OnInit { private readonly uiHealthKit: UIHealthKit, private readonly platform: Platform, private readonly uiFileHelper: UIFileHelper, - private readonly uiBeanStorage: UIBeanStorage, private readonly uiBeanHelper: UIBeanHelper, private readonly visualizerService: VisualizerService ) {} diff --git a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts index 7aa9f234..d1800295 100644 --- a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts +++ b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts @@ -8,19 +8,15 @@ import { NgZone, OnInit, Output, - ViewChild, + ViewChild } from '@angular/core'; import { PREPARATION_STYLE_TYPE } from '../../../enums/preparations/preparationStyleTypes'; import { PreparationDeviceType } from '../../../classes/preparationDevice'; -import { - BluetoothScale, - SCALE_TIMER_COMMAND, - ScaleType, -} from '../../../classes/devices'; +import { BluetoothScale, SCALE_TIMER_COMMAND, ScaleType } from '../../../classes/devices'; import { ModalController, Platform } from '@ionic/angular'; import { CoffeeBluetoothDevicesService, - CoffeeBluetoothServiceEvent, + CoffeeBluetoothServiceEvent } from '../../../services/coffeeBluetoothDevices/coffee-bluetooth-devices.service'; import { TemperatureDevice } from '../../../classes/devices/temperatureBluetoothDevice'; import { PressureDevice } from '../../../classes/devices/pressureBluetoothDevice'; @@ -33,7 +29,7 @@ import { IBrewRealtimeWaterFlow, IBrewTemperatureFlow, IBrewWaterFlow, - IBrewWeightFlow, + IBrewWeightFlow } from '../../../classes/brew/brewFlow'; import { Preparation } from '../../../classes/preparation/preparation'; import { UIPreparationStorage } from '../../../services/uiPreparationStorage'; @@ -62,13 +58,14 @@ import { Graph } from '../../../classes/graph/graph'; import { UIGraphStorage } from '../../../services/uiGraphStorage.service'; import regression from 'regression'; import { TextToSpeechService } from '../../../services/textToSpeech/text-to-speech.service'; +import { SanremoYOUDevice } from '../../../classes/preparationDevice/sanremo/sanremoYOUDevice'; declare var Plotly; @Component({ selector: 'brew-brewing-graph', templateUrl: './brew-brewing-graph.component.html', - styleUrls: ['./brew-brewing-graph.component.scss'], + styleUrls: ['./brew-brewing-graph.component.scss'] }) export class BrewBrewingGraphComponent implements OnInit { @ViewChild('smartScaleWeight', { read: ElementRef }) @@ -133,6 +130,7 @@ export class BrewBrewingGraphComponent implements OnInit { private temperatureThresholdWasHit: boolean = false; private xeniaOverviewInterval: any = undefined; private meticulousInterval: any = undefined; + private sanremoYOUFetchingInterval: any = undefined; public lastChartLayout: any = undefined; public lastChartRenderingInstance: number = 0; @@ -153,6 +151,7 @@ export class BrewBrewingGraphComponent implements OnInit { public textToSpeechWeightInterval: any = undefined; public textToSpeechTimerInterval: any = undefined; + constructor( private readonly platform: Platform, private readonly bleManager: CoffeeBluetoothDevicesService, @@ -172,7 +171,8 @@ export class BrewBrewingGraphComponent implements OnInit { public readonly uiBrewHelper: UIBrewHelper, private readonly uiGraphStorage: UIGraphStorage, private readonly textToSpeech: TextToSpeechService - ) {} + ) { + } public ngOnInit() { this.settings = this.uiSettingsStorage.getSettings(); @@ -205,7 +205,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.pressureDeviceConnected() && this.data.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO + PREPARATION_STYLE_TYPE.ESPRESSO ) { await this.__connectPressureDevice(true); isSomethingConnected = true; @@ -217,7 +217,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + PreparationDeviceType.METICULOUS ) { isSomethingConnected = true; } @@ -360,7 +360,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.temperatureDeviceConnected() === true || (this.pressureDeviceConnected() === true && this.data.getPreparation()?.style_type === - PREPARATION_STYLE_TYPE.ESPRESSO) || + PREPARATION_STYLE_TYPE.ESPRESSO) || this.brewComponent?.brewBrewingPreparationDeviceEl ?.preparationDevice !== undefined ) { @@ -393,7 +393,8 @@ export class BrewBrewingGraphComponent implements OnInit { this.bleManager.getPressureDevice(); try { pressureDevice.updateZero(); - } catch (ex) {} + } catch (ex) { + } } } @@ -401,7 +402,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + PreparationDeviceType.METICULOUS ) { return 3; } @@ -493,7 +494,8 @@ export class BrewBrewingGraphComponent implements OnInit { setTimeout(() => { try { Plotly.purge(this.profileDiv.nativeElement); - } catch (ex) {} + } catch (ex) { + } this.graphSettings = this.uiHelper.cloneData(this.settings.graph.FILTER); if ( this.data.getPreparation().style_type === @@ -526,11 +528,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#ebe6dd', - width: 2, + width: 2 }, visible: this.graphSettings.weight, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; this.flowPerSecondTraceReference = { x: [], @@ -542,11 +544,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#cbd5d9', - width: 2, + width: 2 }, visible: this.graphSettings.calc_flow, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; this.realtimeFlowTraceReference = { @@ -559,11 +561,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#9cb5be', - width: 2, + width: 2 }, visible: this.graphSettings.realtime_flow, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; this.pressureTraceReference = { @@ -576,11 +578,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#9be8d3', - width: 2, + width: 2 }, visible: this.graphSettings.pressure, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; this.temperatureTraceReference = { @@ -593,11 +595,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#eaad9f', - width: 2, + width: 2 }, visible: this.graphSettings.temperature, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; const presetFlowProfile = this.reference_profile_raw; @@ -629,7 +631,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.weightTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.weightTraceReference.y.push(data.actual_weight); @@ -638,7 +640,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.flowPerSecondTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.flowPerSecondTraceReference.y.push(data.value); @@ -648,7 +650,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.realtimeFlowTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.realtimeFlowTraceReference.y.push(data.flow_value); @@ -664,7 +666,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.pressureTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.pressureTraceReference.y.push(data.actual_pressure); @@ -679,7 +681,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.temperatureTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.temperatureTraceReference.y.push(data.actual_temperature); @@ -698,11 +700,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#cdc2ac', - width: 2, + width: 2 }, visible: this.graphSettings.weight, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; this.flowPerSecondTrace = { x: [], @@ -714,11 +716,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#7F97A2', - width: 2, + width: 2 }, visible: this.graphSettings.calc_flow, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; this.realtimeFlowTrace = { @@ -731,11 +733,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#09485D', - width: 2, + width: 2 }, visible: this.graphSettings.realtime_flow, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; this.pressureTrace = { @@ -748,11 +750,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#05C793', - width: 2, + width: 2 }, visible: this.graphSettings.pressure, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; this.temperatureTrace = { @@ -765,11 +767,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#CC3311', - width: 2, + width: 2 }, visible: this.graphSettings.temperature, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false, + showlegend: false }; if ( @@ -796,7 +798,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.weightTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.weightTrace.y.push(data.actual_weight); @@ -805,7 +807,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.flowPerSecondTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.flowPerSecondTrace.y.push(data.value); @@ -815,7 +817,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.realtimeFlowTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.realtimeFlowTrace.y.push(data.flow_value); @@ -830,7 +832,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.pressureTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.pressureTrace.y.push(data.actual_pressure); @@ -844,7 +846,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.temperatureTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.temperatureTrace.y.push(data.actual_temperature); @@ -887,7 +889,8 @@ export class BrewBrewingGraphComponent implements OnInit { this.updateChart(); } }, 250); - } catch (ex) {} + } catch (ex) { + } }, timeout); } @@ -908,7 +911,8 @@ export class BrewBrewingGraphComponent implements OnInit { weightEl.textContent = this.data.brew_quantity + ' g'; } } - } catch (ex) {} + } catch (ex) { + } }, 350); } @@ -916,7 +920,8 @@ export class BrewBrewingGraphComponent implements OnInit { let chartWidth: number = 300; try { chartWidth = this.canvaContainer.nativeElement.offsetWidth; - } catch (ex) {} + } catch (ex) { + } const chartHeight: number = 150; const tickFormat = '%M:%S'; @@ -985,7 +990,7 @@ export class BrewBrewingGraphComponent implements OnInit { r: 20, b: 20, t: 20, - pad: 2, + pad: 2 }, showlegend: false, dragmode: false, @@ -999,7 +1004,7 @@ export class BrewBrewingGraphComponent implements OnInit { domain: [0, 1], fixedrange: true, type: 'date', - range: [startRange, endRange], + range: [startRange, endRange] }, yaxis: { title: '', @@ -1009,7 +1014,7 @@ export class BrewBrewingGraphComponent implements OnInit { side: 'left', position: 0.03, rangemode: 'nonnegative', - range: [suggestedMinWeight, suggestedMaxWeight], + range: [suggestedMinWeight, suggestedMaxWeight] }, yaxis2: { title: '', @@ -1022,14 +1027,14 @@ export class BrewBrewingGraphComponent implements OnInit { position: 0.97, fixedrange: true, rangemode: 'nonnegative', - range: [suggestedMinFlow, suggestedMaxFlow], - }, + range: [suggestedMinFlow, suggestedMaxFlow] + } }; const pressureDevice = this.bleManager.getPressureDevice(); if ( (pressureDevice != null && this.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO) || + PREPARATION_STYLE_TYPE.ESPRESSO) || this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() || !this.platform.is('cordova') ) { @@ -1043,7 +1048,7 @@ export class BrewBrewingGraphComponent implements OnInit { showgrid: false, position: 0.91, fixedrange: true, - range: [0, 10], + range: [0, 10] }; } const temperatureDevice = this.bleManager.getTemperatureDevice(); @@ -1063,7 +1068,7 @@ export class BrewBrewingGraphComponent implements OnInit { position: 0.8, fixedrange: true, visible: false, - range: [0, 100], + range: [0, 100] }; } } else { @@ -1075,14 +1080,14 @@ export class BrewBrewingGraphComponent implements OnInit { r: 20, b: 20, t: 20, - pad: 2, + pad: 2 }, showlegend: false, xaxis: { tickformat: tickFormat, visible: true, domain: [0, 1], - type: 'date', + type: 'date' }, yaxis: { title: '', @@ -1090,7 +1095,7 @@ export class BrewBrewingGraphComponent implements OnInit { tickfont: { color: '#cdc2ac' }, side: 'left', position: 0.05, - visible: true, + visible: true }, yaxis2: { title: '', @@ -1101,8 +1106,8 @@ export class BrewBrewingGraphComponent implements OnInit { side: 'right', position: 0.95, showgrid: false, - visible: true, - }, + visible: true + } }; layout['yaxis4'] = { @@ -1115,7 +1120,7 @@ export class BrewBrewingGraphComponent implements OnInit { showgrid: false, position: 0.93, range: [0, 12], - visible: true, + visible: true }; layout['yaxis5'] = { @@ -1129,7 +1134,7 @@ export class BrewBrewingGraphComponent implements OnInit { position: 0.8, fixedrange: true, range: [0, 100], - visible: true, + visible: true }; if (this.weightTrace.x && this.weightTrace.x.length > 0) { @@ -1159,14 +1164,14 @@ export class BrewBrewingGraphComponent implements OnInit { if (this.isDetail === true) { const config = { displayModeBar: false, // this is the line that hides the bar. - responsive: true, + responsive: true }; return config; } else { const config = { responsive: false, scrollZoom: false, - displayModeBar: false, // this is the line that hides the bar. + displayModeBar: false // this is the line that hides the bar. }; return config; } @@ -1250,7 +1255,8 @@ export class BrewBrewingGraphComponent implements OnInit { this.brewComponent.timer.reset(); this.checkChanges(); }, - () => {} + () => { + } ); break; @@ -1332,8 +1338,8 @@ export class BrewBrewingGraphComponent implements OnInit { try { return this.uiHelper.toFixedIfNecessary( this.flow_profile_raw.realtimeFlow[ - this.flow_profile_raw.realtimeFlow.length - 1 - ].flow_value, + this.flow_profile_raw.realtimeFlow.length - 1 + ].flow_value, 2 ); } catch (ex) { @@ -1345,7 +1351,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.ngZone.runOutsideAngular(() => { if (this.brewComponent.maximizeFlowGraphIsShown === true) { this.brewComponent.brewTemperatureGraphSubject.next({ - temperature: _temperature, + temperature: _temperature }); } @@ -1353,7 +1359,8 @@ export class BrewBrewingGraphComponent implements OnInit { const temperatureEl = this.temperatureEl.nativeElement; temperatureEl.textContent = _temperature; - } catch (ex) {} + } catch (ex) { + } }); } @@ -1361,7 +1368,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.ngZone.runOutsideAngular(() => { if (this.brewComponent.maximizeFlowGraphIsShown === true) { this.brewComponent.brewPressureGraphSubject.next({ - pressure: _pressure, + pressure: _pressure }); } @@ -1369,7 +1376,8 @@ export class BrewBrewingGraphComponent implements OnInit { const pressureEl = this.pressureEl.nativeElement; pressureEl.textContent = _pressure; - } catch (ex) {} + } catch (ex) { + } }); } @@ -1398,7 +1406,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.brewComponent.brewFlowGraphSubject.next({ scaleWeight: actualScaleWeight, smoothedWeight: actualSmoothedWeightPerSecond, - avgFlow: avgFlow, + avgFlow: avgFlow }); } @@ -1410,7 +1418,8 @@ export class BrewBrewingGraphComponent implements OnInit { weightEl.textContent = actualScaleWeight + ' g'; flowEl.textContent = actualSmoothedWeightPerSecond + ' g/s'; avgFlowEl.textContent = 'Ø ' + avgFlow + ' g/s'; - } catch (ex) {} + } catch (ex) { + } }); } @@ -1446,7 +1455,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.profileDiv.nativeElement, { x: xData, - y: yData, + y: yData }, tracesData ); @@ -1598,7 +1607,8 @@ export class BrewBrewingGraphComponent implements OnInit { this.lastChartLayout.xaxis.range = [delay, delayedTime]; Plotly.relayout(this.profileDiv.nativeElement, this.lastChartLayout); } - } catch (ex) {} + } catch (ex) { + } }); } @@ -1686,7 +1696,7 @@ export class BrewBrewingGraphComponent implements OnInit { temperatureDevice || (pressureDevice && this.data.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO) + PREPARATION_STYLE_TYPE.ESPRESSO) ) { this.initializeFlowChart(false); } @@ -1750,9 +1760,10 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA && + PreparationDeviceType.XENIA && this.machineStopScriptWasTriggered === false ) { + this.machineStopScriptWasTriggered = true; // If the event is not xenia, we pressed buttons, if the event was triggerd by xenia, timer already stopped. // If we press pause, stop scripts. this.uiLog.log(`Xenia Script - Pause button pressed, stop script`); @@ -1777,7 +1788,27 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS && + PreparationDeviceType.SANREMO_YOU && + _event !== 'sanremo_you' && this.machineStopScriptWasTriggered === false + ) { + this.machineStopScriptWasTriggered = true; + this.uiLog.log(`Sanremo YOU - Pause button pressed, stop shot`); + const prepDeviceCall: SanremoYOUDevice = this.brewComponent + ?.brewBrewingPreparationDeviceEl?.preparationDevice as SanremoYOUDevice; + prepDeviceCall.stopShot().catch((_msg) => { + this.uiToast.showInfoToast( + 'We could not stop - manual triggered: ' + _msg, + false + ); + this.uiLog.log('We could not stop - manual triggered: ' + _msg); + }); + this.stopFetchingDataFromSanremoYOU(); + } + + if ( + this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && + this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === + PreparationDeviceType.METICULOUS && _event !== 'meticulous' ) { this.stopFetchingDataFromMeticulous(); @@ -1826,6 +1857,35 @@ export class BrewBrewingGraphComponent implements OnInit { } } + public startFetchingDataFromSanremoYOU() { + const prepDeviceCall: SanremoYOUDevice = this.brewComponent + .brewBrewingPreparationDeviceEl.preparationDevice as SanremoYOUDevice; + + this.stopFetchingDataFromSanremoYOU(); + const setSanremoData = () => { + const temp = prepDeviceCall.getTemperature(); + const press = prepDeviceCall.getPressure(); + this.__setPressureFlow({ actual: press, old: press }); + this.__setTemperatureFlow({ actual: temp, old: temp }); + }; + prepDeviceCall.fetchRuntimeData(() => { + // before we start the interval, we fetch the data once to overwrite, and set them. + setSanremoData(); + }); + + this.sanremoYOUFetchingInterval = setInterval(async () => { + try { + // We don't use the callback function to make sure we don't have to many performance issues + prepDeviceCall.fetchRuntimeData(() => { + //before we start the interval, we fetch the data once to overwrite, and set them. + setSanremoData(); + }); + } catch (ex) { + } + }, 100); + + } + public startFetchingDataFromMeticulous() { const prepDeviceCall: MeticulousDevice = this.brewComponent .brewBrewingPreparationDeviceEl.preparationDevice as MeticulousDevice; @@ -1881,18 +1941,18 @@ export class BrewBrewingGraphComponent implements OnInit { if (hasShotStarted) { this.__setPressureFlow({ actual: shotData.pressure, - old: shotData.pressure, + old: shotData.pressure }); this.__setTemperatureFlow({ actual: shotData.temperature, - old: shotData.temperature, + old: shotData.temperature }); this.__setFlowProfile({ actual: shotData.weight, old: shotData.oldWeight, smoothed: shotData.smoothedWeight, - oldSmoothed: shotData.oldSmoothedWeight, + oldSmoothed: shotData.oldSmoothedWeight }); //this.__setMachineWeightFlow({ actual: shotData.weight, old: shotData.weight,smoothed:100,oldSmoothed:100 }); @@ -1939,7 +1999,8 @@ export class BrewBrewingGraphComponent implements OnInit { 2 ); } - } catch (ex) {} + } catch (ex) { + } }); }, 100); @@ -1950,7 +2011,8 @@ export class BrewBrewingGraphComponent implements OnInit { //before we start the interval, we fetch the data once to overwrite, and set them. setTempAndPressure(); }); - } catch (ex) {} + } catch (ex) { + } }, 500); } @@ -1961,6 +2023,13 @@ export class BrewBrewingGraphComponent implements OnInit { } } + public stopFetchingDataFromSanremoYOU() { + if (this.sanremoYOUFetchingInterval !== undefined) { + clearInterval(this.sanremoYOUFetchingInterval); + this.sanremoYOUFetchingInterval = undefined; + } + } + public stopFetchingDataFromMeticulous() { if (this.meticulousInterval !== undefined) { clearInterval(this.meticulousInterval); @@ -2081,7 +2150,7 @@ export class BrewBrewingGraphComponent implements OnInit { actual: weight, old: 1, smoothed: 1, - oldSmoothed: 1, + oldSmoothed: 1 }); this.setActualSmartInformation(); }, 100); @@ -2101,7 +2170,7 @@ export class BrewBrewingGraphComponent implements OnInit { } else { if ( this.data.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO && + PREPARATION_STYLE_TYPE.ESPRESSO && pressureDevice ) { this.brewComponent.maximizeFlowGraph(); @@ -2163,7 +2232,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA + PreparationDeviceType.XENIA ) { if (this.data.preparationDeviceBrew.params.scriptStartId > 0) { this.uiLog.log(`Xenia Script - Script start - Trigger script`); @@ -2184,7 +2253,7 @@ export class BrewBrewingGraphComponent implements OnInit { (_jsonResp: any) => { this.uiLog.log( 'Check of xenia answer if script started MA_STATUS: ' + - _jsonResp.MA_Status + _jsonResp.MA_Status ); if (_jsonResp.MA_STATUS === 3) { //Great we started. @@ -2223,38 +2292,58 @@ export class BrewBrewingGraphComponent implements OnInit { } else if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + PreparationDeviceType.METICULOUS ) { + const prepDeviceCall: MeticulousDevice = this.brewComponent + .brewBrewingPreparationDeviceEl.preparationDevice as MeticulousDevice; + + if (this.data.preparationDeviceBrew.params.chosenProfileId !== '') { + this.uiLog.log( + `A Meticulous profile was choosen, execute it - ${this.data.preparationDeviceBrew.params.chosenProfileId}` + ); + await prepDeviceCall.loadProfileByID( + this.data.preparationDeviceBrew.params.chosenProfileId + ); + await prepDeviceCall.startExecute(); + } else { + this.uiLog.log( + 'No Meticulous profile was selected, just listen for the start' + ); + } + if ( - this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + this.settings.bluetooth_scale_maximize_on_start_timer === true && + this.brewComponent.maximizeFlowGraphIsShown === false ) { - const prepDeviceCall: MeticulousDevice = this.brewComponent - .brewBrewingPreparationDeviceEl.preparationDevice as MeticulousDevice; + this.brewComponent.maximizeFlowGraph(); + } - if (this.data.preparationDeviceBrew.params.chosenProfileId !== '') { - this.uiLog.log( - `A Meticulous profile was choosen, execute it - ${this.data.preparationDeviceBrew.params.chosenProfileId}` - ); - await prepDeviceCall.loadProfileByID( - this.data.preparationDeviceBrew.params.chosenProfileId - ); - await prepDeviceCall.startExecute(); - } else { - this.uiLog.log( - 'No Meticulous profile was selected, just listen for the start' - ); - } + this.startFetchingDataFromMeticulous(); - if ( - this.settings.bluetooth_scale_maximize_on_start_timer === true && - this.brewComponent.maximizeFlowGraphIsShown === false - ) { - this.brewComponent.maximizeFlowGraph(); - } + } else if ( + this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && + this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === + PreparationDeviceType.SANREMO_YOU + ) { + const prepDeviceCall: SanremoYOUDevice = this.brewComponent + .brewBrewingPreparationDeviceEl.preparationDevice as SanremoYOUDevice; + prepDeviceCall.startShot() .catch((_msg) => { + this.uiLog.log('We could not start shot on sanremo: ' + _msg); + this.uiToast.showInfoToast( + 'We could not start shot on sanremo: ' + _msg, + false + ); + }); - this.startFetchingDataFromMeticulous(); + if ( + this.settings.bluetooth_scale_maximize_on_start_timer === true && + this.brewComponent.maximizeFlowGraphIsShown === false + ) { + this.brewComponent.maximizeFlowGraph(); } + + this.startFetchingDataFromSanremoYOU(); + } } @@ -2450,8 +2539,8 @@ export class BrewBrewingGraphComponent implements OnInit { this.ngZone.runOutsideAngular(() => { this.textToSpeech.speak( this.translate.instant('TEXT_TO_SPEECH.TIME') + - ' ' + - this.data.brew_time + ' ' + + this.data.brew_time ); }); }, 5000); @@ -2496,7 +2585,8 @@ export class BrewBrewingGraphComponent implements OnInit { if (scale) { scale.tare(); } - } catch (ex) {} + } catch (ex) { + } } this.brewComponent.timerStartPressed('AUTO_START_PRESSURE'); @@ -2548,7 +2638,8 @@ export class BrewBrewingGraphComponent implements OnInit { }, this.settings.bluetooth_command_delay); }); } - } catch (ex) {} + } catch (ex) { + } } this.brewComponent.timerStartPressed('AUTO_START_TEMPERATURE'); @@ -2656,8 +2747,9 @@ export class BrewBrewingGraphComponent implements OnInit { * We try to match also turbo-shots which are like 7-8 grams. * Scales with just 3 values per second would be like 7 / 3 values per second = 2.33g increase each tick. * So we won't get jump from like 1 to 10 gram, then to like 40 grams + * Update 26.08.24 - We change from 5 to 6, because we had one shot where the value jumped from 0 to 5,5 and we didn't track anymore */ - const plausibleEspressoWeightIncreaseBound: number = 5; + const plausibleEspressoWeightIncreaseBound: number = 6; risingFactorOK = entryBeforeVal + plausibleEspressoWeightIncreaseBound >= weight; @@ -2687,10 +2779,200 @@ export class BrewBrewingGraphComponent implements OnInit { old: oldWeight, smoothed: smoothedWeight, oldSmoothed: oldSmoothedWeight, - notMutatedWeight: notMutatedWeight, + notMutatedWeight: notMutatedWeight }; } + + private calculateBrewByWeight(_currentWeightValue: number, _residualLagTime: number, _targetWeight: number, _brewByWeightActive: boolean, _scale: BluetoothScale) { + let weight: number = this.uiHelper.toFixedIfNecessary( + _currentWeightValue, + 1 + ); + if (this.ignoreScaleWeight === true) { + if (this.flowProfileTempAll.length > 0) { + const oldFlowProfileTemp = + this.flowProfileTempAll[this.flowProfileTempAll.length - 1]; + weight = this.uiHelper.toFixedIfNecessary( + oldFlowProfileTemp.weight, + 1 + ); + } + } + + if ( + this.flow_profile_raw.realtimeFlow && + this.flow_profile_raw.realtimeFlow.length > 0 + ) { + + const targetWeight = _targetWeight; + + const brewByWeightActive: boolean = _brewByWeightActive; + + + let n = 3; + if (this.flowNCalculation > 0) { + n = this.flowNCalculation; + } else { + n = this.flowProfileTempAll.length; + } + const lag_time = this.uiHelper.toFixedIfNecessary(1 / n, 2); + + + let average_flow_rate = 0; + let lastFlowValue = 0; + + const linearArray = []; + + const weightFlowCalc: Array = + this.flow_profile_raw.weight.slice(-(n - 1)); + + for (let i = 0; i < weightFlowCalc.length; i++) { + if (weightFlowCalc[i] && weightFlowCalc[i].actual_weight) { + const linearArrayEntry = [i, weightFlowCalc[i].actual_weight]; + linearArray.push(linearArrayEntry); + } + } + linearArray.push([n - 1, weight]); + + const linearRegressionCalc = regression.linear(linearArray); + average_flow_rate = linearRegressionCalc.equation[0] * n; + + const scaleType = _scale.getScaleType(); + + this.pushBrewByWeight( + targetWeight, + lag_time, + this.flowTime + '.' + this.flowSecondTick, + lastFlowValue, + weight, + lag_time + _residualLagTime, + weight + average_flow_rate * (lag_time + _residualLagTime) >= + targetWeight, + average_flow_rate * (lag_time + _residualLagTime), + _residualLagTime, + average_flow_rate, + scaleType + ); + let thresholdHit: boolean = false; + if (brewByWeightActive) { + thresholdHit = + weight + + average_flow_rate * (lag_time + _residualLagTime) >= + targetWeight; + } else { + thresholdHit = weight >= targetWeight; + } + return thresholdHit; + } + return false; + } + + private triggerStopShotOnXenia(_actualScaleWeight) { + const prepDeviceCall: XeniaDevice = this.brewComponent + .brewBrewingPreparationDeviceEl + .preparationDevice as XeniaDevice; + if ( + this.data.preparationDeviceBrew.params + .scriptAtWeightReachedId > 0 + ) { + this.uiLog.log( + `Xenia Script - Weight Reached: ${_actualScaleWeight} - Trigger custom script` + ); + prepDeviceCall + .startScript( + this.data.preparationDeviceBrew.params + .scriptAtWeightReachedId + ) + .catch((_msg) => { + this.uiToast.showInfoToast( + 'We could not start script at weight: ' + _msg, + false + ); + this.uiLog.log( + 'We could not start script at weight: ' + _msg + ); + }); + this.writeExecutionTimeToNotes( + 'Weight reached script', + this.data.preparationDeviceBrew.params + .scriptAtWeightReachedId, + this.getScriptName( + this.data.preparationDeviceBrew.params + .scriptAtWeightReachedId + ) + ); + } else { + this.uiLog.log( + `Xenia Script - Weight Reached - Trigger stop script` + ); + prepDeviceCall.stopScript().catch((_msg) => { + this.uiToast.showInfoToast( + 'We could not stop script at weight: ' + _msg, + false + ); + this.uiLog.log( + 'We could not stop script at weight: ' + _msg + ); + }); + this.writeExecutionTimeToNotes( + 'Stop script (Weight reached)', + 0, + this.translate.instant( + 'PREPARATION_DEVICE.TYPE_XENIA.SCRIPT_LIST_GENERAL_STOP' + ) + ); + } + + // This will be just called once, we stopped the shot and now we check if we directly shall stop or not + if ( + this.settings + .bluetooth_scale_espresso_stop_on_no_weight_change === + false + ) { + this.stopFetchingAndSettingDataFromXenia(); + this.brewComponent.timer.pauseTimer('xenia'); + } else { + // We weight for the normal "setFlow" to stop the detection of the graph, there then aswell is the stop fetch of the xenia triggered. + } + } + + private triggerStopShotOnSanremoYOU(_actualScaleWeight) { + const prepDeviceCall: SanremoYOUDevice = this.brewComponent + .brewBrewingPreparationDeviceEl + .preparationDevice as SanremoYOUDevice; + + this.uiLog.log( + `Sanremo YOU Stop: ${_actualScaleWeight}` + ); + prepDeviceCall + .stopShot( + + ) + .catch((_msg) => { + this.uiToast.showInfoToast( + 'We could not stop at weight: ' + _msg, + false + ); + this.uiLog.log( + 'We could not start script at weight: ' + _msg + ); + }); + + // This will be just called once, we stopped the shot and now we check if we directly shall stop or not + if ( + this.settings + .bluetooth_scale_espresso_stop_on_no_weight_change === + false + ) { + this.stopFetchingDataFromSanremoYOU(); + this.brewComponent.timer.pauseTimer('sanremo_you'); + } else { + // We weight for the normal "setFlow" to stop the detection of the graph, there then aswell is the stop fetch of the xenia triggered. + } + } + + public attachToScaleWeightChange() { const scale: BluetoothScale = this.bleManager.getScale(); const preparationStyleType = this.data.getPreparation().style_type; @@ -2703,6 +2985,39 @@ export class BrewBrewingGraphComponent implements OnInit { } this.machineStopScriptWasTriggered = false; + + const prepDeviceConnected = this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected(); + let residual_lag_time = 1.35; + let targetWeight = 0; + let brewByWeightActive: boolean = false; + let preparationDeviceType: PreparationDeviceType; + + if (prepDeviceConnected) { + preparationDeviceType = this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType(); + switch (preparationDeviceType) { + case PreparationDeviceType.XENIA: + + const prepXeniaDeviceCall: XeniaDevice = this.brewComponent + .brewBrewingPreparationDeviceEl + .preparationDevice as XeniaDevice; + residual_lag_time = prepXeniaDeviceCall.getResidualLagTime(); + targetWeight = this.data.preparationDeviceBrew.params + .scriptAtWeightReachedNumber; + brewByWeightActive = this.data.preparationDeviceBrew?.params?.brew_by_weight_active; + break; + case PreparationDeviceType.SANREMO_YOU: + const prepSanremoDeviceCall: SanremoYOUDevice = this.brewComponent + .brewBrewingPreparationDeviceEl + .preparationDevice as SanremoYOUDevice; + residual_lag_time = prepSanremoDeviceCall.getResidualLagTime(); + targetWeight = this.data.preparationDeviceBrew.params.stopAtWeight; + brewByWeightActive = true; + break; + + } + } + + this.scaleFlowSubscription = scale.flowChange.subscribe((_valChange) => { let _val; if (this.ignoreScaleWeight === false) { @@ -2715,193 +3030,31 @@ export class BrewBrewingGraphComponent implements OnInit { _val = _valChange; } - if ( - this.brewComponent.timer.isTimerRunning() && - this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected() && - this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === - PreparationDeviceType.XENIA && - this.data.preparationDeviceBrew.params.scriptAtWeightReachedNumber > 0 - ) { - if (this.isFirstXeniaScriptSet()) { - let weight: number = this.uiHelper.toFixedIfNecessary( - _val.actual, - 1 - ); - if (this.ignoreScaleWeight === true) { - if (this.flowProfileTempAll.length > 0) { - const oldFlowProfileTemp = - this.flowProfileTempAll[this.flowProfileTempAll.length - 1]; - weight = this.uiHelper.toFixedIfNecessary( - oldFlowProfileTemp.weight, - 1 - ); - } - } - - if ( - this.flow_profile_raw.realtimeFlow && - this.flow_profile_raw.realtimeFlow.length > 0 - ) { - const prepDeviceCall: XeniaDevice = this.brewComponent - .brewBrewingPreparationDeviceEl - .preparationDevice as XeniaDevice; - - const targetWeight = - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedNumber; + if (this.brewComponent.timer.isTimerRunning() && prepDeviceConnected) { - const brewByWeightActive: boolean = - this.data.preparationDeviceBrew?.params?.brew_by_weight_active; + if (preparationDeviceType === PreparationDeviceType.XENIA && this.data.preparationDeviceBrew.params.scriptAtWeightReachedNumber > 0 && this.isFirstXeniaScriptSet()) { + /**We call this function before the if, because we still log the data**/ + const thresholdHit = this.calculateBrewByWeight(_val.actual, residual_lag_time, targetWeight, brewByWeightActive, scale); - let n = 3; - if (this.flowNCalculation > 0) { - n = this.flowNCalculation; - } else { - n = this.flowProfileTempAll.length; + if (this.machineStopScriptWasTriggered === false) { + if (thresholdHit) { + this.machineStopScriptWasTriggered = true; + this.triggerStopShotOnXenia(_val.actual); } - const lag_time = this.uiHelper.toFixedIfNecessary(1 / n, 2); - const residual_lag_time = prepDeviceCall.getResidualLagTime(); - - let average_flow_rate = 0; - let lastFlowValue = 0; - - const linearArray = []; - - const weightFlowCalc: Array = - this.flow_profile_raw.weight.slice(-(n - 1)); - - for (let i = 0; i < weightFlowCalc.length; i++) { - if (weightFlowCalc[i] && weightFlowCalc[i].actual_weight) { - const linearArrayEntry = [i, weightFlowCalc[i].actual_weight]; - linearArray.push(linearArrayEntry); - } - } - linearArray.push([n - 1, weight]); - - const linearRegressionCalc = regression.linear(linearArray); - average_flow_rate = linearRegressionCalc.equation[0] * n; - - /** Old calculcation - try { - lastFlowValue = - this.flow_profile_raw.realtimeFlow[ - this.flow_profile_raw.realtimeFlow.length - 1 - ].flow_value; - - const avgFlowValCalc: Array = - this.flow_profile_raw.realtimeFlow.slice(-n); - - for (let i = 0; i < avgFlowValCalc.length; i++) { - if (avgFlowValCalc[i] && avgFlowValCalc[i].flow_value) { - average_flow_rate = - average_flow_rate + avgFlowValCalc[i].flow_value; - } - } - if (average_flow_rate > 0) { - average_flow_rate = this.uiHelper.toFixedIfNecessary( - average_flow_rate / n, - 2 - ); - } - } catch (ex) {}**/ - - const scaleType = scale.getScaleType(); - - this.pushBrewByWeight( - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedNumber, - lag_time, - this.flowTime + '.' + this.flowSecondTick, - lastFlowValue, - weight, - lag_time + residual_lag_time, - weight + average_flow_rate * (lag_time + residual_lag_time) >= - targetWeight, - average_flow_rate * (lag_time + residual_lag_time), - residual_lag_time, - average_flow_rate, - scaleType - ); - - if (this.machineStopScriptWasTriggered === false) { - let thresholdHit: boolean = false; - if (brewByWeightActive) { - thresholdHit = - weight + - average_flow_rate * (lag_time + residual_lag_time) >= - targetWeight; - } else { - thresholdHit = weight >= targetWeight; - } - - if (thresholdHit) { - if ( - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedId > 0 - ) { - this.uiLog.log( - `Xenia Script - Weight Reached: ${weight} - Trigger custom script` - ); - prepDeviceCall - .startScript( - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedId - ) - .catch((_msg) => { - this.uiToast.showInfoToast( - 'We could not start script at weight: ' + _msg, - false - ); - this.uiLog.log( - 'We could not start script at weight: ' + _msg - ); - }); - this.writeExecutionTimeToNotes( - 'Weight reached script', - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedId, - this.getScriptName( - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedId - ) - ); - } else { - this.uiLog.log( - `Xenia Script - Weight Reached - Trigger stop script` - ); - prepDeviceCall.stopScript().catch((_msg) => { - this.uiToast.showInfoToast( - 'We could not stop script at weight: ' + _msg, - false - ); - this.uiLog.log( - 'We could not stop script at weight: ' + _msg - ); - }); - this.writeExecutionTimeToNotes( - 'Stop script (Weight reached)', - 0, - this.translate.instant( - 'PREPARATION_DEVICE.TYPE_XENIA.SCRIPT_LIST_GENERAL_STOP' - ) - ); - } - this.machineStopScriptWasTriggered = true; - // This will be just called once, we stopped the shot and now we check if we directly shall stop or not - if ( - this.settings - .bluetooth_scale_espresso_stop_on_no_weight_change === - false - ) { - this.stopFetchingAndSettingDataFromXenia(); - this.brewComponent.timer.pauseTimer('xenia'); - } else { - // We weight for the normal "setFlow" to stop the detection of the graph, there then aswell is the stop fetch of the xenia triggered. - } - } + } + } else if (this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === + PreparationDeviceType.SANREMO_YOU) { + + /**We call this function before the if, because we still log the data**/ + const thresholdHit = this.calculateBrewByWeight(_val.actual, residual_lag_time, targetWeight, brewByWeightActive, scale); + if (this.machineStopScriptWasTriggered === false) { + if (thresholdHit) { + this.machineStopScriptWasTriggered = true; + this.triggerStopShotOnSanremoYOU(_val.actual); } } } + } if (this.ignoreScaleWeight === false) { this.__setFlowProfile(_val); @@ -2914,7 +3067,7 @@ export class BrewBrewingGraphComponent implements OnInit { old: oldFlowProfileTemp.oldWeight, smoothed: oldFlowProfileTemp.smoothedWeight, oldSmoothed: oldFlowProfileTemp.oldSmoothedWeight, - notMutatedWeight: _val.notMutatedWeight, + notMutatedWeight: _val.notMutatedWeight }; this.__setFlowProfile(passVal); } @@ -2940,6 +3093,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.deattachToScaleStartTareListening(); this.stopFetchingAndSettingDataFromXenia(); this.stopFetchingDataFromMeticulous(); + this.stopFetchingDataFromSanremoYOU(); if (this.settings?.text_to_speech_active) { this.textToSpeech.end(); @@ -2960,7 +3114,8 @@ export class BrewBrewingGraphComponent implements OnInit { _flowProfile ); resolve(jsonParsed); - } catch (ex) {} + } catch (ex) { + } } } else { resolve(BeanconquerorFlowTestDataDummySecondDummy); @@ -2975,7 +3130,8 @@ export class BrewBrewingGraphComponent implements OnInit { try { const jsonParsed = await this.uiFileHelper.getJSONFile(flowProfilePath); this.flow_profile_raw = jsonParsed; - } catch (ex) {} + } catch (ex) { + } } private async deleteFlowProfile() { @@ -2985,7 +3141,8 @@ export class BrewBrewingGraphComponent implements OnInit { 'brews/' + this.data.config.uuid + '_flow_profile.json'; await this.uiFileHelper.deleteFile(flowProfilePath); } - } catch (ex) {} + } catch (ex) { + } } private __setMachineWaterFlow(_flow: any) { @@ -3006,7 +3163,7 @@ export class BrewBrewingGraphComponent implements OnInit { old: old, flowTime: this.flowTime, flowTimeSecond: this.flowTime + '.' + this.flowSecondTick, - flowTimestamp: this.uiHelper.getActualTimeWithMilliseconds(), + flowTimestamp: this.uiHelper.getActualTimeWithMilliseconds() }; const realtimeWaterFlow: IBrewRealtimeWaterFlow = @@ -3050,7 +3207,7 @@ export class BrewBrewingGraphComponent implements OnInit { actual: actual, old: old, flowTime: this.flowTime, - flowTimeSecond: this.flowTime + '.' + this.flowSecondTick, + flowTimeSecond: this.flowTime + '.' + this.flowSecondTick }; if (!isSmartScaleConnected) { @@ -3103,7 +3260,7 @@ export class BrewBrewingGraphComponent implements OnInit { actual: actual, old: old, flowTime: this.flowTime, - flowTimeSecond: this.flowTime + '.' + this.flowSecondTick, + flowTimeSecond: this.flowTime + '.' + this.flowSecondTick }; if (!isSmartScaleConnected) { @@ -3171,7 +3328,7 @@ export class BrewBrewingGraphComponent implements OnInit { flowTimeSecond: this.flowTime + '.' + this.flowSecondTick, flowTimestamp: this.uiHelper.getActualTimeWithMilliseconds(), dateUnixTime: undefined, - notMutatedWeight: notMutatedWeight, + notMutatedWeight: notMutatedWeight }; flowObj.dateUnixTime = new Date(flowObj.unixTime); @@ -3272,7 +3429,7 @@ export class BrewBrewingGraphComponent implements OnInit { lastVal - firstVal < 0.5 || (this.flowProfileArr.length > 2 && this.flowProfileArr[this.flowProfileArr.length - 2] - firstVal < - 0.5) + 0.5) ) { // Threshold for filter is bigger, 0.5g // Threshshold, weight changes because of strange thing happening. @@ -3436,7 +3593,8 @@ export class BrewBrewingGraphComponent implements OnInit { timeStampDelta = flowObj.unixTime - this.flowProfileTempAll[this.flowProfileTempAll.length - n].unixTime; - } catch (ex) {} + } catch (ex) { + } } realtimeWaterFlow.timestampdelta = timeStampDelta; @@ -3448,7 +3606,8 @@ export class BrewBrewingGraphComponent implements OnInit { this.flowProfileTempAll[this.flowProfileTempAll.length - n] .smoothedWeight) * (1000 / timeStampDelta); - } catch (ex) {} + } catch (ex) { + } if (Number.isNaN(calcFlowValue)) { calcFlowValue = 0; } @@ -3462,7 +3621,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.data.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO && + PREPARATION_STYLE_TYPE.ESPRESSO && flowObj.weight >= this.settings.bluetooth_scale_first_drip_threshold ) { // If the drip timer is showing, we can set the first drip and not doing a reference to the normal weight. @@ -3510,17 +3669,24 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected() && this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === - PreparationDeviceType.XENIA + PreparationDeviceType.XENIA ) { this.stopFetchingAndSettingDataFromXenia(); } + if ( + this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected() && + this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === + PreparationDeviceType.SANREMO_YOU + ) { + this.stopFetchingDataFromSanremoYOU(); + } let isMeticulous: boolean = false; if ( this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected() && this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + PreparationDeviceType.METICULOUS ) { isMeticulous = true; } @@ -3580,7 +3746,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.settings.bluetooth_scale_espresso_stop_on_no_weight_change === - false || + false || this.weightTrace.y.length < 50 || this.data.brew_time <= 5 ) { @@ -3701,7 +3867,8 @@ export class BrewBrewingGraphComponent implements OnInit { this.lastChartLayout.width = this.canvaContainer.nativeElement.offsetWidth; Plotly.relayout(this.profileDiv.nativeElement, this.lastChartLayout); - } catch (ex) {} + } catch (ex) { + } }, 50); } } @@ -3767,8 +3934,8 @@ export class BrewBrewingGraphComponent implements OnInit { component: BrewChooseGraphReferenceComponent, id: BrewChooseGraphReferenceComponent.COMPONENT_ID, componentProps: { - brew: this.data, - }, + brew: this.data + } }); // will force rerender :D @@ -3806,7 +3973,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA && + PreparationDeviceType.XENIA && this.data.preparationDeviceBrew.params.scriptAtFirstDripId > 0 ) { if (this.isFirstXeniaScriptSet()) { @@ -3842,7 +4009,7 @@ export class BrewBrewingGraphComponent implements OnInit { !this.smartScaleConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA + PreparationDeviceType.XENIA ) { // If scale is not connected but the device, we can now choose that still the script is executed if existing. if (this.isFirstXeniaScriptSet()) { @@ -3859,12 +4026,12 @@ export class BrewBrewingGraphComponent implements OnInit { .catch((_msg) => { this.uiToast.showInfoToast( 'We could not start script at first drip - manual triggered: ' + - _msg, + _msg, false ); this.uiLog.log( 'We could not start script at first drip - manual triggered: ' + - _msg + _msg ); }); this.writeExecutionTimeToNotes( @@ -3883,7 +4050,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA + PreparationDeviceType.XENIA ) { if (this.data.preparationDeviceBrew.params.scriptStartId > 0) { return true; diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html index e052d021..1c314521 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html @@ -79,6 +79,15 @@ {{"IMPORT_SHOT_FROM_METICULOUS" | translate}}
+ + + {{"PREPARATION_DEVICE.TYPE_SANREMO_YOU.TITLE" | translate }} + + + + + diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts index c1346992..1b87af23 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts @@ -37,9 +37,10 @@ import { IBrewTemperatureFlow, IBrewWeightFlow, } from '../../../classes/brew/brewFlow'; -import { BrewChooseGraphReferenceComponent } from '../../../app/brew/brew-choose-graph-reference/brew-choose-graph-reference.component'; import { BrewModalImportShotMeticulousComponent } from '../../../app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component'; import { ModalController } from '@ionic/angular'; +import { HistoryListingEntry } from '@meticulous-home/espresso-api/dist/types'; +import { SanremoYOUDevice, SanremoYOUParams } from '../../../classes/preparationDevice/sanremo/sanremoYOUDevice'; @Component({ selector: 'brew-brewing-preparation-device', templateUrl: './brew-brewing-preparation-device.component.html', @@ -50,7 +51,7 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { @Input() public isEdit: boolean = false; @Output() public dataChange = new EventEmitter(); @Input() public brewComponent: BrewBrewingComponent; - public preparationDevice: XeniaDevice | MeticulousDevice = undefined; + public preparationDevice: XeniaDevice | MeticulousDevice | SanremoYOUDevice = undefined; public preparation: Preparation = undefined; public settings: Settings = undefined; @@ -69,8 +70,10 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { private readonly uiSettingsStorage: UISettingsStorage, private readonly uiPreparationStorage: UIPreparationStorage, private readonly changeDetectorRef: ChangeDetectorRef, - private readonly modalController: ModalController - ) {} + private readonly modalController: ModalController, + public readonly uiBrewHelper: UIBrewHelper + ) { + } public ngOnInit() { this.settings = this.uiSettingsStorage.getSettings(); @@ -107,6 +110,9 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { } else if (connectedDevice instanceof MeticulousDevice) { await this.instanceMeticulousPreparationDevice(connectedDevice, _brew); } + else if (connectedDevice instanceof SanremoYOUDevice) { + await this.instanceSanremoYOUPreparationDevice(connectedDevice, _brew); + } this.checkChanges(); } else { this.preparationDevice = undefined; @@ -293,6 +299,20 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { ); } + private async instanceSanremoYOUPreparationDevice( + connectedDevice: SanremoYOUDevice, + _brew: Brew = null + ) { + this.data.preparationDeviceBrew.type = PreparationDeviceType.SANREMO_YOU; + this.data.preparationDeviceBrew.params = new SanremoYOUParams(); + await connectedDevice.deviceConnected().then(() => { + this.preparationDevice = connectedDevice as SanremoYOUDevice; + }, () => { + //Not connected + }); + + } + public async importShotFromMeticulous() { const modal = await this.modalController.create({ component: BrewModalImportShotMeticulousComponent, @@ -304,6 +324,82 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { await modal.present(); const rData = await modal.onWillDismiss(); + + if (rData && rData.data && rData.data.choosenHistory) { + const chosenEntry = rData.data.choosenHistory as HistoryListingEntry; + this.generateShotFlowProfileFromMeticulousData(chosenEntry); + } + } + + private generateShotFlowProfileFromMeticulousData(_historyData) { + + const newMoment = moment(new Date()).startOf('day'); + + let firstDripTimeSet: boolean = false; + const newBrewFlow = new BrewFlow(); + + let seconds: number = 0; + let milliseconds: number = 0; + for (const entry of _historyData.data as any) { + const shotEntry: any = entry.shot; + const shotEntryTime = newMoment.clone().add('milliseconds', entry.time); + const timestamp = shotEntryTime.format('HH:mm:ss.SSS'); + + seconds = shotEntryTime.diff(newMoment, 'seconds'); + milliseconds = shotEntryTime.get('milliseconds'); + + const realtimeWaterFlow: IBrewRealtimeWaterFlow = + {} as IBrewRealtimeWaterFlow; + + realtimeWaterFlow.brew_time = ''; + realtimeWaterFlow.timestamp = timestamp; + realtimeWaterFlow.smoothed_weight = 0; + realtimeWaterFlow.flow_value = shotEntry.flow; + realtimeWaterFlow.timestampdelta = 0; + + newBrewFlow.realtimeFlow.push(realtimeWaterFlow); + + const brewFlow: IBrewWeightFlow = {} as IBrewWeightFlow; + brewFlow.timestamp = timestamp; + brewFlow.brew_time = ''; + brewFlow.actual_weight = shotEntry.weight; + brewFlow.old_weight = 0; + brewFlow.actual_smoothed_weight = 0; + brewFlow.old_smoothed_weight = 0; + brewFlow.not_mutated_weight = 0; + newBrewFlow.weight.push(brewFlow); + + if (shotEntry.weight > 0 && firstDripTimeSet === false) { + firstDripTimeSet = true; + + this.brewComponent.brewFirstDripTime?.setTime(seconds, milliseconds); + this.brewComponent.brewFirstDripTime?.changeEvent(); + } + + const pressureFlow: IBrewPressureFlow = {} as IBrewPressureFlow; + pressureFlow.timestamp = timestamp; + pressureFlow.brew_time = ''; + pressureFlow.actual_pressure = shotEntry.pressure; + pressureFlow.old_pressure = 0; + newBrewFlow.pressureFlow.push(pressureFlow); + + const temperatureFlow: IBrewTemperatureFlow = {} as IBrewTemperatureFlow; + temperatureFlow.timestamp = timestamp; + temperatureFlow.brew_time = ''; + temperatureFlow.actual_temperature = shotEntry.temperature; + temperatureFlow.old_temperature = 0; + newBrewFlow.temperatureFlow.push(temperatureFlow); + } + + const lastEntry = newBrewFlow.weight[newBrewFlow.weight.length - 1]; + this.brewComponent.data.brew_beverage_quantity = lastEntry.actual_weight; + + this.brewComponent.timer?.setTime(seconds, milliseconds); + this.brewComponent.timer?.changeEvent(); + + this.brewComponent.brewBrewingGraphEl.flow_profile_raw = newBrewFlow; + this.brewComponent.brewBrewingGraphEl.initializeFlowChart(true); + } public getPreparationDeviceType() { @@ -311,6 +407,8 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { return PreparationDeviceType.XENIA; } else if (this.preparationDevice instanceof MeticulousDevice) { return PreparationDeviceType.METICULOUS; + } else if (this.preparationDevice instanceof SanremoYOUDevice) { + return PreparationDeviceType.SANREMO_YOU; } return PreparationDeviceType.NONE; } diff --git a/src/components/graph-display-card/graph-display-card.component.ts b/src/components/graph-display-card/graph-display-card.component.ts index 64c38920..6651cc52 100644 --- a/src/components/graph-display-card/graph-display-card.component.ts +++ b/src/components/graph-display-card/graph-display-card.component.ts @@ -15,6 +15,8 @@ import { UIHelper } from '../../services/uiHelper'; import { UIFileHelper } from '../../services/uiFileHelper'; import { Platform } from '@ionic/angular'; import { UISettingsStorage } from '../../services/uiSettingsStorage'; +import { HistoryListingEntry } from '@meticulous-home/espresso-api/dist/types'; +import { MeticulousDevice } from '../../classes/preparationDevice/meticulous/meticulousDevice'; declare var Plotly; @Component({ @@ -26,6 +28,8 @@ export class GraphDisplayCardComponent implements OnInit { @Input() public flowProfileData: any; @Input() public flowProfilePath: any; + @Input() public meticulousHistoryData: HistoryListingEntry; + @Input() public chartWidth: number; public flow_profile_raw: BrewFlow = new BrewFlow(); @@ -56,8 +60,10 @@ export class GraphDisplayCardComponent implements OnInit { this.settings = this.uiSettingsStorage.getSettings(); if (this.flowProfilePath) { await this.readFlowProfile(); - } else { + } else if (this.flowProfileData) { this.flow_profile_raw = this.uiHelper.cloneData(this.flowProfileData); + } else if (this.meticulousHistoryData) { + this.flow_profile_raw = MeticulousDevice.returnBrewFlowForShotData(this.meticulousHistoryData.data); } setTimeout(() => { this.initializeFlowChart(); diff --git a/src/components/photo-add/photo-add.component.ts b/src/components/photo-add/photo-add.component.ts index 273ebc95..dcaebba0 100644 --- a/src/components/photo-add/photo-add.component.ts +++ b/src/components/photo-add/photo-add.component.ts @@ -2,10 +2,10 @@ import { Component, ElementRef, EventEmitter, - Input, + Input, OnDestroy, OnInit, Output, - ViewChild, + ViewChild } from '@angular/core'; import { UIImage } from '../../services/uiImage'; import { Brew } from '../../classes/brew/brew'; @@ -24,7 +24,7 @@ import { TranslateService } from '@ngx-translate/core'; templateUrl: './photo-add.component.html', styleUrls: ['./photo-add.component.scss'], }) -export class PhotoAddComponent implements OnInit { +export class PhotoAddComponent implements OnInit,OnDestroy { @Input() public data: Brew | Bean | GreenBean | Mill | Preparation; @Output() public dataChange = new EventEmitter< Brew | Bean | GreenBean | Mill | Preparation @@ -47,7 +47,9 @@ export class PhotoAddComponent implements OnInit { this.updateSlider(); }, 250); } - + public ngOnDestroy() { + + } public addImage(): void { this.uiImage.showOptionChooser().then((_option) => { if (_option === 'CHOOSE') { diff --git a/src/components/preparation-information-card/preparation-information-card.component.ts b/src/components/preparation-information-card/preparation-information-card.component.ts index 578bbdcd..b07e55ba 100644 --- a/src/components/preparation-information-card/preparation-information-card.component.ts +++ b/src/components/preparation-information-card/preparation-information-card.component.ts @@ -217,17 +217,7 @@ export class PreparationInformationCardComponent implements OnInit { } public async connectDevice() { - this.uiAnalytics.trackEvent( - PREPARATION_TRACKING.TITLE, - PREPARATION_TRACKING.ACTIONS.CONNECT_DEVICE - ); - const modal = await this.modalController.create({ - component: PreparationConnectedDeviceComponent, - componentProps: { preparation: this.preparation }, - id: PreparationConnectedDeviceComponent.COMPONENT_ID, - }); - await modal.present(); - await modal.onWillDismiss(); + await this.uiPreparationHelper.connectDevice(this.preparation); } public async longPressEditPreparation(event) { diff --git a/src/enums/beans/beanSortAfter.ts b/src/enums/beans/beanSortAfter.ts index 9c324f15..abc8786c 100755 --- a/src/enums/beans/beanSortAfter.ts +++ b/src/enums/beans/beanSortAfter.ts @@ -5,6 +5,6 @@ export enum BEAN_SORT_AFTER { ROASTING_DATE = 'ROASTING DATE', CREATION_DATE = 'CREATION DATE', PURCHASE_DATE = 'PURCHASE DATE', - RATING ='RATING' - + RATING ='RATING', + BEAN_AGE ='BEAN AGE' } diff --git a/src/enums/preparations/preparationTypes.ts b/src/enums/preparations/preparationTypes.ts index 57f5e041..140e7d28 100755 --- a/src/enums/preparations/preparationTypes.ts +++ b/src/enums/preparations/preparationTypes.ts @@ -1,5 +1,8 @@ export enum PREPARATION_TYPES { CUSTOM_PREPARATION = 'CUSTOM_PREPARATION', + METICULOUS = 'METICULOUS', + SANREMO_YOU = 'SANREMO_YOU', + XENIA = 'XENIA', AEROPRESS = 'AEROPRESS', V60 = 'V60', CHEMEX = 'CHEMEX', @@ -40,5 +43,4 @@ export enum PREPARATION_TYPES { ROK = 'ROK', TORNADO_DUO = 'TORNADO_DUO', TRICOLATE = 'TRICOLATE', - METICULOUS = 'METICULOUS', } diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 2a39fae0..63744692 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,4 +1,7 @@ export const environment = { production: true, - API_URL: 'https://backend.beanconqueror.com/' + API_URL: 'https://backend.beanconqueror.com/', + FEATURES_ACTIVE: { + SANREMO_YOU: false + } }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index faa76bbe..af970cf9 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -5,6 +5,9 @@ export const environment = { production: false, API_URL: 'https://backend.beanconqueror.com/', + FEATURES_ACTIVE: { + SANREMO_YOU: false + } }; /* diff --git a/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts b/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts new file mode 100644 index 00000000..b5ce33ea --- /dev/null +++ b/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts @@ -0,0 +1,5 @@ +export interface ISanremoYOUParams { + stopAtWeight: number; + residualLagTime: number; + +} diff --git a/src/interfaces/settings/iSettings.ts b/src/interfaces/settings/iSettings.ts index 60396ee0..2aa0afac 100755 --- a/src/interfaces/settings/iSettings.ts +++ b/src/interfaces/settings/iSettings.ts @@ -84,6 +84,16 @@ export interface ISettings { ARCHIVED: IBeanPageSort; }; + bean_collapsed: { + OPEN: boolean; + ARCHIVED: boolean; + FROZEN: boolean; + }; + brew_collapsed: { + OPEN: boolean; + ARCHIVED: boolean; + }; + green_bean_sort: { OPEN: IBeanPageSort; ARCHIVED: IBeanPageSort; diff --git a/src/popover/data-corruption-found/data-corruption-found.component.html b/src/popover/data-corruption-found/data-corruption-found.component.html new file mode 100644 index 00000000..8f17dd60 --- /dev/null +++ b/src/popover/data-corruption-found/data-corruption-found.component.html @@ -0,0 +1,69 @@ + + Data corruption found + + + + + + It somehow looks that your current data are corrupted, we've checked the backup file, in the following list you'll see how much data you've stored actually and how many are stored in your backup.
+ You can then choose to restore this backup or not.
+ If you don't feel save right now please make a screenshot of this screen, contact info@beanconqueror.com and close this app completely - any issues will be prevent with this +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Key + Actual Storage + + Backup +
Beans{{actualUIStorageDataObj?.BEANS}}{{backupDataObj?.BEANS?.length}}
Brews{{actualUIStorageDataObj?.BREWS}}{{backupDataObj?.BREWS?.length}}
Preparation{{actualUIStorageDataObj?.PREPARATION}}{{backupDataObj?.PREPARATION?.length}}
Grinder{{actualUIStorageDataObj?.MILL}}{{backupDataObj?.MILL?.length}}
+
+
+
+ + + + + Dont import backup + + + Import backup + + + + + diff --git a/src/popover/data-corruption-found/data-corruption-found.component.scss b/src/popover/data-corruption-found/data-corruption-found.component.scss new file mode 100644 index 00000000..25eeb2a5 --- /dev/null +++ b/src/popover/data-corruption-found/data-corruption-found.component.scss @@ -0,0 +1,6 @@ +:host { + table { + width:100%; + text-align:left; + } +} diff --git a/src/popover/data-corruption-found/data-corruption-found.component.spec.ts b/src/popover/data-corruption-found/data-corruption-found.component.spec.ts new file mode 100644 index 00000000..8ffd97dd --- /dev/null +++ b/src/popover/data-corruption-found/data-corruption-found.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { IonicModule } from '@ionic/angular'; + +import { DataCorruptionFoundComponent } from './data-corruption-found.component'; + +describe('DataCorruptionFoundComponent', () => { + let component: DataCorruptionFoundComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ DataCorruptionFoundComponent ], + imports: [IonicModule.forRoot()] + }).compileComponents(); + + fixture = TestBed.createComponent(DataCorruptionFoundComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/popover/data-corruption-found/data-corruption-found.component.ts b/src/popover/data-corruption-found/data-corruption-found.component.ts new file mode 100644 index 00000000..4c859d78 --- /dev/null +++ b/src/popover/data-corruption-found/data-corruption-found.component.ts @@ -0,0 +1,68 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ModalController, Platform } from '@ionic/angular'; + + +@Component({ + selector: 'app-data-corruption-found', + templateUrl: './data-corruption-found.component.html', + styleUrls: ['./data-corruption-found.component.scss'], +}) +export class DataCorruptionFoundComponent implements OnInit { + public static POPOVER_ID: string = 'data-corruption-found-popover'; + + @Input() public actualUIStorageDataObj: any = undefined; + @Input() public backupDataObj: any = undefined; + + private disableHardwareBack; + + constructor( + private readonly modalController: ModalController, + private readonly platform: Platform + ) { + + } + + public ngOnInit() { + try { + + this.disableHardwareBack = this.platform.backButton.subscribeWithPriority( + 9999, + (processNextHandler) => { + // Don't do anything. + } + ); + + } catch (ex) {} + } + + public async dismiss() { + try { + this.disableHardwareBack.unsubscribe(); + } catch (ex) {} + + this.modalController.dismiss( + { + dismissed: true, + }, + undefined, + DataCorruptionFoundComponent.POPOVER_ID + ); + } + + + public async import() { + try { + this.disableHardwareBack.unsubscribe(); + } catch (ex) {} + + this.modalController.dismiss( + { + dismissed: true, + import: true, + }, + undefined, + DataCorruptionFoundComponent.POPOVER_ID + ); + } + +} diff --git a/src/services/coffeeBluetoothDevices/coffee-bluetooth-devices.service.ts b/src/services/coffeeBluetoothDevices/coffee-bluetooth-devices.service.ts index 39f10438..be3849ef 100644 --- a/src/services/coffeeBluetoothDevices/coffee-bluetooth-devices.service.ts +++ b/src/services/coffeeBluetoothDevices/coffee-bluetooth-devices.service.ts @@ -41,6 +41,7 @@ import { BookooPressure } from 'src/classes/devices/bookooPressure'; import { BasicGrillThermometer } from 'src/classes/devices/basicGrillThermometer'; import { MeaterThermometer } from 'src/classes/devices/meaterThermometer'; import { CombustionThermometer } from '../../classes/devices/combustionThermometer'; +import { ArgosThermometer } from '../../classes/devices/argosThermometer'; declare var device: any; declare var ble: any; @@ -546,7 +547,8 @@ export class CoffeeBluetoothDevicesService { ETITemperature.test(scanDevice) || BasicGrillThermometer.test(scanDevice) || MeaterThermometer.test(scanDevice) || - CombustionThermometer.test(scanDevice) + CombustionThermometer.test(scanDevice) || + ArgosThermometer.test(scanDevice) ) { // We found all needed devices. promiseResolved = true; @@ -1047,6 +1049,17 @@ export class CoffeeBluetoothDevicesService { type: TemperatureType.COMBUSTION, }); } + else if (ArgosThermometer.test(deviceTemperature)) { + this.logger.log( + 'BleManager - We found a Argos Thermometer device ' + + JSON.stringify(deviceTemperature) + ); + supportedDevices.push({ + id: deviceTemperature.id, + type: TemperatureType.ARGOS, + }); + } + } resolve(supportedDevices); }); @@ -1092,6 +1105,16 @@ export class CoffeeBluetoothDevicesService { }); return; } + else if (ArgosThermometer.test(deviceTemperature)) { + this.logger.log( + 'BleManager - We found a Argos Thermometer device ' + ); + resolve({ + id: deviceTemperature.id, + type: TemperatureType.ARGOS, + }); + return; + } } resolve(undefined); } diff --git a/src/services/uiBeanHelper.ts b/src/services/uiBeanHelper.ts index 6c3980d5..be5600be 100644 --- a/src/services/uiBeanHelper.ts +++ b/src/services/uiBeanHelper.ts @@ -29,6 +29,8 @@ import { BEAN_ROASTING_TYPE_ENUM } from '../enums/beans/beanRoastingType'; import { AssociatedBrewsComponent } from '../app/brew/associated-brews/associated-brews.component'; import { BrewCuppingComponent } from '../app/brew/brew-cupping/brew-cupping.component'; import { BeanPopoverFreezeComponent } from '../app/beans/bean-popover-freeze/bean-popover-freeze.component'; +import { BeanPopoverFrozenListComponent } from '../app/beans/bean-popover-frozen-list/bean-popover-frozen-list.component'; +import { BeanPopoverListComponent } from '../app/beans/bean-popover-list/bean-popover-list.component'; /** * Handles every helping functionalities @@ -319,6 +321,16 @@ export class UIBeanHelper { await modal.onWillDismiss(); } + public async showBeans(_beanList: Array) { + const modal = await this.modalController.create({ + component: BeanPopoverListComponent, + id: BeanPopoverListComponent.COMPONENT_ID, + componentProps: { beansList: _beanList }, + }); + await modal.present(); + await modal.onWillDismiss(); + } + public async editBean(_bean: Bean) { const modal = await this.modalController.create({ component: BeansEditComponent, diff --git a/src/services/uiExcel.ts b/src/services/uiExcel.ts index d52ebf16..c9cd4e8a 100755 --- a/src/services/uiExcel.ts +++ b/src/services/uiExcel.ts @@ -15,7 +15,6 @@ import { BEAN_ROASTING_TYPE_ENUM } from '../enums/beans/beanRoastingType'; import { BEAN_MIX_ENUM } from '../enums/beans/mix'; import { UIPreparationStorage } from './uiPreparationStorage'; import { UIAlert } from './uiAlert'; -import { SocialSharing } from '@awesome-cordova-plugins/social-sharing/ngx'; import { UIFileHelper } from './uiFileHelper'; import { UIMillStorage } from './uiMillStorage'; import { BrewFlow, IBrewWaterFlow } from '../classes/brew/brewFlow'; @@ -23,6 +22,11 @@ import moment from 'moment'; import { UISettingsStorage } from './uiSettingsStorage'; import { Settings } from '../classes/settings/settings'; import { Brew } from '../classes/brew/brew'; +import { Bean } from '../classes/bean/bean'; +import { IBeanInformation } from '../interfaces/bean/iBeanInformation'; +import { UIBeanHelper } from './uiBeanHelper'; +import { GreenBean } from '../classes/green-bean/green-bean'; +import { UIGreenBeanStorage } from './uiGreenBeanStorage'; @Injectable({ providedIn: 'root', @@ -37,14 +41,14 @@ export class UIExcel { private readonly platform: Platform, private readonly uiBrewStorage: UIBrewStorage, private readonly uiBeanStorage: UIBeanStorage, + private readonly uiGreenBeanStorage: UIGreenBeanStorage, private readonly uiPreparationStoraage: UIPreparationStorage, private readonly translate: TranslateService, private readonly uiAlert: UIAlert, - private readonly socialsharing: SocialSharing, private readonly uiFileHelper: UIFileHelper, private readonly uiMillStorage: UIMillStorage, - private readonly alertCtrl: AlertController, - private readonly uiSettingsStorage: UISettingsStorage + private readonly uiSettingsStorage: UISettingsStorage, + private readonly uiBeanHelper: UIBeanHelper ) { this.settings = this.uiSettingsStorage.getSettings(); } @@ -80,8 +84,6 @@ export class UIExcel { const wsData: any[][] = [header]; for (const entry of _flow.weight) { - const notMutatedWeight: number = 0; - const wbEntry: Array = [ entry.timestamp, entry.brew_time, @@ -719,18 +721,498 @@ export class UIExcel { } } + + public async importGreenBeansByExcel(_arrayBuffer) { + try { + /* data is an ArrayBuffer */ + const wb = XLSX.read(_arrayBuffer); + const data = XLSX.utils.sheet_to_json(wb.Sheets['Green Beans']); + + + let varietyInformationWhereAdded: boolean = false; + const addedBeans: Array = []; + const toAddBeans: Array = []; + for (const entry of data) { + /** + * 1. Bean certification: 14 + * 1. Country: 5 + * 1. Elevation: 9 + * 1. Farm: 7 + * 1. Farmer: 8 + * 1. Harvested: 12 + * 1. Percentage: 13 + * 1. Processing: 11 + * 1. Region: 6 + * 1. Variety: 10 + * 1. Fob Price + * 1. Purchasing Price + * Archived: false - + * Cost: 13 - + * Cupping points: 92 - + * Decaffeinated: false - + * EAN / Articlenumber: 2 - + * Flavour profile: "Red, whine, apple" - + * Name: 123 - + * Notes: 3 + * Rating: 4 + * Website: 1 - + * Weight: 250 - + * Buy Date + */ + + const bean: GreenBean = new GreenBean(); + + const nameEntry = entry['Name']; + if (nameEntry) { + bean.name = nameEntry.toString(); + } else { + continue; + } + + const weightEntry = entry['Weight']; + if (weightEntry && Number(weightEntry) > 0) { + bean.weight = Number(weightEntry); + } + + const buyDateEntry = entry['Buy Date']; + if (buyDateEntry && Number(buyDateEntry) > 0) { + bean.date = this.getJsDateFromExcel(Number(buyDateEntry)); + } + + const websiteEntry = entry['Website']; + if (websiteEntry) { + bean.url = websiteEntry.toString(); + } + + + const flavourProfileEntry = entry['Flavour profile']; + if (flavourProfileEntry) { + bean.aromatics = flavourProfileEntry.toString(); + } + + const eanArticleNumberEntry = entry['EAN / Articlenumber']; + if (eanArticleNumberEntry) { + bean.ean_article_number = eanArticleNumberEntry.toString(); + } + + const decaffeinatedEntry = entry['Decaffeinated']; + if (decaffeinatedEntry) { + bean.decaffeinated = decaffeinatedEntry; + } + + const cuppingPointsEntry = entry['Cupping points']; + if (cuppingPointsEntry) { + bean.cupping_points = cuppingPointsEntry.toString(); + } + + const costEntry = entry['Cost']; + if (costEntry) { + bean.cost = Number(costEntry); + } + + const archivedEntry = entry['Archived']; + if (archivedEntry) { + bean.finished = archivedEntry; + } + + const beanInformation: IBeanInformation = {} as IBeanInformation; + let hasOneBeanInformation: boolean = false; + + const informationCertificationEntry = entry['1. Bean certification']; + if (informationCertificationEntry) { + beanInformation.certification = informationCertificationEntry.toString(); + hasOneBeanInformation=true; + } + + const informationCountryEntry = entry['1. Country']; + if (informationCountryEntry) { + beanInformation.country = informationCountryEntry.toString(); + hasOneBeanInformation=true; + } + + const informationElevationEntry = entry['1. Elevation']; + if (informationElevationEntry) { + beanInformation.elevation = informationElevationEntry.toString(); + hasOneBeanInformation=true; + } + + const informationFarmEntry = entry['1. Farm']; + if (informationFarmEntry) { + beanInformation.farm = informationFarmEntry.toString(); + hasOneBeanInformation=true; + } + + const informationFarmerEntry = entry['1. Farmer']; + if (informationFarmerEntry) { + beanInformation.farmer = informationFarmerEntry.toString(); + hasOneBeanInformation=true; + } + + const informationHarvestedEntry = entry['1. Harvested']; + if (informationHarvestedEntry) { + beanInformation.harvest_time = informationHarvestedEntry.toString(); + hasOneBeanInformation=true; + } + + const informationPercentageEntry = entry['1. Percentage']; + if (informationPercentageEntry && Number(informationPercentageEntry) > 0) { + beanInformation.percentage = Number(informationPercentageEntry); + hasOneBeanInformation=true; + } + + const informationProcessingEntry = entry['1. Processing']; + if (informationProcessingEntry) { + beanInformation.processing = informationProcessingEntry.toString(); + hasOneBeanInformation=true; + } + + const informationRegionEntry = entry['1. Region']; + if (informationRegionEntry) { + beanInformation.region = informationRegionEntry.toString(); + hasOneBeanInformation=true; + } + + const informationVarietyEntry = entry['1. Variety']; + if (informationVarietyEntry) { + beanInformation.variety = informationVarietyEntry.toString(); + hasOneBeanInformation=true; + } + + const informationFobPriceEntry = entry['1. Fob Price']; + if (informationFobPriceEntry && Number(informationFobPriceEntry) > 0) { + beanInformation.fob_price = Number(informationFobPriceEntry); + hasOneBeanInformation=true; + } + + const informationPurchasingPriceEntry = entry['1. Purchasing Price']; + if (informationPurchasingPriceEntry && Number(informationPurchasingPriceEntry) > 0) { + beanInformation.purchasing_price = Number(informationPurchasingPriceEntry); + hasOneBeanInformation=true; + } + + if (hasOneBeanInformation) { + varietyInformationWhereAdded = true; + bean.bean_information.push(beanInformation); + } else { + /** Add atleast one empty bean information**/ + const emptyBeanInformation: IBeanInformation = {} as IBeanInformation; + bean.bean_information.push(emptyBeanInformation); + } + + toAddBeans.push(bean); + } + + + if (varietyInformationWhereAdded) { + if (this.settings.bean_manage_parameters.bean_information === false) { + this.settings.bean_manage_parameters.bean_information = true; + await this.uiSettingsStorage.saveSettings(this.settings); + } + } + + + /** + * Add all beans afterwards to not have some added and then going into an exception + */ + for await (const addBean of toAddBeans) { + try { + const newBean: GreenBean = await this.uiGreenBeanStorage.add(addBean); + addedBeans.push(newBean); + } catch(ex) { + + } + } + + if (addedBeans.length>0) { + try { + await this.uiAlert.showMessage('GREEN_BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION','IMPORT_SUCCESSFULLY',undefined,true); + }catch(ex) { + + } + + } else { + this.uiAlert.showMessage('BEANS_IMPORTED_UNSUCCESSFULLY_WRONG_EXCELFILE','IMPORT_UNSUCCESSFULLY','OK',false); + } + + } catch (ex) { + this.uiAlert.showMessage(ex.message,this.translate.instant('IMPORT_UNSUCCESSFULLY'),this.translate.instant('OK'),false); + } + } + public async importBeansByExcel(_arrayBuffer) { try { /* data is an ArrayBuffer */ const wb = XLSX.read(_arrayBuffer); const data = XLSX.utils.sheet_to_json(wb.Sheets['Beans']); + + let isOneEntryFrozen: boolean = false; + let varietyInformationWhereAdded: boolean = false; + const addedBeans: Array = []; + const toAddBeans: Array = []; for (const entry of data) { - //const bean: Bean = new Bean(); - //bean.bean_information + /** + * 1. Bean certification: 14 + * 1. Country: 5 + * 1. Elevation: 9 + * 1. Farm: 7 + * 1. Farmer: 8 + * 1. Harvested: 12 + * 1. Percentage: 13 + * 1. Processing: 11 + * 1. Region: 6 + * 1. Variety: 10 + * 1. Fob Price + * 1. Purchasing Price + * Archived: false - + * Blend: "UNKNOWN" - + * Cost: 13 - + * Cupping points: 92 - + * Decaffeinated: false - + * Degree of Roast: "UNKNOWN" - + * EAN / Articlenumber: 2 - + * Flavour profile: "Red, whine, apple" - + * Name: 123 - + * Notes: 3 + * Rating: 4 + * Roast date: 44593 + * Roast type: "FILTER" - + * Roaster: 123 - + * Website: 1 - + * Weight: 250 - + * Frozen Date + * Unfrozen Date + * Freezing Storage Type + * Frozen Note + */ + + const bean: Bean = new Bean(); + + const nameEntry = entry['Name']; + if (nameEntry) { + bean.name = nameEntry.toString(); + } else { + continue; + } + + const weightEntry = entry['Weight']; + if (weightEntry && Number(weightEntry) > 0) { + bean.weight = Number(weightEntry); + } + + const roastDateEntry = entry['Roast date']; + if (roastDateEntry && Number(roastDateEntry) > 0) { + bean.roastingDate = this.getJsDateFromExcel(Number(roastDateEntry)); + } + + const websiteEntry = entry['Website']; + if (websiteEntry) { + bean.url = websiteEntry.toString(); + } + + const roasterEntry = entry['Roaster']; + if (roasterEntry) { + bean.roaster = roasterEntry.toString(); + } + + const roastTypeEntry = entry['Roast type']; + if (roastTypeEntry) { + bean.bean_roasting_type = roastTypeEntry; + } + + const flavourProfileEntry = entry['Flavour profile']; + if (flavourProfileEntry) { + bean.aromatics = flavourProfileEntry.toString(); + } + + const eanArticleNumberEntry = entry['EAN / Articlenumber']; + if (eanArticleNumberEntry) { + bean.ean_article_number = eanArticleNumberEntry.toString(); + } + + const degreeOfRoastEntry = entry['Degree of Roast']; + if (degreeOfRoastEntry) { + bean.roast = degreeOfRoastEntry; + } + const decaffeinatedEntry = entry['Decaffeinated']; + if (decaffeinatedEntry) { + bean.decaffeinated = decaffeinatedEntry; + } + + const cuppingPointsEntry = entry['Cupping points']; + if (cuppingPointsEntry) { + bean.cupping_points = cuppingPointsEntry.toString(); + } + + const costEntry = entry['Cost']; + if (costEntry) { + bean.cost = Number(costEntry); + } + + const blendEntry = entry['Blend']; + if (blendEntry) { + bean.beanMix = blendEntry; + } + + const archivedEntry = entry['Archived']; + if (archivedEntry) { + bean.finished = archivedEntry; + } + + const beanInformation: IBeanInformation = {} as IBeanInformation; + let hasOneBeanInformation: boolean = false; + + const informationCertificationEntry = entry['1. Bean certification']; + if (informationCertificationEntry) { + beanInformation.certification = informationCertificationEntry.toString(); + hasOneBeanInformation=true; + } + + const informationCountryEntry = entry['1. Country']; + if (informationCountryEntry) { + beanInformation.country = informationCountryEntry.toString(); + hasOneBeanInformation=true; + } + + const informationElevationEntry = entry['1. Elevation']; + if (informationElevationEntry) { + beanInformation.elevation = informationElevationEntry.toString(); + hasOneBeanInformation=true; + } + + const informationFarmEntry = entry['1. Farm']; + if (informationFarmEntry) { + beanInformation.farm = informationFarmEntry.toString(); + hasOneBeanInformation=true; + } + + const informationFarmerEntry = entry['1. Farmer']; + if (informationFarmerEntry) { + beanInformation.farmer = informationFarmerEntry.toString(); + hasOneBeanInformation=true; + } + + const informationHarvestedEntry = entry['1. Harvested']; + if (informationHarvestedEntry) { + beanInformation.harvest_time = informationHarvestedEntry.toString(); + hasOneBeanInformation=true; + } + + const informationPercentageEntry = entry['1. Percentage']; + if (informationPercentageEntry && Number(informationPercentageEntry) > 0) { + beanInformation.percentage = Number(informationPercentageEntry); + hasOneBeanInformation=true; + } + + const informationProcessingEntry = entry['1. Processing']; + if (informationProcessingEntry) { + beanInformation.processing = informationProcessingEntry.toString(); + hasOneBeanInformation=true; + } + + const informationRegionEntry = entry['1. Region']; + if (informationRegionEntry) { + beanInformation.region = informationRegionEntry.toString(); + hasOneBeanInformation=true; + } + + const informationVarietyEntry = entry['1. Variety']; + if (informationVarietyEntry) { + beanInformation.variety = informationVarietyEntry.toString(); + hasOneBeanInformation=true; + } + + const informationFobPriceEntry = entry['1. Fob Price']; + if (informationFobPriceEntry && Number(informationFobPriceEntry) > 0) { + beanInformation.fob_price = Number(informationFobPriceEntry); + hasOneBeanInformation=true; + } + + const informationPurchasingPriceEntry = entry['1. Purchasing Price']; + if (informationPurchasingPriceEntry && Number(informationPurchasingPriceEntry) > 0) { + beanInformation.purchasing_price = Number(informationPurchasingPriceEntry); + hasOneBeanInformation=true; + } + + if (hasOneBeanInformation) { + varietyInformationWhereAdded = true; + bean.bean_information.push(beanInformation); + } else { + /** Add atleast one empty bean information**/ + const emptyBeanInformation: IBeanInformation = {} as IBeanInformation; + bean.bean_information.push(emptyBeanInformation); + } + + const freezingStorageTypeEntry = entry['Freezing Storage Type']; + if (freezingStorageTypeEntry) { + bean.frozenStorageType = freezingStorageTypeEntry; + } + + const frozenNoteEntry = entry['Frozen Note']; + if (frozenNoteEntry) { + bean.frozenNote = frozenNoteEntry; + } + + const frozenDateEntry = entry['Frozen Date']; + if (frozenDateEntry && Number(frozenDateEntry) > 0) { + isOneEntryFrozen = true; + bean.frozenDate = this.getJsDateFromExcel(Number(frozenDateEntry)); + bean.frozenId = this.uiBeanHelper.generateFrozenId(); + } + + const unfrozenDateEntry = entry['Unfrozen Date']; + if (unfrozenDateEntry && Number(unfrozenDateEntry) > 0) { + isOneEntryFrozen = true; + bean.unfrozenDate = this.getJsDateFromExcel(Number(unfrozenDateEntry)); + } + toAddBeans.push(bean); } - console.log(data); - console.log(wb); - } catch (ex) {} + + if (isOneEntryFrozen) { + // Activate the frozen feature if not active + if (this.settings.freeze_coffee_beans === false) { + this.settings.freeze_coffee_beans = true; + await this.uiSettingsStorage.saveSettings(this.settings); + } + } + if (varietyInformationWhereAdded) { + if (this.settings.bean_manage_parameters.bean_information === false) { + this.settings.bean_manage_parameters.bean_information = true; + await this.uiSettingsStorage.saveSettings(this.settings); + } + } + + + /** + * Add all beans afterwards to not have some added and then going into an exception + */ + for await (const addBean of toAddBeans) { + try { + const newBean: Bean = await this.uiBeanStorage.add(addBean); + addedBeans.push(newBean); + } catch(ex) { + + } + } + + if (addedBeans.length>0) { + try { + await this.uiAlert.showMessage('BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION','IMPORT_SUCCESSFULLY',undefined,true); + }catch(ex) { + + } + this.uiBeanHelper.showBeans(addedBeans); + } else { + this.uiAlert.showMessage('BEANS_IMPORTED_UNSUCCESSFULLY_WRONG_EXCELFILE','IMPORT_UNSUCCESSFULLY','OK',false); + } + + } catch (ex) { + this.uiAlert.showMessage(ex.message,this.translate.instant('IMPORT_UNSUCCESSFULLY'),this.translate.instant('OK'),false); + } + } + + private getJsDateFromExcel(_dateNumber) { + return new Date((_dateNumber - (25567+2))*86400*1000).toISOString(); + } /* Export button */ public async export() { diff --git a/src/services/uiExportImportHelper.ts b/src/services/uiExportImportHelper.ts index 964f5ac9..2b6cfa9f 100644 --- a/src/services/uiExportImportHelper.ts +++ b/src/services/uiExportImportHelper.ts @@ -20,11 +20,13 @@ import { import * as zip from '@zip.js/zip.js'; import { FileEntry } from '@awesome-cordova-plugins/file'; import { UILog } from './uiLog'; -import { Platform } from '@ionic/angular'; +import { ModalController, Platform } from '@ionic/angular'; import { UIFileHelper } from './uiFileHelper'; import { UIAlert } from './uiAlert'; import moment from 'moment'; import { UIBrewStorage } from './uiBrewStorage'; + +import { DataCorruptionFoundComponent } from '../popover/data-corruption-found/data-corruption-found.component'; @Injectable({ providedIn: 'root', }) @@ -43,7 +45,8 @@ export class UIExportImportHelper { private readonly uiFileHelper: UIFileHelper, private readonly uiAlert: UIAlert, private readonly uiSettingsStorage: UISettingsStorage, - private readonly uiBrewStorage: UIBrewStorage + private readonly uiBrewStorage: UIBrewStorage, + private readonly modalController: ModalController ) {} public async buildExportZIP(): Promise { @@ -239,6 +242,64 @@ export class UIExportImportHelper { }); }); } + private async checkBackupAndSeeIfDataAreCorrupted(_actualUIStorageDataObj) { + + try { + this.uiLog.log("checkBackupAndSeeIfDataAreCorrupted - Check if we got a deep corruption"); + const dataObj = _actualUIStorageDataObj.DATA; + const parsedJSON: any = await this.readBackupZIPFile(); + if (parsedJSON) { + let somethingCorrupted = false; + if (parsedJSON.BEANS?.length > dataObj.BEANS) { + somethingCorrupted = true; + } else if (parsedJSON.BREWS?.length > dataObj.BREWS) + { + somethingCorrupted = true; + } else if (parsedJSON.PREPARATION?.length > dataObj.PREPARATION) + { + somethingCorrupted = true; + } + else if (parsedJSON.MILL?.length > dataObj.MILL) + { + somethingCorrupted = true; + } + + this.uiLog.log("checkBackupAndSeeIfDataAreCorrupted- Check over - if we got a deep corruption - Result: " + somethingCorrupted); + if (somethingCorrupted) { + const importBackup = await this.showDataCorruptionPopover(dataObj,parsedJSON); + if (importBackup) { + await this.importBackupJSON(parsedJSON); + } + } else { + this.uiLog.log("checkBackupAndSeeIfDataAreCorrupted - Check over - we didn't find any corrupted data"); + } + } else { + this.uiLog.log("checkBackupAndSeeIfDataAreCorrupted - We didn't found any json backup data so we can't do any checks"); + } + } catch(ex) { + this.uiLog.log("Check over - if we got a deep corruption - Result exception: " + JSON.stringify(ex)); + } + + } + + public async showDataCorruptionPopover(_actualUIStorageDataObj,_backupDataObj) { + const modal = await this.modalController.create({ + component: DataCorruptionFoundComponent, + id: DataCorruptionFoundComponent.POPOVER_ID, + componentProps: { + actualUIStorageDataObj: _actualUIStorageDataObj, + backupDataObj: _backupDataObj, + }, + }); + await modal.present(); + const returnData = await modal.onWillDismiss(); + this.uiLog.log('Data corruption, choose to import: ' + returnData?.data?.import); + if (returnData?.data?.import) { + //User choose to import backup, go + return true; + } + return false; + } public async checkBackup() { try { @@ -248,12 +309,13 @@ export class UIExportImportHelper { this.uiLog.log('Check Backup'); const hasData = await this.uiStorage.hasData(); - let corruptedDataObjCheck: any; + let actualUIStorageDataObj: any; if (hasData) { - corruptedDataObjCheck = await this.uiStorage.hasCorruptedData(); + actualUIStorageDataObj = await this.uiStorage.hasCorruptedData(); } + this.uiLog.log('Check Backup - Has data ' + hasData); - if (!hasData || corruptedDataObjCheck.CORRUPTED) { + if (!hasData || actualUIStorageDataObj.CORRUPTED) { if (!hasData) { this.uiLog.log( 'Check Backup - We didnt found any data inside the app, so try to find a backup and import it' @@ -268,16 +330,9 @@ export class UIExportImportHelper { if (parsedJSON) { await this.importBackupJSON(parsedJSON); } + resolve(null); } else { - /** - * BREWS: number, - * MILL: number, - * PREPARATION: number, - * BEANS: number, - */ - const parsedJSON = await this.readBackupZIPFile(); - console.log('BLAAA'); - console.log(parsedJSON); + await this.checkBackupAndSeeIfDataAreCorrupted(actualUIStorageDataObj); resolve(null); } } else { diff --git a/src/services/uiFileHelper.ts b/src/services/uiFileHelper.ts index fbc07582..1cfe8c19 100644 --- a/src/services/uiFileHelper.ts +++ b/src/services/uiFileHelper.ts @@ -847,10 +847,10 @@ export class UIFileHelper extends InstanceClass { ): Promise { return new Promise(async (resolve, reject) => { if (this.platform.is('cordova')) { - if (this.cachedInternalUrls[_filePath]) { + /** if (this.cachedInternalUrls[_filePath]) { //resolve(this.cachedInternalUrls[_filePath]); // return; - } + }**/ // let filePath: string; // filePath = _filePath; // filePath.slice(0, filePath.lastIndexOf('/')); @@ -884,8 +884,9 @@ export class UIFileHelper extends InstanceClass { this.domSanitizer.bypassSecurityTrustResourceUrl( convertedURL ); - this.cachedInternalUrls[_filePath] = convertedURL; - resolve(convertedURL); + const returningURL = convertedURL; + // this.cachedInternalUrls[_filePath] = convertedURL; + resolve(returningURL); }, () => { resolve(''); diff --git a/src/services/uiHelper.ts b/src/services/uiHelper.ts index 51ec29d8..4805deb9 100755 --- a/src/services/uiHelper.ts +++ b/src/services/uiHelper.ts @@ -147,6 +147,16 @@ export class UIHelper { return moment(_unix).format(format); } + public formatTimeNumber(_time: number|string, _format?: string): string { + let format: string = + this.getSettingsStorageInstance().getSettings().date_format + + ', HH:mm:ss'; + if (_format) { + format = _format; + } + return moment(_time).format(format); + } + public toFixedIfNecessary(value, dp) { const parsedFloat = parseFloat(value); if (isNaN(parsedFloat)) { diff --git a/src/services/uiPreparationHelper.ts b/src/services/uiPreparationHelper.ts index d00acf5e..bc28ca0b 100644 --- a/src/services/uiPreparationHelper.ts +++ b/src/services/uiPreparationHelper.ts @@ -20,9 +20,13 @@ import { PreparationDeviceType, } from '../classes/preparationDevice'; import { HttpClient } from '@angular/common/http'; -import { XeniaDevice } from '../classes/preparationDevice/xenia/xeniaDevice'; import { PreparationDevice } from '../classes/preparationDevice/preparationDevice'; import { PreparationSortToolsComponent } from '../app/preparation/preparation-sort-tools/preparation-sort-tools.component'; +import PREPARATION_TRACKING from '../data/tracking/preparationTracking'; +import { + PreparationConnectedDeviceComponent +} from '../app/preparation/preparation-connected-device/preparation-connected-device.component'; +import { UIAnalytics } from './uiAnalytics'; /** * Handles every helping functionalities @@ -39,7 +43,8 @@ export class UIPreparationHelper { private readonly uiHelper: UIHelper, private readonly translate: TranslateService, private readonly uiPreparationStorage: UIPreparationStorage, - private readonly httpClient: HttpClient + private readonly httpClient: HttpClient, + private readonly uiAnalytics: UIAnalytics ) { this.uiBrewStorage.attachOnEvent().subscribe((_val) => { // If an brew is deleted, we need to reset our array for the next call. @@ -84,6 +89,22 @@ export class UIPreparationHelper { await modal.present(); await modal.onWillDismiss(); } + public async connectDevice(_preparation: Preparation) { + this.uiAnalytics.trackEvent( + PREPARATION_TRACKING.TITLE, + PREPARATION_TRACKING.ACTIONS.CONNECT_DEVICE + ); + const modal = await this.modalController.create({ + component: PreparationConnectedDeviceComponent, + componentProps: { preparation: _preparation }, + id: PreparationConnectedDeviceComponent.COMPONENT_ID, + }); + await modal.present(); + await modal.onWillDismiss(); + } + + + public async editPreparationTool( _preparation: Preparation, diff --git a/src/services/uiUpdate.ts b/src/services/uiUpdate.ts index dd672e8d..60af4c65 100755 --- a/src/services/uiUpdate.ts +++ b/src/services/uiUpdate.ts @@ -66,6 +66,7 @@ export class UIUpdate { 'UPDATE_8', 'UPDATE_9', 'UPDATE_10', + 'UPDATE_11', ]; const version: Version = this.uiVersionStorage.getVersion(); const _silentUpdate = hasData; @@ -89,6 +90,7 @@ export class UIUpdate { await this.__checkUpdateForDataVersion('UPDATE_8', !hasData); await this.__checkUpdateForDataVersion('UPDATE_9', !hasData); await this.__checkUpdateForDataVersion('UPDATE_10', !hasData); + await this.__checkUpdateForDataVersion('UPDATE_11', !hasData); } catch (ex) { if (this.uiAlert.isLoadingSpinnerShown()) { await this.uiAlert.hideLoadingSpinner(); @@ -549,8 +551,15 @@ export class UIUpdate { case 'UPDATE_10': const settings_v10: Settings = this.uiSettingsStorage.getSettings(); settings_v10.resetFilter(); + settings_v10.resetBeanSort(); await this.uiSettingsStorage.saveSettings(settings_v10); break; + case 'UPDATE_11': + //#776 - We added a new beansort, thats why we reset the bean sort here. + const settings_v11: Settings = this.uiSettingsStorage.getSettings(); + settings_v11.resetBeanSort(); + await this.uiSettingsStorage.saveSettings(settings_v11); + break; default: break; } From 6d52f656890d49f187834761dd55b250cf24e1ae Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Tue, 27 Aug 2024 21:02:17 +0200 Subject: [PATCH 06/19] #767 - Frozen beans sort order is now saved #765 - Show popup if data base is corrupted #762 - Read a history shot of the meticulous to import #768 - Add ean search article number #769 - Make brew/bean toggleable #438 - Import beans via excel #772 - Display best brew / favorite / frozen etc. #773 - Show frozen icon for beans on brew-list #775 - Fixing wrong labels #776 - Sorting bean for bean age #629 - Import green beans via excel #777 - grow plausible var from 5 to 6 #778 - Showing bean images on selection #623 - Showing a popup that more informations are there but not visible. --- src/app/app.component.ts | 4 - .../bean-popover-freeze.component.ts | 70 ++- .../bean-popover-list.component.spec.ts | 4 +- .../bean-popover-list.component.ts | 15 +- .../beans/beans-add/beans-add.component.ts | 27 +- src/app/beans/beans.page.ts | 9 +- ...l-import-shot-meticulous.component.spec.ts | 2 +- ...-modal-import-shot-meticulous.component.ts | 24 +- src/app/brew/brew.page.ts | 8 +- .../preparation-add-type.component.ts | 6 +- .../preparation-add.component.ts | 2 +- .../preparation-connected-device.component.ts | 25 +- src/app/settings/settings.page.ts | 11 +- src/classes/devices/argosThermometer.ts | 11 +- src/classes/devices/index.ts | 2 +- src/classes/preparation/preparation.ts | 6 +- .../meticulous/meticulousDevice.ts | 32 +- .../sanremo/sanremoYOUDevice.ts | 10 +- src/classes/settings/settings.ts | 1 - .../brew-information.component.ts | 1 - .../brew-brewing-graph.component.ts | 406 ++++++++---------- ...ew-brewing-preparation-device.component.ts | 30 +- .../graph-display-card.component.ts | 4 +- .../photo-add/photo-add.component.ts | 11 +- src/enums/beans/beanSortAfter.ts | 4 +- src/environments/environment.prod.ts | 4 +- src/environments/environment.ts | 4 +- .../sanremoYOU/iSanremoYOUParams.ts | 1 - .../data-corruption-found.component.spec.ts | 4 +- .../data-corruption-found.component.ts | 11 +- .../coffee-bluetooth-devices.service.ts | 9 +- src/services/uiExcel.ts | 160 ++++--- src/services/uiExportImportHelper.ts | 56 ++- src/services/uiHelper.ts | 2 +- src/services/uiPreparationHelper.ts | 7 +- 35 files changed, 498 insertions(+), 485 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 891080a4..5c9e5762 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -324,7 +324,6 @@ export class AppComponent implements AfterViewInit { }); } catch (ex) {} - // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. // #7 @@ -367,7 +366,6 @@ export class AppComponent implements AfterViewInit { }); } - if (this.platform.is('cordova')) { // Just support deeplinks on devices. this.intentHandlerService.attachOnHandleOpenUrl(); @@ -376,8 +374,6 @@ export class AppComponent implements AfterViewInit { this._translate.setDefaultLang('en'); await this._translate.use('en').toPromise(); - - if (this.platform.is('cordova')) { try { await this.uiExportImportHelper.checkBackup(); diff --git a/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.ts b/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.ts index 9b429b3a..8bb2d0fd 100644 --- a/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.ts +++ b/src/app/beans/bean-popover-freeze/bean-popover-freeze.component.ts @@ -59,7 +59,10 @@ export class BeanPopoverFreezeComponent implements OnInit { public ngOnInit() { // cant be done in constructor, else the bean object is not known - this.leftOverBeanBagWeight = this.uiHelper.toFixedIfNecessary(this.bean.weight - this.getUsedWeightCount(),1); + this.leftOverBeanBagWeight = this.uiHelper.toFixedIfNecessary( + this.bean.weight - this.getUsedWeightCount(), + 1 + ); } public getUsedWeightCount(): number { @@ -86,8 +89,10 @@ export class BeanPopoverFreezeComponent implements OnInit { } public async save() { - const spillOver = - this.uiHelper.toFixedIfNecessary(this.leftOverBeanBagWeight - this.getActualFreezingQuantity(),1); + const spillOver = this.uiHelper.toFixedIfNecessary( + this.leftOverBeanBagWeight - this.getActualFreezingQuantity(), + 1 + ); let index = 1; @@ -109,10 +114,16 @@ export class BeanPopoverFreezeComponent implements OnInit { this.bean.config.uuid ); if (brews.length > 0) { - const oldWeight = this.uiHelper.toFixedIfNecessary(this.bean.weight,1) - this.bean.weight = this.uiHelper.toFixedIfNecessary(this.bean.weight - this.getActualFreezingQuantity(),1); + const oldWeight = this.uiHelper.toFixedIfNecessary(this.bean.weight, 1); + this.bean.weight = this.uiHelper.toFixedIfNecessary( + this.bean.weight - this.getActualFreezingQuantity(), + 1 + ); try { - const newCost = this.uiHelper.toFixedIfNecessary((this.bean.cost * this.bean.weight) / oldWeight,2) + const newCost = this.uiHelper.toFixedIfNecessary( + (this.bean.cost * this.bean.weight) / oldWeight, + 2 + ); this.bean.cost = newCost; } catch (ex) { this.bean.cost = 0; @@ -148,10 +159,16 @@ export class BeanPopoverFreezeComponent implements OnInit { /** * Because we had already maybe some brews, we take the bean weight, and subtract it with the spill over, because just using the spill over would not take previus brews into account */ - const oldWeight = this.uiHelper.toFixedIfNecessary(this.bean.weight,1); - this.bean.weight = this.uiHelper.toFixedIfNecessary(this.bean.weight - this.getActualFreezingQuantity(),1); + const oldWeight = this.uiHelper.toFixedIfNecessary(this.bean.weight, 1); + this.bean.weight = this.uiHelper.toFixedIfNecessary( + this.bean.weight - this.getActualFreezingQuantity(), + 1 + ); try { - const newCost = this.uiHelper.toFixedIfNecessary((this.bean.cost * this.bean.weight) / oldWeight,2); + const newCost = this.uiHelper.toFixedIfNecessary( + (this.bean.cost * this.bean.weight) / oldWeight, + 2 + ); this.bean.cost = newCost; } catch (ex) { this.bean.cost = 0; @@ -189,13 +206,16 @@ export class BeanPopoverFreezeComponent implements OnInit { if (this.bean.cost !== 0) { try { - const newCost = this.uiHelper.toFixedIfNecessary((this.bean.cost * _freezingWeight) / this.bean.weight,2); + const newCost = this.uiHelper.toFixedIfNecessary( + (this.bean.cost * _freezingWeight) / this.bean.weight, + 2 + ); clonedBean.cost = newCost; } catch (ex) { clonedBean.cost = 0; } } - clonedBean.weight = this.uiHelper.toFixedIfNecessary(_freezingWeight,1); + clonedBean.weight = this.uiHelper.toFixedIfNecessary(_freezingWeight, 1); clonedBean.config = new Config(); const newClonedBean = await this.uiBeanStorage.add(clonedBean); const newBean: Bean = new Bean(); @@ -245,11 +265,15 @@ export class BeanPopoverFreezeComponent implements OnInit { } public isAddingBagDisabled() { - - if (this.freezePartialBagGrams <=0) { + if (this.freezePartialBagGrams <= 0) { return true; } - if (this.uiHelper.toFixedIfNecessary(Number(this.freezePartialBagGrams) + this.getActualFreezingQuantity(),1) > this.leftOverBeanBagWeight) { + if ( + this.uiHelper.toFixedIfNecessary( + Number(this.freezePartialBagGrams) + this.getActualFreezingQuantity(), + 1 + ) > this.leftOverBeanBagWeight + ) { return true; } return false; @@ -261,8 +285,10 @@ export class BeanPopoverFreezeComponent implements OnInit { type: this.frozenStorage, }); - const leftFreezingCount = - this.uiHelper.toFixedIfNecessary(this.leftOverBeanBagWeight - this.getActualFreezingQuantity(),1); + const leftFreezingCount = this.uiHelper.toFixedIfNecessary( + this.leftOverBeanBagWeight - this.getActualFreezingQuantity(), + 1 + ); if (leftFreezingCount < this.freezePartialBagGrams) { this.freezePartialBagGrams = this.uiHelper.toFixedIfNecessary( leftFreezingCount, @@ -278,8 +304,10 @@ export class BeanPopoverFreezeComponent implements OnInit { type: this.frozenStorage, }); - const leftFreezingCount = - this.uiHelper.toFixedIfNecessary(this.leftOverBeanBagWeight - this.getActualFreezingQuantity(),1); + const leftFreezingCount = this.uiHelper.toFixedIfNecessary( + this.leftOverBeanBagWeight - this.getActualFreezingQuantity(), + 1 + ); if (leftFreezingCount < this.freezePartialBagGrams) { this.freezePartialBagGrams = this.uiHelper.toFixedIfNecessary( leftFreezingCount, @@ -292,8 +320,10 @@ export class BeanPopoverFreezeComponent implements OnInit { public deleteBag(_index) { this.addedBags.splice(_index, 1); - const leftFreezingCount = - this.uiHelper.toFixedIfNecessary(this.leftOverBeanBagWeight - this.getActualFreezingQuantity(),1); + const leftFreezingCount = this.uiHelper.toFixedIfNecessary( + this.leftOverBeanBagWeight - this.getActualFreezingQuantity(), + 1 + ); if (leftFreezingCount < this.freezePartialBagGrams) { this.freezePartialBagGrams = leftFreezingCount; } diff --git a/src/app/beans/bean-popover-list/bean-popover-list.component.spec.ts b/src/app/beans/bean-popover-list/bean-popover-list.component.spec.ts index 34d578e6..5af36a70 100644 --- a/src/app/beans/bean-popover-list/bean-popover-list.component.spec.ts +++ b/src/app/beans/bean-popover-list/bean-popover-list.component.spec.ts @@ -11,14 +11,14 @@ describe('BeanPopoverListComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - declarations: [ BeanPopoverListComponent ], + declarations: [BeanPopoverListComponent], imports: [IonicModule.forRoot(), TranslateModule.forRoot()], providers: [ { provide: TranslateService, useValue: TranslateServiceMock, }, - ] + ], }).compileComponents(); fixture = TestBed.createComponent(BeanPopoverListComponent); diff --git a/src/app/beans/bean-popover-list/bean-popover-list.component.ts b/src/app/beans/bean-popover-list/bean-popover-list.component.ts index 6ae0948d..7d565d15 100644 --- a/src/app/beans/bean-popover-list/bean-popover-list.component.ts +++ b/src/app/beans/bean-popover-list/bean-popover-list.component.ts @@ -1,4 +1,11 @@ -import { Component, ElementRef, HostListener, Input, OnInit, ViewChild } from '@angular/core'; +import { + Component, + ElementRef, + HostListener, + Input, + OnInit, + ViewChild, +} from '@angular/core'; import { Bean } from '../../../classes/bean/bean'; import { AgVirtualSrollComponent } from 'ag-virtual-scroll'; import { ModalController } from '@ionic/angular'; @@ -9,7 +16,6 @@ import { ModalController } from '@ionic/angular'; styleUrls: ['./bean-popover-list.component.scss'], }) export class BeanPopoverListComponent { - public static readonly COMPONENT_ID = 'bean-popover-list'; @Input() public beansList: Array = undefined; @@ -20,9 +26,7 @@ export class BeanPopoverListComponent { @ViewChild('beanContent', { read: ElementRef }) public beanContent: ElementRef; - constructor( - private readonly modalController: ModalController, - ) {} + constructor(private readonly modalController: ModalController) {} public async ionViewWillEnter() { this.loadBrews(); @@ -61,5 +65,4 @@ export class BeanPopoverListComponent { BeanPopoverListComponent.COMPONENT_ID ); } - } diff --git a/src/app/beans/beans-add/beans-add.component.ts b/src/app/beans/beans-add/beans-add.component.ts index fbad06f2..81f5afaf 100644 --- a/src/app/beans/beans-add/beans-add.component.ts +++ b/src/app/beans/beans-add/beans-add.component.ts @@ -20,7 +20,7 @@ import { Settings } from '../../../classes/settings/settings'; @Component({ selector: 'beans-add', templateUrl: './beans-add.component.html', - styleUrls: ['./beans-add.component.scss'] + styleUrls: ['./beans-add.component.scss'], }) export class BeansAddComponent implements OnInit { public static readonly COMPONENT_ID = 'bean-add'; @@ -49,8 +49,7 @@ export class BeansAddComponent implements OnInit { private readonly platform: Platform, public readonly uiBeanHelper: UIBeanHelper, private readonly uiSettingsStorage: UISettingsStorage - ) { - } + ) {} public ngOnInit() { this.settings = this.uiSettingsStorage.getSettings(); @@ -67,8 +66,6 @@ export class BeansAddComponent implements OnInit { private async checkIfInformationAreSetButNotDisplayed() { try { - - const params = this.settings.bean_manage_parameters; if (this.data.bean_information.length > 0) { const info: IBeanInformation = this.data.bean_information[0]; @@ -114,20 +111,20 @@ export class BeansAddComponent implements OnInit { //Woopsi doopsi, user hasn't enabled the bean_information, lets display him a popover //#623 try { - const yes = await this.uiAlert.showConfirm('BEAN_POPUP_YOU_DONT_SEE_EVERYTHING_DESCRIPTION', 'INFORMATION', true); + const yes = await this.uiAlert.showConfirm( + 'BEAN_POPUP_YOU_DONT_SEE_EVERYTHING_DESCRIPTION', + 'INFORMATION', + true + ); this.settings.bean_manage_parameters.bean_information = true; await this.uiSettingsStorage.update(this.settings); //Activate } catch (ex) { // Don't activate } - } - } - } catch (ex) { - - } + } catch (ex) {} } public async ionViewWillEnter() { @@ -228,11 +225,10 @@ export class BeansAddComponent implements OnInit { if (this.settings.security_check_when_going_back === true) { this.disableHardwareBack.unsubscribe(); } - } catch (ex) { - } + } catch (ex) {} this.modalController.dismiss( { - dismissed: true + dismissed: true, }, undefined, BeansAddComponent.COMPONENT_ID @@ -270,8 +266,7 @@ export class BeansAddComponent implements OnInit { try { const newPath: string = await this.uiFileHelper.copyFile(attachment); copyAttachments.push(newPath); - } catch (ex) { - } + } catch (ex) {} } this.data.attachments = copyAttachments; if (_bean.cupped_flavor) { diff --git a/src/app/beans/beans.page.ts b/src/app/beans/beans.page.ts index a9331db4..3e70c849 100644 --- a/src/app/beans/beans.page.ts +++ b/src/app/beans/beans.page.ts @@ -110,7 +110,7 @@ export class BeansPage implements OnDestroy { this.frozenBeansFilter = this.settings.bean_filter.FROZEN; this.openBeansFilter = this.settings.bean_filter.OPEN; - this.openBeansCollapsed = this.settings.bean_collapsed.OPEN; + this.openBeansCollapsed = this.settings.bean_collapsed.OPEN; this.archivedBeansCollapsed = this.settings.bean_collapsed.ARCHIVED; this.frozenBeansCollapsed = this.settings.bean_collapsed.FROZEN; this.loadBeans(); @@ -129,13 +129,13 @@ export class BeansPage implements OnDestroy { } } public isCollapseActive() { - let collapsed: boolean =false; + let collapsed: boolean = false; if (this.bean_segment === 'open') { collapsed = this.openBeansCollapsed; } else if (this.bean_segment === 'archive') { collapsed = this.archivedBeansCollapsed; } else if (this.bean_segment === 'frozen') { - collapsed = this.frozenBeansCollapsed; + collapsed = this.frozenBeansCollapsed; } return collapsed; } @@ -146,7 +146,7 @@ export class BeansPage implements OnDestroy { } else if (this.bean_segment === 'archive') { this.archivedBeansCollapsed = !this.archivedBeansCollapsed; } else if (this.bean_segment === 'frozen') { - this.frozenBeansCollapsed = !this.frozenBeansCollapsed; + this.frozenBeansCollapsed = !this.frozenBeansCollapsed; } this.__saveCollapseFilter(); this.research(); @@ -158,7 +158,6 @@ export class BeansPage implements OnDestroy { await this.uiSettingsStorage.saveSettings(this.settings); } - public loadBeans(): void { this.__initializeBeans(); this.changeDetectorRef.detectChanges(); diff --git a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.spec.ts b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.spec.ts index f05bd393..629913fa 100644 --- a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.spec.ts +++ b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.spec.ts @@ -25,7 +25,7 @@ describe('BrewModalImportShotMeticulousComponent', () => { provide: TranslateService, useValue: TranslateServiceMock, }, - ] + ], }).compileComponents(); fixture = TestBed.createComponent(BrewModalImportShotMeticulousComponent); diff --git a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts index c98b7487..3ffbddff 100644 --- a/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts +++ b/src/app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component.ts @@ -1,4 +1,11 @@ -import { Component, ElementRef, HostListener, Input, OnInit, ViewChild } from '@angular/core'; +import { + Component, + ElementRef, + HostListener, + Input, + OnInit, + ViewChild, +} from '@angular/core'; import { MeticulousDevice } from '../../../classes/preparationDevice/meticulous/meticulousDevice'; import { ModalController } from '@ionic/angular'; @@ -33,8 +40,10 @@ export class BrewModalImportShotMeticulousComponent implements OnInit { @ViewChild('footerContent', { read: ElementRef }) public footerContent: ElementRef; - constructor(private readonly modalController: ModalController, - public readonly uiHelper: UIHelper) {} + constructor( + private readonly modalController: ModalController, + public readonly uiHelper: UIHelper + ) {} public ngOnInit() { this.readHistory(); @@ -43,7 +52,6 @@ export class BrewModalImportShotMeticulousComponent implements OnInit { private async readHistory() { this.history = await this.meticulousDevice?.getHistory(); this.retriggerScroll(); - } @HostListener('window:resize') @HostListener('window:orientationchange', ['$event']) @@ -51,17 +59,13 @@ export class BrewModalImportShotMeticulousComponent implements OnInit { this.retriggerScroll(); } - private retriggerScroll() { setTimeout(async () => { const el = this.historyShotContent.nativeElement; const scrollComponent: AgVirtualSrollComponent = this.shotDataScroll; if (scrollComponent) { - scrollComponent.el.style.height = - (el.offsetHeight - - 20) + - 'px'; + scrollComponent.el.style.height = el.offsetHeight - 20 + 'px'; } }, 150); } @@ -73,8 +77,6 @@ export class BrewModalImportShotMeticulousComponent implements OnInit { return 0; } - - public dismiss(): void { this.modalController.dismiss( { diff --git a/src/app/brew/brew.page.ts b/src/app/brew/brew.page.ts index 4b291ebb..73b55b43 100644 --- a/src/app/brew/brew.page.ts +++ b/src/app/brew/brew.page.ts @@ -58,7 +58,7 @@ export class BrewPage implements OnInit { private readonly changeDetectorRef: ChangeDetectorRef, public uiHelper: UIHelper, public uiBrewHelper: UIBrewHelper, - private readonly uiSettingsStorage: UISettingsStorage, + private readonly uiSettingsStorage: UISettingsStorage ) { this.settings = this.uiSettingsStorage.getSettings(); this.archivedBrewsFilter = this.settings.GET_BREW_FILTER(); @@ -69,7 +69,7 @@ export class BrewPage implements OnInit { this.archivedBrewsFilter = this.settings.brew_filter.ARCHIVED; this.openBrewsFilter = this.settings.brew_filter.OPEN; this.openBrewsCollapsed = this.settings.brew_collapsed.OPEN; - this.archivedBrewsCollapsed = this.settings.brew_collapsed.ARCHIVED; + this.archivedBrewsCollapsed = this.settings.brew_collapsed.ARCHIVED; this.loadBrews(); this.retriggerScroll(); @@ -124,7 +124,7 @@ export class BrewPage implements OnInit { } public isCollapseActive() { - let collapsed: boolean =false; + let collapsed: boolean = false; if (this.brew_segment === 'open') { collapsed = this.openBrewsCollapsed; } else { @@ -218,8 +218,6 @@ export class BrewPage implements OnInit { return instructor.config.uuid; } - - public async showFilter() { let brewFilter: IBrewPageFilter; if (this.brew_segment === 'open') { diff --git a/src/app/preparation/preparation-add-type/preparation-add-type.component.ts b/src/app/preparation/preparation-add-type/preparation-add-type.component.ts index db570736..09385ab7 100644 --- a/src/app/preparation/preparation-add-type/preparation-add-type.component.ts +++ b/src/app/preparation/preparation-add-type/preparation-add-type.component.ts @@ -78,7 +78,11 @@ export class PreparationAddTypeComponent implements OnInit { this.uiToast.showInfoToast('TOAST_PREPARATION_ADDED_SUCCESSFULLY'); } - if (this.data.type === PREPARATION_TYPES.METICULOUS || this.data.type === PREPARATION_TYPES.XENIA || this.data.type === PREPARATION_TYPES.SANREMO_YOU) { + if ( + this.data.type === PREPARATION_TYPES.METICULOUS || + this.data.type === PREPARATION_TYPES.XENIA || + this.data.type === PREPARATION_TYPES.SANREMO_YOU + ) { await this.uiPreparationHelper.connectDevice(newPreparation); } } diff --git a/src/app/preparation/preparation-add/preparation-add.component.ts b/src/app/preparation/preparation-add/preparation-add.component.ts index ada8b095..cd800c9e 100644 --- a/src/app/preparation/preparation-add/preparation-add.component.ts +++ b/src/app/preparation/preparation-add/preparation-add.component.ts @@ -39,7 +39,7 @@ export class PreparationAddComponent implements OnInit { } public individualPreparationVisible(_key) { - if (_key ==='SANREMO_YOU') { + if (_key === 'SANREMO_YOU') { if (this.ENVIRONMENT.FEATURES_ACTIVE.SANREMO_YOU === true) { return true; } diff --git a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts index 8e9d18f1..f6c2ce88 100644 --- a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts +++ b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts @@ -52,18 +52,21 @@ export class PreparationConnectedDeviceComponent { if (this.preparation !== undefined) { this.data.initializeByObject(this.preparation); } - if (this.data.connectedPreparationDevice.type === PreparationDeviceType.NONE) { + if ( + this.data.connectedPreparationDevice.type === PreparationDeviceType.NONE + ) { if (this.data.type === PREPARATION_TYPES.METICULOUS) { - this.data.connectedPreparationDevice.type = PreparationDeviceType.METICULOUS; + this.data.connectedPreparationDevice.type = + PreparationDeviceType.METICULOUS; } if (this.data.type === PREPARATION_TYPES.XENIA) { this.data.connectedPreparationDevice.type = PreparationDeviceType.XENIA; } if (this.data.type === PREPARATION_TYPES.SANREMO_YOU) { - this.data.connectedPreparationDevice.type = PreparationDeviceType.SANREMO_YOU; + this.data.connectedPreparationDevice.type = + PreparationDeviceType.SANREMO_YOU; } } - } public dismiss(): void { @@ -117,15 +120,13 @@ export class PreparationConnectedDeviceComponent { if ( this.data.connectedPreparationDevice.type === PreparationDeviceType.METICULOUS - ) - { + ) { if (this.data.connectedPreparationDevice.url.endsWith('/') === true) { this.data.connectedPreparationDevice.url = this.data.connectedPreparationDevice.url.slice(0, -1); } if ( - this.data.connectedPreparationDevice.url.startsWith('http') === - false + this.data.connectedPreparationDevice.url.startsWith('http') === false ) { this.data.connectedPreparationDevice.url = 'http://' + this.data.connectedPreparationDevice.url; @@ -134,15 +135,13 @@ export class PreparationConnectedDeviceComponent { if ( this.data.connectedPreparationDevice.type === PreparationDeviceType.SANREMO_YOU - ) - { + ) { if (this.data.connectedPreparationDevice.url.endsWith('/') === true) { this.data.connectedPreparationDevice.url = this.data.connectedPreparationDevice.url.slice(0, -1); } if ( - this.data.connectedPreparationDevice.url.startsWith('http') === - false + this.data.connectedPreparationDevice.url.startsWith('http') === false ) { this.data.connectedPreparationDevice.url = 'http://' + this.data.connectedPreparationDevice.url; @@ -185,6 +184,4 @@ export class PreparationConnectedDeviceComponent { } public ngOnInit() {} - - } diff --git a/src/app/settings/settings.page.ts b/src/app/settings/settings.page.ts index c5047fb9..5495aa60 100644 --- a/src/app/settings/settings.page.ts +++ b/src/app/settings/settings.page.ts @@ -1227,7 +1227,7 @@ export class SettingsPage { const allXeniaPreps = []; let allPreparations = this.uiPreparationStorage.getAllEntries(); // Just take 60, else the excel will be exploding. - allPreparations = allPreparations.reverse().slice(0,60); + allPreparations = allPreparations.reverse().slice(0, 60); for (const prep of allPreparations) { if ( prep.connectedPreparationDevice.type === PreparationDeviceType.XENIA @@ -1278,7 +1278,7 @@ export class SettingsPage { } } - public importBeansExcel(_type: string='roasted'): void { + public importBeansExcel(_type: string = 'roasted'): void { if (this.platform.is('cordova')) { this.uiAnalytics.trackEvent( SETTINGS_TRACKING.TITLE, @@ -1295,12 +1295,11 @@ export class SettingsPage { this.uiFileHelper.readFileEntryAsArrayBuffer(fileEntry).then( async (_arrayBuffer) => { - if (_type ==='roasted') { + if (_type === 'roasted') { this.uiExcel.importBeansByExcel(_arrayBuffer); - }else { + } else { this.uiExcel.importGreenBeansByExcel(_arrayBuffer); } - }, () => { // Backup, maybe it was a .JSON? @@ -1326,7 +1325,7 @@ export class SettingsPage { } this.uiFileHelper.readFileAsArrayBuffer(path, file).then( async (_arrayBuffer) => { - if (_type ==='roasted') { + if (_type === 'roasted') { this.uiExcel.importBeansByExcel(_arrayBuffer); } else { this.uiExcel.importGreenBeansByExcel(_arrayBuffer); diff --git a/src/classes/devices/argosThermometer.ts b/src/classes/devices/argosThermometer.ts index 5b04c434..8957aadc 100644 --- a/src/classes/devices/argosThermometer.ts +++ b/src/classes/devices/argosThermometer.ts @@ -23,7 +23,9 @@ export class ArgosThermometer extends TemperatureDevice { return ( device && device.name && - device.name.toLowerCase().startsWith(ArgosThermometer.DEVICE_NAME.toLowerCase()) + device.name + .toLowerCase() + .startsWith(ArgosThermometer.DEVICE_NAME.toLowerCase()) ); } @@ -42,7 +44,7 @@ export class ArgosThermometer extends TemperatureDevice { ArgosThermometer.TEMPERATURE_CHAR_UUID, async (_data: any) => { - let newData = new Uint8Array(_data.slice(0,-1)); + let newData = new Uint8Array(_data.slice(0, -1)); this.parseStatusUpdate(newData); }, @@ -55,8 +57,9 @@ export class ArgosThermometer extends TemperatureDevice { 'temperatureRawStatus received is: ' + temperatureRawStatus ); - const temperature_in_f = temperatureRawStatus[-1] << 8 + temperatureRawStatus[-2]; -console.log("New temperature inc" + temperature_in_f); + const temperature_in_f = + temperatureRawStatus[-1] << (8 + temperatureRawStatus[-2]); + console.log('New temperature inc' + temperature_in_f); this.setTemperature(temperature_in_f, temperatureRawStatus); } diff --git a/src/classes/devices/index.ts b/src/classes/devices/index.ts index c6657b1c..34c3e63b 100644 --- a/src/classes/devices/index.ts +++ b/src/classes/devices/index.ts @@ -57,7 +57,7 @@ export enum TemperatureType { BASICGRILL = 'BASICGRILL', MEATER = 'MEATER', COMBUSTION = 'COMBUSTION', - ARGOS = 'ARGOS' + ARGOS = 'ARGOS', } export enum RefractometerType { diff --git a/src/classes/preparation/preparation.ts b/src/classes/preparation/preparation.ts index d163ddfb..d6d35f76 100755 --- a/src/classes/preparation/preparation.ts +++ b/src/classes/preparation/preparation.ts @@ -311,10 +311,6 @@ export class Preparation implements IPreparation { return this.attachments && this.attachments.length > 0; } public hasDeviceConnection(): boolean { - return ( - this.connectedPreparationDevice?.type !== - PreparationDeviceType.NONE - ); + return this.connectedPreparationDevice?.type !== PreparationDeviceType.NONE; } - } diff --git a/src/classes/preparationDevice/meticulous/meticulousDevice.ts b/src/classes/preparationDevice/meticulous/meticulousDevice.ts index 5dae48b3..25a0daf6 100644 --- a/src/classes/preparationDevice/meticulous/meticulousDevice.ts +++ b/src/classes/preparationDevice/meticulous/meticulousDevice.ts @@ -10,7 +10,13 @@ import { catchError, timeout } from 'rxjs/operators'; import { of } from 'rxjs'; import { HistoryListingEntry } from '@meticulous-home/espresso-api/dist/types'; import moment from 'moment'; -import { BrewFlow, IBrewPressureFlow, IBrewRealtimeWaterFlow, IBrewTemperatureFlow, IBrewWeightFlow } from '../../brew/brewFlow'; +import { + BrewFlow, + IBrewPressureFlow, + IBrewRealtimeWaterFlow, + IBrewTemperatureFlow, + IBrewWeightFlow, +} from '../../brew/brewFlow'; declare var cordova; declare var io; @@ -23,7 +29,6 @@ export class MeticulousDevice extends PreparationDevice { private _profiles: Array = []; - private serverURL: string = ''; public static returnBrewFlowForShotData(_shotData) { @@ -141,7 +146,7 @@ export class MeticulousDevice extends PreparationDevice { const profile = profileResponse.data as unknown as Profile; return profile; - /* if (profileResponse instanceof Profile) { + /* if (profileResponse instanceof Profile) { } else { }*/ @@ -150,16 +155,12 @@ export class MeticulousDevice extends PreparationDevice { } public async getHistoryShortListing() { - const response = await this.metApi.getHistoryShortListing(); - if (response && response.data && response.data.history) - { - return response.data.history as Array; + if (response && response.data && response.data.history) { + return response.data.history as Array; } } - - public async searchHistory() { const response = await this.metApi.searchHistory({ query: '', @@ -167,12 +168,11 @@ export class MeticulousDevice extends PreparationDevice { start_date: '', end_date: '', order_by: ['date'], - sort: 'desc', + sort: 'desc', max_results: 10, - dump_data: true - } ); - if (response && response.data && response.data.history) - { + dump_data: true, + }); + if (response && response.data && response.data.history) { return response.data.history as Array; } } @@ -182,7 +182,6 @@ export class MeticulousDevice extends PreparationDevice { const loadProfile = await this.metApi.loadProfileByID(_profileId); const profile = loadProfile.data as unknown as Profile; return profile; - } catch (ex) { console.log(ex.message); } @@ -208,7 +207,6 @@ export class MeticulousDevice extends PreparationDevice { if (this._profiles.length <= 0) { const profiles = await this.metApi.listProfiles(); this._profiles = profiles.data as Array; - } } catch (ex) {} } @@ -218,7 +216,7 @@ export class MeticulousDevice extends PreparationDevice { } public override async deviceConnected(): Promise { - const promise = new Promise(async(resolve, reject) => { + const promise = new Promise(async (resolve, reject) => { const settings: any = await this.metApi.getSettings(); if (settings?.data?.config) { resolve(true); diff --git a/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts b/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts index d110aa9d..c36b1dad 100644 --- a/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts +++ b/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts @@ -7,12 +7,11 @@ declare var cordova; export class SanremoYOUDevice extends PreparationDevice { public scriptList: Array<{ INDEX: number; TITLE: string }> = []; - - private connectionURL: string =''; + private connectionURL: string = ''; constructor(protected httpClient: HttpClient, _preparation: Preparation) { super(httpClient, _preparation); - this.connectionURL =this.getPreparation().connectedPreparationDevice.url; + this.connectionURL = this.getPreparation().connectedPreparationDevice.url; } public async deviceConnected(): Promise { @@ -104,7 +103,7 @@ export class SanremoYOUDevice extends PreparationDevice { /**{"status":1,"description":"ON","statusPhase":0,"alarms":0,"warnings":2,"tempBoilerCoffe":82.1,"tempBolierServices":100.2,"pumpServicesPress":0.2,"pumpPress":0.0,"counterVol":0,"realtimeFlow":0,"setPressPaddle":0.0}**/ const parsedJSON = JSON.parse(response.data); const temp = parsedJSON.tempBoilerCoffe; - const press = parsedJSON.pumpPress*10; + const press = parsedJSON.pumpPress * 10; this.temperature = temp; this.pressure = press; @@ -119,9 +118,6 @@ export class SanremoYOUDevice extends PreparationDevice { ); } - - - public startShot() { const promise = new Promise((resolve, reject) => { const options = { diff --git a/src/classes/settings/settings.ts b/src/classes/settings/settings.ts index 6ff1711d..a247d49f 100755 --- a/src/classes/settings/settings.ts +++ b/src/classes/settings/settings.ts @@ -98,7 +98,6 @@ export class Settings implements ISettings { ARCHIVED: boolean; }; - public green_bean_sort: { OPEN: IBeanPageSort; ARCHIVED: IBeanPageSort; diff --git a/src/components/brew-information/brew-information.component.ts b/src/components/brew-information/brew-information.component.ts index 28d1a2b5..ea234ce8 100644 --- a/src/components/brew-information/brew-information.component.ts +++ b/src/components/brew-information/brew-information.component.ts @@ -34,7 +34,6 @@ import { BrewTrackingService } from '../../services/brewTracking/brew-tracking.s import { UIHealthKit } from '../../services/uiHealthKit'; import * as htmlToImage from 'html-to-image'; - import { UIFileHelper } from '../../services/uiFileHelper'; import { BrewFlow } from '../../classes/brew/brewFlow'; import { UIBeanStorage } from '../../services/uiBeanStorage'; diff --git a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts index d1800295..3f54feab 100644 --- a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts +++ b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts @@ -8,15 +8,19 @@ import { NgZone, OnInit, Output, - ViewChild + ViewChild, } from '@angular/core'; import { PREPARATION_STYLE_TYPE } from '../../../enums/preparations/preparationStyleTypes'; import { PreparationDeviceType } from '../../../classes/preparationDevice'; -import { BluetoothScale, SCALE_TIMER_COMMAND, ScaleType } from '../../../classes/devices'; +import { + BluetoothScale, + SCALE_TIMER_COMMAND, + ScaleType, +} from '../../../classes/devices'; import { ModalController, Platform } from '@ionic/angular'; import { CoffeeBluetoothDevicesService, - CoffeeBluetoothServiceEvent + CoffeeBluetoothServiceEvent, } from '../../../services/coffeeBluetoothDevices/coffee-bluetooth-devices.service'; import { TemperatureDevice } from '../../../classes/devices/temperatureBluetoothDevice'; import { PressureDevice } from '../../../classes/devices/pressureBluetoothDevice'; @@ -29,7 +33,7 @@ import { IBrewRealtimeWaterFlow, IBrewTemperatureFlow, IBrewWaterFlow, - IBrewWeightFlow + IBrewWeightFlow, } from '../../../classes/brew/brewFlow'; import { Preparation } from '../../../classes/preparation/preparation'; import { UIPreparationStorage } from '../../../services/uiPreparationStorage'; @@ -65,7 +69,7 @@ declare var Plotly; @Component({ selector: 'brew-brewing-graph', templateUrl: './brew-brewing-graph.component.html', - styleUrls: ['./brew-brewing-graph.component.scss'] + styleUrls: ['./brew-brewing-graph.component.scss'], }) export class BrewBrewingGraphComponent implements OnInit { @ViewChild('smartScaleWeight', { read: ElementRef }) @@ -171,8 +175,7 @@ export class BrewBrewingGraphComponent implements OnInit { public readonly uiBrewHelper: UIBrewHelper, private readonly uiGraphStorage: UIGraphStorage, private readonly textToSpeech: TextToSpeechService - ) { - } + ) {} public ngOnInit() { this.settings = this.uiSettingsStorage.getSettings(); @@ -205,7 +208,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.pressureDeviceConnected() && this.data.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO + PREPARATION_STYLE_TYPE.ESPRESSO ) { await this.__connectPressureDevice(true); isSomethingConnected = true; @@ -217,7 +220,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + PreparationDeviceType.METICULOUS ) { isSomethingConnected = true; } @@ -360,7 +363,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.temperatureDeviceConnected() === true || (this.pressureDeviceConnected() === true && this.data.getPreparation()?.style_type === - PREPARATION_STYLE_TYPE.ESPRESSO) || + PREPARATION_STYLE_TYPE.ESPRESSO) || this.brewComponent?.brewBrewingPreparationDeviceEl ?.preparationDevice !== undefined ) { @@ -393,8 +396,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.bleManager.getPressureDevice(); try { pressureDevice.updateZero(); - } catch (ex) { - } + } catch (ex) {} } } @@ -402,7 +404,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + PreparationDeviceType.METICULOUS ) { return 3; } @@ -494,8 +496,7 @@ export class BrewBrewingGraphComponent implements OnInit { setTimeout(() => { try { Plotly.purge(this.profileDiv.nativeElement); - } catch (ex) { - } + } catch (ex) {} this.graphSettings = this.uiHelper.cloneData(this.settings.graph.FILTER); if ( this.data.getPreparation().style_type === @@ -528,11 +529,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#ebe6dd', - width: 2 + width: 2, }, visible: this.graphSettings.weight, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; this.flowPerSecondTraceReference = { x: [], @@ -544,11 +545,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#cbd5d9', - width: 2 + width: 2, }, visible: this.graphSettings.calc_flow, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; this.realtimeFlowTraceReference = { @@ -561,11 +562,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#9cb5be', - width: 2 + width: 2, }, visible: this.graphSettings.realtime_flow, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; this.pressureTraceReference = { @@ -578,11 +579,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#9be8d3', - width: 2 + width: 2, }, visible: this.graphSettings.pressure, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; this.temperatureTraceReference = { @@ -595,11 +596,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#eaad9f', - width: 2 + width: 2, }, visible: this.graphSettings.temperature, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; const presetFlowProfile = this.reference_profile_raw; @@ -631,7 +632,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.weightTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.weightTraceReference.y.push(data.actual_weight); @@ -640,7 +641,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.flowPerSecondTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.flowPerSecondTraceReference.y.push(data.value); @@ -650,7 +651,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.realtimeFlowTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.realtimeFlowTraceReference.y.push(data.flow_value); @@ -666,7 +667,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.pressureTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.pressureTraceReference.y.push(data.actual_pressure); @@ -681,7 +682,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.temperatureTraceReference.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.temperatureTraceReference.y.push(data.actual_temperature); @@ -700,11 +701,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#cdc2ac', - width: 2 + width: 2, }, visible: this.graphSettings.weight, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; this.flowPerSecondTrace = { x: [], @@ -716,11 +717,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#7F97A2', - width: 2 + width: 2, }, visible: this.graphSettings.calc_flow, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; this.realtimeFlowTrace = { @@ -733,11 +734,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#09485D', - width: 2 + width: 2, }, visible: this.graphSettings.realtime_flow, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; this.pressureTrace = { @@ -750,11 +751,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#05C793', - width: 2 + width: 2, }, visible: this.graphSettings.pressure, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; this.temperatureTrace = { @@ -767,11 +768,11 @@ export class BrewBrewingGraphComponent implements OnInit { line: { shape: 'linear', color: '#CC3311', - width: 2 + width: 2, }, visible: this.graphSettings.temperature, hoverinfo: this.isDetail ? 'all' : 'skip', - showlegend: false + showlegend: false, }; if ( @@ -798,7 +799,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.weightTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.weightTrace.y.push(data.actual_weight); @@ -807,7 +808,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.flowPerSecondTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.flowPerSecondTrace.y.push(data.value); @@ -817,7 +818,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.realtimeFlowTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.realtimeFlowTrace.y.push(data.flow_value); @@ -832,7 +833,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.pressureTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.pressureTrace.y.push(data.actual_pressure); @@ -846,7 +847,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.temperatureTrace.x.push( new Date( moment(data.timestamp, 'HH:mm:ss.SSS').toDate().getTime() - - delay + delay ) ); this.temperatureTrace.y.push(data.actual_temperature); @@ -889,8 +890,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.updateChart(); } }, 250); - } catch (ex) { - } + } catch (ex) {} }, timeout); } @@ -911,8 +911,7 @@ export class BrewBrewingGraphComponent implements OnInit { weightEl.textContent = this.data.brew_quantity + ' g'; } } - } catch (ex) { - } + } catch (ex) {} }, 350); } @@ -920,8 +919,7 @@ export class BrewBrewingGraphComponent implements OnInit { let chartWidth: number = 300; try { chartWidth = this.canvaContainer.nativeElement.offsetWidth; - } catch (ex) { - } + } catch (ex) {} const chartHeight: number = 150; const tickFormat = '%M:%S'; @@ -990,7 +988,7 @@ export class BrewBrewingGraphComponent implements OnInit { r: 20, b: 20, t: 20, - pad: 2 + pad: 2, }, showlegend: false, dragmode: false, @@ -1004,7 +1002,7 @@ export class BrewBrewingGraphComponent implements OnInit { domain: [0, 1], fixedrange: true, type: 'date', - range: [startRange, endRange] + range: [startRange, endRange], }, yaxis: { title: '', @@ -1014,7 +1012,7 @@ export class BrewBrewingGraphComponent implements OnInit { side: 'left', position: 0.03, rangemode: 'nonnegative', - range: [suggestedMinWeight, suggestedMaxWeight] + range: [suggestedMinWeight, suggestedMaxWeight], }, yaxis2: { title: '', @@ -1027,14 +1025,14 @@ export class BrewBrewingGraphComponent implements OnInit { position: 0.97, fixedrange: true, rangemode: 'nonnegative', - range: [suggestedMinFlow, suggestedMaxFlow] - } + range: [suggestedMinFlow, suggestedMaxFlow], + }, }; const pressureDevice = this.bleManager.getPressureDevice(); if ( (pressureDevice != null && this.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO) || + PREPARATION_STYLE_TYPE.ESPRESSO) || this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() || !this.platform.is('cordova') ) { @@ -1048,7 +1046,7 @@ export class BrewBrewingGraphComponent implements OnInit { showgrid: false, position: 0.91, fixedrange: true, - range: [0, 10] + range: [0, 10], }; } const temperatureDevice = this.bleManager.getTemperatureDevice(); @@ -1068,7 +1066,7 @@ export class BrewBrewingGraphComponent implements OnInit { position: 0.8, fixedrange: true, visible: false, - range: [0, 100] + range: [0, 100], }; } } else { @@ -1080,14 +1078,14 @@ export class BrewBrewingGraphComponent implements OnInit { r: 20, b: 20, t: 20, - pad: 2 + pad: 2, }, showlegend: false, xaxis: { tickformat: tickFormat, visible: true, domain: [0, 1], - type: 'date' + type: 'date', }, yaxis: { title: '', @@ -1095,7 +1093,7 @@ export class BrewBrewingGraphComponent implements OnInit { tickfont: { color: '#cdc2ac' }, side: 'left', position: 0.05, - visible: true + visible: true, }, yaxis2: { title: '', @@ -1106,8 +1104,8 @@ export class BrewBrewingGraphComponent implements OnInit { side: 'right', position: 0.95, showgrid: false, - visible: true - } + visible: true, + }, }; layout['yaxis4'] = { @@ -1120,7 +1118,7 @@ export class BrewBrewingGraphComponent implements OnInit { showgrid: false, position: 0.93, range: [0, 12], - visible: true + visible: true, }; layout['yaxis5'] = { @@ -1134,7 +1132,7 @@ export class BrewBrewingGraphComponent implements OnInit { position: 0.8, fixedrange: true, range: [0, 100], - visible: true + visible: true, }; if (this.weightTrace.x && this.weightTrace.x.length > 0) { @@ -1164,14 +1162,14 @@ export class BrewBrewingGraphComponent implements OnInit { if (this.isDetail === true) { const config = { displayModeBar: false, // this is the line that hides the bar. - responsive: true + responsive: true, }; return config; } else { const config = { responsive: false, scrollZoom: false, - displayModeBar: false // this is the line that hides the bar. + displayModeBar: false, // this is the line that hides the bar. }; return config; } @@ -1255,8 +1253,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.brewComponent.timer.reset(); this.checkChanges(); }, - () => { - } + () => {} ); break; @@ -1338,8 +1335,8 @@ export class BrewBrewingGraphComponent implements OnInit { try { return this.uiHelper.toFixedIfNecessary( this.flow_profile_raw.realtimeFlow[ - this.flow_profile_raw.realtimeFlow.length - 1 - ].flow_value, + this.flow_profile_raw.realtimeFlow.length - 1 + ].flow_value, 2 ); } catch (ex) { @@ -1351,7 +1348,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.ngZone.runOutsideAngular(() => { if (this.brewComponent.maximizeFlowGraphIsShown === true) { this.brewComponent.brewTemperatureGraphSubject.next({ - temperature: _temperature + temperature: _temperature, }); } @@ -1359,8 +1356,7 @@ export class BrewBrewingGraphComponent implements OnInit { const temperatureEl = this.temperatureEl.nativeElement; temperatureEl.textContent = _temperature; - } catch (ex) { - } + } catch (ex) {} }); } @@ -1368,7 +1364,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.ngZone.runOutsideAngular(() => { if (this.brewComponent.maximizeFlowGraphIsShown === true) { this.brewComponent.brewPressureGraphSubject.next({ - pressure: _pressure + pressure: _pressure, }); } @@ -1376,8 +1372,7 @@ export class BrewBrewingGraphComponent implements OnInit { const pressureEl = this.pressureEl.nativeElement; pressureEl.textContent = _pressure; - } catch (ex) { - } + } catch (ex) {} }); } @@ -1406,7 +1401,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.brewComponent.brewFlowGraphSubject.next({ scaleWeight: actualScaleWeight, smoothedWeight: actualSmoothedWeightPerSecond, - avgFlow: avgFlow + avgFlow: avgFlow, }); } @@ -1418,8 +1413,7 @@ export class BrewBrewingGraphComponent implements OnInit { weightEl.textContent = actualScaleWeight + ' g'; flowEl.textContent = actualSmoothedWeightPerSecond + ' g/s'; avgFlowEl.textContent = 'Ø ' + avgFlow + ' g/s'; - } catch (ex) { - } + } catch (ex) {} }); } @@ -1455,7 +1449,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.profileDiv.nativeElement, { x: xData, - y: yData + y: yData, }, tracesData ); @@ -1607,8 +1601,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.lastChartLayout.xaxis.range = [delay, delayedTime]; Plotly.relayout(this.profileDiv.nativeElement, this.lastChartLayout); } - } catch (ex) { - } + } catch (ex) {} }); } @@ -1696,7 +1689,7 @@ export class BrewBrewingGraphComponent implements OnInit { temperatureDevice || (pressureDevice && this.data.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO) + PREPARATION_STYLE_TYPE.ESPRESSO) ) { this.initializeFlowChart(false); } @@ -1760,7 +1753,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA && + PreparationDeviceType.XENIA && this.machineStopScriptWasTriggered === false ) { this.machineStopScriptWasTriggered = true; @@ -1788,8 +1781,9 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.SANREMO_YOU && - _event !== 'sanremo_you' && this.machineStopScriptWasTriggered === false + PreparationDeviceType.SANREMO_YOU && + _event !== 'sanremo_you' && + this.machineStopScriptWasTriggered === false ) { this.machineStopScriptWasTriggered = true; this.uiLog.log(`Sanremo YOU - Pause button pressed, stop shot`); @@ -1808,7 +1802,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS && + PreparationDeviceType.METICULOUS && _event !== 'meticulous' ) { this.stopFetchingDataFromMeticulous(); @@ -1880,10 +1874,8 @@ export class BrewBrewingGraphComponent implements OnInit { //before we start the interval, we fetch the data once to overwrite, and set them. setSanremoData(); }); - } catch (ex) { - } + } catch (ex) {} }, 100); - } public startFetchingDataFromMeticulous() { @@ -1941,18 +1933,18 @@ export class BrewBrewingGraphComponent implements OnInit { if (hasShotStarted) { this.__setPressureFlow({ actual: shotData.pressure, - old: shotData.pressure + old: shotData.pressure, }); this.__setTemperatureFlow({ actual: shotData.temperature, - old: shotData.temperature + old: shotData.temperature, }); this.__setFlowProfile({ actual: shotData.weight, old: shotData.oldWeight, smoothed: shotData.smoothedWeight, - oldSmoothed: shotData.oldSmoothedWeight + oldSmoothed: shotData.oldSmoothedWeight, }); //this.__setMachineWeightFlow({ actual: shotData.weight, old: shotData.weight,smoothed:100,oldSmoothed:100 }); @@ -1999,8 +1991,7 @@ export class BrewBrewingGraphComponent implements OnInit { 2 ); } - } catch (ex) { - } + } catch (ex) {} }); }, 100); @@ -2011,8 +2002,7 @@ export class BrewBrewingGraphComponent implements OnInit { //before we start the interval, we fetch the data once to overwrite, and set them. setTempAndPressure(); }); - } catch (ex) { - } + } catch (ex) {} }, 500); } @@ -2150,7 +2140,7 @@ export class BrewBrewingGraphComponent implements OnInit { actual: weight, old: 1, smoothed: 1, - oldSmoothed: 1 + oldSmoothed: 1, }); this.setActualSmartInformation(); }, 100); @@ -2170,7 +2160,7 @@ export class BrewBrewingGraphComponent implements OnInit { } else { if ( this.data.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO && + PREPARATION_STYLE_TYPE.ESPRESSO && pressureDevice ) { this.brewComponent.maximizeFlowGraph(); @@ -2232,7 +2222,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA + PreparationDeviceType.XENIA ) { if (this.data.preparationDeviceBrew.params.scriptStartId > 0) { this.uiLog.log(`Xenia Script - Script start - Trigger script`); @@ -2253,7 +2243,7 @@ export class BrewBrewingGraphComponent implements OnInit { (_jsonResp: any) => { this.uiLog.log( 'Check of xenia answer if script started MA_STATUS: ' + - _jsonResp.MA_Status + _jsonResp.MA_Status ); if (_jsonResp.MA_STATUS === 3) { //Great we started. @@ -2292,7 +2282,7 @@ export class BrewBrewingGraphComponent implements OnInit { } else if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + PreparationDeviceType.METICULOUS ) { const prepDeviceCall: MeticulousDevice = this.brewComponent .brewBrewingPreparationDeviceEl.preparationDevice as MeticulousDevice; @@ -2319,15 +2309,14 @@ export class BrewBrewingGraphComponent implements OnInit { } this.startFetchingDataFromMeticulous(); - } else if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.SANREMO_YOU + PreparationDeviceType.SANREMO_YOU ) { const prepDeviceCall: SanremoYOUDevice = this.brewComponent .brewBrewingPreparationDeviceEl.preparationDevice as SanremoYOUDevice; - prepDeviceCall.startShot() .catch((_msg) => { + prepDeviceCall.startShot().catch((_msg) => { this.uiLog.log('We could not start shot on sanremo: ' + _msg); this.uiToast.showInfoToast( 'We could not start shot on sanremo: ' + _msg, @@ -2343,7 +2332,6 @@ export class BrewBrewingGraphComponent implements OnInit { } this.startFetchingDataFromSanremoYOU(); - } } @@ -2539,8 +2527,8 @@ export class BrewBrewingGraphComponent implements OnInit { this.ngZone.runOutsideAngular(() => { this.textToSpeech.speak( this.translate.instant('TEXT_TO_SPEECH.TIME') + - ' ' + - this.data.brew_time + ' ' + + this.data.brew_time ); }); }, 5000); @@ -2585,8 +2573,7 @@ export class BrewBrewingGraphComponent implements OnInit { if (scale) { scale.tare(); } - } catch (ex) { - } + } catch (ex) {} } this.brewComponent.timerStartPressed('AUTO_START_PRESSURE'); @@ -2638,8 +2625,7 @@ export class BrewBrewingGraphComponent implements OnInit { }, this.settings.bluetooth_command_delay); }); } - } catch (ex) { - } + } catch (ex) {} } this.brewComponent.timerStartPressed('AUTO_START_TEMPERATURE'); @@ -2779,12 +2765,17 @@ export class BrewBrewingGraphComponent implements OnInit { old: oldWeight, smoothed: smoothedWeight, oldSmoothed: oldSmoothedWeight, - notMutatedWeight: notMutatedWeight + notMutatedWeight: notMutatedWeight, }; } - - private calculateBrewByWeight(_currentWeightValue: number, _residualLagTime: number, _targetWeight: number, _brewByWeightActive: boolean, _scale: BluetoothScale) { + private calculateBrewByWeight( + _currentWeightValue: number, + _residualLagTime: number, + _targetWeight: number, + _brewByWeightActive: boolean, + _scale: BluetoothScale + ) { let weight: number = this.uiHelper.toFixedIfNecessary( _currentWeightValue, 1 @@ -2793,10 +2784,7 @@ export class BrewBrewingGraphComponent implements OnInit { if (this.flowProfileTempAll.length > 0) { const oldFlowProfileTemp = this.flowProfileTempAll[this.flowProfileTempAll.length - 1]; - weight = this.uiHelper.toFixedIfNecessary( - oldFlowProfileTemp.weight, - 1 - ); + weight = this.uiHelper.toFixedIfNecessary(oldFlowProfileTemp.weight, 1); } } @@ -2804,12 +2792,10 @@ export class BrewBrewingGraphComponent implements OnInit { this.flow_profile_raw.realtimeFlow && this.flow_profile_raw.realtimeFlow.length > 0 ) { - const targetWeight = _targetWeight; const brewByWeightActive: boolean = _brewByWeightActive; - let n = 3; if (this.flowNCalculation > 0) { n = this.flowNCalculation; @@ -2818,7 +2804,6 @@ export class BrewBrewingGraphComponent implements OnInit { } const lag_time = this.uiHelper.toFixedIfNecessary(1 / n, 2); - let average_flow_rate = 0; let lastFlowValue = 0; @@ -2848,7 +2833,7 @@ export class BrewBrewingGraphComponent implements OnInit { weight, lag_time + _residualLagTime, weight + average_flow_rate * (lag_time + _residualLagTime) >= - targetWeight, + targetWeight, average_flow_rate * (lag_time + _residualLagTime), _residualLagTime, average_flow_rate, @@ -2857,8 +2842,7 @@ export class BrewBrewingGraphComponent implements OnInit { let thresholdHit: boolean = false; if (brewByWeightActive) { thresholdHit = - weight + - average_flow_rate * (lag_time + _residualLagTime) >= + weight + average_flow_rate * (lag_time + _residualLagTime) >= targetWeight; } else { thresholdHit = weight >= targetWeight; @@ -2870,50 +2854,37 @@ export class BrewBrewingGraphComponent implements OnInit { private triggerStopShotOnXenia(_actualScaleWeight) { const prepDeviceCall: XeniaDevice = this.brewComponent - .brewBrewingPreparationDeviceEl - .preparationDevice as XeniaDevice; - if ( - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedId > 0 - ) { + .brewBrewingPreparationDeviceEl.preparationDevice as XeniaDevice; + if (this.data.preparationDeviceBrew.params.scriptAtWeightReachedId > 0) { this.uiLog.log( `Xenia Script - Weight Reached: ${_actualScaleWeight} - Trigger custom script` ); prepDeviceCall .startScript( - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedId + this.data.preparationDeviceBrew.params.scriptAtWeightReachedId ) .catch((_msg) => { this.uiToast.showInfoToast( 'We could not start script at weight: ' + _msg, false ); - this.uiLog.log( - 'We could not start script at weight: ' + _msg - ); + this.uiLog.log('We could not start script at weight: ' + _msg); }); this.writeExecutionTimeToNotes( 'Weight reached script', - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedId, + this.data.preparationDeviceBrew.params.scriptAtWeightReachedId, this.getScriptName( - this.data.preparationDeviceBrew.params - .scriptAtWeightReachedId + this.data.preparationDeviceBrew.params.scriptAtWeightReachedId ) ); } else { - this.uiLog.log( - `Xenia Script - Weight Reached - Trigger stop script` - ); + this.uiLog.log(`Xenia Script - Weight Reached - Trigger stop script`); prepDeviceCall.stopScript().catch((_msg) => { this.uiToast.showInfoToast( 'We could not stop script at weight: ' + _msg, false ); - this.uiLog.log( - 'We could not stop script at weight: ' + _msg - ); + this.uiLog.log('We could not stop script at weight: ' + _msg); }); this.writeExecutionTimeToNotes( 'Stop script (Weight reached)', @@ -2926,9 +2897,7 @@ export class BrewBrewingGraphComponent implements OnInit { // This will be just called once, we stopped the shot and now we check if we directly shall stop or not if ( - this.settings - .bluetooth_scale_espresso_stop_on_no_weight_change === - false + this.settings.bluetooth_scale_espresso_stop_on_no_weight_change === false ) { this.stopFetchingAndSettingDataFromXenia(); this.brewComponent.timer.pauseTimer('xenia'); @@ -2939,31 +2908,17 @@ export class BrewBrewingGraphComponent implements OnInit { private triggerStopShotOnSanremoYOU(_actualScaleWeight) { const prepDeviceCall: SanremoYOUDevice = this.brewComponent - .brewBrewingPreparationDeviceEl - .preparationDevice as SanremoYOUDevice; - - this.uiLog.log( - `Sanremo YOU Stop: ${_actualScaleWeight}` - ); - prepDeviceCall - .stopShot( + .brewBrewingPreparationDeviceEl.preparationDevice as SanremoYOUDevice; - ) - .catch((_msg) => { - this.uiToast.showInfoToast( - 'We could not stop at weight: ' + _msg, - false - ); - this.uiLog.log( - 'We could not start script at weight: ' + _msg - ); - }); + this.uiLog.log(`Sanremo YOU Stop: ${_actualScaleWeight}`); + prepDeviceCall.stopShot().catch((_msg) => { + this.uiToast.showInfoToast('We could not stop at weight: ' + _msg, false); + this.uiLog.log('We could not start script at weight: ' + _msg); + }); // This will be just called once, we stopped the shot and now we check if we directly shall stop or not if ( - this.settings - .bluetooth_scale_espresso_stop_on_no_weight_change === - false + this.settings.bluetooth_scale_espresso_stop_on_no_weight_change === false ) { this.stopFetchingDataFromSanremoYOU(); this.brewComponent.timer.pauseTimer('sanremo_you'); @@ -2972,7 +2927,6 @@ export class BrewBrewingGraphComponent implements OnInit { } } - public attachToScaleWeightChange() { const scale: BluetoothScale = this.bleManager.getScale(); const preparationStyleType = this.data.getPreparation().style_type; @@ -2986,24 +2940,26 @@ export class BrewBrewingGraphComponent implements OnInit { this.machineStopScriptWasTriggered = false; - const prepDeviceConnected = this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected(); + const prepDeviceConnected = + this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected(); let residual_lag_time = 1.35; let targetWeight = 0; let brewByWeightActive: boolean = false; let preparationDeviceType: PreparationDeviceType; if (prepDeviceConnected) { - preparationDeviceType = this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType(); + preparationDeviceType = + this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType(); switch (preparationDeviceType) { case PreparationDeviceType.XENIA: - const prepXeniaDeviceCall: XeniaDevice = this.brewComponent - .brewBrewingPreparationDeviceEl - .preparationDevice as XeniaDevice; + .brewBrewingPreparationDeviceEl.preparationDevice as XeniaDevice; residual_lag_time = prepXeniaDeviceCall.getResidualLagTime(); - targetWeight = this.data.preparationDeviceBrew.params - .scriptAtWeightReachedNumber; - brewByWeightActive = this.data.preparationDeviceBrew?.params?.brew_by_weight_active; + targetWeight = + this.data.preparationDeviceBrew.params + .scriptAtWeightReachedNumber; + brewByWeightActive = + this.data.preparationDeviceBrew?.params?.brew_by_weight_active; break; case PreparationDeviceType.SANREMO_YOU: const prepSanremoDeviceCall: SanremoYOUDevice = this.brewComponent @@ -3013,11 +2969,9 @@ export class BrewBrewingGraphComponent implements OnInit { targetWeight = this.data.preparationDeviceBrew.params.stopAtWeight; brewByWeightActive = true; break; - } } - this.scaleFlowSubscription = scale.flowChange.subscribe((_valChange) => { let _val; if (this.ignoreScaleWeight === false) { @@ -3031,10 +2985,20 @@ export class BrewBrewingGraphComponent implements OnInit { } if (this.brewComponent.timer.isTimerRunning() && prepDeviceConnected) { - - if (preparationDeviceType === PreparationDeviceType.XENIA && this.data.preparationDeviceBrew.params.scriptAtWeightReachedNumber > 0 && this.isFirstXeniaScriptSet()) { + if ( + preparationDeviceType === PreparationDeviceType.XENIA && + this.data.preparationDeviceBrew.params.scriptAtWeightReachedNumber > + 0 && + this.isFirstXeniaScriptSet() + ) { /**We call this function before the if, because we still log the data**/ - const thresholdHit = this.calculateBrewByWeight(_val.actual, residual_lag_time, targetWeight, brewByWeightActive, scale); + const thresholdHit = this.calculateBrewByWeight( + _val.actual, + residual_lag_time, + targetWeight, + brewByWeightActive, + scale + ); if (this.machineStopScriptWasTriggered === false) { if (thresholdHit) { @@ -3042,11 +3006,18 @@ export class BrewBrewingGraphComponent implements OnInit { this.triggerStopShotOnXenia(_val.actual); } } - } else if (this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === - PreparationDeviceType.SANREMO_YOU) { - + } else if ( + this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === + PreparationDeviceType.SANREMO_YOU + ) { /**We call this function before the if, because we still log the data**/ - const thresholdHit = this.calculateBrewByWeight(_val.actual, residual_lag_time, targetWeight, brewByWeightActive, scale); + const thresholdHit = this.calculateBrewByWeight( + _val.actual, + residual_lag_time, + targetWeight, + brewByWeightActive, + scale + ); if (this.machineStopScriptWasTriggered === false) { if (thresholdHit) { this.machineStopScriptWasTriggered = true; @@ -3054,7 +3025,6 @@ export class BrewBrewingGraphComponent implements OnInit { } } } - } if (this.ignoreScaleWeight === false) { this.__setFlowProfile(_val); @@ -3067,7 +3037,7 @@ export class BrewBrewingGraphComponent implements OnInit { old: oldFlowProfileTemp.oldWeight, smoothed: oldFlowProfileTemp.smoothedWeight, oldSmoothed: oldFlowProfileTemp.oldSmoothedWeight, - notMutatedWeight: _val.notMutatedWeight + notMutatedWeight: _val.notMutatedWeight, }; this.__setFlowProfile(passVal); } @@ -3114,8 +3084,7 @@ export class BrewBrewingGraphComponent implements OnInit { _flowProfile ); resolve(jsonParsed); - } catch (ex) { - } + } catch (ex) {} } } else { resolve(BeanconquerorFlowTestDataDummySecondDummy); @@ -3130,8 +3099,7 @@ export class BrewBrewingGraphComponent implements OnInit { try { const jsonParsed = await this.uiFileHelper.getJSONFile(flowProfilePath); this.flow_profile_raw = jsonParsed; - } catch (ex) { - } + } catch (ex) {} } private async deleteFlowProfile() { @@ -3141,8 +3109,7 @@ export class BrewBrewingGraphComponent implements OnInit { 'brews/' + this.data.config.uuid + '_flow_profile.json'; await this.uiFileHelper.deleteFile(flowProfilePath); } - } catch (ex) { - } + } catch (ex) {} } private __setMachineWaterFlow(_flow: any) { @@ -3163,7 +3130,7 @@ export class BrewBrewingGraphComponent implements OnInit { old: old, flowTime: this.flowTime, flowTimeSecond: this.flowTime + '.' + this.flowSecondTick, - flowTimestamp: this.uiHelper.getActualTimeWithMilliseconds() + flowTimestamp: this.uiHelper.getActualTimeWithMilliseconds(), }; const realtimeWaterFlow: IBrewRealtimeWaterFlow = @@ -3207,7 +3174,7 @@ export class BrewBrewingGraphComponent implements OnInit { actual: actual, old: old, flowTime: this.flowTime, - flowTimeSecond: this.flowTime + '.' + this.flowSecondTick + flowTimeSecond: this.flowTime + '.' + this.flowSecondTick, }; if (!isSmartScaleConnected) { @@ -3260,7 +3227,7 @@ export class BrewBrewingGraphComponent implements OnInit { actual: actual, old: old, flowTime: this.flowTime, - flowTimeSecond: this.flowTime + '.' + this.flowSecondTick + flowTimeSecond: this.flowTime + '.' + this.flowSecondTick, }; if (!isSmartScaleConnected) { @@ -3328,7 +3295,7 @@ export class BrewBrewingGraphComponent implements OnInit { flowTimeSecond: this.flowTime + '.' + this.flowSecondTick, flowTimestamp: this.uiHelper.getActualTimeWithMilliseconds(), dateUnixTime: undefined, - notMutatedWeight: notMutatedWeight + notMutatedWeight: notMutatedWeight, }; flowObj.dateUnixTime = new Date(flowObj.unixTime); @@ -3429,7 +3396,7 @@ export class BrewBrewingGraphComponent implements OnInit { lastVal - firstVal < 0.5 || (this.flowProfileArr.length > 2 && this.flowProfileArr[this.flowProfileArr.length - 2] - firstVal < - 0.5) + 0.5) ) { // Threshold for filter is bigger, 0.5g // Threshshold, weight changes because of strange thing happening. @@ -3593,8 +3560,7 @@ export class BrewBrewingGraphComponent implements OnInit { timeStampDelta = flowObj.unixTime - this.flowProfileTempAll[this.flowProfileTempAll.length - n].unixTime; - } catch (ex) { - } + } catch (ex) {} } realtimeWaterFlow.timestampdelta = timeStampDelta; @@ -3606,8 +3572,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.flowProfileTempAll[this.flowProfileTempAll.length - n] .smoothedWeight) * (1000 / timeStampDelta); - } catch (ex) { - } + } catch (ex) {} if (Number.isNaN(calcFlowValue)) { calcFlowValue = 0; } @@ -3621,7 +3586,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.data.getPreparation().style_type === - PREPARATION_STYLE_TYPE.ESPRESSO && + PREPARATION_STYLE_TYPE.ESPRESSO && flowObj.weight >= this.settings.bluetooth_scale_first_drip_threshold ) { // If the drip timer is showing, we can set the first drip and not doing a reference to the normal weight. @@ -3669,14 +3634,14 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected() && this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === - PreparationDeviceType.XENIA + PreparationDeviceType.XENIA ) { this.stopFetchingAndSettingDataFromXenia(); } if ( this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected() && this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === - PreparationDeviceType.SANREMO_YOU + PreparationDeviceType.SANREMO_YOU ) { this.stopFetchingDataFromSanremoYOU(); } @@ -3686,7 +3651,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent.brewBrewingPreparationDeviceEl.preparationDeviceConnected() && this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === - PreparationDeviceType.METICULOUS + PreparationDeviceType.METICULOUS ) { isMeticulous = true; } @@ -3746,7 +3711,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.settings.bluetooth_scale_espresso_stop_on_no_weight_change === - false || + false || this.weightTrace.y.length < 50 || this.data.brew_time <= 5 ) { @@ -3867,8 +3832,7 @@ export class BrewBrewingGraphComponent implements OnInit { this.lastChartLayout.width = this.canvaContainer.nativeElement.offsetWidth; Plotly.relayout(this.profileDiv.nativeElement, this.lastChartLayout); - } catch (ex) { - } + } catch (ex) {} }, 50); } } @@ -3934,8 +3898,8 @@ export class BrewBrewingGraphComponent implements OnInit { component: BrewChooseGraphReferenceComponent, id: BrewChooseGraphReferenceComponent.COMPONENT_ID, componentProps: { - brew: this.data - } + brew: this.data, + }, }); // will force rerender :D @@ -3973,7 +3937,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA && + PreparationDeviceType.XENIA && this.data.preparationDeviceBrew.params.scriptAtFirstDripId > 0 ) { if (this.isFirstXeniaScriptSet()) { @@ -4009,7 +3973,7 @@ export class BrewBrewingGraphComponent implements OnInit { !this.smartScaleConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA + PreparationDeviceType.XENIA ) { // If scale is not connected but the device, we can now choose that still the script is executed if existing. if (this.isFirstXeniaScriptSet()) { @@ -4026,12 +3990,12 @@ export class BrewBrewingGraphComponent implements OnInit { .catch((_msg) => { this.uiToast.showInfoToast( 'We could not start script at first drip - manual triggered: ' + - _msg, + _msg, false ); this.uiLog.log( 'We could not start script at first drip - manual triggered: ' + - _msg + _msg ); }); this.writeExecutionTimeToNotes( @@ -4050,7 +4014,7 @@ export class BrewBrewingGraphComponent implements OnInit { if ( this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() && this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === - PreparationDeviceType.XENIA + PreparationDeviceType.XENIA ) { if (this.data.preparationDeviceBrew.params.scriptStartId > 0) { return true; diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts index 1b87af23..f84204e2 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts @@ -40,7 +40,10 @@ import { import { BrewModalImportShotMeticulousComponent } from '../../../app/brew/brew-modal-import-shot-meticulous/brew-modal-import-shot-meticulous.component'; import { ModalController } from '@ionic/angular'; import { HistoryListingEntry } from '@meticulous-home/espresso-api/dist/types'; -import { SanremoYOUDevice, SanremoYOUParams } from '../../../classes/preparationDevice/sanremo/sanremoYOUDevice'; +import { + SanremoYOUDevice, + SanremoYOUParams, +} from '../../../classes/preparationDevice/sanremo/sanremoYOUDevice'; @Component({ selector: 'brew-brewing-preparation-device', templateUrl: './brew-brewing-preparation-device.component.html', @@ -51,7 +54,8 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { @Input() public isEdit: boolean = false; @Output() public dataChange = new EventEmitter(); @Input() public brewComponent: BrewBrewingComponent; - public preparationDevice: XeniaDevice | MeticulousDevice | SanremoYOUDevice = undefined; + public preparationDevice: XeniaDevice | MeticulousDevice | SanremoYOUDevice = + undefined; public preparation: Preparation = undefined; public settings: Settings = undefined; @@ -72,8 +76,7 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { private readonly changeDetectorRef: ChangeDetectorRef, private readonly modalController: ModalController, public readonly uiBrewHelper: UIBrewHelper - ) { - } + ) {} public ngOnInit() { this.settings = this.uiSettingsStorage.getSettings(); @@ -109,8 +112,7 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { await this.instanceXeniaPreparationDevice(connectedDevice, _brew); } else if (connectedDevice instanceof MeticulousDevice) { await this.instanceMeticulousPreparationDevice(connectedDevice, _brew); - } - else if (connectedDevice instanceof SanremoYOUDevice) { + } else if (connectedDevice instanceof SanremoYOUDevice) { await this.instanceSanremoYOUPreparationDevice(connectedDevice, _brew); } this.checkChanges(); @@ -305,12 +307,14 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { ) { this.data.preparationDeviceBrew.type = PreparationDeviceType.SANREMO_YOU; this.data.preparationDeviceBrew.params = new SanremoYOUParams(); - await connectedDevice.deviceConnected().then(() => { - this.preparationDevice = connectedDevice as SanremoYOUDevice; - }, () => { - //Not connected - }); - + await connectedDevice.deviceConnected().then( + () => { + this.preparationDevice = connectedDevice as SanremoYOUDevice; + }, + () => { + //Not connected + } + ); } public async importShotFromMeticulous() { @@ -332,7 +336,6 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { } private generateShotFlowProfileFromMeticulousData(_historyData) { - const newMoment = moment(new Date()).startOf('day'); let firstDripTimeSet: boolean = false; @@ -399,7 +402,6 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { this.brewComponent.brewBrewingGraphEl.flow_profile_raw = newBrewFlow; this.brewComponent.brewBrewingGraphEl.initializeFlowChart(true); - } public getPreparationDeviceType() { diff --git a/src/components/graph-display-card/graph-display-card.component.ts b/src/components/graph-display-card/graph-display-card.component.ts index 6651cc52..1eaab91d 100644 --- a/src/components/graph-display-card/graph-display-card.component.ts +++ b/src/components/graph-display-card/graph-display-card.component.ts @@ -63,7 +63,9 @@ export class GraphDisplayCardComponent implements OnInit { } else if (this.flowProfileData) { this.flow_profile_raw = this.uiHelper.cloneData(this.flowProfileData); } else if (this.meticulousHistoryData) { - this.flow_profile_raw = MeticulousDevice.returnBrewFlowForShotData(this.meticulousHistoryData.data); + this.flow_profile_raw = MeticulousDevice.returnBrewFlowForShotData( + this.meticulousHistoryData.data + ); } setTimeout(() => { this.initializeFlowChart(); diff --git a/src/components/photo-add/photo-add.component.ts b/src/components/photo-add/photo-add.component.ts index dcaebba0..ff93088a 100644 --- a/src/components/photo-add/photo-add.component.ts +++ b/src/components/photo-add/photo-add.component.ts @@ -2,10 +2,11 @@ import { Component, ElementRef, EventEmitter, - Input, OnDestroy, + Input, + OnDestroy, OnInit, Output, - ViewChild + ViewChild, } from '@angular/core'; import { UIImage } from '../../services/uiImage'; import { Brew } from '../../classes/brew/brew'; @@ -24,7 +25,7 @@ import { TranslateService } from '@ngx-translate/core'; templateUrl: './photo-add.component.html', styleUrls: ['./photo-add.component.scss'], }) -export class PhotoAddComponent implements OnInit,OnDestroy { +export class PhotoAddComponent implements OnInit, OnDestroy { @Input() public data: Brew | Bean | GreenBean | Mill | Preparation; @Output() public dataChange = new EventEmitter< Brew | Bean | GreenBean | Mill | Preparation @@ -47,9 +48,7 @@ export class PhotoAddComponent implements OnInit,OnDestroy { this.updateSlider(); }, 250); } - public ngOnDestroy() { - - } + public ngOnDestroy() {} public addImage(): void { this.uiImage.showOptionChooser().then((_option) => { if (_option === 'CHOOSE') { diff --git a/src/enums/beans/beanSortAfter.ts b/src/enums/beans/beanSortAfter.ts index abc8786c..5b042736 100755 --- a/src/enums/beans/beanSortAfter.ts +++ b/src/enums/beans/beanSortAfter.ts @@ -5,6 +5,6 @@ export enum BEAN_SORT_AFTER { ROASTING_DATE = 'ROASTING DATE', CREATION_DATE = 'CREATION DATE', PURCHASE_DATE = 'PURCHASE DATE', - RATING ='RATING', - BEAN_AGE ='BEAN AGE' + RATING = 'RATING', + BEAN_AGE = 'BEAN AGE', } diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 63744692..073bb229 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -2,6 +2,6 @@ export const environment = { production: true, API_URL: 'https://backend.beanconqueror.com/', FEATURES_ACTIVE: { - SANREMO_YOU: false - } + SANREMO_YOU: false, + }, }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index af970cf9..0c448127 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -6,8 +6,8 @@ export const environment = { production: false, API_URL: 'https://backend.beanconqueror.com/', FEATURES_ACTIVE: { - SANREMO_YOU: false - } + SANREMO_YOU: false, + }, }; /* diff --git a/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts b/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts index b5ce33ea..a04a7335 100644 --- a/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts +++ b/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts @@ -1,5 +1,4 @@ export interface ISanremoYOUParams { stopAtWeight: number; residualLagTime: number; - } diff --git a/src/popover/data-corruption-found/data-corruption-found.component.spec.ts b/src/popover/data-corruption-found/data-corruption-found.component.spec.ts index 8ffd97dd..6962cefa 100644 --- a/src/popover/data-corruption-found/data-corruption-found.component.spec.ts +++ b/src/popover/data-corruption-found/data-corruption-found.component.spec.ts @@ -9,8 +9,8 @@ describe('DataCorruptionFoundComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - declarations: [ DataCorruptionFoundComponent ], - imports: [IonicModule.forRoot()] + declarations: [DataCorruptionFoundComponent], + imports: [IonicModule.forRoot()], }).compileComponents(); fixture = TestBed.createComponent(DataCorruptionFoundComponent); diff --git a/src/popover/data-corruption-found/data-corruption-found.component.ts b/src/popover/data-corruption-found/data-corruption-found.component.ts index 4c859d78..30fc8e56 100644 --- a/src/popover/data-corruption-found/data-corruption-found.component.ts +++ b/src/popover/data-corruption-found/data-corruption-found.component.ts @@ -1,13 +1,12 @@ import { Component, Input, OnInit } from '@angular/core'; import { ModalController, Platform } from '@ionic/angular'; - @Component({ selector: 'app-data-corruption-found', templateUrl: './data-corruption-found.component.html', styleUrls: ['./data-corruption-found.component.scss'], }) -export class DataCorruptionFoundComponent implements OnInit { +export class DataCorruptionFoundComponent implements OnInit { public static POPOVER_ID: string = 'data-corruption-found-popover'; @Input() public actualUIStorageDataObj: any = undefined; @@ -18,20 +17,16 @@ export class DataCorruptionFoundComponent implements OnInit { constructor( private readonly modalController: ModalController, private readonly platform: Platform - ) { - - } + ) {} public ngOnInit() { try { - this.disableHardwareBack = this.platform.backButton.subscribeWithPriority( 9999, (processNextHandler) => { // Don't do anything. } ); - } catch (ex) {} } @@ -49,7 +44,6 @@ export class DataCorruptionFoundComponent implements OnInit { ); } - public async import() { try { this.disableHardwareBack.unsubscribe(); @@ -64,5 +58,4 @@ export class DataCorruptionFoundComponent implements OnInit { DataCorruptionFoundComponent.POPOVER_ID ); } - } diff --git a/src/services/coffeeBluetoothDevices/coffee-bluetooth-devices.service.ts b/src/services/coffeeBluetoothDevices/coffee-bluetooth-devices.service.ts index be3849ef..a23dd3d4 100644 --- a/src/services/coffeeBluetoothDevices/coffee-bluetooth-devices.service.ts +++ b/src/services/coffeeBluetoothDevices/coffee-bluetooth-devices.service.ts @@ -1048,18 +1048,16 @@ export class CoffeeBluetoothDevicesService { id: deviceTemperature.id, type: TemperatureType.COMBUSTION, }); - } - else if (ArgosThermometer.test(deviceTemperature)) { + } else if (ArgosThermometer.test(deviceTemperature)) { this.logger.log( 'BleManager - We found a Argos Thermometer device ' + - JSON.stringify(deviceTemperature) + JSON.stringify(deviceTemperature) ); supportedDevices.push({ id: deviceTemperature.id, type: TemperatureType.ARGOS, }); } - } resolve(supportedDevices); }); @@ -1104,8 +1102,7 @@ export class CoffeeBluetoothDevicesService { type: TemperatureType.COMBUSTION, }); return; - } - else if (ArgosThermometer.test(deviceTemperature)) { + } else if (ArgosThermometer.test(deviceTemperature)) { this.logger.log( 'BleManager - We found a Argos Thermometer device ' ); diff --git a/src/services/uiExcel.ts b/src/services/uiExcel.ts index c9cd4e8a..d8f3f7f3 100755 --- a/src/services/uiExcel.ts +++ b/src/services/uiExcel.ts @@ -721,14 +721,12 @@ export class UIExcel { } } - public async importGreenBeansByExcel(_arrayBuffer) { try { /* data is an ArrayBuffer */ const wb = XLSX.read(_arrayBuffer); const data = XLSX.utils.sheet_to_json(wb.Sheets['Green Beans']); - let varietyInformationWhereAdded: boolean = false; const addedBeans: Array = []; const toAddBeans: Array = []; @@ -784,7 +782,6 @@ export class UIExcel { bean.url = websiteEntry.toString(); } - const flavourProfileEntry = entry['Flavour profile']; if (flavourProfileEntry) { bean.aromatics = flavourProfileEntry.toString(); @@ -820,74 +817,83 @@ export class UIExcel { const informationCertificationEntry = entry['1. Bean certification']; if (informationCertificationEntry) { - beanInformation.certification = informationCertificationEntry.toString(); - hasOneBeanInformation=true; + beanInformation.certification = + informationCertificationEntry.toString(); + hasOneBeanInformation = true; } const informationCountryEntry = entry['1. Country']; if (informationCountryEntry) { beanInformation.country = informationCountryEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationElevationEntry = entry['1. Elevation']; if (informationElevationEntry) { beanInformation.elevation = informationElevationEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationFarmEntry = entry['1. Farm']; if (informationFarmEntry) { beanInformation.farm = informationFarmEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationFarmerEntry = entry['1. Farmer']; if (informationFarmerEntry) { beanInformation.farmer = informationFarmerEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationHarvestedEntry = entry['1. Harvested']; if (informationHarvestedEntry) { beanInformation.harvest_time = informationHarvestedEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationPercentageEntry = entry['1. Percentage']; - if (informationPercentageEntry && Number(informationPercentageEntry) > 0) { + if ( + informationPercentageEntry && + Number(informationPercentageEntry) > 0 + ) { beanInformation.percentage = Number(informationPercentageEntry); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationProcessingEntry = entry['1. Processing']; if (informationProcessingEntry) { beanInformation.processing = informationProcessingEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationRegionEntry = entry['1. Region']; if (informationRegionEntry) { beanInformation.region = informationRegionEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationVarietyEntry = entry['1. Variety']; if (informationVarietyEntry) { beanInformation.variety = informationVarietyEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationFobPriceEntry = entry['1. Fob Price']; if (informationFobPriceEntry && Number(informationFobPriceEntry) > 0) { beanInformation.fob_price = Number(informationFobPriceEntry); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationPurchasingPriceEntry = entry['1. Purchasing Price']; - if (informationPurchasingPriceEntry && Number(informationPurchasingPriceEntry) > 0) { - beanInformation.purchasing_price = Number(informationPurchasingPriceEntry); - hasOneBeanInformation=true; + if ( + informationPurchasingPriceEntry && + Number(informationPurchasingPriceEntry) > 0 + ) { + beanInformation.purchasing_price = Number( + informationPurchasingPriceEntry + ); + hasOneBeanInformation = true; } if (hasOneBeanInformation) { @@ -902,7 +908,6 @@ export class UIExcel { toAddBeans.push(bean); } - if (varietyInformationWhereAdded) { if (this.settings.bean_manage_parameters.bean_information === false) { this.settings.bean_manage_parameters.bean_information = true; @@ -910,7 +915,6 @@ export class UIExcel { } } - /** * Add all beans afterwards to not have some added and then going into an exception */ @@ -918,24 +922,33 @@ export class UIExcel { try { const newBean: GreenBean = await this.uiGreenBeanStorage.add(addBean); addedBeans.push(newBean); - } catch(ex) { - - } + } catch (ex) {} } - if (addedBeans.length>0) { + if (addedBeans.length > 0) { try { - await this.uiAlert.showMessage('GREEN_BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION','IMPORT_SUCCESSFULLY',undefined,true); - }catch(ex) { - - } - + await this.uiAlert.showMessage( + 'GREEN_BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION', + 'IMPORT_SUCCESSFULLY', + undefined, + true + ); + } catch (ex) {} } else { - this.uiAlert.showMessage('BEANS_IMPORTED_UNSUCCESSFULLY_WRONG_EXCELFILE','IMPORT_UNSUCCESSFULLY','OK',false); + this.uiAlert.showMessage( + 'BEANS_IMPORTED_UNSUCCESSFULLY_WRONG_EXCELFILE', + 'IMPORT_UNSUCCESSFULLY', + 'OK', + false + ); } - } catch (ex) { - this.uiAlert.showMessage(ex.message,this.translate.instant('IMPORT_UNSUCCESSFULLY'),this.translate.instant('OK'),false); + this.uiAlert.showMessage( + ex.message, + this.translate.instant('IMPORT_UNSUCCESSFULLY'), + this.translate.instant('OK'), + false + ); } } @@ -1063,74 +1076,83 @@ export class UIExcel { const informationCertificationEntry = entry['1. Bean certification']; if (informationCertificationEntry) { - beanInformation.certification = informationCertificationEntry.toString(); - hasOneBeanInformation=true; + beanInformation.certification = + informationCertificationEntry.toString(); + hasOneBeanInformation = true; } const informationCountryEntry = entry['1. Country']; if (informationCountryEntry) { beanInformation.country = informationCountryEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationElevationEntry = entry['1. Elevation']; if (informationElevationEntry) { beanInformation.elevation = informationElevationEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationFarmEntry = entry['1. Farm']; if (informationFarmEntry) { beanInformation.farm = informationFarmEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationFarmerEntry = entry['1. Farmer']; if (informationFarmerEntry) { beanInformation.farmer = informationFarmerEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationHarvestedEntry = entry['1. Harvested']; if (informationHarvestedEntry) { beanInformation.harvest_time = informationHarvestedEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationPercentageEntry = entry['1. Percentage']; - if (informationPercentageEntry && Number(informationPercentageEntry) > 0) { + if ( + informationPercentageEntry && + Number(informationPercentageEntry) > 0 + ) { beanInformation.percentage = Number(informationPercentageEntry); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationProcessingEntry = entry['1. Processing']; if (informationProcessingEntry) { beanInformation.processing = informationProcessingEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationRegionEntry = entry['1. Region']; if (informationRegionEntry) { beanInformation.region = informationRegionEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationVarietyEntry = entry['1. Variety']; if (informationVarietyEntry) { beanInformation.variety = informationVarietyEntry.toString(); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationFobPriceEntry = entry['1. Fob Price']; if (informationFobPriceEntry && Number(informationFobPriceEntry) > 0) { beanInformation.fob_price = Number(informationFobPriceEntry); - hasOneBeanInformation=true; + hasOneBeanInformation = true; } const informationPurchasingPriceEntry = entry['1. Purchasing Price']; - if (informationPurchasingPriceEntry && Number(informationPurchasingPriceEntry) > 0) { - beanInformation.purchasing_price = Number(informationPurchasingPriceEntry); - hasOneBeanInformation=true; + if ( + informationPurchasingPriceEntry && + Number(informationPurchasingPriceEntry) > 0 + ) { + beanInformation.purchasing_price = Number( + informationPurchasingPriceEntry + ); + hasOneBeanInformation = true; } if (hasOneBeanInformation) { @@ -1162,7 +1184,9 @@ export class UIExcel { const unfrozenDateEntry = entry['Unfrozen Date']; if (unfrozenDateEntry && Number(unfrozenDateEntry) > 0) { isOneEntryFrozen = true; - bean.unfrozenDate = this.getJsDateFromExcel(Number(unfrozenDateEntry)); + bean.unfrozenDate = this.getJsDateFromExcel( + Number(unfrozenDateEntry) + ); } toAddBeans.push(bean); } @@ -1181,7 +1205,6 @@ export class UIExcel { } } - /** * Add all beans afterwards to not have some added and then going into an exception */ @@ -1189,30 +1212,39 @@ export class UIExcel { try { const newBean: Bean = await this.uiBeanStorage.add(addBean); addedBeans.push(newBean); - } catch(ex) { - - } + } catch (ex) {} } - if (addedBeans.length>0) { + if (addedBeans.length > 0) { try { - await this.uiAlert.showMessage('BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION','IMPORT_SUCCESSFULLY',undefined,true); - }catch(ex) { - - } + await this.uiAlert.showMessage( + 'BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION', + 'IMPORT_SUCCESSFULLY', + undefined, + true + ); + } catch (ex) {} this.uiBeanHelper.showBeans(addedBeans); } else { - this.uiAlert.showMessage('BEANS_IMPORTED_UNSUCCESSFULLY_WRONG_EXCELFILE','IMPORT_UNSUCCESSFULLY','OK',false); + this.uiAlert.showMessage( + 'BEANS_IMPORTED_UNSUCCESSFULLY_WRONG_EXCELFILE', + 'IMPORT_UNSUCCESSFULLY', + 'OK', + false + ); } - } catch (ex) { - this.uiAlert.showMessage(ex.message,this.translate.instant('IMPORT_UNSUCCESSFULLY'),this.translate.instant('OK'),false); + this.uiAlert.showMessage( + ex.message, + this.translate.instant('IMPORT_UNSUCCESSFULLY'), + this.translate.instant('OK'), + false + ); } } private getJsDateFromExcel(_dateNumber) { - return new Date((_dateNumber - (25567+2))*86400*1000).toISOString(); - + return new Date((_dateNumber - (25567 + 2)) * 86400 * 1000).toISOString(); } /* Export button */ public async export() { diff --git a/src/services/uiExportImportHelper.ts b/src/services/uiExportImportHelper.ts index 2b6cfa9f..19c1d846 100644 --- a/src/services/uiExportImportHelper.ts +++ b/src/services/uiExportImportHelper.ts @@ -243,46 +243,58 @@ export class UIExportImportHelper { }); } private async checkBackupAndSeeIfDataAreCorrupted(_actualUIStorageDataObj) { - try { - this.uiLog.log("checkBackupAndSeeIfDataAreCorrupted - Check if we got a deep corruption"); + this.uiLog.log( + 'checkBackupAndSeeIfDataAreCorrupted - Check if we got a deep corruption' + ); const dataObj = _actualUIStorageDataObj.DATA; const parsedJSON: any = await this.readBackupZIPFile(); if (parsedJSON) { let somethingCorrupted = false; if (parsedJSON.BEANS?.length > dataObj.BEANS) { somethingCorrupted = true; - } else if (parsedJSON.BREWS?.length > dataObj.BREWS) - { + } else if (parsedJSON.BREWS?.length > dataObj.BREWS) { somethingCorrupted = true; - } else if (parsedJSON.PREPARATION?.length > dataObj.PREPARATION) - { + } else if (parsedJSON.PREPARATION?.length > dataObj.PREPARATION) { somethingCorrupted = true; - } - else if (parsedJSON.MILL?.length > dataObj.MILL) - { + } else if (parsedJSON.MILL?.length > dataObj.MILL) { somethingCorrupted = true; } - this.uiLog.log("checkBackupAndSeeIfDataAreCorrupted- Check over - if we got a deep corruption - Result: " + somethingCorrupted); + this.uiLog.log( + 'checkBackupAndSeeIfDataAreCorrupted- Check over - if we got a deep corruption - Result: ' + + somethingCorrupted + ); if (somethingCorrupted) { - const importBackup = await this.showDataCorruptionPopover(dataObj,parsedJSON); + const importBackup = await this.showDataCorruptionPopover( + dataObj, + parsedJSON + ); if (importBackup) { await this.importBackupJSON(parsedJSON); } } else { - this.uiLog.log("checkBackupAndSeeIfDataAreCorrupted - Check over - we didn't find any corrupted data"); + this.uiLog.log( + "checkBackupAndSeeIfDataAreCorrupted - Check over - we didn't find any corrupted data" + ); } } else { - this.uiLog.log("checkBackupAndSeeIfDataAreCorrupted - We didn't found any json backup data so we can't do any checks"); + this.uiLog.log( + "checkBackupAndSeeIfDataAreCorrupted - We didn't found any json backup data so we can't do any checks" + ); } - } catch(ex) { - this.uiLog.log("Check over - if we got a deep corruption - Result exception: " + JSON.stringify(ex)); + } catch (ex) { + this.uiLog.log( + 'Check over - if we got a deep corruption - Result exception: ' + + JSON.stringify(ex) + ); } - } - public async showDataCorruptionPopover(_actualUIStorageDataObj,_backupDataObj) { + public async showDataCorruptionPopover( + _actualUIStorageDataObj, + _backupDataObj + ) { const modal = await this.modalController.create({ component: DataCorruptionFoundComponent, id: DataCorruptionFoundComponent.POPOVER_ID, @@ -292,8 +304,10 @@ export class UIExportImportHelper { }, }); await modal.present(); - const returnData = await modal.onWillDismiss(); - this.uiLog.log('Data corruption, choose to import: ' + returnData?.data?.import); + const returnData = await modal.onWillDismiss(); + this.uiLog.log( + 'Data corruption, choose to import: ' + returnData?.data?.import + ); if (returnData?.data?.import) { //User choose to import backup, go return true; @@ -332,7 +346,9 @@ export class UIExportImportHelper { } resolve(null); } else { - await this.checkBackupAndSeeIfDataAreCorrupted(actualUIStorageDataObj); + await this.checkBackupAndSeeIfDataAreCorrupted( + actualUIStorageDataObj + ); resolve(null); } } else { diff --git a/src/services/uiHelper.ts b/src/services/uiHelper.ts index 4805deb9..8026bcb1 100755 --- a/src/services/uiHelper.ts +++ b/src/services/uiHelper.ts @@ -147,7 +147,7 @@ export class UIHelper { return moment(_unix).format(format); } - public formatTimeNumber(_time: number|string, _format?: string): string { + public formatTimeNumber(_time: number | string, _format?: string): string { let format: string = this.getSettingsStorageInstance().getSettings().date_format + ', HH:mm:ss'; diff --git a/src/services/uiPreparationHelper.ts b/src/services/uiPreparationHelper.ts index bc28ca0b..3fd8ca61 100644 --- a/src/services/uiPreparationHelper.ts +++ b/src/services/uiPreparationHelper.ts @@ -23,9 +23,7 @@ import { HttpClient } from '@angular/common/http'; import { PreparationDevice } from '../classes/preparationDevice/preparationDevice'; import { PreparationSortToolsComponent } from '../app/preparation/preparation-sort-tools/preparation-sort-tools.component'; import PREPARATION_TRACKING from '../data/tracking/preparationTracking'; -import { - PreparationConnectedDeviceComponent -} from '../app/preparation/preparation-connected-device/preparation-connected-device.component'; +import { PreparationConnectedDeviceComponent } from '../app/preparation/preparation-connected-device/preparation-connected-device.component'; import { UIAnalytics } from './uiAnalytics'; /** @@ -103,9 +101,6 @@ export class UIPreparationHelper { await modal.onWillDismiss(); } - - - public async editPreparationTool( _preparation: Preparation, _preparationTool: PreparationTool From 3e87507a3877f0eaa41dcb04e642161940572d80 Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Tue, 27 Aug 2024 21:28:00 +0200 Subject: [PATCH 07/19] Changing to .toPng as screenshot after images where not rendered anymore --- .../brew-information/brew-information.component.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/brew-information/brew-information.component.ts b/src/components/brew-information/brew-information.component.ts index ea234ce8..a1455d89 100644 --- a/src/components/brew-information/brew-information.component.ts +++ b/src/components/brew-information/brew-information.component.ts @@ -399,12 +399,13 @@ export class BrewInformationComponent implements OnInit { await this.uiAlert.showLoadingSpinner(); if (this.platform.is('ios')) { htmlToImage - .toJpeg(this.cardEl.nativeElement) + .toPng(this.cardEl.nativeElement) .then((_dataURL) => { + console.log(_dataURL); // On iOS we need to do this a second time, because the rendering doesn't render everything (strange thing) setTimeout(() => { htmlToImage - .toJpeg(this.cardEl.nativeElement) + .toPng(this.cardEl.nativeElement) .then(async (_dataURLSecond) => { await this.uiAlert.hideLoadingSpinner(); setTimeout(() => { @@ -421,7 +422,7 @@ export class BrewInformationComponent implements OnInit { }); } else { htmlToImage - .toJpeg(this.cardEl.nativeElement) + .toPng(this.cardEl.nativeElement) .then(async (_dataURL) => { await this.uiAlert.hideLoadingSpinner(); setTimeout(() => { From 3d66ac2098df5d52b308d59163e573e7eeb1cdd4 Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Tue, 27 Aug 2024 22:27:36 +0200 Subject: [PATCH 08/19] #779 - Fixing the range for pressure graph --- .../graph-detail/graph-detail.component.ts | 1 - src/app/settings/settings.page.html | 19 +++++++++++++++++++ src/app/settings/settings.page.ts | 9 +++++++++ src/assets/i18n/en.json | 5 ++++- src/classes/settings/settings.ts | 10 ++++++++++ .../brew-brewing-graph.component.ts | 6 +++++- .../graph-display-card.component.ts | 1 - src/interfaces/settings/iSettings.ts | 4 ++++ 8 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/app/graph-section/graph/graph-detail/graph-detail.component.ts b/src/app/graph-section/graph/graph-detail/graph-detail.component.ts index 4bc1b9dd..a0ead927 100644 --- a/src/app/graph-section/graph/graph-detail/graph-detail.component.ts +++ b/src/app/graph-section/graph/graph-detail/graph-detail.component.ts @@ -183,7 +183,6 @@ export class GraphDetailComponent implements OnInit { side: 'right', showgrid: false, position: 0.93, - range: [0, 10], visible: true, }; diff --git a/src/app/settings/settings.page.html b/src/app/settings/settings.page.html index 9ead758f..fc663f98 100644 --- a/src/app/settings/settings.page.html +++ b/src/app/settings/settings.page.html @@ -986,6 +986,25 @@

{{"PRESSURE_LOG" | translate}}

+ + + + {{"PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS" | translate }} +

{{"PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_DESCRIPTION" | translate}}

+
+ + + {{"PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_RANGE" | translate}} {{this.uiHelper.toFixedIfNecessary(settings.graph_pressure.lower,2)}} - {{this.uiHelper.toFixedIfNecessary(settings.graph_pressure.upper,2)}} + + + + + + + +
+
diff --git a/src/app/settings/settings.page.ts b/src/app/settings/settings.page.ts index 5495aa60..fcae3d57 100644 --- a/src/app/settings/settings.page.ts +++ b/src/app/settings/settings.page.ts @@ -1210,6 +1210,15 @@ export class SettingsPage { this.uiExcel.export(); } + public pinFormatter(value: any) { + const parsedFloat = parseFloat(value); + if (isNaN(parsedFloat)) { + return `${0}`; + } + const newValue = +parsedFloat.toFixed(2); + return `${newValue}`; + } + public doWeHaveBrewByWeights(): boolean { const allPreparations = this.uiPreparationStorage.getAllEntries(); for (const prep of allPreparations) { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 5990d359..8e12661a 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1370,5 +1370,8 @@ "GREEN_BEANS_IMPORTED_SUCCESSFULLY_DESCRIPTION": "All found entries in the excel list, have been transformed into new green beans, have great roasts!", "PREPARATION_TYPE_SANREMO_YOU": "Sanremo YOU", "PREPARATION_TYPE_XENIA": "Xenia", - "BEAN_POPUP_YOU_DONT_SEE_EVERYTHING_DESCRIPTION": "You're adding a bean which has variety information in it, but those parameters are not activated. Do you want to activate them now?" + "BEAN_POPUP_YOU_DONT_SEE_EVERYTHING_DESCRIPTION": "You're adding a bean which has variety information in it, but those parameters are not activated. Do you want to activate them now?", + "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS": "Define the axes for the pressure graph", + "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_DESCRIPTION": "Set the starting and end size of the axes for pressure", + "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_RANGE": "Pressure axes" } diff --git a/src/classes/settings/settings.ts b/src/classes/settings/settings.ts index a247d49f..3a4839c1 100755 --- a/src/classes/settings/settings.ts +++ b/src/classes/settings/settings.ts @@ -140,6 +140,11 @@ export class Settings implements ISettings { }; }; + public graph_pressure: { + upper: number; + lower: number; + }; + public wake_lock: boolean; public security_check_when_going_back: boolean; @@ -381,6 +386,11 @@ export class Settings implements ISettings { }, }; + this.graph_pressure = { + upper: 0, + lower: 9, + }; + this.brew_rating = 5; this.brew_rating_steps = 1; this.bean_rating = 5; diff --git a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts index 3f54feab..c0aa6771 100644 --- a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts +++ b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts @@ -928,6 +928,7 @@ export class BrewBrewingGraphComponent implements OnInit { if (this.isDetail === false) { let graph_weight_settings; let graph_flow_settings; + if ( this.data.getPreparation().style_type === PREPARATION_STYLE_TYPE.ESPRESSO @@ -1036,6 +1037,9 @@ export class BrewBrewingGraphComponent implements OnInit { this.brewComponent?.brewBrewingPreparationDeviceEl?.preparationDeviceConnected() || !this.platform.is('cordova') ) { + const graph_pressure_settings = this.settings.graph_pressure; + const suggestedMinPressure: number = graph_pressure_settings.lower; + const suggestedMaxPressure: number = graph_pressure_settings.upper; layout['yaxis4'] = { title: '', titlefont: { color: '#05C793' }, @@ -1046,7 +1050,7 @@ export class BrewBrewingGraphComponent implements OnInit { showgrid: false, position: 0.91, fixedrange: true, - range: [0, 10], + range: [suggestedMinPressure, suggestedMaxPressure], }; } const temperatureDevice = this.bleManager.getTemperatureDevice(); diff --git a/src/components/graph-display-card/graph-display-card.component.ts b/src/components/graph-display-card/graph-display-card.component.ts index 1eaab91d..9896b7fb 100644 --- a/src/components/graph-display-card/graph-display-card.component.ts +++ b/src/components/graph-display-card/graph-display-card.component.ts @@ -169,7 +169,6 @@ export class GraphDisplayCardComponent implements OnInit { fixedrange: true, showgrid: false, position: 0.93, - range: [0, 10], visible: true, }; diff --git a/src/interfaces/settings/iSettings.ts b/src/interfaces/settings/iSettings.ts index 2aa0afac..35d8d7c1 100755 --- a/src/interfaces/settings/iSettings.ts +++ b/src/interfaces/settings/iSettings.ts @@ -135,6 +135,10 @@ export interface ISettings { lower: number; }; }; + graph_pressure: { + upper: number; + lower: number; + }; welcome_page_showed: boolean; From 7cc183650c9084b86854d71ca20cbed14cf79bbb Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Wed, 28 Aug 2024 21:50:39 +0200 Subject: [PATCH 09/19] Lokalise update --- src/assets/i18n/de.json | 33 - src/assets/i18n/en.json | 33 - src/assets/i18n/es.json | 33 - src/assets/i18n/fr.json | 37 +- src/assets/i18n/id.json | 33 - src/assets/i18n/it.json | 45 +- src/assets/i18n/nl_NL.json | 1323 ++++++++++++++++++++++++++++++++++++ src/assets/i18n/pl.json | 33 - src/assets/i18n/tr.json | 33 - src/assets/i18n/zh.json | 33 - 10 files changed, 1331 insertions(+), 305 deletions(-) create mode 100644 src/assets/i18n/nl_NL.json diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 90777414..d63be163 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Minuten anzeigen", "BEANS_UNARCHIVE": "Archivierung aufheben", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Bean wurde dearchiviert", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Version 7.4.0: Das ist neu", - "DESCRIPTION": [ - "Bohnen<\/b>", - "Es ist jetzt möglich Kaffeebohnen einzufrieren. Aktiviere diese Funktion in den Einstellungen", - "Bestes und offenes Datum für Bohnen hinzugefügt. Diese Parameter müssen aktiviert werden.", - "Bohnen können nun direkt aus der Auswahlübersicht hinzugefügt werden", - "", - " Thermometer <\/b>", - "Unterstützung des Combustion Inc. Thermometers – Danke für das Gerät!", - "Unterstützung des Meater-Thermometers (nicht Meater 2 oder Meater +) – Danke an Yannick!", - "", - "Wasserbereich<\/b>", - "Pure Coffee Water hinzugefügt", - "Empirical Water hinzugefügt", - "", - "Brühmethoden Tools<\/b>", - "Sortiere deine Zubereitungsmethoden", - "", - "Mühlen<\/b>", - "Mühlenbilder werden in der Übersicht angezeigt", - "", - "Einstellungen<\/b>", - "Sicherheitsmeldung, wenn du die Bewertung für Brühen oder Bohnen geändert hast und das Maximum niedriger ist als ein bereits bewerteter Eintrag", - "", - "Sonstiges<\/b>", - "Der direkte Sekundenfokus beim Öffnen des Timers wurde ausgebaut", - "Einige technische Änderungen im Code", - "Kleine Optimierungen" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index b73e2994..6408bd8f 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Show minutes", "BEANS_UNARCHIVE": "Unarchive", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Bean has been unarchived", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Version 7.4.0: What's new", - "DESCRIPTION": [ - "Beans<\/b>", - "Its now possible to freeze your coffee beans, activate this feature in the settings", - "Added best and open date for beans, you need to activate this parameter", - "Beans can now be directly added from the select overview", - "", - "Thermometer<\/b>", - "Support of the Combustion Inc. Thermometer - Thanks for the Device!", - "Support of the Meater Thermometer (not Meater 2 or Meater +) - Thanks to Yannick!", - "", - "Water Section<\/b>", - "Added Pure Coffee Water", - "Added Empirical Water", - "", - "Preparation Tools<\/b>", - "Sort now your preparation tools", - "", - "Grinder<\/b>", - "Grinder images are now shown in the select overview", - "", - "Settings<\/b>", - "Security message if you changed the rating for brews or beans, and the maximum is lower then an already rated entry", - "", - "Other<\/b>", - "Reverted the direct seconds focus when opening the timer", - "Some technical changes in the code", - "Small tweaks" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index 9736cc49..38d1a467 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Mostrar minutos", "BEANS_UNARCHIVE": "Desarchivar", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Café desarchivado", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Versión 7.4.0: Novedades", - "DESCRIPTION": [ - "Cafés<\/b>", - "Ahora es posible congelar tus cafés, puedes activar esta opción en ajustes.", - "Añadidas fechas de apertura y de consumo óptimo para tus cafés (desactivadas por defecto).", - "Ahora puedes añadir un nuevo café desde el menú de selección de cafés de una preparación.", - "", - "Termómetro<\/b>", - "Añadido soporte para el termómetro Combustion Inc. - Gracias por el aporte!", - "Añadido soporte para el termómetro Meater (no Meater 2 o Meater+) - Gracias a Yannick!", - "", - "Sección de agua<\/b>", - "Añadida agua Pure Coffee Water", - "Añadida agua Empirical Water", - "", - "Métodos de preparación<\/b>", - "Ahora puedes ordenar tus métodos de preparación", - "", - "Molinos<\/b>", - "Ahora se muestran las imágenes de los molinos en el menú de selección.", - "", - "Ajustes<\/b>", - "Se muestra una alerta si cambias la puntuación de una preparación o un café, y el máximo es menor que otra entrada ya puntuada.", - "", - "Otros<\/b>", - "El campo \"segundos\" ya no se selecciona automáticamente al abrir el selector de tiempo.", - "Cambios técnicos en el código.", - "Pequeños ajustes y mejoras." - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 8f71307e..17a5ccbe 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -479,7 +479,7 @@ "CUSTOM_MANAGE_PARAMETERS": "Gérer", "CUSTOM_SORT_PARAMETERS": "Trier", "BREW_PARAMETER_CUSTOMIZE_TITLE": "Paramètres personnalisés pour chaque méthode de préparation", - "BREW_PARAMETER_CUSTOMIZE_DESCRIPTION": "Tu veux choisir des paramètres personnalisés pour chaque méthode de préparation ? Navigues jusqu'à \"Méthodes\", ouvre le menu de la méthode de préparation spécifique et choisissez \"Personnaliser les paramètres\". Là, tu peux choisir quels paramètres seront utilisés pour cette préparation !", + "BREW_PARAMETER_CUSTOMIZE_DESCRIPTION": "Tu veux choisir des paramètres personnalisés pour chaque méthode de préparation ? Navigue jusqu'à \"Méthodes\", ouvre le menu de la méthode de préparation spécifique et choisissez \"Personnaliser les paramètres\". Là, tu peux choisir quels paramètres seront utilisés pour cette préparation !", "BREW_DATA_BREW_QUANTITY_TOOLTIP": "Quantité d'eau (non utilisable pour l'espresso)", "BREW_DATA_COFFEE_FIRST_DRIP_TIME_TOOLTIP": "Premier temps d'égouttage du café (espresso uniquement)", "BREW_DATA_PREPARATION_METHOD_TOOLTIP": "Préparation (uniquement personnalisable lorsqu'elle est active)", @@ -1148,7 +1148,7 @@ }, "SHOT": { "UPLOAD_SUCCESSFULLY": "Infusion téléchargé sur Visualizer.", - "UPLOAD_UNSUCCESSFULLY": "L'infusion n'a pas pu être téléchargé sur Visualizer." + "UPLOAD_UNSUCCESSFULLY": "L'infusion n'a pas pu être téléchargée sur Visualizer." }, "URL": "URL du serveur", "USERNAME": "Nom d'utilisateur", @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Afficher les minutes", "BEANS_UNARCHIVE": "Désarchiver", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Le grain a été désarchivé", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Version 7.4.0: c'est nouveau", - "DESCRIPTION": [ - "Grains<\/b>", - "Il est possible de congeler des grains de café. Active cette fonction dans les réglages", - "Ajout de la meilleure date et de la date d'ouverture pour les grains. Ces paramètres doivent être activés.", - "Les grains peuvent désormais être ajoutés directement à partir de l’aperçu de la sélection", - "", - " Thermomètre <\/b>", - "Support pour les thermomètres de Combustion Inc. – Merci pour l'appareil !", - "Support du thermomètre Meater (pas Meater 2 ou Meater +) – Merci à Yannick !", - "", - " Zone d'eau <\/b>", - "Ajouté Pure Coffee Water", - "Ajouté Empirical Water", - "", - " Outils de méthode d'infusion <\/b>", - "Trier tes méthodes de préparation", - "", - "Moulins<\/b>", - "Les images des moulins sont affichées dans l'aperçu", - "", - "Paramètres<\/b>", - "Message de sécurité si tu as modifié l'évaluation des infusions ou des grains et que le maximum est inférieur à une entrée déjà évaluée.", - "", - "Autres<\/b>", - "La mise au point directe en secondes lors de l'ouverture de la minuterie a été rétablie", - "Quelques changements techniques dans le code", - "Petites optimisations" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/id.json b/src/assets/i18n/id.json index fc9969cd..50594012 100644 --- a/src/assets/i18n/id.json +++ b/src/assets/i18n/id.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Tampilkan menit", "BEANS_UNARCHIVE": "Tidak diarsipkan", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Bean tidak diarsipkan", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Versi 7.4.0: Apa yang baru", - "DESCRIPTION": [ - "Biji<\/b>", - "Sekarang dimungkinkan untuk mencatat pembekuan biji kopi Anda, aktifkan fitur ini di pengaturan", - "Menambahkan tanggal terbaik dan tanggal membuka kopi, Anda perlu mengaktifkan parameter ini", - "Biji sekarang dapat langsung ditambahkan dari pilihan", - "", - "Thermometer<\/b>", - "Dukungan Termometer Combustion Inc. - Terima kasih untuk Perangkatnya!", - "Dukungan Termometer Meater (bukan Meater 2 atau Meater +) - Terima kasih kepada Yannick!", - "", - "Water Section<\/b>", - "Penambahan Pure Coffee Water", - "Penambahan Empirical Water", - "", - "Preparation Tools<\/b>", - "Jenis alat-alat seduhan dapat diurutkan", - "", - "Grinder<\/b>", - "Gambar grinder sekarang ditampilkan dalam pilihan", - "", - "Pengaturan<\/b>", - "Pesan keamanan jika Anda mengubah peringkat untuk seduhan atau biji kopi, dan nilai maksimumnya lebih rendah dari entri yang sudah diberi peringkat", - "", - "Lain-lain<\/b>", - "Mengembalikan fokus detik langsung saat membuka pengatur waktu", - "Beberapa perubahan teknis pada kode", - "Perubahan kecil" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index 0face123..522b9323 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -44,13 +44,13 @@ "PAGE_HOME_DIFFERENT_PREPARATION_METHODS": "metodi di preparazione", "PAGE_HOME_DIFFERENT_MILLS": "macinacaffè", "PAGE_HOME_SUPPORTER": "App Supporter", - "PAGE_HOME_START_BREW": "", + "PAGE_HOME_START_BREW": "Inizia la preparazione", "PAGE_BEANS_LIST_OBTAINABLE": "Disponibili", "PAGE_BEANS_LIST_YOU_GOT_NO_FRESH_BEANS": "Non c'è più caffè!", "PAGE_BEANS_LIST_YOU_GOT_NO_FINISHED_BEANS": "Nessun caffè archiviato", "PAGE_MILL_LIST_NO_MILL_EXISTING": "Nessun macinacaffè", "PAGE_PREPARATION_LIST_NO_PREPARATION_EXISTING": "Nessun metodo di preparazione", - "PAGE_CONTACT_SUGGESTIONS_QUESTIONS_WISHES": "Suggerimenti, domande, bug o richieste?", + "PAGE_CONTACT_SUGGESTIONS_QUESTIONS_WISHES": "Suggerimenti, domande, bugs o richieste?", "PAGE_THANKS_THANKS_FOR_YOUR_SUPPORT": "Grazie per il sostegno!", "PAGE_SETTINGS_LANGUAGE": "Impostazioni della lingua", "PAGE_SETTINGS_LANGUAGE_GERMAN": "Deutsch", @@ -61,8 +61,8 @@ "PAGE_SETTINGS_GENERAL_SETTINGS": "Impostazioni generali", "PAGE_SETTINGS_TRANSFER": "Trasferisci dati", "PAGE_SETTINGS_PRESET_LAST_BREW": "Attiva parametri preimpostati", - "PAGE_SETTINGS_DISPLAY": "", - "PAGE_SETTINGS_DISPLAY_SINGLE_PAGE": "", + "PAGE_SETTINGS_DISPLAY": "Visualizza", + "PAGE_SETTINGS_DISPLAY_SINGLE_PAGE": "Pagina singola", "PAGE_SETTINGS_DISPLAY_PAGING": "Paginazione", "PAGE_SETTINGS_STARTUP_VIEW": "Pagina iniziale", "PAGE_SETTINGS_ANALYTICS_INFORMATION": "Analytics", @@ -76,10 +76,10 @@ "PAGE_STATISTICS_TOTAL_GROUND_BEANS": "Totale caffè macinato", "PAGE_STATISTICS_MONEY_SPENT_FOR_COFFEE": "Soldi spesi in caffè", "PAGE_STATISTICS_DRUNKEN_BREWS": "Numero totale preparazioni", - "PAGE_STATISTICS_BREW_PROCESSES": "Preparazioni", + "PAGE_STATISTICS_BREW_PROCESSES": "Preparazioni totali", "PAGE_STATISTICS_DRUNKEN_QUANTITY": "Quantità consumata", "PAGE_STATISTICS_BEAN_WEIGHT_USED": "Totale caffè macinato", - "PAGE_BREW_TEXT_INFORMATION_FROM_ROASTER": "", + "PAGE_BREW_TEXT_INFORMATION_FROM_ROASTER": "Info sulla torrefazione", "PAGE_ABOUT_NO_VERSION_AVAILABLE": "Nessuna versione disponibile", "PAGE_ABOUT_APP_VERSION": "Versione App", "PAGE_LICENCES_WEBSITE": "Sito web", @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Mostra minuti", "BEANS_UNARCHIVE": "Annulla l'archiviazione", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Il caffè è stato disarchiviato", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Versione 7.4.0: Cosa c'è di nuovo", - "DESCRIPTION": [ - "Caffè<\/b>", - "Ora è possibile tenere traccia del caffè congelato, puoi attivare questa funzione nelle impostazioni", - "Aggiunta della data suggerita e di apertura per i caffè, è necessario attivare questo parametro nelle impostazioni", - "Ora è possibile aggiungere del caffè direttamente dalla selezione", - "", - " Termometro <\/b>", - "Supporto del termometro Combustion Inc. - Grazie per il dispositivo!", - "Supporto del termometro Meater (non Meater 2 o Meater +) - Grazie a Yannick!", - "", - "Sezione Acqua<\/b>", - "Aggiunta l'acqua Pure Coffee Water", - "Aggiunta l'acqua Empirical Water", - "", - "Accessori preparazione<\/b>", - "Ordina ora i tuoi strumenti di preparazione", - "", - "Macinacaffè<\/b>", - "Le immagini del macinacaffè sono mostrate nella selezione", - "", - "Impostazioni<\/b>", - "Messaggio di sicurezza se hai modificato la valutazione e il massimo è inferiore a cioè che è già valutato", - "", - "Altro<\/b>", - "Rimossa la recente aggiunta di auto-focus sui secondi del timer della preparazione", - "Piccole migliorie nel codice", - "Piccole migliorie" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/nl_NL.json b/src/assets/i18n/nl_NL.json new file mode 100644 index 00000000..31e2cd3e --- /dev/null +++ b/src/assets/i18n/nl_NL.json @@ -0,0 +1,1323 @@ +{ + "NAV_MENU": "Menu", + "NAV_HOME": "Thuis", + "NAV_SETTINGS": "Instellingen", + "NAV_BREWS": "Brouwsels", + "NAV_BEANS": "Bonen", + "NAV_PREPARATION": "Methoden", + "NAV_MILL": "Malers", + "NAV_ABOUT_US": "Over ons", + "NAV_CONTACT": "Contact", + "NAV_PRIVACY": "Privacy", + "NAV_CREDITS": "Credits", + "NAV_TERMS": "Algemene voorwaarden", + "NAV_THANKS": "Bedankt!", + "NAV_LICENCES": "OSS-licenties", + "NAV_STATISTICS": "Statistieken", + "NAV_IMPRESSUM": "Impressum", + "NAV_COOKIE": "Cookies", + "NAV_LOGS": "Logboeken", + "NAV_BREW_PARAMS": "Brouwparameters", + "NAV_INFORMATION_TO_APP": "Over Beanconqueror", + "NAV_WATER_SECTION": "Water", + "NAV_HELPER": "Calculaties", + "POPOVER_BREWS_OPTION_REPEAT": "Herhalen", + "POPOVER_BREWS_OPTION_DETAIL": "Details", + "DETAIL": "Details", + "POPOVER_BREWS_OPTION_EDIT": "Bewerking", + "POPOVER_BREWS_OPTION_DELETE": "Verwijder", + "POPOVER_BREWS_OPTION_PHOTO_GALLERY": "Fotogalerij", + "POPOVER_BREWS_OPTION_CUPPING": "Cupping", + "POPOVER_BREWS_OPTION_MAP_COORDINATES": "Toon op kaart", + "POPOVER_BREWS_OPTION_FAST_REPEAT": "Snel brouwen herhalen", + "PAGE_BREWS_NO_ENTRIES": "Nog geen brouwsels toegevoegd", + "PAGE_BREWS_NO_ARCHIVED_ENTRIES": "Je hebt nog geen brouwsels gearchiveerd", + "CANT_START_NEW_BREW_TITLE": "Er ontbreekt hier iets...", + "CANT_START_NEW_BREW_DESCRIPTION": "Om te beginnen, maak een beschrijving voor één type bonen, één zetmethode en één grinder. Gebruik het menu om naar de verschillende categorieën te navigeren om deze informatie toe te voegen.", + "PAGE_HOME_WELCOME_GREETINGS": "Leuk dat je er bent!", + "PAGE_HOME_TOTAL_BREW": "Brouwen", + "PAGE_HOME_TOTAL_BREWS": "Brouwsels", + "PAGE_HOME_BEAN_EXPLORED": "Bonen onderzocht", + "PAGE_HOME_BEANS_EXPLORED": "Bonen onderzocht", + "PAGE_HOME_LAST_BREWS": "Laatste brouwsels", + "PAGE_HOME_LAST_BREW": "Laatste brouwsel", + "PAGE_HOME_DIFFERENT_PREPARATION_METHODS": "Verschillende bereidingsmethoden", + "PAGE_HOME_DIFFERENT_MILLS": "Verschillende malers", + "PAGE_HOME_SUPPORTER": "App Supporter", + "PAGE_HOME_START_BREW": "Begin met brouwen", + "PAGE_BEANS_LIST_OBTAINABLE": "Beschikbaar", + "PAGE_BEANS_LIST_YOU_GOT_NO_FRESH_BEANS": "Je hebt geen verse bonen meer!", + "PAGE_BEANS_LIST_YOU_GOT_NO_FINISHED_BEANS": "Je hebt geen gearchiveerde bonen.", + "PAGE_MILL_LIST_NO_MILL_EXISTING": "Je hebt nog geen grinders toegevoegd.", + "PAGE_PREPARATION_LIST_NO_PREPARATION_EXISTING": "Je hebt nog geen zetmethodes toegevoegd.", + "PAGE_CONTACT_SUGGESTIONS_QUESTIONS_WISHES": "Suggesties, vragen, bugs of verzoeken?", + "PAGE_THANKS_THANKS_FOR_YOUR_SUPPORT": "Bedankt voor je steun!", + "PAGE_SETTINGS_LANGUAGE": "Taalinstellingen", + "PAGE_SETTINGS_LANGUAGE_GERMAN": "Duits", + "PAGE_SETTINGS_LANGUAGE_ENGLISH": "Engels", + "PAGE_SETTINGS_LANGUAGE_SPANISH": "Spaans", + "PAGE_SETTINGS_LANGUAGE_TURKISH": "Turks", + "PAGE_SETTINGS_LANGUAGE_CHINESE": "Chinees", + "PAGE_SETTINGS_GENERAL_SETTINGS": "Algemene instellingen", + "PAGE_SETTINGS_TRANSFER": "Gegevens overdragen", + "PAGE_SETTINGS_PRESET_LAST_BREW": "Vooraf ingestelde waarden?", + "PAGE_SETTINGS_DISPLAY": "Weergave", + "PAGE_SETTINGS_DISPLAY_SINGLE_PAGE": "Eén pagina", + "PAGE_SETTINGS_DISPLAY_PAGING": "Paging", + "PAGE_SETTINGS_STARTUP_VIEW": "Startpagina", + "PAGE_SETTINGS_ANALYTICS_INFORMATION": "Analytics", + "PAGE_SETTINGS_ANALYTICS_INFORMATION_TOOLTIP": "Druk op i voor meer informatie", + "PAGE_SETTINGS_TRACK_BREW_COORDINATES": "Geolocatie van brouwsel opslaan", + "PAGE_SETTINGS_FAST_REPEAT": "Snel herhalen", + "PAGE_SETTINGS_TRACK_CAFFEINE_CONSUMPTION": "bewaar cafeïneconsumptie", + "PAGE_SETTINGS_WAKE_LOCK": "Houd het display actief tijdens het brouwen", + "PAGE_SETTINGS_CURRENCY": "Valuta", + "PAGE_STATISTICS_DIFFERENT_PREPARATION_METHOD": "Bereidingsmethoden", + "PAGE_STATISTICS_TOTAL_GROUND_BEANS": "Totaal gemalen bonen", + "PAGE_STATISTICS_MONEY_SPENT_FOR_COFFEE": "Geld uitgegeven aan bonen", + "PAGE_STATISTICS_DRUNKEN_BREWS": "Totaal aantal brouwsels", + "PAGE_STATISTICS_BREW_PROCESSES": "Totaal brouwsels", + "PAGE_STATISTICS_DRUNKEN_QUANTITY": "Verbruikte hoeveelheid", + "PAGE_STATISTICS_BEAN_WEIGHT_USED": "Totaal gemalen bonen", + "PAGE_BREW_TEXT_INFORMATION_FROM_ROASTER": "Informatie over de brander", + "PAGE_ABOUT_NO_VERSION_AVAILABLE": "Geen Versie beschikbaar", + "PAGE_ABOUT_APP_VERSION": "App Versie", + "PAGE_LICENCES_WEBSITE": "Website", + "BEAN_DATA_ROAST_NAME": "Mate van branding", + "BEAN_DATA_CUSTOM_ROAST_NAME": "Aangepaste mate van branding", + "BEAN_DATA_ROASTING_DATE": "Brand datum", + "BEAN_DATA_ROASTER": "Brander", + "BEAN_DATA_VARIETY": "Variëteit", + "BEAN_DATA_PROCESSING": "Verwerking", + "BEAN_DATA_COUNTRY": "Land", + "BEAN_DATA_MIX": "Melange", + "BEAN_DATA_AROMATICS": "Smaakprofiel", + "BEAN_DATA_WEIGHT": "Gewicht", + "BEAN_DATA_COST": "kosten", + "BEAN_DATA_NAME": "Naam", + "BEAN_DATA_REGION": "Regio", + "BEAN_DATA_FARM": "Boerderij", + "BEAN_DATA_FARMER": "Boer", + "BEAN_DATA_ELEVATION": "Elevatie", + "BEAN_DATA_HARVEST_TIME": "Geoogst", + "BEAN_DATA_PERCENTAGE": "Percentage", + "BEAN_DATA_CERTIFICATION": "Bonencertificering", + "BEAN_DATA_ROASTING_TYPE": "type branding", + "BEAN_DATA_DECAFFEINATED": "Cafeïnevrij", + "BEAN_DATA_URL": "Website", + "BEAN_DATA_EAN": "EAN \/ Artikelnummer", + "BEAN_DATA_PURCHASING_PRICE": "Aankoopprijs", + "BEAN_DATA_FOB_PRICE": "FOB-prijs", + "BEAN_DATA_CUPPING_POINTS": "Cupping-punten", + "BREW_DATA_CUSTOM_BREW_TIME": "Aangepaste brouwtijd", + "BREW_CREATION_DATE": "Aanmaakdatum", + "REPEAT": "Herhalen", + "EDIT": "Bewerken", + "DELETE": "Verwijderen", + "FINISHED": "Archief", + "NOTES": "Notities", + "ADD_PHOTO": "Foto toevoegen", + "CANCEL": "Annuleren", + "GENERATE": "Genereren", + "SAVE": "Opslaan", + "ADD_SOMETHING": "Toevoegen", + "CONTACT": "Contact", + "NAME": "Naam", + "IMPORT": "import", + "EXPORT": "Export", + "VIEW": "Weergave", + "ARCHIVE": "archief", + "CURRENT": "huidig", + "BACK": "Terug", + "CLOSE": "sluiten", + "DAY": "Dag", + "BREW_DATA_TEMPERATURE_TIME": "Temperatuur Tijd", + "BREW_DATA_SURF_TIME": "Surftijd", + "BREW_DATA_TIME": "Tijd", + "BREW_DATA_GRIND_SIZE": "Maalinstelling", + "BREW_DATA_GRIND_WEIGHT": "Gemalen koffie (gr)", + "BREW_DATA_IN_OUT_BR": "In\/Uit (BR)", + "BREW_DATA_NOTES": "Notities", + "BREW_DATA_PREPARATION_METHOD": "Bereidingswijze", + "BREW_DATA_MILL": "Maler", + "BREW_DATA_MILL_SPEED": "Maalsnelheid (rpm)", + "BREW_DATA_MILL_TIMER": "Maaltijd", + "BREW_DATA_BREW_QUANTITY": "Hoeveelheid water", + "BREW_DATA_BEAN_TYPE": "Boon type", + "BREW_DATA_BREW_TEMPERATURE": "Brouwtemperatuur", + "BREW_DATA_PRESSURE_PROFILE": "Profiel", + "BREW_DATA_COFFEE_TYPE": "Type koffie", + "BREW_DATA_COFFEE_CONCENTRATION": "Koffie Concentratie", + "BREW_DATA_COFFEE_FIRST_DRIP_TIME": "Eerste druppeltijd", + "BREW_DATA_COFFEE_BLOOMING_TIME": "Bloeitijd \/ Pre-infusie", + "BREW_DATA_ATTACHMENTS": "Bijlagen \/ Foto's", + "BREW_DATA_RATING": "Beoordeling", + "BREW_DATA_CALCULATED_COFFEE_BREW_TIME": "Koffiezettijd", + "BREW_DATA_TDS": "Totaal opgeloste vaste stoffen %", + "BREW_DATA_CALCULATED_EXTRACTION_YIELD": "Extractie Opbrengst %", + "BREW_INFORMATION_BREW_RATIO": "Brouw Verhouding", + "BREW_INFORMATION_BEAN_AGE": "Boon leeftijd", + "BREW_INFORMATION_BREW_QUANTITY_TYPE_NAME": "Hoeveelheidstype", + "BREW_DATA_TDS_EY": "TDS \/ %EY", + "BREW_DATA_BREW_BEVERAGE_QUANTITY": "Hoeveelheid drank", + "BREW_DATA_PREPARATION_METHOD_TOOL": "bereidings gereedschappen", + "BREW_DATA_WATER": "Water", + "BREW_DATA_BEAN_WEIGHT_IN": "Bonengewicht (g)", + "BREW_DATA_VESSEL": "Serveerkan", + "BREW_DATA_VESSEL_WEIGHT": "Serveerkan gewicht", + "BREW_DATA_VESSEL_NAME": "Serveerkan naam", + "BREW_DATA_FLAVOR": "Smaak", + "BREW_DATA_FLOW_PROFILE": "Stroom", + "ONE_DAY": "Dag", + "DAYS": "Dagen", + "ONE_HOUR": "uur", + "HOURS": "uren", + "ONE_MINUTE": "minuut", + "MINUTES": "minuten", + "WITHOUT_COFFEE": "zonder koffie", + "NOT_FOUND": "Niet gevonden", + "INVALID_FILE_FORMAT": "Ongeldig bestandsformaat", + "FILE_NOT_FOUND_INFORMATION": "Bestand niet gevonden", + "ERROR_ON_FILE_READING": "Fout bij het lezen van bestandsgegevens", + "IMPORT_SUCCESSFULLY": "Importeren succesvol", + "IMPORT_UNSUCCESSFULLY_DATA_NOT_CHANGED": "Import mislukt, er zijn geen gegevens gewijzigd", + "INVALID_FILE_DATA": "Ongeldige bestandsinhoud", + "DOWNLOADED": "Gedownload", + "FILE_DOWNLOADED_SUCCESSFULLY": "Bestand ' {{fileName}} ' is succesvol gedownload naar uw downloadmap!", + "NO": "Nee", + "YES": "Ja", + "SURE_QUESTION": "Weet je het zeker?", + "DELETE_BREW_QUESTION": "Brouwsel verwijderen?", + "DELETE_BEAN_QUESTION": "Boon verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", + "DELETE_GREEN_BEAN_QUESTION": "Groene bonen verwijderen? Alle bijbehorende geroosterde bonen, evenals brouwsels worden verwijderd!", + "DELETE_MILL_QUESTION": "Grinder verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", + "DELETE_PREPARATION_METHOD_QUESTION": "Bereidingswijze verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", + "DELETE_PREPARATION_TOOL_QUESTION": "Bereidingstool verwijderen? Alle brouwsels die aan deze tool zijn gekoppeld, worden bijgewerkt.", + "APP_COULD_NOT_STARTED_CORRECTLY_BECAUSE_MISSING_FILESYSTEM": "App kon niet correct worden gestart vanwege ontbrekend bestandssysteem", + "CARE": "Zorg", + "ERROR_OCCURED": "Er is een fout opgetreden", + "CSV_FILE_NOT_DOWNLOADED": "CSV-bestand kon niet worden gedownload!", + "CSV_FILE_DOWNLOADED_SUCCESSFULLY": "CSV-bestand ' {{fileName}} ' is succesvol gedownload naar uw downloadmap!", + "ADD_BREW": "Voeg brouwsel toe", + "CHOOSE": "Kies", + "CHOOSE_PHOTO_OR_LIBRARY": "Maak een foto of kies uit de fotogalerij.", + "RECORD": "Maak een foto", + "PAGE_BEAN_INFORMATION": "Boon informatie", + "PAGE_BEAN_INFORMATION_GOOD_BREWS": "Goed", + "PAGE_BEAN_INFORMATION_BAD_BREWS": "Slecht", + "PAGE_BEAN_INFORMATION_COUNT_BREWS": "Totaal aantal brouwsels", + "INFORMATION": "Informatie", + "PAGE_BEAN_BREW_CHART_TITLE": "Brouwoverzicht voor deze boon", + "PAGE_BEAN_INFORMATION_AWESOME_BREWS": "Geweldig", + "PAGE_BEAN_INFORMATION_NORMAL_BREWS": "Normaal", + "PAGE_BEAN_INFORMATION_NOT_RATED_BREWS": "Niet beoordeeld", + "PAGE_PREPARATION_INFORMATION_BREWS_DONE": "Brouwsels met deze bereidingswijze", + "PAGE_PREPARATION_INFORMATION_BREWED_QUANTITY": "Gebrouwen hoeveelheid", + "PAGE_PREPARATION_INFORMATION_GRIND_WEIGHT": "Verbruikt gewicht van bonen", + "PAGE_PREPARATION_INFORMATION_TIME_SPENT_BREWING": "Totale bereidingstijd", + "PAGE_PREPARATION_INFORMATION": "Informatie over de bereiding", + "SECONDS": "Seconden", + "PAGE_MILL_INFORMATION": "Maler informatie", + "PAGE_MILL_INFORMATION_BREWS_DONE": "Brouwsels met deze maler", + "PAGE_MILL_INFORMATION_GRIND_WEIGHT": "Verbruikt gewicht van bonen", + "PAGE_HELPER_WATER_HARDNESS": "Waterhardheid", + "PAGE_HELPER_WATER_HARDNESS_CA_CONTENTS": "Calciumgehalte mg\/l", + "PAGE_HELPER_WATER_HARDNESS_MG_CONTENTS": "Magnesiumgehalte mg\/l", + "PAGE_HELPER_WATER_HARDNESS_GERMAN_HARDNESS": "Duitse hardheidsgraad", + "PAGE_HELPER_WATER_HARDNESS_TOTAL_HARDNESS": "Totale hardheid", + "PAGE_HELPER_BREW_RATIO": "Brouw Verhouding", + "PAGE_HELPER_BREW_RATIO_GROUND_COFFEE": "Gemalen koffie (gr)", + "PAGE_HELPER_BREW_RATIO_WATER": "Vloeistof (gr\/ml)", + "PAGE_HELPER_BREW_RATIO_CALCULATED": "Berekende brouwverhouding", + "PAGE_SETTINGS_SHOW_ARCHIVED_BREWS": "Gearchiveerde brouwsels weergeven", + "PAGE_SETTINGS_SHOW_ARCHIVED_BEANS": "Gearchiveerde bonen weergeven", + "PAGE_SETTINGS_SHOW_ARCHIVED_GREEN_BEANS": "Toon gearchiveerde groene bonen", + "CUPPING_SCORE": "Score", + "CUPPING_SCORE_DRY_FRAGRANCE": "Droge geur", + "CUPPING_SCORE_WET_AROMA": "Nat aroma", + "CUPPING_SCORE_BRIGHTNESS": "Helderheid", + "CUPPING_SCORE_FLAVOR": "Smaak", + "CUPPING_SCORE_BODY": "Body", + "CUPPING_SCORE_FINISH": "Afwerking", + "CUPPING_SCORE_SWEETNESS": "Zoetheid", + "CUPPING_SCORE_CLEAN_CUP": "Clean Cup", + "CUPPING_SCORE_COMPLEXITY": "Complexiteit", + "CUPPING_SCORE_UNIFORMITY": "Uniformiteit", + "CUPPING_SCORE_CUPPERS_CORRECTION": "Cuppers-correctie", + "CUPPING_SCORE_DRY_FRAGRANCE_TOOLTIP": "Verwijst naar het aroma van de droge gemalen koffie voordat er heet water aan wordt toegevoegd.", + "CUPPING_SCORE_WET_AROMA_TOOLTIP": "De geur van nat koffiedik, nadat er heet water aan is toegevoegd.", + "CUPPING_SCORE_BRIGHTNESS_TOOLTIP": "Zuurgraad is de smaak van scherpe hoge tonen in de koffie, veroorzaakt door een set van chlorogeen, citroenzuur, kininezuur, azijnzuur en andere, voornamelijk waargenomen in de voorkant van de mond en op de tong. (Het is een goede kwaliteit; niet gerelateerd aan bitterheid in koffie, en niet direct verantwoordelijk voor maagklachten). Zuurgraad wordt gewaardeerd door veel kopers, en is direct gerelateerd aan de kwaliteit van de kop, aangezien zuurgraad het product is van aanplantingen op grote hoogte.", + "CUPPING_SCORE_FLAVOR_TOOLTIP": "Dit is de algehele indruk in de mond, inclusief alle andere beoordelingen. Er zijn 4 \"primaire smaak\"-groeperingen (zuur, zoet, zout, bitter) en veel \"secundaire smaken\".", + "CUPPING_SCORE_BODY_TOOLTIP": "Vaak \"mondgevoel\" genoemd, is body het gevoel van gewicht en dikte van de gezette koffie, veroorzaakt door het percentage oplosbare vaste stoffen in de kop, inclusief alle organische verbindingen die worden geëxtraheerd (de zetmethode en de hoeveelheid gemalen koffie die wordt gebruikt, hebben hier grote invloed op). We beoordelen Body op een lagere schaal omdat licht gebodyde koffiesoorten zeker niet slecht zijn en in sommige origines past de lichtere body het beste bij het algehele karakter van de kop.", + "CUPPING_SCORE_FINISH_TOOLTIP": "De aanhoudende of opkomende smaken die komen nadat de mond is schoongemaakt. Dit omvat de tijd dat de koffie je mond verlaat tot minuten daarna...een reden dat je veel cuppers zult vinden die hun nasmaakscores herzien terwijl ze een minuut of twee later nog steeds een positieve smaak ervaren.", + "CUPPING_SCORE_SWEETNESS_TOOLTIP": "Zoetheid is bijna altijd een gewenste kwaliteit in koffie, zelfs als het op eufemistische wijze wordt beschreven, zoals \"rustieke zoetheid\" of \"bitterzoetheid\". U zult merken dat verfijnde zoetheid (denk aan Europees gebak, fijn snoepgoed, witte suiker, pure zoetheid) hoog scoort, evenals complexe zoetheid van fruitsuikers (fructose). Moutige zoetheid (maltose) is minder traditioneel, maar wel wenselijk en honing kan variëren van heel puur en schoon tot complex, rustiek, bijna gistachtig. Kortom, als zoetheid een sleutel is tot de kop, zal het goed worden beoordeeld.", + "CUPPING_SCORE_CLEAN_CUP_TOOLTIP": "Let op dat \"clean cup\" niet letterlijk betekent dat er geen vuil op de koffie zit. Het gaat alleen om smaak en rauwe, funky koffies die \"onrein\" zijn en de smaak kan ook heel wenselijk zijn, zoals nat-gepelde Indonesische koffies uit Sumatra, of droog verwerkte Ethiopische en Jemenitische types.", + "CUPPING_SCORE_COMPLEXITY_TOOLTIP": "Complexiteit complimenteert de scores voor \"smaak\" en \"afwerking\", om een veelheid of gelaagdheid van veel smaken te communiceren. Het betekent dat er veel te ontdekken valt in de kop. Aan de andere kant kunnen simpele koffies een opluchting zijn na overmatige blootstelling aan veel krachtige, intense, complexe koffies.", + "CUPPING_SCORE_UNIFORMITY_TOOLTIP": "Uniformiteit verwijst naar verschillen tussen kopjes. Koffiesoorten die met een droog proces zijn bereid, kunnen van nature minder uniform zijn dan koffiesoorten die met een nat proces zijn bereid. We zouden nooit een partij met fantastische smaken vermijden als deze af en toe afwijkt. Dit wordt gescoord tijdens het cuppingprotocol, waarbij meerdere kopjes worden gemaakt van elke partij die wordt beoordeeld.", + "CUPPING_SCORE_CUPPERS_CORRECTION_TOOLTIP": "Dit is aangepast van het SCAA-systeem en de Cup of Excellence-score (soms noemen ze het \"Overall Points\"). Het stelt een cupper in staat om ervoor te zorgen dat de totale score de algehele indruk van de cup correct weergeeft. U zou deze aanpak kunnen bekritiseren en het \"vervalsen\" van het totaal kunnen beschouwen. In zekere zin zou u gelijk hebben ... maar het zou veel erger zijn om de categoriescores te veranderen om het gewenste totaal te bereiken (om een koffie een 9 te geven voor zuurgraad terwijl u weet dat het een 7 is), of omgekeerd om een koffie die absoluut een 90 verdient, op 84 te laten eindigen. Het specifieke Cupper's Correction-nummer doet er niet toe, of het nu een 5 of een 8 is ... het idee is dat de totale score een correcte indruk geeft van de kwaliteit van de koffie.", + "CUPPING_SCORE_TOOLTIP": "100-95 = Verbazingwekkend, 90-94 = Uitstekend, 85-89 = Zeer goed, 80-84 = Goed, 75-79 = Redelijk, 70-74 = Slecht", + "DETAIL_BREW": "Brouw details", + "DETAIL_BEAN": "Boon details", + "DETAIL_MILL": "Maler details", + "DETAIL_PREPARATION": "Bereidings details", + "EDIT_BREW": "Bewerk brouwsel", + "ADD_BEAN": "Boon toevoegen", + "EDIT_BEAN": "Bewerken boon", + "ADD_PREPARATION": "Bereidingsmethode toevoegen", + "EDIT_PREPARATION": "Bewerk bereidingsmethode", + "ADD_MILL": "Voeg maler toe", + "EDIT_MILL": "Maler bewerken", + "USE_FILTER": "Filter toepassen", + "RESET_FILTER": "Filter resetten", + "COFFEE_GRAMS_GRINDED": "Gram gemalen", + "BEANS_USED": "Bonen geconsumeerd", + "BREW_HEADER_BEFORE_BREW": "Voor het brouwen", + "BREW_HEADER_WHILE_BREW": "Tijdens het brouwen", + "BREW_HEADER_AFTER_BREW": "Na het brouwen", + "BREW_HEADER_CUPPING": "Proeven", + "BEANS_CONSUMED": "Archieveer", + "NAV_MANAGE_PARAMETERS": "Parameters beheren", + "NAV_SORT_PARAMETERS": "Sorteer parameters", + "NAV_DEFAULT_PARAMETERS": "Standaardparameters definiëren", + "PAGE_SORT_PARAMETERS_DESCRIPTION": "Versleep parameters om te bepalen in welke volgorde ze worden weergegeven.", + "PAGE_MANAGE_PARAMETERS_DESCRIPTION": "Geef aan welke parameters moeten worden weergegeven bij het bewerken van brouwinformatie.", + "PAGE_DEFAULT_PARAMETERS_DESCRIPTION": "Markeer welke parameters standaard moeten worden ingesteld op de laatst gebruikte waarde.", + "SORT_PARAMETERS_BEFORE": "Voor het brouwen", + "SORT_PARAMETERS_MEANWHILE": "Tijdens het brouwen", + "SORT_PARAMETERS_AFTER": "Na het brouwen", + "MORE_INFORMATION": "Meer informatie", + "UNDERSTOOD": "Begrepen", + "WELCOME_PAGE_ACTIVATE_ANALYTICS_TITLE": "Analyse en tracking", + "WELCOME_PAGE_ACTIVATE_ANALYTICS_DESCRIPTION": "We willen de app, de website en onze toekomstige diensten voor u voortdurend verbeteren. Om dit te doen, moeten we wat gegevens bijhouden over hoe u de app en de functies ervan gebruikt. Maar we beloven dat we nooit persoonlijke gegevens zullen bijhouden. Om deze beloften waar te maken, gebruiken we Matomo, een open source service gericht op gegevensbeveiliging en privacy die op onze eigen server wordt gehost - dit zorgt ervoor dat alleen wij eigenaar zijn van de gegevens. Onze website biedt alle informatie over de parameters die we bijhouden en bovendien kunt u de broncode bekijken die 100% open source is. Heeft u vragen? Neem dan gerust contact met ons op.", + "ANALYTICS_INFORMATION_TITLE": "Analyse en tracking", + "ANALYTICS_INFORMATION_DESCRIPTION": "Zoals u weet, is de veiligheid van uw gegevens en uw privacy onze topprioriteit. Daarom zijn we overgestapt van Google Analytics naar de open source service Matomo, die zich richt op gegevensbeveiliging en privacy. Deze service wordt gehost op onze eigen server. Dit betekent dat wij volledig eigenaar zijn van de gegevens. De bijgehouden parameters zijn niet gewijzigd en we beloven nog steeds dat we nooit persoonlijke gegevens zullen bijhouden. Op onze website vindt u alle informatie over de parameters die we bijhouden. Bovendien kunt u de broncode bekijken, die 100% open source is. Heeft u vragen? Neem dan gerust contact met ons op.", + "ACTIVATE": "Activeren", + "DO_NOT_ACTIVE": "Niet activeren", + "WELCOME_PAGE_BEAN_TITLE": "Boon", + "WELCOME_PAGE_BEAN_DESCRIPTION": "Koffie zetten zonder bonen is een beetje lastig. Voeg je eerste boon toe om te beginnen!", + "WELCOME_PAGE_BEAN_ADD": "Boon toevoegen", + "SKIP": "Overslaan", + "WELCOME_PAGE_PREPARATION_TITLE": "Bereidingswijze", + "WELCOME_PAGE_PREPARATION_DESCRIPTION": "V60, Aeropress, Espresso - er zijn veel manieren om koffie te zetten. Voeg er minstens één toe.", + "WELCOME_PAGE_PREPARATION_ADD": "Bereidingswijze toevoegen", + "WELCOME_PAGE_MILL_TITLE": "Maler", + "WELCOME_PAGE_MILL_DESCRIPTION": "Bijna klaar, maar je hebt iets nodig om je bonen te malen! Voeg minstens één maler toe.", + "WELCOME_PAGE_MILL_ADD": "Voeg Maler toe", + "WELCOME_PAGE_TITLE": "Welkom!", + "WELCOME_PAGE_BEAN_HEADLINE": "Eerste boon", + "WELCOME_PAGE_PREPARATION_HEADLINE": "Bereidingswijze toevoegen", + "WELCOME_PAGE_MILL_HEADLINE": "Eerste Maler", + "WELCOME_PAGE_LETS_START_HEADLINE": "Nu kunnen we beginnen met brouwen!", + "WELCOME_PAGE_LETS_START_TITLE": "Nu kunnen we beginnen met brouwen!", + "WELCOME_PAGE_LETS_START_DESCRIPTION": "Gefeliciteerd, je bent klaar om de beste koffie van je leven te zetten. Veel plezier en verspreid de liefde voor goede koffie!", + "PREPARATION_TYPE": "Bereidingsmethode", + "PREPARATION_TYPE_NAME": "Naam", + "ARCHIVED": "Gearchiveerd", + "PAGE_SETTINGS_SHOW_ARCHIVED_PREPARATIONS": "Toon gearchiveerde bereidingsmethoden", + "PAGE_SETTINGS_SHOW_ARCHIVED_MILLS": "Toon gearchiveerde malers", + "PAGE_MILL_LIST_NO_ARCHIVED_MILL_EXISTING": "Er zijn nog geen malers gearchiveerd.", + "PAGE_PREPARATION_LIST_NO_ARCHIVED_PREPARATION_EXISTING": "Je hebt geen gearchiveerde bereidingswijzen.", + "TOAST_BREW_ADDED_SUCCESSFULLY": "Brouwsel succesvol toegevoegd", + "TOAST_BREW_REPEATED_SUCCESSFULLY": "Brouwsel succesvol herhaald", + "TOAST_BEAN_ADDED_SUCCESSFULLY": "Boon succesvol toegevoegd", + "TOAST_MILL_ADDED_SUCCESSFULLY": "Maler succesvol toegevoegd", + "TOAST_PREPARATION_ADDED_SUCCESSFULLY": "Bereidingswijze succesvol toegevoegd", + "TOAST_WATER_ADDED_SUCCESSFULLY": "Water succesvol toegevoegd", + "TOAST_BREW_DELETED_SUCCESSFULLY": "Brouwsel is verwijderd", + "TOAST_BEAN_DELETED_SUCCESSFULLY": "Boon is verwijderd", + "TOAST_GREEN_BEAN_DELETED_SUCCESSFULLY": "Groene boon is verwijderd", + "TOAST_MILL_DELETED_SUCCESSFULLY": "Maler is verwijderd", + "TOAST_WATER_DELETED_SUCCESSFULLY": "Water is verwijderd", + "TOAST_PREPARATION_DELETED_SUCCESSFULLY": "Bereidingswijze is verwijderd", + "TOAST_BREW_EDITED_SUCCESSFULLY": "Brouwsel is bewerkt", + "TOAST_BEAN_EDITED_SUCCESSFULLY": "Boon is bewerkt", + "TOAST_MILL_EDITED_SUCCESSFULLY": "Maler is bewerkt", + "TOAST_PREPARATION_EDITED_SUCCESSFULLY": "Bereiding is bewerkt", + "TOAST_WATER_EDITED_SUCCESSFULLY": "Water is bewerkt", + "TOAST_BEAN_ARCHIVED_SUCCESSFULLY": "Boon is gearchiveerd", + "TOAST_MILL_ARCHIVED_SUCCESSFULLY": "Maler is gearchiveerd", + "TOAST_PREPARATION_ARCHIVED_SUCCESSFULLY": "Bereidingsmethode is gearchiveerd", + "TOAST_WATER_ARCHIVED_SUCCESSFULLY": "Water is gearchiveerd", + "BEAN_WEIGHT_ALREADY_USED": "{{gramUsed}} g van {{gramTotal}} g ( {{leftOver}} g)", + "PREPARATION_TYPE_CUSTOM_PREPARATION": "Aangepaste bereidingsmethode", + "PREPARATION_TYPE_AEROPRESS": "Aeropress", + "PREPARATION_TYPE_V60": "V60", + "PREPARATION_TYPE_CHEMEX": "Chemex", + "PREPARATION_TYPE_BIALETTI": "Bialetti", + "PREPARATION_TYPE_PORTAFILTER": "Espresso machine", + "PREPARATION_TYPE_KALITA_WAVE": "Kalita Wave", + "PREPARATION_TYPE_FRENCH_PRESS": "French Press", + "PREPARATION_TYPE_SWANNECK": "Swan Neck", + "PREPARATION_TYPE_DRIPPER": "Dripper", + "PREPARATION_TYPE_DELTER_PRESS": "Delter Press", + "PREPARATION_TYPE_COLD_BREW": "Koud brouwsel", + "PREPARATION_TYPE_AEROPRESS_INVERTED": "Aeropress Omgekeerd", + "PREPARATION_TYPE_TURKISH": "Turks", + "PREPARATION_TYPE_BLUE_DRIPPER": "Blue Dripper", + "PREPARATION_TYPE_ADD_CUSTOM": "Aangepaste methode toevoegen", + "PREPARATION_TYPE_GINA": "Gina", + "PREPARATION_TYPE_KONO": "Kono", + "PREPARATION_TYPE_ORIGAMI": "Origami", + "PREPARATION_TYPE_CAFELAT": "Cafelat", + "PREPARATION_TYPE_OREA": "Orea", + "PREPARATION_TYPE_COLD_DRIP": "Cold Drip", + "PREPARATION_TYPE_HAND_LEVER": "Handmatige hendel", + "PREPARATION_TYPE_FLAIR": "Flair", + "PREPARATION_TYPE_APRIL_BREWER": "April Brewer", + "PREPARATION_TYPE_ESPRO_BLOOM": "Espreo Bloom", + "PREPARATION_TYPE_FELLOW_STAGG": "Fellow Stagg", + "PREPARATION_TYPE_HSIAO_50": "Hsiao 50", + "PREPARATION_TYPE_KARLSBADER_KANNE": "Karlsbader", + "PREPARATION_TYPE_MOCCA_MASTER": "Mocca Master", + "PREPARATION_TYPE_SIPHON": "Sifon", + "CHOOSE_BEANS": "Selecteer bonen", + "CHOOSE_BEAN": "Selecteer boon", + "CHOOSE_WATERS": "Selecteer wateren", + "CHOOSE_WATER": "Selecteer water", + "CHOOSE_PREPARATIONS": "Selecteer bereidingsmethoden", + "CHOOSE_PREPARATION": "Selecteer bereidingsmethode", + "CHOOSE_MILLS": "Selecteer molens", + "CHOOSE_MILL": "Selecteer molen", + "BEAN": { + "PLACE_HOLDER": { + "BEAN_DATA_NAME": "Naam toevoegen", + "BEAN_DATA_ROAST_NAME": "Voeg de mate van branding toe", + "BEAN_DATA_ROASTING_DATE": "Wanneer werden de bonen geroosterd?", + "BEAN_DATA_ROASTER": "Wie heeft de bonen geroosterd?", + "BEAN_DATA_VARIETY": "Voeg de koffievariant toe", + "BEAN_DATA_PROCESSING": "Koffieverwerking, bijvoorbeeld gewassen", + "BEAN_DATA_COUNTRY": "Waar komt de boon vandaan?", + "BEAN_DATA_MIX": "Wat is de melange ratio?", + "BEAN_DATA_AROMATICS": "Voeg smaken toe", + "BEAN_DATA_WEIGHT": "Gewicht van de bonen", + "BEAN_DATA_COST": "Hoeveel hebben de bonen gekost?", + "BEAN_DATA_REGION": "Regio toevoegen", + "BEAN_DATA_FARM": "Voeg de boerderij toe", + "BEAN_DATA_FARMER": "Voeg de boer toe", + "BEAN_DATA_ELEVATION": "Op welke hoogte werden de bonen geteeld", + "BEAN_DATA_HARVEST_TIME": "wanneer zijn de bonen geoogst?", + "BEAN_DATA_BUY_DATE": "Wanneer zijn de bonen gekocht?", + "BEAN_DATA_PERCENTAGE": "Voeg het percentage van deze boon in de melange toe", + "BEAN_DATA_CERTIFICATION": "Voeg de bonencertificering toe (bijv. fairtrade, bio)", + "BEAN_DATA_ROASTING_TYPE": "Voeg brand type toe", + "BEAN_DATA_DECAFFEINATED": "Is deze koffie cafeïnevrij", + "BEAN_DATA_URL": "Voeg de website-url toe", + "BEAN_DATA_EAN": "Voeg het EAN- of artikelnummer toe", + "BEAN_DATA_CUPPING_POINTS": "Voeg de cuppingpunten toe", + "BEAN_DATA_PURCHASING_PRICE": "Voeg de aankoopprijs toe", + "BEAN_DATA_FOB_PRICE": "Voeg de FOB-prijs toe", + "NOTES": "Voeg notities toe over deze bonen", + "CHOOSE_DATA_ROASTER": "Kies een brander", + "CHOOSE_DATA_ROASTING_TYPE": "Kies type branding", + "BEAN_DATA_BEST_DATE": "Wanneer is de beste datum om de bonen te gebruiken?", + "BEAN_DATA_OPEN_DATE": "Wanneer is de zak bonen geopend?", + "FROZEN_NOTES": "Zijn er opmerkingen over de bevroren koffie? Bijvoorbeeld in welke vriezer je het hebt bewaard." + } + }, + "PREPARATION": { + "PLACE_HOLDER": { + "PREPARATION_TYPE_NAME": "Voeg een naam toe", + "NOTES": "Voeg notities toe over deze bereidingsmethode" + } + }, + "MILL": { + "PLACE_HOLDER": { + "NAME": "Voeg een naam toe", + "NOTES": "Voeg notities toe over deze grinder" + } + }, + "BREW": { + "PLACE_HOLDER": { + "BREW_DATA_GRIND_SIZE": "Voer de maalinstelling in", + "BREW_DATA_GRIND_WEIGHT": "Vul de hoeveelheid koffie in (gr)", + "BREW_DATA_BREW_TEMPERATURE": "Voer de brouwtemperatuur in", + "BREW_DATA_PREPARATION_METHOD": "Selecteer bereidingsmethode", + "BREW_DATA_BEAN_TYPE": "Selecteer bonen", + "BREW_DATA_MILL": "Selecteer een molen", + "BREW_DATA_MILL_SPEED": "Voer de maalsnelheid in", + "BREW_DATA_MILL_TIMER": "Voer de maal tijd in", + "BREW_DATA_PRESSURE_PROFILE": "Druk\/stroomprofiel, brouwmethodologie", + "BREW_DATA_TEMPERATURE_TIME": "Voer de tijd in die de machine heeft mogen opwarmen", + "BREW_DATA_COFFEE_BLOOMING_TIME": "Hoe lang is de bloom?", + "BREW_DATA_COFFEE_FIRST_DRIP_TIME": "Wanneer verscheen de eerste druppel?", + "BREW_DATA_BREW_QUANTITY": "Hoeveel water heb je gebruikt om te brouwen?", + "BREW_DATA_COFFEE_TYPE": "Voer de koffiestijl in (bijv. ristretto)", + "BREW_DATA_COFFEE_CONCENTRATION": "Voer de koffie concentratie in", + "BREW_DATA_TDS": "Wat was de gemeten hoeveelheid opgeloste vaste stoffen (TDS)?", + "BREW_DATA_NOTES": "Voeg notities toe over dit brouwsel", + "BREW_DATA_BREW_BEVERAGE_QUANTITY": "Voeg totale drank hoeveelheid toe", + "BREW_DATA_PREPARATION_METHOD_TOOL": "Kies je bereiding tools", + "BREW_DATA_WATER": "Kies het gebruikte water", + "BREW_DATA_BEAN_WEIGHT_IN": "Welk gewicht aan bonen heb je gebruikt?" + } + }, + "ROASTED_BEFORE": "Geroosterd voor", + "DAY_OLD": "dag oud", + "DAYS_OLD": "dagen oud", + "BEANS_AMOUNT_USED": "Verbruikt", + "CUPPING_BREW": "Proeven", + "COFFEE_DRUNKEN_QUANTITY": "Koffie dronken", + "IMAGE_DELETED": "Afbeelding is verwijderd", + "IMAGE_NOT_DELETED": "Afbeelding kon niet worden verwijderd", + "EXTERNAL_STORAGE_NOT_SUPPORTED": "Sorry, externe opslag wordt niet ondersteund", + "BEANS_ARCHIVED": "Gearchiveerd", + "TAB_ARCHIVE": "Archief", + "TODAY": "Vandaag", + "PLEASE_WAIT": "Even geduld aub...", + "PREPARATION_STYLE_POUR_OVER": "Pourover", + "PREPARATION_STYLE_ESPRESSO": "Espresso", + "PREPARATION_STYLE_FULL_IMMERSION": "Immersie", + "PREPARATION_STYLE_PERCOLATION": "Percolatie", + "PREPARATION_TYPE_STYLE": "Bereidingsstijl", + "PAGE_SETTINGS_FAST_REPEAT_DESCRIPTION": "Activeert een nieuw menu-item - hiermee kun je een brouwsel kopieren.", + "PAGE_SETTINGS_TRACK_BREW_COORDINATES_DESCRIPTION": "Sla geolocatie gegevens op voor elk brouwsel.", + "PAGE_SETTINGS_TRACK_CAFFEINE_CONSUMPTION_DESCRIPTION": "Bewaar de hoeveelheid geconsumeerde cafeïne", + "UPDATE_TITLE": "Wat is er nieuw?", + "NEXT": "Volgende", + "CUSTOM_PARAMETERS": "Parameters aanpassen", + "CUSTOM_DEFAULT_PARAMETERS": "Standaard", + "CUSTOM_MANAGE_PARAMETERS": "Beheer", + "CUSTOM_SORT_PARAMETERS": "Sorteer", + "BREW_PARAMETER_CUSTOMIZE_TITLE": "Aangepaste parameters voor elke bereidingsmethode", + "BREW_PARAMETER_CUSTOMIZE_DESCRIPTION": "Wilt u voor elke bereidingsmethode aangepaste parameters kiezen? Navigeer naar \"Methoden\", open het menu van de specifieke bereidingsmethode en kies \"Parameters aanpassen\". Daar kunt u kiezen welke parameters voor deze bereiding worden gebruikt!", + "BREW_DATA_BREW_QUANTITY_TOOLTIP": "Hoeveelheid water (niet bruikbaar voor espresso)", + "BREW_DATA_COFFEE_FIRST_DRIP_TIME_TOOLTIP": "Eerste druppel tijd van de koffie (alleen espresso)", + "BREW_DATA_PREPARATION_METHOD_TOOLTIP": "Voorbereiding (alleen aanpasbaar indien actief)", + "PAGE_SETTINGS_GENERAL": "Algemene instellingen", + "EDIT_PREPARATION_CUSTOM_PARAMETERS": "Parameters aanpassen", + "ENABLE_PREPARATION_CUSTOM_PARAMETERS": "Aangepaste parameters gebruiken", + "BEAN_ADD_ANOTHER_SORT": "Voeg een andere boon type toe", + "BEAN_SORT": "Boon Type", + "BEAN_SORT_INFORMATION": "Informatie over de variëteit", + "BEAN_SORT_MORE_INFORMATION": "Meer informatie", + "NAVIGATE_TO_PREPARATION_METHODS": "Navigeer naar bereidingsmethoden", + "PREPARATION_TOOLS": "bereidingsmiddelen", + "PREPARATION_TOOLS_INFORMATION": "Voeg verschillende mandjes toe, WDT-gereedschappen voor uw espressomachine; stoffen, papieren of gaasfilters voor uw filterkoffie, enz.", + "PREPARATION_TOOLS_PLACEHOLDER": "Papieren of stoffen filter, VST 20g, 14g mandje, enz.", + "PREPARATION_PARAMETERS_CUSTOMIZED": "Aangepaste parameters", + "BEANS_WEIGHT_AVAILABLE": "Beschikbare bonen", + "SORT_ORDER": "Sorteervolgorde wijzigen", + "ASCENDING": "Oplopend", + "DESCENDING": "Aflopend", + "SORT_AFTER": "Sorteren na", + "BEAN_SORT_NAME_OF_BEAN": "Boon naam", + "BEAN_SORT_ROASTER": "Brander", + "BEAN_SORT_ROASTING_DATE": "Datum van roosteren", + "BEAN_TAB_ROAST_INFORMATION": "Geroosterde informatie", + "BEAN_TAB_GENERAL_INFORMATION": "Algemeen", + "BEAN_TAB_SORT_INFORMATION": "Informatie over de variëteit", + "PAGE_SETTINGS_MANAGE_ARCHIVE": "Archief beheren", + "LAST_USE": "Laatst gebruikt", + "SEARCH": "Zoeken", + "OVERVIEW": "Overzicht", + "BEAN_HEADER_ADDITIONALE_INFORMATION": "Aanvullende informatie", + "THREE_DEE_TOUCH_ACTION_BREW": "Brouw", + "THREE_DEE_TOUCH_ACTION_BEAN": "Boon", + "THREE_DEE_TOUCH_ACTION_PREPARATION": "Bereidingsmethode", + "THREE_DEE_TOUCH_ACTION_MILL": "Koffiemolen", + "PAGE_CREDITS_NOT_EXISTING": "Geen inhoud", + "TIMER_HOUR": "Uren", + "TIMER_MINUTES": "Minuten", + "TIMER_SECONDS": "Seconden", + "EXCEL": { + "BEAN": { + "CREATION_DATE": "Aanmaakdatum", + "ID": "Bonen-ID" + }, + "PREPARATION": { + "CREATION_DATE": "Aanmaakdatum", + "ID": "bereidingsmiddelen" + }, + "GRINDER": { + "CREATION_DATE": "Aanmaakdatum", + "ID": "Molen-ID" + } + }, + "EXCEL_EXPORT": "Excel-export", + "HEALTH_KIT_QUESTION_TITLE": "cafeïneconsumptie opslaan", + "HEALTH_KIT_QUESTION_MESSAGE": "Na activering wordt de geschatte cafeïne van elk brouwsel automatisch opgeslagen in Apple Health.", + "NAV_ROASTING_SECTION": "Bonen roosteren", + "ROASTING_SECTION": { + "NAV_GREEN_BEANS": "Groene bonen", + "NAV_ROASTING_MACHINE": "Roostermachine", + "ROASTING_MACHINE": { + "TOTAL_ROAST_QUANTITY": "Totaalgewicht geroosterd", + "TOTAL_ROAST_COUNT": "Aantal brandingen" + }, + "GREEN_BEAN": { + "ADD": "Toevoegen", + "EDIT": "Bewerking", + "DETAIL": "Groene bonen details", + "ROASTABLE": "Roosterbaar", + "NO_ROASTS_YET": "Nog geen gebrande bonen" + }, + "BEAN": { + "DROP_TEMPERATURE": "Eindtemperatuur van de gebrande boon", + "ROAST_LENGTH": "brand lengte", + "ROASTER_MACHINE": "Roostermachine", + "GREEN_BEAN_WEIGHT": "Gewicht van groene bonen", + "OUTSIDE_TEMPERATURE": "Omgevingstemperatuur", + "HUMIDITY": "Vochtigheid", + "FIRST_CRACK_MINUTE": "eerst kraak minuut", + "FIRST_CRACK_TEMPERATURE": "eerste kraak temperatuur", + "SECOND_CRACK_MINUTE": "Tweede kraak minuut", + "SECOND_CRACK_TEMPERATURE": "tweede kraak temperatuur", + "PLACE_HOLDER": { + "DROP_TEMPERATURE": "Eindtemperatuur van de gebrande boon", + "ROAST_LENGTH": "brand lengte", + "ROASTER_MACHINE": "Roostermachine", + "GREEN_BEAN_WEIGHT": "Gewicht van groene bonen", + "OUTSIDE_TEMPERATURE": "Omgevingstemperatuur", + "HUMIDITY": "Vochtigheid", + "FIRST_CRACK_MINUTE": "Eerste kraak minuut", + "FIRST_CRACK_TEMPERATURE": "Eerste kraak temperatuur", + "SECOND_CRACK_TEMPERATURE": "Tweede kraak temperatuur", + "SECOND_CRACK_MINUTE": "Tweede kraak minuut" + } + } + }, + "PAGE_SETTINGS_MANAGE_SECTIONS": "Meer secties", + "PAGE_SETTINGS_SHOW_ROASTING_SECTION": "Activeer brandersectie", + "PAGE_SETTINGS_SHOW_WATER_SECTION": "Activeer water sectie", + "PAGE_SETTINGS_SHOW_CUPPING_SECTION": "Activeer cupping-sectie", + "BEAN_DATA_BUY_DATE": "Aankoopdatum", + "BEAN_SORT_CREATION_DATE": "Aanmaakdatum", + "BEAN_SORT_PURCHASE_DATE": "Aankoopdatum", + "BEAN_ROAST_COUNT": "Roost aantal", + "TRANSFER_ROAST": "Geroosterd", + "BEAN_TAB_LINKED_ROASTS": "Geroosterd", + "BEAN_DATA_WEIGHT_AFTER_ROASTING": "Gewicht na het roosteren", + "TOAST_GREEN_BEAN_ADDED_SUCCESSFULLY": "Groene bonen toegevoegd", + "TOAST_GREEN_BEAN_EDITED_SUCCESSFULLY": "Groene boon bewerkt", + "TOAST_GREEN_BEAN_ARCHIVED_SUCCESSFULLY": "Groene bonen gearchiveerd", + "TOAST_ROASTING_MACHINE_ADDED_SUCCESSFULLY": "Roostermachine toegevoegd", + "TOAST_ROASTING_MACHINE_EDITED_SUCCESSFULLY": "Brandmachine bewerkt", + "TOAST_ROASTING_MACHINE_ARCHIVED_SUCCESSFULLY": "Brander gearchiveerd", + "DELETE_ROASTING_MACHINE_QUESTION": "Brander verwijderen? Alle gebrande bonen waarnaar verwezen wordt, worden bijgewerkt en niet verwijderd.", + "TOAST_ROASTING_MACHINE_DELETED_SUCCESSFULLY": "Brander verwijderd", + "EDIT_ROASTING_MACHINE": "Bewerk", + "DETAIL_ROASTING_MACHINE": "Details van de brander", + "DELETE_WATER_QUESTION": "Water verwijderen? Alle gerefereerde brouwsels worden bijgewerkt en niet verwijderd", + "ROASTING_MACHINE": { + "PLACE_HOLDER": { + "NAME": "Voeg een naam toe", + "NOTES": "Opmerkingen toevoegen voor deze brander" + } + }, + "NAV_ROASTING_MACHINE": "koffierooster machines", + "PAGE_ROASTING_MACHINE_LIST_NO_MACHINES_EXISTING": "U hebt geen koffiebrander toegevoegd", + "PAGE_ROASTING_MACHINE_LIST_NO_ARCHIVED_MACHINES_EXISTING": "je hebt geen koffiebrander gearchiveerd", + "CHOOSE_ROASTING_MACHINES": "koffiebrander", + "CHOOSE_ROASTING_MACHINE": "koffiebrander", + "POPOVER_BREWS_OPTION_TOGGLE_FAVOURITE": "Favoriet", + "TOAST_BREW_FAVOURITE_ADDED": "Favoriet toegevoegd", + "TOAST_BREW_FAVOURITE_REMOVED": "Favoriet verwijderd", + "BREW_FILTER_JUST_FAVOURITE": "Favorieten", + "STATISTICS_PREPARATION_USAGES": "Bereidingsmethode gebruik", + "STATISTICS_PREPARATION_TIMELINE_USAGES": "Gebruiksgeschiedenis bereidingsmethode", + "STATISTICS_GRINDER_TIMELINE_USAGES": "Gebruiksgeschiedenis van de Maler", + "ACCEPT": "Accepteer", + "STATISTIC_TAB_GENERAL": "Algemeen", + "STATISTIC_TAB_BREWS": "Brouwsels", + "STATISTIC_TAB_BEANS": "Bonen", + "STATISTIC_TAB_PREPARATIONS": "Voorbereidingen", + "STATISTIC_TAB_GRINDERS": "Malers", + "PAGE_STATISTICS_BREW_PER_DAYPROCESSES": "Brouwsels per dag", + "PAGE_STATISTICS_BREW_TIME": "Brouwtijd", + "PAGE_STATISTICS_PHOTOS_TAKEN": "Foto's gemaakt", + "PAGE_SETTINGS_IMAGE_QUALITY": "afbeelding kwaliteit", + "PAGE_SETTINGS_IMAGE_QUALITY_TOOLTIP": "Bepaal in welke kwaliteit uw afbeeldingen moeten worden opgeslagen. Dit kan uw dataverbruik verlagen.", + "PAGE_SETTINGS_BREW_RATING": "Brouw beoordeling", + "PAGE_SETTINGS_BREW_RATING_TOOLTIP": "Is de standaard '-1 tot 5' niet de juiste beoordeling voor u? U kunt in plaats daarvan een '-1 tot 100' schaal gebruiken", + "UPDATE_ENTRY_OF": "Update item {{index}} van {{count}}", + "WEBSITE": "Website", + "SHARE": "Deel", + "ANDROID_FILE_ACCESS_NEEDED_TITLE": "Toegang tot gedeeld bestand vereist", + "ANDROID_FILE_ACCESS_NEEDED_DESCRIPTION": "Om de app volledig te laten werken, vragen we u om bestandstoegang te autoriseren. Anders ontstaan er problemen bij het gebruik van de app. Dit is specifiek nodig voor het automatische back-upsysteem.", + "COULD_NOT_ACCESS_FILE": "We konden het gekozen bestand niet openen", + "WRONG_FILE_FORMAT": "U hebt een niet-ondersteund bestandsformaat gekozen", + "SCAN_BEAN": "Scan pakket", + "CLEAR": "leeg maken", + "BEAN_LOOKS_LIKE_CONSUMED": "Het lijkt erop dat deze bonen op zijn. Wil je ze archiveren?", + "CUPPING_1": "Fruit", + "CUPPING_2": "Citrus", + "CUPPING_3": "Citroen & limonade", + "CUPPING_4": "Limoen", + "CUPPING_5": "Grapefruit", + "CUPPING_6": "Clementine", + "CUPPING_7": "Mandarijn", + "CUPPING_8": "mandarijn sinaasappel", + "CUPPING_9": "sinasappel", + "CUPPING_10": "Appel\/peer", + "CUPPING_11": "Groene appel", + "CUPPING_12": "Rode appel", + "CUPPING_13": "Meloen", + "CUPPING_14": "Watermeloen", + "CUPPING_15": "Honingdauw meloen", + "CUPPING_16": "Cantaloupe meloen", + "CUPPING_17": "Druif", + "CUPPING_18": "Witte druif", + "CUPPING_19": "Groene druif", + "CUPPING_20": "Rode druif", + "CUPPING_21": "Concord-druif", + "CUPPING_22": "Tropisch fruit", + "CUPPING_23": "Litchi", + "CUPPING_24": "Stervrucht", + "CUPPING_25": "Tamarinde", + "CUPPING_26": "Passievrucht", + "CUPPING_27": "Ananas", + "CUPPING_28": "Mango", + "CUPPING_29": "Papaja", + "CUPPING_30": "Kiwi", + "CUPPING_31": "Banaan", + "CUPPING_32": "Kokosnoot", + "CUPPING_33": "Steenvrucht", + "CUPPING_34": "Perzik", + "CUPPING_35": "Nectarine", + "CUPPING_36": "Abrikoos", + "CUPPING_37": "Pruim", + "CUPPING_38": "Kers", + "CUPPING_39": "Zwarte kers", + "CUPPING_40": "Bes", + "CUPPING_41": "Cranberry", + "CUPPING_42": "Framboos", + "CUPPING_43": "Aardbei", + "CUPPING_44": "Bosbes", + "CUPPING_45": "Rode bes", + "CUPPING_46": "Zwarte bes", + "CUPPING_47": "Gedroogd fruit", + "CUPPING_48": "Gouden rozijn", + "CUPPING_49": "Rozijn", + "CUPPING_50": "Gedroogde vijg", + "CUPPING_51": "Gedroogde dadels", + "CUPPING_52": "Gedroogde Pruim", + "CUPPING_53": "Zoet & gebrand", + "CUPPING_54": "Chocolade", + "CUPPING_55": "Cacaonibs", + "CUPPING_56": "Donkere chocolade", + "CUPPING_57": "Bakkers chocolade", + "CUPPING_58": "Bitterzoete chocolade", + "CUPPING_59": "Cacaopoeder", + "CUPPING_60": "Melkchocolade", + "CUPPING_61": "Noot", + "CUPPING_62": "Walnoot", + "CUPPING_63": "Pinda", + "CUPPING_64": "Cashew", + "CUPPING_65": "Pecannoot", + "CUPPING_66": "Hazelnoot", + "CUPPING_67": "Amandel", + "CUPPING_68": "Graan & Graanproducten", + "CUPPING_69": "Zoet broodgebak", + "CUPPING_70": "Granola", + "CUPPING_71": "Graham-cracker", + "CUPPING_72": "Rogge", + "CUPPING_73": "Tarwe", + "CUPPING_74": "Gerst", + "CUPPING_75": "Vers brood", + "CUPPING_76": "Zoet & Suikerachtig", + "CUPPING_77": "Vanille", + "CUPPING_78": "Noga", + "CUPPING_79": "Honing", + "CUPPING_80": "Boter", + "CUPPING_81": "Room", + "CUPPING_82": "Marshmallow", + "CUPPING_83": "Rietsuiker", + "CUPPING_84": "Bruine suiker", + "CUPPING_85": "Karamel", + "CUPPING_86": "Ahornsiroop", + "CUPPING_87": "Melasse", + "CUPPING_88": "Cola", + "CUPPING_89": "Geroosterd", + "CUPPING_90": "Toast", + "CUPPING_91": "Verbrande suiker", + "CUPPING_92": "Rokerig", + "CUPPING_93": "Koolstof", + "CUPPING_94": "Plantaardig, hartig en kruidig", + "CUPPING_95": "Kruiden", + "CUPPING_96": "Zwarte peper", + "CUPPING_97": "Witte peper", + "CUPPING_98": "Kaneel", + "CUPPING_99": "Koriander", + "CUPPING_100": "Gember", + "CUPPING_101": "Nootmuskaat", + "CUPPING_102": "Kerrie", + "CUPPING_103": "Drop-anijs", + "CUPPING_104": "Kruidnagel", + "CUPPING_105": "Hartig", + "CUPPING_106": "Leerachtig", + "CUPPING_107": "Vleesachtig", + "CUPPING_108": "Sojasaus", + "CUPPING_109": "Zongedroogde tomaat", + "CUPPING_110": "Tomaat", + "CUPPING_111": "Plantaardig aards kruid", + "CUPPING_112": "Grond", + "CUPPING_113": "Vers hout", + "CUPPING_114": "Ceder", + "CUPPING_115": "Tabak", + "CUPPING_116": "Hooi \/ stro", + "CUPPING_117": "Bladgroenten", + "CUPPING_118": "Olijf", + "CUPPING_119": "Groene peper", + "CUPPING_120": "Pompoen", + "CUPPING_121": "Paddestoel", + "CUPPING_122": "Zoete erwt", + "CUPPING_123": "Sneeuwerwt", + "CUPPING_124": "Grassig", + "CUPPING_125": "Dille", + "CUPPING_126": "Salie", + "CUPPING_127": "Munt", + "CUPPING_128": "Groene thee", + "CUPPING_129": "Zwarte thee", + "CUPPING_130": "Hop", + "CUPPING_131": "Bergamot", + "CUPPING_132": "Bloemrijk", + "CUPPING_133": "Bloemen", + "CUPPING_134": "Hibiscus", + "CUPPING_135": "Rozenbottels", + "CUPPING_136": "Lavendel", + "CUPPING_137": "Magnolia", + "CUPPING_138": "Jasmijn kamperfoelie", + "CUPPING_139": "Oranjebloesem", + "CUPPING_140": "Citroengras", + "WATER_SECTION": { + "NAV_WATER": "Water", + "YOU_GOT_NO_ARCHIVED_WATER": "Je hebt nog geen water gearchiveerd", + "YOU_GOT_NO_WATER": "Je hebt nog geen water toegevoegd", + "CATEGORY_INFORMATION": "Water informatie", + "CATEGORY_GENERAL": "Algemeen", + "WATER_BOTTLE_EXPLANATION": "Waterflessen vermelden de concentratie meestal in eenheden van ppm = mg\/L", + "USED_TIMES": "Aantal keren gebruikt", + "AMOUNT": "Gebruikte hoeveelheid", + "WATER": { + "GENERAL_HARDNESS": "Algemene hardheid (GH)", + "TOTAL_ALKALINITY": "Totale alkaliteit (KH)", + "CALCIUM": "Kalium (Ca)", + "MAGNESIUM": "Magnesium (Mg)", + "SODIUM": "Natrium (Na)", + "TDS": "Totaal opgeloste vaste stoffen (TDS)", + "UNITS": "Eenheden", + "PLACE_HOLDER": { + "GENERAL_HARDNESS": "Algemene hardheid", + "TOTAL_ALKALINITY": "Totale alkaliteit", + "CALCIUM": "Kalium (Ca)", + "MAGNESIUM": "Magnesium (Mg)", + "SODIUM": "Natrium (Na)", + "TDS": "Totaal opgeloste vaste stoffen (TDS)", + "NAME": "Voeg waternaam toe", + "NOTES": "Voeg wat notities toe voor je water", + "POTASSIUM": "Kalium (K)", + "CHLORIDE": "Chloride (Cl)", + "SULFATE": "Sulfaat (SO4)" + }, + "WATER_UNIT": { + "UNKNOWN": "Onbekend", + "PPM": "ppm als CaCO3", + "MG_L": "mg\/L", + "MMOL_L": "mmol\/L", + "DH": "°dH" + }, + "POTASSIUM": "Kalium (K)", + "CHLORIDE": "Chloride (Cl)", + "SULFATE": "Sulfaat (SO4)" + } + }, + "BREW_BRIX_CALCULATION": "Graden Brix", + "SET_TDS": "TDS instellen", + "TOTAL_WEIGHT": "Totaal gewicht", + "CALCULATED_WEIGHT": "Berekend gewicht", + "SET_WEIGHT": "Gewicht instellen", + "ADD_FLAVORS_AROMAS_TITLE": "Aroma's \/ Smaken", + "CUSTOM_FLAVORS_AROMAS": "Individueel aroma", + "CUSTOM_FLAVORS_AROMAS_PLACEHOLDER": "Voeg je individuele aroma toe", + "PREDEFINED_FLAVORS_AROMAS": "Veel voorkomende aroma's", + "ADD_AROMA_FLAVOR": "Aroma's\/smaken toevoegen", + "BEAN_WEIGHT_IN_PLACEHOLDER": "Bonen uit de verpakking gehaald", + "VESSEL_PLACEHOLDER": "Naam van het Serveerkan en het leeggewicht ervan", + "GRIND_WEIGHT_PLACEHOLDER": "Gewicht van de gemalen bonen die voor het brouwen worden gebruikt", + "PRESET_BREW_TITLE": "Gebruik laatste brouwsel als voorinstelling", + "CUPPING_BREW_TAB_AROMA": "Aroma", + "CUPPING_BREW_TAB_TASTING": "Systematische cupping", + "WATER_PLACEHOLDER": "Activeer het watergedeelte in het instellingenmenu voor volledige functionaliteit", + "PAGE_SETTINGS_SCALES": "Weegschalen", + "CONNECT": "Verbinden", + "DISCONNECT": "Loskoppelen", + "SCALE": { + "BLUETOOTH_SCAN_RUNNING": "Zoeken naar weegschaal tot 60s", + "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", + "CONNECTION_NOT_ESTABLISHED": "Weegschaal niet gevonden, of verbinding kon niet tot stand worden gebracht", + "CONNECTED_SUCCESSFULLY": "Weegschaal verbonden", + "DISCONNECTED_SUCCESSFULLY": "Weegschaal losgekoppeld", + "DISCONNECTED_UNPLANNED": "Weegschaal onverwachts losgekoppeld", + "REQUEST_PERMISSION": { + "LOCATION": "Om Bluetooth-weegschalen te vinden, heeft de app toegang nodig tot de locatie.", + "BLUETOOTH": "Om bluetooth-weegschalen te vinden, heeft de app toegang tot bluetooth nodig" + }, + "INFORMATION_DESCRIPTION": "Ondersteunde weegschalen zijn: Decent Scale, Acaia, Felicita, Hiroia Jimmy, Skale 2, DiFluid Microbalance, Smartchef Scale, Blackcoffee.io, Bookoo Mini Scale en Eureka Precisa. Let op: Als de Eureka Precisa een negatieve waarde ontvangt, stopt de timer" + }, + "QR": { + "WRONG_QRCODE_DESCRIPTION": "Ongeldige QR-code of onbekende inhoud", + "WRONG_QRCODE_TITLE": "Fout", + "WRONG_LINK_DESCRIPTION": "Ongeldige QR-link", + "WRONG_LINK_TITLE": "Fout", + "SERVER": { + "ERROR_OCCURED": "Er is een fout opgetreden. De QR-code kon niet worden gelezen. Probeer het opnieuw.", + "BEAN_NOT_APPROVED": "Boon is nog niet goedgekeurd, probeer het later nog eens" + }, + "BEAN_SUCCESSFULLY_SCANNED": "Bean succesvol gescand", + "BEAN_SUCCESSFULLY_REFRESHED": "Boon succesvol bijgewerkt", + "IMAGES_GETTING_DOWNLOADED": "Afbeeldingen downloaden" + }, + "RETRY_CONNECT": "Verbinding opnieuw proberen", + "SMART_SCALE_STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de weegschaal verbonden, zelfs als de app op de achtergrond draait", + "BREW_FLOW_WEIGHT": "Gewicht", + "BREW_FLOW_WEIGHT_PER_SECOND": "Stroom (afgevlakt)", + "ROAST_TYPE_UNKNOWN": "onbekend", + "ROAST_TYPE_CINNAMON_ROAST": "Cinnamon Branding", + "ROAST_TYPE_AMERICAN_ROAST": "Amerikaans Branding", + "ROAST_TYPE_NEW_ENGLAND_ROAST": "Nieuw-Engeland Branding", + "ROAST_TYPE_HALF_CITY_ROAST": "Half City Branding", + "ROAST_TYPE_MODERATE_LIGHT_ROAST": "Matig-lichte branding", + "ROAST_TYPE_CITY_ROAST": "City Branding", + "ROAST_TYPE_CITY_PLUS_ROAST": "City+ Branding", + "ROAST_TYPE_FULL_CITY_ROAST": "Full City Branding", + "ROAST_TYPE_FULL_CITY_PLUS_ROAST": "Full City + Branding", + "ROAST_TYPE_ITALIAN_ROAST": "Ialiaanse Branding", + "ROAST_TYPE_VIEANNA_ROAST": "Weense Branding", + "ROAST_TYPE_FRENCH_ROAST": "Franse Branding", + "ROAST_TYPE_CUSTOM_ROAST": "Aangepast", + "BEAN_MIX_UNKNOWN": "onbekend", + "BEAN_MIX_SINGLE_ORIGIN": "Single Origin", + "BEAN_MIX_BLEND": "Melange", + "BEAN_ROASTING_TYPE_FILTER": "Filter", + "BEAN_ROASTING_TYPE_ESPRESSO": "Espresso", + "BEAN_ROASTING_TYPE_OMNI": "Omni", + "BEAN_ROASTING_TYPE_UNKNOWN": "Onbekend", + "SMART_SCALE_LOG": "Activeer logbestanden voor slimme weegschaal (alleen voor foutopsporing)", + "TOAST_PREPARATION_TOOL_EDITED_SUCCESSFULLY": "Voorbereidingstool bewerkt", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE": "Bluetooth-weegschaal", + "PAGE_SETTINGS_TAB_GENERAL": "Algemeen", + "SMART_SCALE_TARE_ON_BREW": "Tarraweegschaal op nieuw brouwsel", + "SMART_SCALE_TARE_ON_START_TIMER": "Tarra weegschaal bij het starten van de timer", + "PAGE_SETTINGS_BREW_RATING_STEPS": "Beoordelingsstappen", + "BREW_AVG_FLOW_WEIGHT_PER_SECOND": "Ø Stroom", + "CUSTOM_LIST_VIEW_PARAMETERS": "Parameters voor lijstweergave", + "NAV_LIST_VIEW_CUSTOM_PARAMETERS": "Parameters voor lijstweergave", + "PAGE_LIST_VIEW_CUSTOM_PARAMETERS_DESCRIPTION": "Bepaal welke parameters moeten worden weergegeven op de tegels van de lijstweergave", + "BREW_DATA_VESSEL_NAME_WEIGHT": "Serveerkan Naam\/Gewicht", + "IGNORE_NEGATIVE_VALUES": "Negeer negatieve gewichtswaarden", + "IGNORE_ANOMALY_VALUES": "Negeer afwijkende waarden", + "IGNORE_ANOMALY_VALUES_TOOLTIP": "Bijvoorbeeld: Een kopje rond bewegen op de weegschaal", + "TOAST_BEAN_FAVOURITE_ADDED": "Favoriet toegevoegd", + "TOAST_BEAN_FAVOURITE_REMOVED": "Favoriet verwijderd", + "QR_CODE_SCANNER_INFORMATION_TITLE": "QR-code", + "QR_CODE_SCANNER_INFORMATION_DESCRIPTION": "Alle gescande boneninformatie komt rechtstreeks van de branderij. Mocht u onjuiste of misleidende informatie aantreffen, laat het mij dan weten via e-mail: info@beanconqueror.com.", + "DONT_SHOW_AGAIN": "Niet meer weergeven", + "ARCHIVED_TOOLS": "Gearchiveerd gereedschap", + "UNARCHIVE": "Herstel", + "PAGE_SETTINGS_HIDE_ARCHIVED_BREWS_DASHBOARD": "Toon gearchiveerde brouwsels op dashboard", + "PAGE_SETTINGS_HIDE_ARCHIVED_BREWS_DASHBOARD_DESCRIPTION": "Moeten gearchiveerde brouwsels op de startpagina worden weergegeven?", + "COPY": "Kopiëren", + "TOAST_PREPARATION_METHOD_REPEATED_SUCCESSFULLY": "Bereidingsmethode succesvol gekopieerd", + "PREPARATION_TYPE_CAFEC_FLOWER": "Cafec Flower", + "PREPARATION_TYPE_DECEMBER_DRIPPER": "December Dripper", + "PREPARATION_TYPE_DECENT_ESPRESSO": "Decent Espresso", + "PREPARATION_TYPE_HARIO_SWITCH": "Hario Switch", + "PREPARATION_TYPE_HARIO_WOODNECK": "Hario Woodneck", + "PREPARATION_TYPE_RATIO_SIX_COFFEE_BREWER": "Ratio Six-koffiezetapparaat", + "PREPARATION_TYPE_ROK": "ROK", + "PREPARATION_TYPE_TORNADO_DUO": "Tornado-duo", + "PREPARATION_TYPE_TRICOLATE": "Tricolate", + "QR_CODE_REFRESH_DATA_MESSAGE": "Alle informatie voor deze boon wordt overschreven, doorgaan?", + "POPOVER_QR_CODE_REFRESH": "Gegevens opnieuw laden", + "BREW_FLOW_WEIGHT_REALTIME": "Stroom (realtime)", + "SMART_SCALE_STOP_TIMER_ON_BREW": "Stop de timer van de weegschaal bij een nieuw brouwsel", + "SMART_SCALE_RESET_TIMER_ON_BREW": "Reset de weegschaaltimer bij een nieuw brouwsel", + "BREW_PRESSURE_FLOW": "Druk", + "BREW_TEMPERATURE_REALTIME": "Temperatuur", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_SHOW_GRAPHS_FILTER": "Grafieken weergeven voor filter", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_SHOW_GRAPHS_ESPRESSO": "Toon grafieken voor espresso", + "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE": "Drukapparaat", + "PAGE_SETTINGS_TAB_BLUETOOTH_TEMPERATURE": "Temperatuur apparaat", + "PRESSURE_LOG": "Activeer logbestanden voor drukapparaat", + "PRESSURE_THRESHOLD_ACTIVE": "Starttimer met vooraf gedefinieerde druk", + "PRESSURE_THRESHOLD_BAR": "Drempelwaarde druk", + "TIMER_MILLISECONDS": "MS", + "PAGE_SETTINGS_BREW_ENABLE_MILLISECONDS": "Milliseconden?", + "PAGE_SETTINGS_BREW_ENABLE_MILLISECONDS_DESCRIPTION": "Gebruik milliseconden om uw brouwsels nog nauwkeuriger te analyseren", + "PAGE_SETTINGS_BEAN_RATING": "Bonen beoordeling", + "PAGE_SETTINGS_BEAN_RATING_TOOLTIP": "Is de standaard '0 tot 5' niet de juiste beoordeling voor u? U kunt in plaats daarvan een '0 tot 100'-schaal gebruiken", + "PAGE_SETTINGS_BEAN_RATING_STEPS": "Stappen voor het beoordelen van bonen", + "COFFEE_GRAMS_BREWED": "grammen gebrouwen", + "SMART_SCALE_MAXIMIZE_ON_START_TIMER": "Maximaliseer realtime-grafiek bij het starten van de timer", + "PRESSURE": { + "CONNECTION_NOT_ESTABLISHED": "Drukapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", + "CONNECTED_SUCCESSFULLY": "Drukapparaat aangesloten", + "DISCONNECTED_SUCCESSFULLY": "Drukapparaat losgekoppeld", + "DISCONNECTED_UNPLANNED": "Drukapparaat onverwachts losgekoppeld", + "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd het drukapparaat aangesloten, zelfs als de app op de achtergrond draait", + "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: Popsicle, Pressensor, Smart Espresso Profiler, Bookoo Espresso Monitor", + "BLUETOOTH_SCAN_RUNNING": "Zoeken naar drukapparaat gedurende maximaal 60 seconden", + "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", + "REQUEST_PERMISSION": { + "LOCATION": "Om drukapparaten te vinden, heeft de app toegang nodig tot de locatie.", + "BLUETOOTH": "Om drukapparaten te vinden, heeft de app toegang tot Bluetooth nodig" + } + }, + "POPOVER_BLUETOOTH_ACTION_RECONNECT_SCALE": "Weegschaal opnieuw verbinden", + "POPOVER_BLUETOOTH_ACTION_RECONNECT_PRESSURE_DEVICE": "Drukapparaat opnieuw aansluiten", + "POPOVER_SHOW_BREWS": "Toon brouwsels", + "LAST_USED_GRIND_SIZE_SETTING": "Laatste maalstand", + "LAST_USED_BEAN": "Laatste boon", + "PAGE_SETTINGS_BREW_MILLISECONDS_DECIMAL_PLACES_DESCRIPTION": "Hoeveel decimalen moeten er worden weergegeven?", + "SMART_SCALE_COMMAND_DELAY": "Opdracht vertraging", + "SMART_SCALE_COMMAND_DELAY_TOOLTIP": "Hoeveel tijd moet er verstrijken tussen elk bluetooth-commando?", + "SUPPORT_ME": "Donatie", + "PAGE_SETTINGS_BREW_DISPLAY_BEAN_IMAGE": "Bonenafbeeldingen op brouwsels weergeven?", + "PAGE_SETTINGS_BREW_DISPLAY_BEAN_IMAGE_DESCRIPTION": "Als er een bonenafbeelding bestaat, wordt deze gebruikt in plaats van de afbeelding van de bereidingsmethode", + "DOWNLOAD_XLSX": "Excel downloaden", + "DOWNLOAD_JSON": "JSON downloaden", + "NAV_BEAN_PARAMS": "Boon Parameters", + "BEAN_DATA_ROAST_NAME_TYPE": "Brand graad", + "ENABLE_BEAN_SORT_INFORMATION": "Variëteit-informatie inschakelen", + "BEAN_SORT_MIX": "Bonenmix", + "PAGE_MANAGE_BEAN_PARAMETERS_DESCRIPTION": "Markeer welke parameters moeten worden weergegeven bij het bewerken van bean-informatie.", + "PAGE_BEAN_LIST_VIEW_CUSTOM_PARAMETERS_DESCRIPTION": "Bepaal de parameters die moeten worden weergegeven in lijstweergaven voor bonen", + "BEAN_DATA_NAME_TOOLTIP": "De naam van de bonen", + "BEAN_DATA_ROASTER_TOOLTIP": "Wie is de brander", + "BEAN_DATA_BUY_DATE_TOOLTIP": "Wanneer heb je de bonen gekocht?", + "BEAN_DATA_ROASTING_DATE_TOOLTIP": "Wat is de branddatum van de bonen?", + "BEAN_DATA_ROASTING_TYPE_TOOLTIP": "Voor welke bereidingswijze is deze boon geroosterd, bijvoorbeeld Filter", + "BEAN_DATA_ROAST_NAME_TOOLTIP": "Wat is de brandingsgraad van de bonen?", + "BEAN_DATA_ROAST_NAME_TYPE_TOOLTIP": "Welk type branding (Cinnamon, New England, etc.)", + "BREW_DATA_RATING_TOOLTIP": "Je waardering", + "BEAN_SORT_MIX_TOOLTIP": "Zijn de bonen een melange?", + "BEAN_DATA_WEIGHT_TOOLTIP": "Hoeveel wegen de bonen?", + "BEAN_DATA_COST_TOOLTIP": "Hoeveel hebben de bonen gekost?", + "BEAN_DATA_AROMATICS_TOOLTIP": "Welke aroma's\/smaken hebben de bonen?", + "BEAN_DATA_CUPPING_POINTS_TOOLTIP": "Hoeveel cupping-punten heeft de boon?", + "BEAN_DATA_DECAFFEINATED_TOOLTIP": "Is het cafeïnevrij?", + "BEAN_DATA_URL_TOOLTIP": "URL naar de winkel", + "BEAN_DATA_EAN_TOOLTIP": "Het EAN\/artikelnummer", + "NOTES_TOOLTIP": "Aantekeningen gemaakt", + "BREW_DATA_ATTACHMENTS_TOOLTIP": "Foto's toevoegen?", + "ENABLE_BEAN_SORT_INFORMATION_TOOLTIP": "Meer informatie over de bonen: waar komen ze vandaan, wanneer zijn ze geoogst, etc.", + "BEAN_DATA_COUNTRY_TOOLTIP": "Uit welk land komen de bonen?", + "BEAN_DATA_REGION_TOOLTIP": "Uit welke regio komen de bonen?", + "BEAN_DATA_FARM_TOOLTIP": "Van welke boerderij komen de bonen?", + "BEAN_DATA_FARMER_TOOLTIP": "Wie verbouwde deze bonen", + "BEAN_DATA_ELEVATION_TOOLTIP": "Op welke hoogte groeiden de bonen?", + "BEAN_DATA_PROCESSING_TOOLTIP": "Hoe zijn de bonen verwerkt (natuurlijk, gewassen, enz.)", + "BEAN_DATA_VARIETY_TOOLTIP": "De Koffieboon Variëteit (SL28 bv.)", + "BEAN_DATA_HARVEST_TIME_TOOLTIP": "In welk jaar\/maand werden deze bonen geoogst?", + "BEAN_DATA_PERCENTAGE_TOOLTIP": "Hoeveel procent van deze bonen zit er in de zak?", + "BEAN_DATA_CERTIFICATION_TOOLTIP": "Welke certificeringen hebben de bonen (bijvoorbeeld fairtrade)", + "BEAN_DATA_PURCHASING_PRICE_TOOLTIP": "Wat was de aankoopprijs van de koffiebrander", + "BEAN_DATA_FOB_PRICE_TOOLTIP": "Wat was de Free-On-Board (FOB) prijs toen de brander het kocht?", + "BEAN_PARAMETER_CUSTOMIZE_TITLE": "Pas de informatie aan die u voor bonen wilt gebruiken", + "BEAN_PARAMETER_CUSTOMIZE_DESCRIPTION": "Er kan veel informatie over de bonen worden ingevoerd of gebruikt. Kies zelf de parameters die u wilt invullen en welke u wilt weergeven", + "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_TITLE": "Timer resetten!", + "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_DESCRIPTION": "Omdat je een Bluetooth-apparaat hebt aangesloten, moet je eerst je timer resetten voordat je kunt beginnen.", + "BREW_FILTER_JUST_CHART_DATA": "Alleen grafieken", + "SCALE_RESET_TRIGGERED_DESCRIPTION": "De bluetooth weegschaal wil zowel de app-timer als de brouwgrafiek resetten, wil je doorgaan?", + "SCALE_RESET_TRIGGERED_TITLE": "Opnieuw instellen?", + "NAV_REPEAT_PARAMETERS": "Herhalingsparameters definiëren", + "PAGE_REPEAT_PARAMETERS_DESCRIPTION": "Markeer welke parameters vooraf moeten worden ingesteld wanneer u een specifieke brouwbeurt herhaalt", + "CUSTOM_REPEAT_PARAMETERS": "Herhalen", + "CUSTOM_REPEAT_PARAMETERS_DESCRIPTION": "Aangepaste herhaling activeren?", + "PAGE_SETTINGS_USE_NUERMIC_KEYBOARD_FOR_GRIND_SIZE": "Numeriek toetsenbord voor maalinstelling?", + "PAGE_SETTINGS_USE_NUERMIC_KEYBOARD_FOR_GRIND_SIZE_DESCRIPTION": "Wilt u een numeriek toetsenbord gebruiken voor de maalinstelling, in plaats van het hele toetsenbord?", + "PREPARATION_DEVICE": { + "TYPE": { + "NONE": "Geen", + "XENIA": "Xenia", + "METICULOUS": "Meticulous" + }, + "URL": "URL-adres", + "CHOOSE_DEVICE": "Kies apparaat", + "CONNECTION": { + "UNSUCCESFULLY": "Er kon geen verbinding met de machine worden gemaakt", + "SUCCESFULLY": "Verbinding met machine was succesvol" + }, + "TYPE_XENIA": { + "TITLE": "Xenia machine", + "PRESS_START_SCRIPT": "Start script bij start", + "FIRST_DRIP_SCRIPT": "Start script bij eerste druppel", + "SCRIPT_AT_WEIGHT": "Gewicht voor scriptuitvoering", + "SCRIPT_LIST_GENERAL_0": "Niets", + "SCRIPT_LIST_GENERAL_1": "Espresso, 25 seconden", + "SCRIPT_LIST_GENERAL_2": "Espresso, eindeloos", + "SCRIPT_LIST_GENERAL_STOP": "Schot stoppen", + "CHOOSE_SCRIPT_AT_WEIGHT": "Kies script voor gewicht bereikt", + "ERROR_NOT_ALL_SCRIPTS_FOUND": "Een of meer scripts konden niet worden gevonden, ze zijn gereset", + "ERROR_CONNECTION_COULD_NOT_BE_ESTABLISHED": "De verbinding met de xenia espressomachine kon niet tot stand worden gebracht. Controleer of u zich op het juiste netwerk (LAN) bevindt, of u het juiste IP-adres hebt ingevoerd, etc.", + "CHECKING_CONNECTION_TO_PORTAFILTER": "Verbinding met Xenia wordt gecontroleerd", + "GRABING_SCRIPTS": "Scripts laden vanuit Xenia", + "BREW_BY_WEIGHT_ACTIVE": "Brouwen op gewicht actief" + }, + "API_VERSION": "Api-versie", + "RESIDUAL_LAG_TIME": "Resterende vertragingstijd", + "RESIDUAL_LAG_TIME_DESCRIPTION": "Stel de tijd in die overeenkomt met het resterende water. Met een naakte portafilter heb je een lagere tijd nodig, met een tuit een hogere. Hoe langzamer uw weegschaal het gewicht rapporteert, hoe meer tijd u nodig heeft", + "TYPE_METICULOUS": { + "TITLE": "Meticulous machine", + "NO_PROFILE": "Geen profiel", + "CHOOSE_PROFILE": "Profiel kiezen", + "SHOT_STARTED": "Brouwen gestart", + "SHOT_ENDED": "Brouwen gestopt" + } + }, + "DEVICE_CONNECTION": "Apparaatverbinding", + "PREPARATION_DEVICE_CONNECTION": "Apparaatverbinding", + "MANUAL_EXPORT_TO_VISUALIZER": "Exporteren naar Visualizer", + "ONLY_FAVOURITES": "Alleen favorieten", + "TEMPERATURE": { + "CONNECTION_NOT_ESTABLISHED": "Temperatuurapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", + "CONNECTED_SUCCESSFULLY": "Temperatuurapparaat aangesloten", + "DISCONNECTED_SUCCESSFULLY": "Temperatuurapparaat losgekoppeld", + "DISCONNECTED_UNPLANNED": "Temperatuurapparaat onverwachts losgekoppeld", + "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de thermometer verbonden, zelfs als de app op de achtergrond staat", + "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: ETI Ltd BLE-thermometers (ThermaQ Blue, BlueTherm, enz.), Combustion Inc., Meater (niet Meater+ of Meater 2)", + "BLUETOOTH_SCAN_RUNNING": "Zoeken naar temperatuurapparaat gedurende maximaal 60 seconden", + "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", + "REQUEST_PERMISSION": { + "LOCATION": "Om temperatuurmeters te vinden, heeft de app toegang nodig tot de locatie.", + "BLUETOOTH": "Om temperatuurapparaten te vinden, heeft de app toegang tot Bluetooth nodig" + }, + "LOG": "Logbestanden voor temperatuurapparaat activeren", + "THRESHOLD_ACTIVE": "Start timer met vooraf ingestelde temperatuur", + "THRESHOLD_TEMP": "Drempel temperatuur" + }, + "POPOVER_BLUETOOTH_ACTION_RECONNECT_TEMPERATURE_DEVICE": "Temperatuurapparaat opnieuw aansluiten", + "PRESSURE_DEVICE_JUST_VISIBLE_ON_ESPRESSO": "Drukapparaat is alleen bruikbaar bij de bereidingswijze 'Espresso'", + "PRESSURE_MESSAGE_AFTER_CONNECTION": "Bekend gedrag (in analyse): Houd er rekening mee dat het langer kan duren om verbinding te maken nadat u uw telefoon opnieuw hebt opgestart of wanneer u de app langere tijd niet hebt gebruikt. Na deze tijd zou het verbindingsprobleem opgelost moeten zijn.", + "SMART_SCALE_ACAIA_HEARTBEAT_TIMER": "Hartslagtimer - Speciaal voor Acaia Scales", + "SMART_SCALE_ACAIA_HEARTBEAT_TIMER_TOOLTIP": "Alleen gebruikt voor Acaia-weegschalen! - Oudere Acaia-weegschalen hebben een hartslagsignaal nodig. Als u problemen ondervindt, probeer dan de hartslag op een hogere frequentie in te stellen.", + "SHARE_BEAN_URL": "Delen als URL", + "SHARE_BEAN_IMAGE": "Delen als afbeelding", + "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE": "Espresso - Automatisch stoppen met brouwen", + "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE_DESCRIPTION": "Deze instelling wordt alleen gebruikt voor brouwsels van het type 'espresso'. Het brouwsel wordt automatisch gestopt wanneer er geen flow wordt gedetecteerd.", + "BREW_DATA_BREW_QUANTITY_TOOLTIP_BREW_RATIO": "De zetverhouding wordt berekend met deze waarde voor alle brouwsels, maar niet voor type 'espresso'.", + "BREW_DATA_BREW_BEVERAGE_QUANTITY_TOOLTIP_BREW_RATIO": "De zetverhouding wordt alleen met deze waarde berekend voor brouwsels van het type 'espresso'", + "SMART_SCALE_DID_NOT_SEND_ANY_WEIGHT_DESCRIPTION": "Het lijkt erop dat de bluetooth weegschaal niet goed is aangesloten. Dit gebeurt meestal op iOS-apparaten met Acaia weegschalen, sluit de weegschaal opnieuw aan en zorg ervoor dat de gewichtstegel wordt bijgewerkt.", + "SMART_SCALE_DID_NOT_SEND_ANY_WEIGHT_TITLE": "Geen gewichtswaarden?", + "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE_MIN_FLOW_DESCRIPTION": "De stroomsnelheid waarbij het zetten moet worden gestopt. Het zetten wordt pas gestopt als er minimaal 5 seconden zijn verstreken, er 5 gram in de kop zit of als u het gewicht van de gemalen koffie hebt ingevoerd - er is minimaal een zetverhouding van 1:1 bereikt (bijv.: 18 g erin, 18 g eruit). Nadat aan deze voorwaarden is voldaan, wordt de hier ingestelde minimale stroomsnelheid gecontroleerd", + "ONLY_BEST_BREWS": "Alleen de beste brouwsels", + "POPOVER_BEST_BREW": "Beste brouwsel", + "PAGE_SETTINGS_BEST_BREW": "Beste brouwsels activeren", + "PAGE_SETTINGS_BEST_BREW_DESCRIPTION": "Markeer je beste brouwsel voor een specifieke boon. Elke boon kan één beste brouwsel hebben in plaats van meerdere favorieten.", + "PAGE_SETTINGS_TAB_BLUETOOTH_REFRACTOMETER": "Refractometer apparaat", + "REFRACTOMETER": { + "CONNECTION_NOT_ESTABLISHED": "Refractometerapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", + "CONNECTED_SUCCESSFULLY": "Refractometerapparaat aangesloten", + "DISCONNECTED_SUCCESSFULLY": "Refractometerapparaat losgekoppeld", + "DISCONNECTED_UNPLANNED": "Refractometerapparaat onverwachts losgekoppeld", + "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de refractometer verbonden, zelfs als de app op de achtergrond draait", + "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: DiFluid R2", + "BLUETOOTH_SCAN_RUNNING": "Zoeken naar refractometer-apparaat gedurende maximaal 60 seconden", + "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", + "REQUEST_PERMISSION": { + "LOCATION": "Om refractometerapparaten te vinden, heeft de app toegang nodig tot de locatie.", + "BLUETOOTH": "Om refractometerapparaten te vinden, heeft de app toegang tot Bluetooth nodig" + }, + "LOG": "Activeer logbestanden voor refractometerapparaat", + "READ_END": "Test voltooid - resultaat ontvangen" + }, + "COPIED_TO_CLIPBOARD_SUCCESSFULLY": "Toegevoegd aan klembord", + "COPIED_TO_CLIPBOARD_UNSUCCESSFULLY": "Kan niet worden toegevoegd aan het klembord", + "PAGE_SETTINGS_LANGUAGE_FRENCH": "Frans", + "ANDROID_EXTERNAL_FILE_ACCESS_NOT_POSSIBLE_TITLE": "Gegevens kunnen niet worden opgeslagen vanwege Android-beperkingen", + "ANDROID_EXTERNAL_FILE_ACCESS_NEEDED_DESCRIPTION": "Je Android-telefoon ondersteunt geen externe bestandssystemen, dus je moet het ZIP-bestand downloaden zonder mediabestanden. Ga voor meer informatie naar https:\/\/beanconqueror.com\/faq.", + "PAGE_SETTINGS_SECURITY_CHECK_WHEN_GOING_BACK": "Beveiligingsbericht voor afsluiten?", + "PAGE_SETTINGS_SECURITY_CHECK_WHEN_GOING_BACK_DESCRIPTION": "Controleer of de gegevens zijn gewijzigd bij het toevoegen\/bewerken van bonen of brouwsels; als dat het geval is, wordt er een veiligheidswaarschuwing weergegeven bij het teruggaan.", + "PAGE_BEANS_DISCARD_CONFIRM": "Boon informatie is gewijzigd. Weet je zeker dat je de pagina wilt verlaten zonder op te slaan?", + "PAGE_BREW_DISCARD_CONFIRM": "De brouw informatie is gewijzigd. Weet je zeker dat je de pagina wilt verlaten zonder op te slaan?", + "NO_ENTRIES_FOUND": "Geen vermeldingen gevonden", + "POPOVER_BEANS_OPTION_REPEAT": "Herhaal laatste brouwsel", + "REPEAT_LAST_BREW": "Herhaal laatste brouwsel", + "REPEAT_BEST_BREW": "Herhaal beste brouwsel", + "PAGE_SETTINGS_VISUALIZER_SECTION": "Visualizer", + "VISUALIZER": { + "ACTIVATE": "Visualizer activeren", + "CHOOSE_SERVER": "Server kiezen", + "CONNECTION": { + "UNSUCCESSFULLY": "Er kon geen verbinding tot stand worden gebracht.", + "SUCCESSFULLY": "Verbinding kon tot stand worden gebracht." + }, + "SERVER": { + "VISUALIZER": "Visualizer-server", + "CUSTOM": "Aangepaste server" + }, + "SHOT": { + "UPLOAD_SUCCESSFULLY": "Brouwen geüpload naar visualizer.", + "UPLOAD_UNSUCCESSFULLY": "Brouwen kon niet worden geüpload naar de Visualizer." + }, + "URL": "Server-URL", + "USERNAME": "Gebruikersnaam", + "PASSWORD": "Wachtwoord", + "UPLOAD_AUTOMATIC": "Elke brouwsessie automatisch uploaden?", + "UPLOAD_AUTOMATIC_TOOLTIP": "Zorg ervoor dat u een actieve internetverbinding hebt wanneer u uw brouwsel opslaat.", + "UPLOAD_ALL": "Alle brouwsels uploaden", + "NOT_ALL_SHOTS_UPLOADED": "Niet alle brouwsels konden worden geüpload", + "ALL_SHOTS_UPLOADED": "Alle brouwsels zijn geüpload" + }, + "SMART_SCALE_AUTO_START_LISTENING": "Timer automatisch starten?", + "SMART_SCALE_AUTO_START_LISTENING_DESCRIPTION": "Start de timer automatisch bij het bereiken van de volgende gewichtswaarde", + "CHOOSE_REFERENCE_GRAPH": "Referentiegrafiek selecteren", + "RESET": "Opnieuw instellen", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_AXIS": "Definieer de beginassen van de grafiek", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_AXIS_DESCRIPTION": "Stel de begingrootte van de assen in voor zowel filter- als espressokoffie.", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_FILTER_WEIGHT": "Filter - Gewicht", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_FILTER_FLOW": "Filter - Doorstroming", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_ESPRESSO_WEIGHT": "Espresso - Gewicht", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_ESPRESSO_FLOW": "Espresso - Doorstroming", + "SMART_SCALE_IGNORE_INCOMING_WEIGHT": "Negeer huidige gewichtsoverdracht ", + "SMART_SCALE_IGNORE_INCOMING_WEIGHT_TOOLTIP": "Er verschijnt een nieuwe knop in het brouwgedeelte, die nieuwe gewichtswaarden van de bluetooth weegschaal zal negeren.", + "BREWS_ACTIVE": "Actieve brouwsels", + "BREWS_ARCHIVED": "Gearchiveerde brouwsels", + "GRAPHS": "Grafieken", + "GRAPH_SECTION": { + "NAV_GRAPH": "Grafieken", + "NO_ARCHIVED_ENTRIES": "Geen gearchiveerde vermeldingen", + "NO_ENTRIES": "Geen vermeldingen", + "SECTION_HAS_BEEN_ACTIVATED": "Grafieksectie is geactiveerd" + }, + "TOAST_GRAPH_ARCHIVED_SUCCESSFULLY": "Grafiek gearchiveerd", + "TOAST_GRAPH_DELETED_SUCCESSFULLY": "Grafiek verwijderd", + "TOAST_GRAPH_EDITED_SUCCESSFULLY": "Grafiek bewerkt", + "TOAST_GRAPH_ADD_SUCCESSFULLY": "Grafiek toegevoegd", + "NAV_GRAPH_SECTION": "Grafieken", + "DELETE_GRAPH_QUESTION": "Wilt u deze grafiek verwijderen?", + "PAGE_SETTINGS_SHOW_ARCHIVED_GRAPHS": "Gearchiveerde grafieken weergeven", + "PAGE_SETTINGS_SHOW_GRAPH_SECTION": "Grafieksectie activeren", + "EDIT_GRAPH": "Grafiek bewerken", + "ADD_GRAPH": "Grafiek toevoegen", + "GRAPH": { + "PLACE_HOLDER": { + "NAME": "Grafiek naam", + "NOTES": "Notities" + }, + "UPLOAD": "Grafiek uploaden", + "DELETE": "Grafiek verwijderen", + "UPLOAD_DESCRIPTION": "Importeer een .JSON-bestand dat u kunt downloaden in de brew-detailweergave. U kunt ook gedeelde grafieken van de community importeren die van het type .JSON zijn." + }, + "SHOW_VISUALIZER": "Visualiseerder weergeven", + "NO_BREWS_FOUND": "Geen brouwsels gevonden", + "NO_GRAPHS_FOUND": "Geen grafieken gevonden", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_AXIS": "Definieer de maximale tijdsas van de grafiek", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_DESCRIPTION": "Stel het maximum aantal seconden in op de tijd-as voor zowel filterkoffie als espresso.", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_FILTER_AXIS_NORMAL_SCREEN": "Filter - Normaal scherm", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_FILTER_AXIS_FULL_SCREEN_SCREEN": "Filter - Volledig scherm", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_ESPRESSO_AXIS_NORMAL_SCREEN": "Espresso - Normaal scherm", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_ESPRESSO_AXIS_FULL_SCREEN_SCREEN": "Espresso - Volledig scherm", + "PAGE_SETTINGS_DATE_FORMAT": "Datum notatie", + "PAGE_SETTINGS_LANGUAGE_FRANCE": "Frans", + "PAGE_SETTINGS_LANGUAGE_INDONESIA": "Indonesisch", + "EXTRACTION_CHART_TITLE": "Extractie grafiek", + "PAGE_SETTINGS_SHOW_BACKUP_ISSUES": "Back-up problemen weergeven", + "PAGE_SETTINGS_SHOW_BACKUP_ISSUES_DESCRIPTION": "Geef een pop-up weer als er geen back-ups naar het bestandssysteem kunnen worden geschreven", + "AUTOMATIC_BACKUP_DID_FAIL": "Automatische back-up werkte niet, zorg ervoor dat u werkende back-ups hebt! Deze informatie kan worden uitgeschakeld in de instellingen", + "INTERNAL_BACKUP_DID_FAIL": "Interne back-up werkte niet, zorg ervoor dat u werkende back-ups hebt! Deze informatie kan worden uitgeschakeld in de instellingen", + "ZIP_BACKUP_FILE_COULD_NOT_BE_BUILD": "ZIP-bestand kon niet worden opgeslagen! Deze informatie kan worden uitgeschakeld in de instellingen", + "SEND_LOGS": "Logboeken verzenden", + "POPOVER_BLUETOOTH_ACTION_RECONNECT_REFRACTOMETER": "Sluit refractometer apparaat opnieuw aan", + "PAGE_SETTINGS_LANGUAGE_ITALIAN": "Italiaans", + "PAGE_SETTINGS_LANGUAGE_POLISH": "Pools", + "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_GENERAL_DESCRIPTION": "Je moet eerst je timer resetten voordat je kunt beginnen.", + "SMART_SCALE_FIRST_DRIP_THRESHOLD": "Eerste druppel drempel", + "SMART_SCALE_FIRST_DRIP_THRESHOLD_TOOLTIP": "Bij welk weegschaalgewicht moet de eerste druppel worden geteld? Standaard: >= 0,1g", + "PAGE_SETTINGS_BREW_TIMER_START_DELAY_ACTIVE": "Zetvertraging starten", + "PAGE_SETTINGS_BREW_TIMER_START_DELAY_ACTIVE_DESCRIPTION": "Stel een vertragingstijd in die een laadspinner weergeeft totdat het brouwen begint", + "STARTING_IN": "Beginnend in ... {{time}}", + "IOS_DATABASE_ISSUE_TITLE": "ATTENTIE !!!!! - DATABASEVERBINDING VERLOREN", + "IOS_DATABASE_ISSUE_DESCRIPTION": "Het spijt ons u te moeten meedelen dat de verbinding met de database is verbroken. Dit probleem is het gevolg van een onopgeloste bug in het systeem van Apple, waarover Beanconqueror geen controle heeft. Om mogelijk gegevensverlies te voorkomen, verzoeken wij u vriendelijk de Beanconqueror-applicatie onmiddellijk geforceerd af te sluiten en opnieuw te openen.", + "RELOAD_APP": "Herstart de app", + "WATER_TYPE_ADD_CUSTOM": "Water op maat", + "WATER_TYPE_THIRD_WAVE_WATER_CLASSIC_LIGHT_ROAST_PROFILE": "Third Wave Water - Klassiek licht geroosterd profiel", + "WATER_TYPE_THIRD_WAVE_WATER_MEDIUM_ROAST_PROFILE": "Third Wave Water - Middel geroosterd profiel", + "WATER_TYPE_THIRD_WAVE_WATER_DARK_ROAST_PROFILE": "Third Wave Water - Donker geroosterd profiel", + "WATER_TYPE_THIRD_WAVE_WATER_ESPRESSO_MACHINE_PROFILE": "Third Wave Water - Espressomachine Profiel", + "WATER_TYPE_THIRD_WAVE_WATER_COLD_BREW_PROFILE": "Third Wave Water - koud brouwprofiel", + "WATER_TYPE_THIRD_WAVE_WATER_LOW_ACID_PROFILE": "Third Wave Water - Laag Zuurprofiel", + "ADD_WATER": "Voeg water toe", + "EXTRACTION_CHART_LABEL_STRONG_UNDEREXTRACTED": "STERK
onderextractie", + "EXTRACTION_CHART_LABEL_STRONG": "Strong
", + "EXTRACTION_CHART_LABEL_STRONG_HARSH": "STERK
ruw", + "EXTRACTION_CHART_LABEL_UNDEREXTRACTED": "ondergeëxtraheerd", + "EXTRACTION_CHART_LABEL_IDEAL": "IDEAAL", + "EXTRACTION_CHART_LABEL_HARSH": "ruw", + "EXTRACTION_CHART_LABEL_WEAK_UNDEREXTRACTED": "ZWAK
onderextractie", + "EXTRACTION_CHART_LABEL_WEAK": "ZWAK
", + "EXTRACTION_CHART_LABEL_WEAK_HARSH": "ZWAK
ruw", + "PAGE_SETTINGS_TEXT_TO_SPEECH_SECTION": "Tekst naar spraak", + "TEXT_TO_SPEECH": { + "ACTIVATE": "Activeer tekst naar spraak", + "BREW_STARTED": "Brouwen gestart", + "BREW_ENDED": "Einde brouwen", + "TIME": "Tijd", + "SPEAK_EVERY_MS": "Spreek elke geselecteerde milliseconde", + "FOLLOWING_NUMBERS_WILL_BE_TEST_SPOKEN": "De volgende nummers worden als test uitgesproken", + "TEST_SPEAK": "Start test spraak", + "PITCH": "Toonhoogte", + "RATE": "beoordeling" + }, + "PAGE_SETTINGS_HAPTIC_FEEDBACK_SECTION": "Haptische feedback", + "HAPTIC_FEEDBACK": { + "ACTIVATE": "Activeer haptische feedback", + "BREW_STARTED": "Trillen bij het starten van het brouwen", + "BREW_STOPPED": "Trillen bij het stoppen van het brouwen", + "TARE": "Trillen bij tarra van de weegschaal" + }, + "CONNECTED": "Verbonden", + "DISCONNECTED": "Losgekoppeld", + "EXPERIMENTAL_FEATURE_DISCLAIMER": "Dit is een experimentele functie", + "SHOW_HOURS": "Toon uren", + "SHOW_MINUTES": "Toon Minuten", + "BEANS_UNARCHIVE": "uit het archief halen", + "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Boon is uit het archief gehaald", + "WATER_TYPE_PURE_COFFEE_WATER": "Zuiver Koffiewater", + "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", + "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", + "SORT_PREPARATION_TOOLS": "Sorteer bereidingsmiddelen", + "PREPARATION_TYPE_METICULOUS": "Meticulous", + "EXPORT_CAUTION": "Exporteren exporteert alleen de database, geen afbeeldingen, geen stromingsprofielen . Als deze nodig zijn, ga dan naar Gitbook voor meer informatie", + "POPOVER_FREEZE_COFFEE_BEAN": "Bevries koffieboon", + "POPOVER_UNFREEZE_COFFEE_BEAN": "Koffieboon ontdooien", + "BEAN_POPOVER_EDIT_FREEZE_DATE": "invries datum bewerken", + "BEAN_POPOVER_EDIT_UNFREEZE_DATE": "ontdooi datum bewerken", + "BEAN_POPOVER_LEFT_UNFROZEN": "Niet ingevroren", + "BEAN_POPOVER_FREEZE_PARTIAL_BAG": "Gedeelte zak invriezen (g)", + "FROZEN_BEANS": "Bevroren", + "BEAN_TAB_FROZEN_INFORMATION": "Bevroren notities", + "BEAN_POPOVER_FROZEN_BAGS": "Bevroren zakken", + "BEAN_POPOVER_FROZEN_DELETE_BEAN_MESSAGE": "Je gaat de hele zak invriezen en we hebben geen brouwsels gevonden die ermee gemaakt zijn, wil je de originele zak verwijderen?", + "CREATE_FROZEN_BEANS": "creëer bonen", + "BEAN_POPOVER_COPY_ATTACHMENTS": "Kopieer bijlagen", + "BEAN_POPOVER_COPY_ATTACHMENTS_DESCRIPTION": "Het kopiëren van bijlagen is aan het begin van deze functie gedeactiveerd", + "BEAN_DATA_FROZEN_DATE": "Invries datum", + "BEAN_DATA_UNFROZEN_DATE": "ontdooi datum", + "PAGE_BEANS_LIST_YOU_GOT_NO_FROZEN_BEANS": "Je hebt geen ingevroren bonen", + "BEAN_DATA_FROZEN_ID": "Ingevroren id", + "PAGE_SETTINGS_MANAGE_FEATURES": "Functies beheren", + "ACTIVE_BEAN_FREEZING_FEATURE": "Activeer het invriezen van bonen", + "NAV_FROZEN_BEANS_LIST": "Lijst met ingevroren bonen", + "BEAN_BREW_LIST_VIEW_PARAMETERS": "Boon informatie voor brouwen", + "BEAN_AGE_BY_BREW_DATE": "Leeftijd van de bonen op brouwdatum", + "BEAN_POPOVER_FROZEN_BEAN_WILL_BE_ARCHIVED_NOW_MESSAGE": "Je diepvrieszakken hebben als resultaat dat je originele zak geen gewicht meer heeft, maar je hebt er wel mee gebrouwen, dus beoordeel en stuur naar het archief.", + "BEAN_POPOVER_YOU_CANT_FREEZE_WITH_ZERO_WEIGHT_LEFT": "Je kunt niet bevriezen, want het restgewicht van je zak is nul", + "BEAN_DATA_BEST_DATE": "Beste Bonen Datum", + "BEAN_DATA_BEST_DATE_TOOLTIP": "Wanneer is de beste datum om de bonen te gebruiken?", + "BEAN_DATA_OPEN_DATE": "Openingsdatum van de zak", + "BEAN_DATA_OPEN_DATE_TOOLTIP": "Wanneer heb je de zak bonen geopend?", + "BEAN_FREEZING_STORAGE_TYPE_UNKNOWN": "Onbekend", + "BEAN_FREEZING_STORAGE_TYPE_COFFEE_BAG": "Koffiezak", + "BEAN_FREEZING_STORAGE_TYPE_COFFEE_JAR": "Koffie pot", + "BEAN_FREEZING_STORAGE_TYPE_ZIP_LOCK": "Ritssluiting", + "BEAN_FREEZING_STORAGE_TYPE_VACUUM_SEALED": "Vacuüm verzegeld", + "BEAN_FREEZING_STORAGE_TYPE_TUBE": "Buis", + "BEAN_DATA_FROZEN_STORAGE_TYPE": "Vriezer opslagtype", + "PAGE_SETTINGS_BREW_RATING_CHANGED_BREWS_NOT_VISIBLE": "U heeft de maximale beoordeling van uw brouwsels gewijzigd, maar u heeft uw brouwsels al hoger beoordeeld dan uw werkelijke maximum. Deze worden dus niet weergegeven bij de normale filterinstellingen.", + "PAGE_SETTINGS_BEAN_RATING_CHANGED_BEANS_NOT_VISIBLE": "U heeft de maximale beoordeling voor bonen gewijzigd, maar u heeft bonen al hoger beoordeeld dan uw werkelijke maximum. Ze worden dus niet weergegeven met de normale filterinstellingen.", + "BEAN_DATA_FROZEN_NOTE": "Bevroren notities", + "IGNORE_NEGATIVE_VALUES_DESCRIPTION": "Als je dit activeert, loopt de grafiek één seconde achter", + "IGNORE_ANOMALY_VALUES_DESCRIPTION": "Als je dit activeert, loopt de grafiek één seconde achter", + "SAVE_LOGFILES_TO_NOTES_FROM_MACHINE": "Bewaar de machine logs bij het opslaan van een brouwsel" +} \ No newline at end of file diff --git a/src/assets/i18n/pl.json b/src/assets/i18n/pl.json index ca541d8e..23e94e5e 100644 --- a/src/assets/i18n/pl.json +++ b/src/assets/i18n/pl.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Pokaż minuty", "BEANS_UNARCHIVE": "Cofnij archiwizację", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Ziarno nie zostało zarchiwizowane", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Wersja 7.4.0: Co nowego", - "DESCRIPTION": [ - "Ziarna<\/b>", - "Teraz możliwe jest zamrożenie ziaren kawy, aktywując tę funkcję w ustawieniach.", - "Dodano najlepszą i otwartą datę dla fasoli, należy aktywować ten parametr", - "Ziarna można teraz dodawać bezpośrednio z przeglądu wyboru.", - "", - "Termometr<\/b>", - "Wsparcie Combustion Inc. Termometr - Dziękujemy za urządzenie!", - "Wsparcie dla termometru Meater (nie Meater 2 lub Meater +) - dzięki Yannick!", - "", - "Sekcja wodna<\/b>", - "Dodano czystą wodę kawową", - "Dodana woda empiryczna", - "", - "Narzędzia przygotowawcze<\/b>", - "Posortuj teraz swoje narzędzia przygotowawcze", - "", - "Młynek<\/b>", - "Obrazy młynka są teraz wyświetlane w przeglądzie wyboru", - "", - "Ustawienia<\/b>", - "Komunikat bezpieczeństwa, jeśli zmieniono ocenę dla naparów lub ziaren, a maksymalna ocena jest niższa niż już oceniony wpis.", - "", - "Inne<\/b>", - "Przywrócono bezpośrednie ustawianie ostrości w sekundach podczas otwierania timera.", - "Kilka zmian technicznych w kodzie", - "Drobne poprawki" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Czysta woda kawowa", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "woda empiryczna GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "woda empiryczna SPRING", diff --git a/src/assets/i18n/tr.json b/src/assets/i18n/tr.json index cfb0c409..f2e49174 100644 --- a/src/assets/i18n/tr.json +++ b/src/assets/i18n/tr.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Dakikayı göster", "BEANS_UNARCHIVE": "Arşivden çıkar", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Çekirdek arşivden çıkarıldı", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Sürüm 7.4.0: Yenilikler", - "DESCRIPTION": [ - " Fasulye <\/b>", - "Artık kahve çekirdeklerinizi dondurmak mümkün, bu özelliği ayarlardan etkinleştirin", - "Çekirdek için en iyi ve açık tarih eklendi, bu parametreyi etkinleştirmeniz gerekir", - "Çekirdekler artık doğrudan seçime genel bakıştan eklenebilir", - "", - "Termometre<\/b>", - "Combustion Inc. Termometre Desteği - Cihaz için teşekkürler!", - "Meater Termometre desteği (Meater 2 veya Meater + değil) - Yannick'e teşekkürler!", - "", - "Su Bölümü<\/b>", - "Saf Kahve Suyu Eklendi", - "Ampirik su eklendi", - "", - "Hazırlık Araçları<\/b>", - "Hazırlık araçlarınızı şimdi sıralayın", - "", - "Öğütücü<\/b>", - "Öğütücü görüntüleri artık seçim genel görünümünde gösteriliyor", - "", - "Ayarlar<\/b>", - "Demleme veya çekirdek derecelendirmesini değiştirdiyseniz ve maksimum değer, halihazırda derecelendirilmiş bir girişten düşükse güvenlik mesajı", - "", - "Diğer<\/b>", - "Zamanlayıcıyı açarken doğrudan saniye odağı geri döndürüldü", - "Koddaki bazı teknik değişiklikler", - "Küçük değişiklikler" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Saf Kahve Suyu", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "ampirik su GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "ampirik su SPRING", diff --git a/src/assets/i18n/zh.json b/src/assets/i18n/zh.json index b7c5bd63..bca45dc7 100644 --- a/src/assets/i18n/zh.json +++ b/src/assets/i18n/zh.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "显示分钟", "BEANS_UNARCHIVE": "取消归档", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "咖啡豆已经取消归档", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "版本7.4.0:有什么新功能?", - "DESCRIPTION": [ - "豆子<\/b>", - "现在可以将您的咖啡豆冷冻保存,您可以在设置中激活这个功能", - "为咖啡豆添加了最佳和开封日期,您需要激活此参数", - "现在可以直接从选择概览中添加豆子", - "空的", - "温度计<\/b>", - "支持 Combustion Inc. 温度计 - 感谢提供设备!", - "支持 Meater 温度计(不支持 Meater 2 或 Meater +) - 感谢 Yannick!", - "空的", - "水分区<\/b>", - "添加Pure Coffee Water", - "添加Empirical水", - "空的", - "准备工具<\/b>", - "整理您的准备工具", - "空的", - "磨豆机<\/b>", - "磨豆机的图片现在在选择概览中显示", - "空的", - "设置<\/b>", - "如果您更改了冲泡或咖啡豆的评分,并且最高评分低于已评分条目的评分,则显示安全提示信息", - "空的", - "其他<\/b>", - "在打开计时器时,恢复到以秒数计时为准", - "代码中的一些技术修改", - "小调整" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", From 0b17805d3fe2b7a335fe9e0569b30a81f3ade94d Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Wed, 28 Aug 2024 21:56:44 +0200 Subject: [PATCH 10/19] Lokalise update --- src/assets/i18n/de.json | 33 - src/assets/i18n/en.json | 33 - src/assets/i18n/es.json | 33 - src/assets/i18n/fr.json | 37 +- src/assets/i18n/id.json | 33 - src/assets/i18n/it.json | 45 +- src/assets/i18n/nl.json | 1323 +++++++++++++++++++++++++++++++++++++++ src/assets/i18n/pl.json | 33 - src/assets/i18n/tr.json | 33 - src/assets/i18n/zh.json | 33 - 10 files changed, 1331 insertions(+), 305 deletions(-) create mode 100644 src/assets/i18n/nl.json diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 90777414..d63be163 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Minuten anzeigen", "BEANS_UNARCHIVE": "Archivierung aufheben", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Bean wurde dearchiviert", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Version 7.4.0: Das ist neu", - "DESCRIPTION": [ - "Bohnen<\/b>", - "Es ist jetzt möglich Kaffeebohnen einzufrieren. Aktiviere diese Funktion in den Einstellungen", - "Bestes und offenes Datum für Bohnen hinzugefügt. Diese Parameter müssen aktiviert werden.", - "Bohnen können nun direkt aus der Auswahlübersicht hinzugefügt werden", - "", - " Thermometer <\/b>", - "Unterstützung des Combustion Inc. Thermometers – Danke für das Gerät!", - "Unterstützung des Meater-Thermometers (nicht Meater 2 oder Meater +) – Danke an Yannick!", - "", - "Wasserbereich<\/b>", - "Pure Coffee Water hinzugefügt", - "Empirical Water hinzugefügt", - "", - "Brühmethoden Tools<\/b>", - "Sortiere deine Zubereitungsmethoden", - "", - "Mühlen<\/b>", - "Mühlenbilder werden in der Übersicht angezeigt", - "", - "Einstellungen<\/b>", - "Sicherheitsmeldung, wenn du die Bewertung für Brühen oder Bohnen geändert hast und das Maximum niedriger ist als ein bereits bewerteter Eintrag", - "", - "Sonstiges<\/b>", - "Der direkte Sekundenfokus beim Öffnen des Timers wurde ausgebaut", - "Einige technische Änderungen im Code", - "Kleine Optimierungen" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index b73e2994..6408bd8f 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Show minutes", "BEANS_UNARCHIVE": "Unarchive", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Bean has been unarchived", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Version 7.4.0: What's new", - "DESCRIPTION": [ - "Beans<\/b>", - "Its now possible to freeze your coffee beans, activate this feature in the settings", - "Added best and open date for beans, you need to activate this parameter", - "Beans can now be directly added from the select overview", - "", - "Thermometer<\/b>", - "Support of the Combustion Inc. Thermometer - Thanks for the Device!", - "Support of the Meater Thermometer (not Meater 2 or Meater +) - Thanks to Yannick!", - "", - "Water Section<\/b>", - "Added Pure Coffee Water", - "Added Empirical Water", - "", - "Preparation Tools<\/b>", - "Sort now your preparation tools", - "", - "Grinder<\/b>", - "Grinder images are now shown in the select overview", - "", - "Settings<\/b>", - "Security message if you changed the rating for brews or beans, and the maximum is lower then an already rated entry", - "", - "Other<\/b>", - "Reverted the direct seconds focus when opening the timer", - "Some technical changes in the code", - "Small tweaks" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index 9736cc49..38d1a467 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Mostrar minutos", "BEANS_UNARCHIVE": "Desarchivar", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Café desarchivado", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Versión 7.4.0: Novedades", - "DESCRIPTION": [ - "Cafés<\/b>", - "Ahora es posible congelar tus cafés, puedes activar esta opción en ajustes.", - "Añadidas fechas de apertura y de consumo óptimo para tus cafés (desactivadas por defecto).", - "Ahora puedes añadir un nuevo café desde el menú de selección de cafés de una preparación.", - "", - "Termómetro<\/b>", - "Añadido soporte para el termómetro Combustion Inc. - Gracias por el aporte!", - "Añadido soporte para el termómetro Meater (no Meater 2 o Meater+) - Gracias a Yannick!", - "", - "Sección de agua<\/b>", - "Añadida agua Pure Coffee Water", - "Añadida agua Empirical Water", - "", - "Métodos de preparación<\/b>", - "Ahora puedes ordenar tus métodos de preparación", - "", - "Molinos<\/b>", - "Ahora se muestran las imágenes de los molinos en el menú de selección.", - "", - "Ajustes<\/b>", - "Se muestra una alerta si cambias la puntuación de una preparación o un café, y el máximo es menor que otra entrada ya puntuada.", - "", - "Otros<\/b>", - "El campo \"segundos\" ya no se selecciona automáticamente al abrir el selector de tiempo.", - "Cambios técnicos en el código.", - "Pequeños ajustes y mejoras." - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 8f71307e..17a5ccbe 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -479,7 +479,7 @@ "CUSTOM_MANAGE_PARAMETERS": "Gérer", "CUSTOM_SORT_PARAMETERS": "Trier", "BREW_PARAMETER_CUSTOMIZE_TITLE": "Paramètres personnalisés pour chaque méthode de préparation", - "BREW_PARAMETER_CUSTOMIZE_DESCRIPTION": "Tu veux choisir des paramètres personnalisés pour chaque méthode de préparation ? Navigues jusqu'à \"Méthodes\", ouvre le menu de la méthode de préparation spécifique et choisissez \"Personnaliser les paramètres\". Là, tu peux choisir quels paramètres seront utilisés pour cette préparation !", + "BREW_PARAMETER_CUSTOMIZE_DESCRIPTION": "Tu veux choisir des paramètres personnalisés pour chaque méthode de préparation ? Navigue jusqu'à \"Méthodes\", ouvre le menu de la méthode de préparation spécifique et choisissez \"Personnaliser les paramètres\". Là, tu peux choisir quels paramètres seront utilisés pour cette préparation !", "BREW_DATA_BREW_QUANTITY_TOOLTIP": "Quantité d'eau (non utilisable pour l'espresso)", "BREW_DATA_COFFEE_FIRST_DRIP_TIME_TOOLTIP": "Premier temps d'égouttage du café (espresso uniquement)", "BREW_DATA_PREPARATION_METHOD_TOOLTIP": "Préparation (uniquement personnalisable lorsqu'elle est active)", @@ -1148,7 +1148,7 @@ }, "SHOT": { "UPLOAD_SUCCESSFULLY": "Infusion téléchargé sur Visualizer.", - "UPLOAD_UNSUCCESSFULLY": "L'infusion n'a pas pu être téléchargé sur Visualizer." + "UPLOAD_UNSUCCESSFULLY": "L'infusion n'a pas pu être téléchargée sur Visualizer." }, "URL": "URL du serveur", "USERNAME": "Nom d'utilisateur", @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Afficher les minutes", "BEANS_UNARCHIVE": "Désarchiver", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Le grain a été désarchivé", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Version 7.4.0: c'est nouveau", - "DESCRIPTION": [ - "Grains<\/b>", - "Il est possible de congeler des grains de café. Active cette fonction dans les réglages", - "Ajout de la meilleure date et de la date d'ouverture pour les grains. Ces paramètres doivent être activés.", - "Les grains peuvent désormais être ajoutés directement à partir de l’aperçu de la sélection", - "", - " Thermomètre <\/b>", - "Support pour les thermomètres de Combustion Inc. – Merci pour l'appareil !", - "Support du thermomètre Meater (pas Meater 2 ou Meater +) – Merci à Yannick !", - "", - " Zone d'eau <\/b>", - "Ajouté Pure Coffee Water", - "Ajouté Empirical Water", - "", - " Outils de méthode d'infusion <\/b>", - "Trier tes méthodes de préparation", - "", - "Moulins<\/b>", - "Les images des moulins sont affichées dans l'aperçu", - "", - "Paramètres<\/b>", - "Message de sécurité si tu as modifié l'évaluation des infusions ou des grains et que le maximum est inférieur à une entrée déjà évaluée.", - "", - "Autres<\/b>", - "La mise au point directe en secondes lors de l'ouverture de la minuterie a été rétablie", - "Quelques changements techniques dans le code", - "Petites optimisations" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/id.json b/src/assets/i18n/id.json index fc9969cd..50594012 100644 --- a/src/assets/i18n/id.json +++ b/src/assets/i18n/id.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Tampilkan menit", "BEANS_UNARCHIVE": "Tidak diarsipkan", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Bean tidak diarsipkan", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Versi 7.4.0: Apa yang baru", - "DESCRIPTION": [ - "Biji<\/b>", - "Sekarang dimungkinkan untuk mencatat pembekuan biji kopi Anda, aktifkan fitur ini di pengaturan", - "Menambahkan tanggal terbaik dan tanggal membuka kopi, Anda perlu mengaktifkan parameter ini", - "Biji sekarang dapat langsung ditambahkan dari pilihan", - "", - "Thermometer<\/b>", - "Dukungan Termometer Combustion Inc. - Terima kasih untuk Perangkatnya!", - "Dukungan Termometer Meater (bukan Meater 2 atau Meater +) - Terima kasih kepada Yannick!", - "", - "Water Section<\/b>", - "Penambahan Pure Coffee Water", - "Penambahan Empirical Water", - "", - "Preparation Tools<\/b>", - "Jenis alat-alat seduhan dapat diurutkan", - "", - "Grinder<\/b>", - "Gambar grinder sekarang ditampilkan dalam pilihan", - "", - "Pengaturan<\/b>", - "Pesan keamanan jika Anda mengubah peringkat untuk seduhan atau biji kopi, dan nilai maksimumnya lebih rendah dari entri yang sudah diberi peringkat", - "", - "Lain-lain<\/b>", - "Mengembalikan fokus detik langsung saat membuka pengatur waktu", - "Beberapa perubahan teknis pada kode", - "Perubahan kecil" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index 0face123..522b9323 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -44,13 +44,13 @@ "PAGE_HOME_DIFFERENT_PREPARATION_METHODS": "metodi di preparazione", "PAGE_HOME_DIFFERENT_MILLS": "macinacaffè", "PAGE_HOME_SUPPORTER": "App Supporter", - "PAGE_HOME_START_BREW": "", + "PAGE_HOME_START_BREW": "Inizia la preparazione", "PAGE_BEANS_LIST_OBTAINABLE": "Disponibili", "PAGE_BEANS_LIST_YOU_GOT_NO_FRESH_BEANS": "Non c'è più caffè!", "PAGE_BEANS_LIST_YOU_GOT_NO_FINISHED_BEANS": "Nessun caffè archiviato", "PAGE_MILL_LIST_NO_MILL_EXISTING": "Nessun macinacaffè", "PAGE_PREPARATION_LIST_NO_PREPARATION_EXISTING": "Nessun metodo di preparazione", - "PAGE_CONTACT_SUGGESTIONS_QUESTIONS_WISHES": "Suggerimenti, domande, bug o richieste?", + "PAGE_CONTACT_SUGGESTIONS_QUESTIONS_WISHES": "Suggerimenti, domande, bugs o richieste?", "PAGE_THANKS_THANKS_FOR_YOUR_SUPPORT": "Grazie per il sostegno!", "PAGE_SETTINGS_LANGUAGE": "Impostazioni della lingua", "PAGE_SETTINGS_LANGUAGE_GERMAN": "Deutsch", @@ -61,8 +61,8 @@ "PAGE_SETTINGS_GENERAL_SETTINGS": "Impostazioni generali", "PAGE_SETTINGS_TRANSFER": "Trasferisci dati", "PAGE_SETTINGS_PRESET_LAST_BREW": "Attiva parametri preimpostati", - "PAGE_SETTINGS_DISPLAY": "", - "PAGE_SETTINGS_DISPLAY_SINGLE_PAGE": "", + "PAGE_SETTINGS_DISPLAY": "Visualizza", + "PAGE_SETTINGS_DISPLAY_SINGLE_PAGE": "Pagina singola", "PAGE_SETTINGS_DISPLAY_PAGING": "Paginazione", "PAGE_SETTINGS_STARTUP_VIEW": "Pagina iniziale", "PAGE_SETTINGS_ANALYTICS_INFORMATION": "Analytics", @@ -76,10 +76,10 @@ "PAGE_STATISTICS_TOTAL_GROUND_BEANS": "Totale caffè macinato", "PAGE_STATISTICS_MONEY_SPENT_FOR_COFFEE": "Soldi spesi in caffè", "PAGE_STATISTICS_DRUNKEN_BREWS": "Numero totale preparazioni", - "PAGE_STATISTICS_BREW_PROCESSES": "Preparazioni", + "PAGE_STATISTICS_BREW_PROCESSES": "Preparazioni totali", "PAGE_STATISTICS_DRUNKEN_QUANTITY": "Quantità consumata", "PAGE_STATISTICS_BEAN_WEIGHT_USED": "Totale caffè macinato", - "PAGE_BREW_TEXT_INFORMATION_FROM_ROASTER": "", + "PAGE_BREW_TEXT_INFORMATION_FROM_ROASTER": "Info sulla torrefazione", "PAGE_ABOUT_NO_VERSION_AVAILABLE": "Nessuna versione disponibile", "PAGE_ABOUT_APP_VERSION": "Versione App", "PAGE_LICENCES_WEBSITE": "Sito web", @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Mostra minuti", "BEANS_UNARCHIVE": "Annulla l'archiviazione", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Il caffè è stato disarchiviato", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Versione 7.4.0: Cosa c'è di nuovo", - "DESCRIPTION": [ - "Caffè<\/b>", - "Ora è possibile tenere traccia del caffè congelato, puoi attivare questa funzione nelle impostazioni", - "Aggiunta della data suggerita e di apertura per i caffè, è necessario attivare questo parametro nelle impostazioni", - "Ora è possibile aggiungere del caffè direttamente dalla selezione", - "", - " Termometro <\/b>", - "Supporto del termometro Combustion Inc. - Grazie per il dispositivo!", - "Supporto del termometro Meater (non Meater 2 o Meater +) - Grazie a Yannick!", - "", - "Sezione Acqua<\/b>", - "Aggiunta l'acqua Pure Coffee Water", - "Aggiunta l'acqua Empirical Water", - "", - "Accessori preparazione<\/b>", - "Ordina ora i tuoi strumenti di preparazione", - "", - "Macinacaffè<\/b>", - "Le immagini del macinacaffè sono mostrate nella selezione", - "", - "Impostazioni<\/b>", - "Messaggio di sicurezza se hai modificato la valutazione e il massimo è inferiore a cioè che è già valutato", - "", - "Altro<\/b>", - "Rimossa la recente aggiunta di auto-focus sui secondi del timer della preparazione", - "Piccole migliorie nel codice", - "Piccole migliorie" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", diff --git a/src/assets/i18n/nl.json b/src/assets/i18n/nl.json new file mode 100644 index 00000000..31e2cd3e --- /dev/null +++ b/src/assets/i18n/nl.json @@ -0,0 +1,1323 @@ +{ + "NAV_MENU": "Menu", + "NAV_HOME": "Thuis", + "NAV_SETTINGS": "Instellingen", + "NAV_BREWS": "Brouwsels", + "NAV_BEANS": "Bonen", + "NAV_PREPARATION": "Methoden", + "NAV_MILL": "Malers", + "NAV_ABOUT_US": "Over ons", + "NAV_CONTACT": "Contact", + "NAV_PRIVACY": "Privacy", + "NAV_CREDITS": "Credits", + "NAV_TERMS": "Algemene voorwaarden", + "NAV_THANKS": "Bedankt!", + "NAV_LICENCES": "OSS-licenties", + "NAV_STATISTICS": "Statistieken", + "NAV_IMPRESSUM": "Impressum", + "NAV_COOKIE": "Cookies", + "NAV_LOGS": "Logboeken", + "NAV_BREW_PARAMS": "Brouwparameters", + "NAV_INFORMATION_TO_APP": "Over Beanconqueror", + "NAV_WATER_SECTION": "Water", + "NAV_HELPER": "Calculaties", + "POPOVER_BREWS_OPTION_REPEAT": "Herhalen", + "POPOVER_BREWS_OPTION_DETAIL": "Details", + "DETAIL": "Details", + "POPOVER_BREWS_OPTION_EDIT": "Bewerking", + "POPOVER_BREWS_OPTION_DELETE": "Verwijder", + "POPOVER_BREWS_OPTION_PHOTO_GALLERY": "Fotogalerij", + "POPOVER_BREWS_OPTION_CUPPING": "Cupping", + "POPOVER_BREWS_OPTION_MAP_COORDINATES": "Toon op kaart", + "POPOVER_BREWS_OPTION_FAST_REPEAT": "Snel brouwen herhalen", + "PAGE_BREWS_NO_ENTRIES": "Nog geen brouwsels toegevoegd", + "PAGE_BREWS_NO_ARCHIVED_ENTRIES": "Je hebt nog geen brouwsels gearchiveerd", + "CANT_START_NEW_BREW_TITLE": "Er ontbreekt hier iets...", + "CANT_START_NEW_BREW_DESCRIPTION": "Om te beginnen, maak een beschrijving voor één type bonen, één zetmethode en één grinder. Gebruik het menu om naar de verschillende categorieën te navigeren om deze informatie toe te voegen.", + "PAGE_HOME_WELCOME_GREETINGS": "Leuk dat je er bent!", + "PAGE_HOME_TOTAL_BREW": "Brouwen", + "PAGE_HOME_TOTAL_BREWS": "Brouwsels", + "PAGE_HOME_BEAN_EXPLORED": "Bonen onderzocht", + "PAGE_HOME_BEANS_EXPLORED": "Bonen onderzocht", + "PAGE_HOME_LAST_BREWS": "Laatste brouwsels", + "PAGE_HOME_LAST_BREW": "Laatste brouwsel", + "PAGE_HOME_DIFFERENT_PREPARATION_METHODS": "Verschillende bereidingsmethoden", + "PAGE_HOME_DIFFERENT_MILLS": "Verschillende malers", + "PAGE_HOME_SUPPORTER": "App Supporter", + "PAGE_HOME_START_BREW": "Begin met brouwen", + "PAGE_BEANS_LIST_OBTAINABLE": "Beschikbaar", + "PAGE_BEANS_LIST_YOU_GOT_NO_FRESH_BEANS": "Je hebt geen verse bonen meer!", + "PAGE_BEANS_LIST_YOU_GOT_NO_FINISHED_BEANS": "Je hebt geen gearchiveerde bonen.", + "PAGE_MILL_LIST_NO_MILL_EXISTING": "Je hebt nog geen grinders toegevoegd.", + "PAGE_PREPARATION_LIST_NO_PREPARATION_EXISTING": "Je hebt nog geen zetmethodes toegevoegd.", + "PAGE_CONTACT_SUGGESTIONS_QUESTIONS_WISHES": "Suggesties, vragen, bugs of verzoeken?", + "PAGE_THANKS_THANKS_FOR_YOUR_SUPPORT": "Bedankt voor je steun!", + "PAGE_SETTINGS_LANGUAGE": "Taalinstellingen", + "PAGE_SETTINGS_LANGUAGE_GERMAN": "Duits", + "PAGE_SETTINGS_LANGUAGE_ENGLISH": "Engels", + "PAGE_SETTINGS_LANGUAGE_SPANISH": "Spaans", + "PAGE_SETTINGS_LANGUAGE_TURKISH": "Turks", + "PAGE_SETTINGS_LANGUAGE_CHINESE": "Chinees", + "PAGE_SETTINGS_GENERAL_SETTINGS": "Algemene instellingen", + "PAGE_SETTINGS_TRANSFER": "Gegevens overdragen", + "PAGE_SETTINGS_PRESET_LAST_BREW": "Vooraf ingestelde waarden?", + "PAGE_SETTINGS_DISPLAY": "Weergave", + "PAGE_SETTINGS_DISPLAY_SINGLE_PAGE": "Eén pagina", + "PAGE_SETTINGS_DISPLAY_PAGING": "Paging", + "PAGE_SETTINGS_STARTUP_VIEW": "Startpagina", + "PAGE_SETTINGS_ANALYTICS_INFORMATION": "Analytics", + "PAGE_SETTINGS_ANALYTICS_INFORMATION_TOOLTIP": "Druk op i voor meer informatie", + "PAGE_SETTINGS_TRACK_BREW_COORDINATES": "Geolocatie van brouwsel opslaan", + "PAGE_SETTINGS_FAST_REPEAT": "Snel herhalen", + "PAGE_SETTINGS_TRACK_CAFFEINE_CONSUMPTION": "bewaar cafeïneconsumptie", + "PAGE_SETTINGS_WAKE_LOCK": "Houd het display actief tijdens het brouwen", + "PAGE_SETTINGS_CURRENCY": "Valuta", + "PAGE_STATISTICS_DIFFERENT_PREPARATION_METHOD": "Bereidingsmethoden", + "PAGE_STATISTICS_TOTAL_GROUND_BEANS": "Totaal gemalen bonen", + "PAGE_STATISTICS_MONEY_SPENT_FOR_COFFEE": "Geld uitgegeven aan bonen", + "PAGE_STATISTICS_DRUNKEN_BREWS": "Totaal aantal brouwsels", + "PAGE_STATISTICS_BREW_PROCESSES": "Totaal brouwsels", + "PAGE_STATISTICS_DRUNKEN_QUANTITY": "Verbruikte hoeveelheid", + "PAGE_STATISTICS_BEAN_WEIGHT_USED": "Totaal gemalen bonen", + "PAGE_BREW_TEXT_INFORMATION_FROM_ROASTER": "Informatie over de brander", + "PAGE_ABOUT_NO_VERSION_AVAILABLE": "Geen Versie beschikbaar", + "PAGE_ABOUT_APP_VERSION": "App Versie", + "PAGE_LICENCES_WEBSITE": "Website", + "BEAN_DATA_ROAST_NAME": "Mate van branding", + "BEAN_DATA_CUSTOM_ROAST_NAME": "Aangepaste mate van branding", + "BEAN_DATA_ROASTING_DATE": "Brand datum", + "BEAN_DATA_ROASTER": "Brander", + "BEAN_DATA_VARIETY": "Variëteit", + "BEAN_DATA_PROCESSING": "Verwerking", + "BEAN_DATA_COUNTRY": "Land", + "BEAN_DATA_MIX": "Melange", + "BEAN_DATA_AROMATICS": "Smaakprofiel", + "BEAN_DATA_WEIGHT": "Gewicht", + "BEAN_DATA_COST": "kosten", + "BEAN_DATA_NAME": "Naam", + "BEAN_DATA_REGION": "Regio", + "BEAN_DATA_FARM": "Boerderij", + "BEAN_DATA_FARMER": "Boer", + "BEAN_DATA_ELEVATION": "Elevatie", + "BEAN_DATA_HARVEST_TIME": "Geoogst", + "BEAN_DATA_PERCENTAGE": "Percentage", + "BEAN_DATA_CERTIFICATION": "Bonencertificering", + "BEAN_DATA_ROASTING_TYPE": "type branding", + "BEAN_DATA_DECAFFEINATED": "Cafeïnevrij", + "BEAN_DATA_URL": "Website", + "BEAN_DATA_EAN": "EAN \/ Artikelnummer", + "BEAN_DATA_PURCHASING_PRICE": "Aankoopprijs", + "BEAN_DATA_FOB_PRICE": "FOB-prijs", + "BEAN_DATA_CUPPING_POINTS": "Cupping-punten", + "BREW_DATA_CUSTOM_BREW_TIME": "Aangepaste brouwtijd", + "BREW_CREATION_DATE": "Aanmaakdatum", + "REPEAT": "Herhalen", + "EDIT": "Bewerken", + "DELETE": "Verwijderen", + "FINISHED": "Archief", + "NOTES": "Notities", + "ADD_PHOTO": "Foto toevoegen", + "CANCEL": "Annuleren", + "GENERATE": "Genereren", + "SAVE": "Opslaan", + "ADD_SOMETHING": "Toevoegen", + "CONTACT": "Contact", + "NAME": "Naam", + "IMPORT": "import", + "EXPORT": "Export", + "VIEW": "Weergave", + "ARCHIVE": "archief", + "CURRENT": "huidig", + "BACK": "Terug", + "CLOSE": "sluiten", + "DAY": "Dag", + "BREW_DATA_TEMPERATURE_TIME": "Temperatuur Tijd", + "BREW_DATA_SURF_TIME": "Surftijd", + "BREW_DATA_TIME": "Tijd", + "BREW_DATA_GRIND_SIZE": "Maalinstelling", + "BREW_DATA_GRIND_WEIGHT": "Gemalen koffie (gr)", + "BREW_DATA_IN_OUT_BR": "In\/Uit (BR)", + "BREW_DATA_NOTES": "Notities", + "BREW_DATA_PREPARATION_METHOD": "Bereidingswijze", + "BREW_DATA_MILL": "Maler", + "BREW_DATA_MILL_SPEED": "Maalsnelheid (rpm)", + "BREW_DATA_MILL_TIMER": "Maaltijd", + "BREW_DATA_BREW_QUANTITY": "Hoeveelheid water", + "BREW_DATA_BEAN_TYPE": "Boon type", + "BREW_DATA_BREW_TEMPERATURE": "Brouwtemperatuur", + "BREW_DATA_PRESSURE_PROFILE": "Profiel", + "BREW_DATA_COFFEE_TYPE": "Type koffie", + "BREW_DATA_COFFEE_CONCENTRATION": "Koffie Concentratie", + "BREW_DATA_COFFEE_FIRST_DRIP_TIME": "Eerste druppeltijd", + "BREW_DATA_COFFEE_BLOOMING_TIME": "Bloeitijd \/ Pre-infusie", + "BREW_DATA_ATTACHMENTS": "Bijlagen \/ Foto's", + "BREW_DATA_RATING": "Beoordeling", + "BREW_DATA_CALCULATED_COFFEE_BREW_TIME": "Koffiezettijd", + "BREW_DATA_TDS": "Totaal opgeloste vaste stoffen %", + "BREW_DATA_CALCULATED_EXTRACTION_YIELD": "Extractie Opbrengst %", + "BREW_INFORMATION_BREW_RATIO": "Brouw Verhouding", + "BREW_INFORMATION_BEAN_AGE": "Boon leeftijd", + "BREW_INFORMATION_BREW_QUANTITY_TYPE_NAME": "Hoeveelheidstype", + "BREW_DATA_TDS_EY": "TDS \/ %EY", + "BREW_DATA_BREW_BEVERAGE_QUANTITY": "Hoeveelheid drank", + "BREW_DATA_PREPARATION_METHOD_TOOL": "bereidings gereedschappen", + "BREW_DATA_WATER": "Water", + "BREW_DATA_BEAN_WEIGHT_IN": "Bonengewicht (g)", + "BREW_DATA_VESSEL": "Serveerkan", + "BREW_DATA_VESSEL_WEIGHT": "Serveerkan gewicht", + "BREW_DATA_VESSEL_NAME": "Serveerkan naam", + "BREW_DATA_FLAVOR": "Smaak", + "BREW_DATA_FLOW_PROFILE": "Stroom", + "ONE_DAY": "Dag", + "DAYS": "Dagen", + "ONE_HOUR": "uur", + "HOURS": "uren", + "ONE_MINUTE": "minuut", + "MINUTES": "minuten", + "WITHOUT_COFFEE": "zonder koffie", + "NOT_FOUND": "Niet gevonden", + "INVALID_FILE_FORMAT": "Ongeldig bestandsformaat", + "FILE_NOT_FOUND_INFORMATION": "Bestand niet gevonden", + "ERROR_ON_FILE_READING": "Fout bij het lezen van bestandsgegevens", + "IMPORT_SUCCESSFULLY": "Importeren succesvol", + "IMPORT_UNSUCCESSFULLY_DATA_NOT_CHANGED": "Import mislukt, er zijn geen gegevens gewijzigd", + "INVALID_FILE_DATA": "Ongeldige bestandsinhoud", + "DOWNLOADED": "Gedownload", + "FILE_DOWNLOADED_SUCCESSFULLY": "Bestand ' {{fileName}} ' is succesvol gedownload naar uw downloadmap!", + "NO": "Nee", + "YES": "Ja", + "SURE_QUESTION": "Weet je het zeker?", + "DELETE_BREW_QUESTION": "Brouwsel verwijderen?", + "DELETE_BEAN_QUESTION": "Boon verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", + "DELETE_GREEN_BEAN_QUESTION": "Groene bonen verwijderen? Alle bijbehorende geroosterde bonen, evenals brouwsels worden verwijderd!", + "DELETE_MILL_QUESTION": "Grinder verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", + "DELETE_PREPARATION_METHOD_QUESTION": "Bereidingswijze verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", + "DELETE_PREPARATION_TOOL_QUESTION": "Bereidingstool verwijderen? Alle brouwsels die aan deze tool zijn gekoppeld, worden bijgewerkt.", + "APP_COULD_NOT_STARTED_CORRECTLY_BECAUSE_MISSING_FILESYSTEM": "App kon niet correct worden gestart vanwege ontbrekend bestandssysteem", + "CARE": "Zorg", + "ERROR_OCCURED": "Er is een fout opgetreden", + "CSV_FILE_NOT_DOWNLOADED": "CSV-bestand kon niet worden gedownload!", + "CSV_FILE_DOWNLOADED_SUCCESSFULLY": "CSV-bestand ' {{fileName}} ' is succesvol gedownload naar uw downloadmap!", + "ADD_BREW": "Voeg brouwsel toe", + "CHOOSE": "Kies", + "CHOOSE_PHOTO_OR_LIBRARY": "Maak een foto of kies uit de fotogalerij.", + "RECORD": "Maak een foto", + "PAGE_BEAN_INFORMATION": "Boon informatie", + "PAGE_BEAN_INFORMATION_GOOD_BREWS": "Goed", + "PAGE_BEAN_INFORMATION_BAD_BREWS": "Slecht", + "PAGE_BEAN_INFORMATION_COUNT_BREWS": "Totaal aantal brouwsels", + "INFORMATION": "Informatie", + "PAGE_BEAN_BREW_CHART_TITLE": "Brouwoverzicht voor deze boon", + "PAGE_BEAN_INFORMATION_AWESOME_BREWS": "Geweldig", + "PAGE_BEAN_INFORMATION_NORMAL_BREWS": "Normaal", + "PAGE_BEAN_INFORMATION_NOT_RATED_BREWS": "Niet beoordeeld", + "PAGE_PREPARATION_INFORMATION_BREWS_DONE": "Brouwsels met deze bereidingswijze", + "PAGE_PREPARATION_INFORMATION_BREWED_QUANTITY": "Gebrouwen hoeveelheid", + "PAGE_PREPARATION_INFORMATION_GRIND_WEIGHT": "Verbruikt gewicht van bonen", + "PAGE_PREPARATION_INFORMATION_TIME_SPENT_BREWING": "Totale bereidingstijd", + "PAGE_PREPARATION_INFORMATION": "Informatie over de bereiding", + "SECONDS": "Seconden", + "PAGE_MILL_INFORMATION": "Maler informatie", + "PAGE_MILL_INFORMATION_BREWS_DONE": "Brouwsels met deze maler", + "PAGE_MILL_INFORMATION_GRIND_WEIGHT": "Verbruikt gewicht van bonen", + "PAGE_HELPER_WATER_HARDNESS": "Waterhardheid", + "PAGE_HELPER_WATER_HARDNESS_CA_CONTENTS": "Calciumgehalte mg\/l", + "PAGE_HELPER_WATER_HARDNESS_MG_CONTENTS": "Magnesiumgehalte mg\/l", + "PAGE_HELPER_WATER_HARDNESS_GERMAN_HARDNESS": "Duitse hardheidsgraad", + "PAGE_HELPER_WATER_HARDNESS_TOTAL_HARDNESS": "Totale hardheid", + "PAGE_HELPER_BREW_RATIO": "Brouw Verhouding", + "PAGE_HELPER_BREW_RATIO_GROUND_COFFEE": "Gemalen koffie (gr)", + "PAGE_HELPER_BREW_RATIO_WATER": "Vloeistof (gr\/ml)", + "PAGE_HELPER_BREW_RATIO_CALCULATED": "Berekende brouwverhouding", + "PAGE_SETTINGS_SHOW_ARCHIVED_BREWS": "Gearchiveerde brouwsels weergeven", + "PAGE_SETTINGS_SHOW_ARCHIVED_BEANS": "Gearchiveerde bonen weergeven", + "PAGE_SETTINGS_SHOW_ARCHIVED_GREEN_BEANS": "Toon gearchiveerde groene bonen", + "CUPPING_SCORE": "Score", + "CUPPING_SCORE_DRY_FRAGRANCE": "Droge geur", + "CUPPING_SCORE_WET_AROMA": "Nat aroma", + "CUPPING_SCORE_BRIGHTNESS": "Helderheid", + "CUPPING_SCORE_FLAVOR": "Smaak", + "CUPPING_SCORE_BODY": "Body", + "CUPPING_SCORE_FINISH": "Afwerking", + "CUPPING_SCORE_SWEETNESS": "Zoetheid", + "CUPPING_SCORE_CLEAN_CUP": "Clean Cup", + "CUPPING_SCORE_COMPLEXITY": "Complexiteit", + "CUPPING_SCORE_UNIFORMITY": "Uniformiteit", + "CUPPING_SCORE_CUPPERS_CORRECTION": "Cuppers-correctie", + "CUPPING_SCORE_DRY_FRAGRANCE_TOOLTIP": "Verwijst naar het aroma van de droge gemalen koffie voordat er heet water aan wordt toegevoegd.", + "CUPPING_SCORE_WET_AROMA_TOOLTIP": "De geur van nat koffiedik, nadat er heet water aan is toegevoegd.", + "CUPPING_SCORE_BRIGHTNESS_TOOLTIP": "Zuurgraad is de smaak van scherpe hoge tonen in de koffie, veroorzaakt door een set van chlorogeen, citroenzuur, kininezuur, azijnzuur en andere, voornamelijk waargenomen in de voorkant van de mond en op de tong. (Het is een goede kwaliteit; niet gerelateerd aan bitterheid in koffie, en niet direct verantwoordelijk voor maagklachten). Zuurgraad wordt gewaardeerd door veel kopers, en is direct gerelateerd aan de kwaliteit van de kop, aangezien zuurgraad het product is van aanplantingen op grote hoogte.", + "CUPPING_SCORE_FLAVOR_TOOLTIP": "Dit is de algehele indruk in de mond, inclusief alle andere beoordelingen. Er zijn 4 \"primaire smaak\"-groeperingen (zuur, zoet, zout, bitter) en veel \"secundaire smaken\".", + "CUPPING_SCORE_BODY_TOOLTIP": "Vaak \"mondgevoel\" genoemd, is body het gevoel van gewicht en dikte van de gezette koffie, veroorzaakt door het percentage oplosbare vaste stoffen in de kop, inclusief alle organische verbindingen die worden geëxtraheerd (de zetmethode en de hoeveelheid gemalen koffie die wordt gebruikt, hebben hier grote invloed op). We beoordelen Body op een lagere schaal omdat licht gebodyde koffiesoorten zeker niet slecht zijn en in sommige origines past de lichtere body het beste bij het algehele karakter van de kop.", + "CUPPING_SCORE_FINISH_TOOLTIP": "De aanhoudende of opkomende smaken die komen nadat de mond is schoongemaakt. Dit omvat de tijd dat de koffie je mond verlaat tot minuten daarna...een reden dat je veel cuppers zult vinden die hun nasmaakscores herzien terwijl ze een minuut of twee later nog steeds een positieve smaak ervaren.", + "CUPPING_SCORE_SWEETNESS_TOOLTIP": "Zoetheid is bijna altijd een gewenste kwaliteit in koffie, zelfs als het op eufemistische wijze wordt beschreven, zoals \"rustieke zoetheid\" of \"bitterzoetheid\". U zult merken dat verfijnde zoetheid (denk aan Europees gebak, fijn snoepgoed, witte suiker, pure zoetheid) hoog scoort, evenals complexe zoetheid van fruitsuikers (fructose). Moutige zoetheid (maltose) is minder traditioneel, maar wel wenselijk en honing kan variëren van heel puur en schoon tot complex, rustiek, bijna gistachtig. Kortom, als zoetheid een sleutel is tot de kop, zal het goed worden beoordeeld.", + "CUPPING_SCORE_CLEAN_CUP_TOOLTIP": "Let op dat \"clean cup\" niet letterlijk betekent dat er geen vuil op de koffie zit. Het gaat alleen om smaak en rauwe, funky koffies die \"onrein\" zijn en de smaak kan ook heel wenselijk zijn, zoals nat-gepelde Indonesische koffies uit Sumatra, of droog verwerkte Ethiopische en Jemenitische types.", + "CUPPING_SCORE_COMPLEXITY_TOOLTIP": "Complexiteit complimenteert de scores voor \"smaak\" en \"afwerking\", om een veelheid of gelaagdheid van veel smaken te communiceren. Het betekent dat er veel te ontdekken valt in de kop. Aan de andere kant kunnen simpele koffies een opluchting zijn na overmatige blootstelling aan veel krachtige, intense, complexe koffies.", + "CUPPING_SCORE_UNIFORMITY_TOOLTIP": "Uniformiteit verwijst naar verschillen tussen kopjes. Koffiesoorten die met een droog proces zijn bereid, kunnen van nature minder uniform zijn dan koffiesoorten die met een nat proces zijn bereid. We zouden nooit een partij met fantastische smaken vermijden als deze af en toe afwijkt. Dit wordt gescoord tijdens het cuppingprotocol, waarbij meerdere kopjes worden gemaakt van elke partij die wordt beoordeeld.", + "CUPPING_SCORE_CUPPERS_CORRECTION_TOOLTIP": "Dit is aangepast van het SCAA-systeem en de Cup of Excellence-score (soms noemen ze het \"Overall Points\"). Het stelt een cupper in staat om ervoor te zorgen dat de totale score de algehele indruk van de cup correct weergeeft. U zou deze aanpak kunnen bekritiseren en het \"vervalsen\" van het totaal kunnen beschouwen. In zekere zin zou u gelijk hebben ... maar het zou veel erger zijn om de categoriescores te veranderen om het gewenste totaal te bereiken (om een koffie een 9 te geven voor zuurgraad terwijl u weet dat het een 7 is), of omgekeerd om een koffie die absoluut een 90 verdient, op 84 te laten eindigen. Het specifieke Cupper's Correction-nummer doet er niet toe, of het nu een 5 of een 8 is ... het idee is dat de totale score een correcte indruk geeft van de kwaliteit van de koffie.", + "CUPPING_SCORE_TOOLTIP": "100-95 = Verbazingwekkend, 90-94 = Uitstekend, 85-89 = Zeer goed, 80-84 = Goed, 75-79 = Redelijk, 70-74 = Slecht", + "DETAIL_BREW": "Brouw details", + "DETAIL_BEAN": "Boon details", + "DETAIL_MILL": "Maler details", + "DETAIL_PREPARATION": "Bereidings details", + "EDIT_BREW": "Bewerk brouwsel", + "ADD_BEAN": "Boon toevoegen", + "EDIT_BEAN": "Bewerken boon", + "ADD_PREPARATION": "Bereidingsmethode toevoegen", + "EDIT_PREPARATION": "Bewerk bereidingsmethode", + "ADD_MILL": "Voeg maler toe", + "EDIT_MILL": "Maler bewerken", + "USE_FILTER": "Filter toepassen", + "RESET_FILTER": "Filter resetten", + "COFFEE_GRAMS_GRINDED": "Gram gemalen", + "BEANS_USED": "Bonen geconsumeerd", + "BREW_HEADER_BEFORE_BREW": "Voor het brouwen", + "BREW_HEADER_WHILE_BREW": "Tijdens het brouwen", + "BREW_HEADER_AFTER_BREW": "Na het brouwen", + "BREW_HEADER_CUPPING": "Proeven", + "BEANS_CONSUMED": "Archieveer", + "NAV_MANAGE_PARAMETERS": "Parameters beheren", + "NAV_SORT_PARAMETERS": "Sorteer parameters", + "NAV_DEFAULT_PARAMETERS": "Standaardparameters definiëren", + "PAGE_SORT_PARAMETERS_DESCRIPTION": "Versleep parameters om te bepalen in welke volgorde ze worden weergegeven.", + "PAGE_MANAGE_PARAMETERS_DESCRIPTION": "Geef aan welke parameters moeten worden weergegeven bij het bewerken van brouwinformatie.", + "PAGE_DEFAULT_PARAMETERS_DESCRIPTION": "Markeer welke parameters standaard moeten worden ingesteld op de laatst gebruikte waarde.", + "SORT_PARAMETERS_BEFORE": "Voor het brouwen", + "SORT_PARAMETERS_MEANWHILE": "Tijdens het brouwen", + "SORT_PARAMETERS_AFTER": "Na het brouwen", + "MORE_INFORMATION": "Meer informatie", + "UNDERSTOOD": "Begrepen", + "WELCOME_PAGE_ACTIVATE_ANALYTICS_TITLE": "Analyse en tracking", + "WELCOME_PAGE_ACTIVATE_ANALYTICS_DESCRIPTION": "We willen de app, de website en onze toekomstige diensten voor u voortdurend verbeteren. Om dit te doen, moeten we wat gegevens bijhouden over hoe u de app en de functies ervan gebruikt. Maar we beloven dat we nooit persoonlijke gegevens zullen bijhouden. Om deze beloften waar te maken, gebruiken we Matomo, een open source service gericht op gegevensbeveiliging en privacy die op onze eigen server wordt gehost - dit zorgt ervoor dat alleen wij eigenaar zijn van de gegevens. Onze website biedt alle informatie over de parameters die we bijhouden en bovendien kunt u de broncode bekijken die 100% open source is. Heeft u vragen? Neem dan gerust contact met ons op.", + "ANALYTICS_INFORMATION_TITLE": "Analyse en tracking", + "ANALYTICS_INFORMATION_DESCRIPTION": "Zoals u weet, is de veiligheid van uw gegevens en uw privacy onze topprioriteit. Daarom zijn we overgestapt van Google Analytics naar de open source service Matomo, die zich richt op gegevensbeveiliging en privacy. Deze service wordt gehost op onze eigen server. Dit betekent dat wij volledig eigenaar zijn van de gegevens. De bijgehouden parameters zijn niet gewijzigd en we beloven nog steeds dat we nooit persoonlijke gegevens zullen bijhouden. Op onze website vindt u alle informatie over de parameters die we bijhouden. Bovendien kunt u de broncode bekijken, die 100% open source is. Heeft u vragen? Neem dan gerust contact met ons op.", + "ACTIVATE": "Activeren", + "DO_NOT_ACTIVE": "Niet activeren", + "WELCOME_PAGE_BEAN_TITLE": "Boon", + "WELCOME_PAGE_BEAN_DESCRIPTION": "Koffie zetten zonder bonen is een beetje lastig. Voeg je eerste boon toe om te beginnen!", + "WELCOME_PAGE_BEAN_ADD": "Boon toevoegen", + "SKIP": "Overslaan", + "WELCOME_PAGE_PREPARATION_TITLE": "Bereidingswijze", + "WELCOME_PAGE_PREPARATION_DESCRIPTION": "V60, Aeropress, Espresso - er zijn veel manieren om koffie te zetten. Voeg er minstens één toe.", + "WELCOME_PAGE_PREPARATION_ADD": "Bereidingswijze toevoegen", + "WELCOME_PAGE_MILL_TITLE": "Maler", + "WELCOME_PAGE_MILL_DESCRIPTION": "Bijna klaar, maar je hebt iets nodig om je bonen te malen! Voeg minstens één maler toe.", + "WELCOME_PAGE_MILL_ADD": "Voeg Maler toe", + "WELCOME_PAGE_TITLE": "Welkom!", + "WELCOME_PAGE_BEAN_HEADLINE": "Eerste boon", + "WELCOME_PAGE_PREPARATION_HEADLINE": "Bereidingswijze toevoegen", + "WELCOME_PAGE_MILL_HEADLINE": "Eerste Maler", + "WELCOME_PAGE_LETS_START_HEADLINE": "Nu kunnen we beginnen met brouwen!", + "WELCOME_PAGE_LETS_START_TITLE": "Nu kunnen we beginnen met brouwen!", + "WELCOME_PAGE_LETS_START_DESCRIPTION": "Gefeliciteerd, je bent klaar om de beste koffie van je leven te zetten. Veel plezier en verspreid de liefde voor goede koffie!", + "PREPARATION_TYPE": "Bereidingsmethode", + "PREPARATION_TYPE_NAME": "Naam", + "ARCHIVED": "Gearchiveerd", + "PAGE_SETTINGS_SHOW_ARCHIVED_PREPARATIONS": "Toon gearchiveerde bereidingsmethoden", + "PAGE_SETTINGS_SHOW_ARCHIVED_MILLS": "Toon gearchiveerde malers", + "PAGE_MILL_LIST_NO_ARCHIVED_MILL_EXISTING": "Er zijn nog geen malers gearchiveerd.", + "PAGE_PREPARATION_LIST_NO_ARCHIVED_PREPARATION_EXISTING": "Je hebt geen gearchiveerde bereidingswijzen.", + "TOAST_BREW_ADDED_SUCCESSFULLY": "Brouwsel succesvol toegevoegd", + "TOAST_BREW_REPEATED_SUCCESSFULLY": "Brouwsel succesvol herhaald", + "TOAST_BEAN_ADDED_SUCCESSFULLY": "Boon succesvol toegevoegd", + "TOAST_MILL_ADDED_SUCCESSFULLY": "Maler succesvol toegevoegd", + "TOAST_PREPARATION_ADDED_SUCCESSFULLY": "Bereidingswijze succesvol toegevoegd", + "TOAST_WATER_ADDED_SUCCESSFULLY": "Water succesvol toegevoegd", + "TOAST_BREW_DELETED_SUCCESSFULLY": "Brouwsel is verwijderd", + "TOAST_BEAN_DELETED_SUCCESSFULLY": "Boon is verwijderd", + "TOAST_GREEN_BEAN_DELETED_SUCCESSFULLY": "Groene boon is verwijderd", + "TOAST_MILL_DELETED_SUCCESSFULLY": "Maler is verwijderd", + "TOAST_WATER_DELETED_SUCCESSFULLY": "Water is verwijderd", + "TOAST_PREPARATION_DELETED_SUCCESSFULLY": "Bereidingswijze is verwijderd", + "TOAST_BREW_EDITED_SUCCESSFULLY": "Brouwsel is bewerkt", + "TOAST_BEAN_EDITED_SUCCESSFULLY": "Boon is bewerkt", + "TOAST_MILL_EDITED_SUCCESSFULLY": "Maler is bewerkt", + "TOAST_PREPARATION_EDITED_SUCCESSFULLY": "Bereiding is bewerkt", + "TOAST_WATER_EDITED_SUCCESSFULLY": "Water is bewerkt", + "TOAST_BEAN_ARCHIVED_SUCCESSFULLY": "Boon is gearchiveerd", + "TOAST_MILL_ARCHIVED_SUCCESSFULLY": "Maler is gearchiveerd", + "TOAST_PREPARATION_ARCHIVED_SUCCESSFULLY": "Bereidingsmethode is gearchiveerd", + "TOAST_WATER_ARCHIVED_SUCCESSFULLY": "Water is gearchiveerd", + "BEAN_WEIGHT_ALREADY_USED": "{{gramUsed}} g van {{gramTotal}} g ( {{leftOver}} g)", + "PREPARATION_TYPE_CUSTOM_PREPARATION": "Aangepaste bereidingsmethode", + "PREPARATION_TYPE_AEROPRESS": "Aeropress", + "PREPARATION_TYPE_V60": "V60", + "PREPARATION_TYPE_CHEMEX": "Chemex", + "PREPARATION_TYPE_BIALETTI": "Bialetti", + "PREPARATION_TYPE_PORTAFILTER": "Espresso machine", + "PREPARATION_TYPE_KALITA_WAVE": "Kalita Wave", + "PREPARATION_TYPE_FRENCH_PRESS": "French Press", + "PREPARATION_TYPE_SWANNECK": "Swan Neck", + "PREPARATION_TYPE_DRIPPER": "Dripper", + "PREPARATION_TYPE_DELTER_PRESS": "Delter Press", + "PREPARATION_TYPE_COLD_BREW": "Koud brouwsel", + "PREPARATION_TYPE_AEROPRESS_INVERTED": "Aeropress Omgekeerd", + "PREPARATION_TYPE_TURKISH": "Turks", + "PREPARATION_TYPE_BLUE_DRIPPER": "Blue Dripper", + "PREPARATION_TYPE_ADD_CUSTOM": "Aangepaste methode toevoegen", + "PREPARATION_TYPE_GINA": "Gina", + "PREPARATION_TYPE_KONO": "Kono", + "PREPARATION_TYPE_ORIGAMI": "Origami", + "PREPARATION_TYPE_CAFELAT": "Cafelat", + "PREPARATION_TYPE_OREA": "Orea", + "PREPARATION_TYPE_COLD_DRIP": "Cold Drip", + "PREPARATION_TYPE_HAND_LEVER": "Handmatige hendel", + "PREPARATION_TYPE_FLAIR": "Flair", + "PREPARATION_TYPE_APRIL_BREWER": "April Brewer", + "PREPARATION_TYPE_ESPRO_BLOOM": "Espreo Bloom", + "PREPARATION_TYPE_FELLOW_STAGG": "Fellow Stagg", + "PREPARATION_TYPE_HSIAO_50": "Hsiao 50", + "PREPARATION_TYPE_KARLSBADER_KANNE": "Karlsbader", + "PREPARATION_TYPE_MOCCA_MASTER": "Mocca Master", + "PREPARATION_TYPE_SIPHON": "Sifon", + "CHOOSE_BEANS": "Selecteer bonen", + "CHOOSE_BEAN": "Selecteer boon", + "CHOOSE_WATERS": "Selecteer wateren", + "CHOOSE_WATER": "Selecteer water", + "CHOOSE_PREPARATIONS": "Selecteer bereidingsmethoden", + "CHOOSE_PREPARATION": "Selecteer bereidingsmethode", + "CHOOSE_MILLS": "Selecteer molens", + "CHOOSE_MILL": "Selecteer molen", + "BEAN": { + "PLACE_HOLDER": { + "BEAN_DATA_NAME": "Naam toevoegen", + "BEAN_DATA_ROAST_NAME": "Voeg de mate van branding toe", + "BEAN_DATA_ROASTING_DATE": "Wanneer werden de bonen geroosterd?", + "BEAN_DATA_ROASTER": "Wie heeft de bonen geroosterd?", + "BEAN_DATA_VARIETY": "Voeg de koffievariant toe", + "BEAN_DATA_PROCESSING": "Koffieverwerking, bijvoorbeeld gewassen", + "BEAN_DATA_COUNTRY": "Waar komt de boon vandaan?", + "BEAN_DATA_MIX": "Wat is de melange ratio?", + "BEAN_DATA_AROMATICS": "Voeg smaken toe", + "BEAN_DATA_WEIGHT": "Gewicht van de bonen", + "BEAN_DATA_COST": "Hoeveel hebben de bonen gekost?", + "BEAN_DATA_REGION": "Regio toevoegen", + "BEAN_DATA_FARM": "Voeg de boerderij toe", + "BEAN_DATA_FARMER": "Voeg de boer toe", + "BEAN_DATA_ELEVATION": "Op welke hoogte werden de bonen geteeld", + "BEAN_DATA_HARVEST_TIME": "wanneer zijn de bonen geoogst?", + "BEAN_DATA_BUY_DATE": "Wanneer zijn de bonen gekocht?", + "BEAN_DATA_PERCENTAGE": "Voeg het percentage van deze boon in de melange toe", + "BEAN_DATA_CERTIFICATION": "Voeg de bonencertificering toe (bijv. fairtrade, bio)", + "BEAN_DATA_ROASTING_TYPE": "Voeg brand type toe", + "BEAN_DATA_DECAFFEINATED": "Is deze koffie cafeïnevrij", + "BEAN_DATA_URL": "Voeg de website-url toe", + "BEAN_DATA_EAN": "Voeg het EAN- of artikelnummer toe", + "BEAN_DATA_CUPPING_POINTS": "Voeg de cuppingpunten toe", + "BEAN_DATA_PURCHASING_PRICE": "Voeg de aankoopprijs toe", + "BEAN_DATA_FOB_PRICE": "Voeg de FOB-prijs toe", + "NOTES": "Voeg notities toe over deze bonen", + "CHOOSE_DATA_ROASTER": "Kies een brander", + "CHOOSE_DATA_ROASTING_TYPE": "Kies type branding", + "BEAN_DATA_BEST_DATE": "Wanneer is de beste datum om de bonen te gebruiken?", + "BEAN_DATA_OPEN_DATE": "Wanneer is de zak bonen geopend?", + "FROZEN_NOTES": "Zijn er opmerkingen over de bevroren koffie? Bijvoorbeeld in welke vriezer je het hebt bewaard." + } + }, + "PREPARATION": { + "PLACE_HOLDER": { + "PREPARATION_TYPE_NAME": "Voeg een naam toe", + "NOTES": "Voeg notities toe over deze bereidingsmethode" + } + }, + "MILL": { + "PLACE_HOLDER": { + "NAME": "Voeg een naam toe", + "NOTES": "Voeg notities toe over deze grinder" + } + }, + "BREW": { + "PLACE_HOLDER": { + "BREW_DATA_GRIND_SIZE": "Voer de maalinstelling in", + "BREW_DATA_GRIND_WEIGHT": "Vul de hoeveelheid koffie in (gr)", + "BREW_DATA_BREW_TEMPERATURE": "Voer de brouwtemperatuur in", + "BREW_DATA_PREPARATION_METHOD": "Selecteer bereidingsmethode", + "BREW_DATA_BEAN_TYPE": "Selecteer bonen", + "BREW_DATA_MILL": "Selecteer een molen", + "BREW_DATA_MILL_SPEED": "Voer de maalsnelheid in", + "BREW_DATA_MILL_TIMER": "Voer de maal tijd in", + "BREW_DATA_PRESSURE_PROFILE": "Druk\/stroomprofiel, brouwmethodologie", + "BREW_DATA_TEMPERATURE_TIME": "Voer de tijd in die de machine heeft mogen opwarmen", + "BREW_DATA_COFFEE_BLOOMING_TIME": "Hoe lang is de bloom?", + "BREW_DATA_COFFEE_FIRST_DRIP_TIME": "Wanneer verscheen de eerste druppel?", + "BREW_DATA_BREW_QUANTITY": "Hoeveel water heb je gebruikt om te brouwen?", + "BREW_DATA_COFFEE_TYPE": "Voer de koffiestijl in (bijv. ristretto)", + "BREW_DATA_COFFEE_CONCENTRATION": "Voer de koffie concentratie in", + "BREW_DATA_TDS": "Wat was de gemeten hoeveelheid opgeloste vaste stoffen (TDS)?", + "BREW_DATA_NOTES": "Voeg notities toe over dit brouwsel", + "BREW_DATA_BREW_BEVERAGE_QUANTITY": "Voeg totale drank hoeveelheid toe", + "BREW_DATA_PREPARATION_METHOD_TOOL": "Kies je bereiding tools", + "BREW_DATA_WATER": "Kies het gebruikte water", + "BREW_DATA_BEAN_WEIGHT_IN": "Welk gewicht aan bonen heb je gebruikt?" + } + }, + "ROASTED_BEFORE": "Geroosterd voor", + "DAY_OLD": "dag oud", + "DAYS_OLD": "dagen oud", + "BEANS_AMOUNT_USED": "Verbruikt", + "CUPPING_BREW": "Proeven", + "COFFEE_DRUNKEN_QUANTITY": "Koffie dronken", + "IMAGE_DELETED": "Afbeelding is verwijderd", + "IMAGE_NOT_DELETED": "Afbeelding kon niet worden verwijderd", + "EXTERNAL_STORAGE_NOT_SUPPORTED": "Sorry, externe opslag wordt niet ondersteund", + "BEANS_ARCHIVED": "Gearchiveerd", + "TAB_ARCHIVE": "Archief", + "TODAY": "Vandaag", + "PLEASE_WAIT": "Even geduld aub...", + "PREPARATION_STYLE_POUR_OVER": "Pourover", + "PREPARATION_STYLE_ESPRESSO": "Espresso", + "PREPARATION_STYLE_FULL_IMMERSION": "Immersie", + "PREPARATION_STYLE_PERCOLATION": "Percolatie", + "PREPARATION_TYPE_STYLE": "Bereidingsstijl", + "PAGE_SETTINGS_FAST_REPEAT_DESCRIPTION": "Activeert een nieuw menu-item - hiermee kun je een brouwsel kopieren.", + "PAGE_SETTINGS_TRACK_BREW_COORDINATES_DESCRIPTION": "Sla geolocatie gegevens op voor elk brouwsel.", + "PAGE_SETTINGS_TRACK_CAFFEINE_CONSUMPTION_DESCRIPTION": "Bewaar de hoeveelheid geconsumeerde cafeïne", + "UPDATE_TITLE": "Wat is er nieuw?", + "NEXT": "Volgende", + "CUSTOM_PARAMETERS": "Parameters aanpassen", + "CUSTOM_DEFAULT_PARAMETERS": "Standaard", + "CUSTOM_MANAGE_PARAMETERS": "Beheer", + "CUSTOM_SORT_PARAMETERS": "Sorteer", + "BREW_PARAMETER_CUSTOMIZE_TITLE": "Aangepaste parameters voor elke bereidingsmethode", + "BREW_PARAMETER_CUSTOMIZE_DESCRIPTION": "Wilt u voor elke bereidingsmethode aangepaste parameters kiezen? Navigeer naar \"Methoden\", open het menu van de specifieke bereidingsmethode en kies \"Parameters aanpassen\". Daar kunt u kiezen welke parameters voor deze bereiding worden gebruikt!", + "BREW_DATA_BREW_QUANTITY_TOOLTIP": "Hoeveelheid water (niet bruikbaar voor espresso)", + "BREW_DATA_COFFEE_FIRST_DRIP_TIME_TOOLTIP": "Eerste druppel tijd van de koffie (alleen espresso)", + "BREW_DATA_PREPARATION_METHOD_TOOLTIP": "Voorbereiding (alleen aanpasbaar indien actief)", + "PAGE_SETTINGS_GENERAL": "Algemene instellingen", + "EDIT_PREPARATION_CUSTOM_PARAMETERS": "Parameters aanpassen", + "ENABLE_PREPARATION_CUSTOM_PARAMETERS": "Aangepaste parameters gebruiken", + "BEAN_ADD_ANOTHER_SORT": "Voeg een andere boon type toe", + "BEAN_SORT": "Boon Type", + "BEAN_SORT_INFORMATION": "Informatie over de variëteit", + "BEAN_SORT_MORE_INFORMATION": "Meer informatie", + "NAVIGATE_TO_PREPARATION_METHODS": "Navigeer naar bereidingsmethoden", + "PREPARATION_TOOLS": "bereidingsmiddelen", + "PREPARATION_TOOLS_INFORMATION": "Voeg verschillende mandjes toe, WDT-gereedschappen voor uw espressomachine; stoffen, papieren of gaasfilters voor uw filterkoffie, enz.", + "PREPARATION_TOOLS_PLACEHOLDER": "Papieren of stoffen filter, VST 20g, 14g mandje, enz.", + "PREPARATION_PARAMETERS_CUSTOMIZED": "Aangepaste parameters", + "BEANS_WEIGHT_AVAILABLE": "Beschikbare bonen", + "SORT_ORDER": "Sorteervolgorde wijzigen", + "ASCENDING": "Oplopend", + "DESCENDING": "Aflopend", + "SORT_AFTER": "Sorteren na", + "BEAN_SORT_NAME_OF_BEAN": "Boon naam", + "BEAN_SORT_ROASTER": "Brander", + "BEAN_SORT_ROASTING_DATE": "Datum van roosteren", + "BEAN_TAB_ROAST_INFORMATION": "Geroosterde informatie", + "BEAN_TAB_GENERAL_INFORMATION": "Algemeen", + "BEAN_TAB_SORT_INFORMATION": "Informatie over de variëteit", + "PAGE_SETTINGS_MANAGE_ARCHIVE": "Archief beheren", + "LAST_USE": "Laatst gebruikt", + "SEARCH": "Zoeken", + "OVERVIEW": "Overzicht", + "BEAN_HEADER_ADDITIONALE_INFORMATION": "Aanvullende informatie", + "THREE_DEE_TOUCH_ACTION_BREW": "Brouw", + "THREE_DEE_TOUCH_ACTION_BEAN": "Boon", + "THREE_DEE_TOUCH_ACTION_PREPARATION": "Bereidingsmethode", + "THREE_DEE_TOUCH_ACTION_MILL": "Koffiemolen", + "PAGE_CREDITS_NOT_EXISTING": "Geen inhoud", + "TIMER_HOUR": "Uren", + "TIMER_MINUTES": "Minuten", + "TIMER_SECONDS": "Seconden", + "EXCEL": { + "BEAN": { + "CREATION_DATE": "Aanmaakdatum", + "ID": "Bonen-ID" + }, + "PREPARATION": { + "CREATION_DATE": "Aanmaakdatum", + "ID": "bereidingsmiddelen" + }, + "GRINDER": { + "CREATION_DATE": "Aanmaakdatum", + "ID": "Molen-ID" + } + }, + "EXCEL_EXPORT": "Excel-export", + "HEALTH_KIT_QUESTION_TITLE": "cafeïneconsumptie opslaan", + "HEALTH_KIT_QUESTION_MESSAGE": "Na activering wordt de geschatte cafeïne van elk brouwsel automatisch opgeslagen in Apple Health.", + "NAV_ROASTING_SECTION": "Bonen roosteren", + "ROASTING_SECTION": { + "NAV_GREEN_BEANS": "Groene bonen", + "NAV_ROASTING_MACHINE": "Roostermachine", + "ROASTING_MACHINE": { + "TOTAL_ROAST_QUANTITY": "Totaalgewicht geroosterd", + "TOTAL_ROAST_COUNT": "Aantal brandingen" + }, + "GREEN_BEAN": { + "ADD": "Toevoegen", + "EDIT": "Bewerking", + "DETAIL": "Groene bonen details", + "ROASTABLE": "Roosterbaar", + "NO_ROASTS_YET": "Nog geen gebrande bonen" + }, + "BEAN": { + "DROP_TEMPERATURE": "Eindtemperatuur van de gebrande boon", + "ROAST_LENGTH": "brand lengte", + "ROASTER_MACHINE": "Roostermachine", + "GREEN_BEAN_WEIGHT": "Gewicht van groene bonen", + "OUTSIDE_TEMPERATURE": "Omgevingstemperatuur", + "HUMIDITY": "Vochtigheid", + "FIRST_CRACK_MINUTE": "eerst kraak minuut", + "FIRST_CRACK_TEMPERATURE": "eerste kraak temperatuur", + "SECOND_CRACK_MINUTE": "Tweede kraak minuut", + "SECOND_CRACK_TEMPERATURE": "tweede kraak temperatuur", + "PLACE_HOLDER": { + "DROP_TEMPERATURE": "Eindtemperatuur van de gebrande boon", + "ROAST_LENGTH": "brand lengte", + "ROASTER_MACHINE": "Roostermachine", + "GREEN_BEAN_WEIGHT": "Gewicht van groene bonen", + "OUTSIDE_TEMPERATURE": "Omgevingstemperatuur", + "HUMIDITY": "Vochtigheid", + "FIRST_CRACK_MINUTE": "Eerste kraak minuut", + "FIRST_CRACK_TEMPERATURE": "Eerste kraak temperatuur", + "SECOND_CRACK_TEMPERATURE": "Tweede kraak temperatuur", + "SECOND_CRACK_MINUTE": "Tweede kraak minuut" + } + } + }, + "PAGE_SETTINGS_MANAGE_SECTIONS": "Meer secties", + "PAGE_SETTINGS_SHOW_ROASTING_SECTION": "Activeer brandersectie", + "PAGE_SETTINGS_SHOW_WATER_SECTION": "Activeer water sectie", + "PAGE_SETTINGS_SHOW_CUPPING_SECTION": "Activeer cupping-sectie", + "BEAN_DATA_BUY_DATE": "Aankoopdatum", + "BEAN_SORT_CREATION_DATE": "Aanmaakdatum", + "BEAN_SORT_PURCHASE_DATE": "Aankoopdatum", + "BEAN_ROAST_COUNT": "Roost aantal", + "TRANSFER_ROAST": "Geroosterd", + "BEAN_TAB_LINKED_ROASTS": "Geroosterd", + "BEAN_DATA_WEIGHT_AFTER_ROASTING": "Gewicht na het roosteren", + "TOAST_GREEN_BEAN_ADDED_SUCCESSFULLY": "Groene bonen toegevoegd", + "TOAST_GREEN_BEAN_EDITED_SUCCESSFULLY": "Groene boon bewerkt", + "TOAST_GREEN_BEAN_ARCHIVED_SUCCESSFULLY": "Groene bonen gearchiveerd", + "TOAST_ROASTING_MACHINE_ADDED_SUCCESSFULLY": "Roostermachine toegevoegd", + "TOAST_ROASTING_MACHINE_EDITED_SUCCESSFULLY": "Brandmachine bewerkt", + "TOAST_ROASTING_MACHINE_ARCHIVED_SUCCESSFULLY": "Brander gearchiveerd", + "DELETE_ROASTING_MACHINE_QUESTION": "Brander verwijderen? Alle gebrande bonen waarnaar verwezen wordt, worden bijgewerkt en niet verwijderd.", + "TOAST_ROASTING_MACHINE_DELETED_SUCCESSFULLY": "Brander verwijderd", + "EDIT_ROASTING_MACHINE": "Bewerk", + "DETAIL_ROASTING_MACHINE": "Details van de brander", + "DELETE_WATER_QUESTION": "Water verwijderen? Alle gerefereerde brouwsels worden bijgewerkt en niet verwijderd", + "ROASTING_MACHINE": { + "PLACE_HOLDER": { + "NAME": "Voeg een naam toe", + "NOTES": "Opmerkingen toevoegen voor deze brander" + } + }, + "NAV_ROASTING_MACHINE": "koffierooster machines", + "PAGE_ROASTING_MACHINE_LIST_NO_MACHINES_EXISTING": "U hebt geen koffiebrander toegevoegd", + "PAGE_ROASTING_MACHINE_LIST_NO_ARCHIVED_MACHINES_EXISTING": "je hebt geen koffiebrander gearchiveerd", + "CHOOSE_ROASTING_MACHINES": "koffiebrander", + "CHOOSE_ROASTING_MACHINE": "koffiebrander", + "POPOVER_BREWS_OPTION_TOGGLE_FAVOURITE": "Favoriet", + "TOAST_BREW_FAVOURITE_ADDED": "Favoriet toegevoegd", + "TOAST_BREW_FAVOURITE_REMOVED": "Favoriet verwijderd", + "BREW_FILTER_JUST_FAVOURITE": "Favorieten", + "STATISTICS_PREPARATION_USAGES": "Bereidingsmethode gebruik", + "STATISTICS_PREPARATION_TIMELINE_USAGES": "Gebruiksgeschiedenis bereidingsmethode", + "STATISTICS_GRINDER_TIMELINE_USAGES": "Gebruiksgeschiedenis van de Maler", + "ACCEPT": "Accepteer", + "STATISTIC_TAB_GENERAL": "Algemeen", + "STATISTIC_TAB_BREWS": "Brouwsels", + "STATISTIC_TAB_BEANS": "Bonen", + "STATISTIC_TAB_PREPARATIONS": "Voorbereidingen", + "STATISTIC_TAB_GRINDERS": "Malers", + "PAGE_STATISTICS_BREW_PER_DAYPROCESSES": "Brouwsels per dag", + "PAGE_STATISTICS_BREW_TIME": "Brouwtijd", + "PAGE_STATISTICS_PHOTOS_TAKEN": "Foto's gemaakt", + "PAGE_SETTINGS_IMAGE_QUALITY": "afbeelding kwaliteit", + "PAGE_SETTINGS_IMAGE_QUALITY_TOOLTIP": "Bepaal in welke kwaliteit uw afbeeldingen moeten worden opgeslagen. Dit kan uw dataverbruik verlagen.", + "PAGE_SETTINGS_BREW_RATING": "Brouw beoordeling", + "PAGE_SETTINGS_BREW_RATING_TOOLTIP": "Is de standaard '-1 tot 5' niet de juiste beoordeling voor u? U kunt in plaats daarvan een '-1 tot 100' schaal gebruiken", + "UPDATE_ENTRY_OF": "Update item {{index}} van {{count}}", + "WEBSITE": "Website", + "SHARE": "Deel", + "ANDROID_FILE_ACCESS_NEEDED_TITLE": "Toegang tot gedeeld bestand vereist", + "ANDROID_FILE_ACCESS_NEEDED_DESCRIPTION": "Om de app volledig te laten werken, vragen we u om bestandstoegang te autoriseren. Anders ontstaan er problemen bij het gebruik van de app. Dit is specifiek nodig voor het automatische back-upsysteem.", + "COULD_NOT_ACCESS_FILE": "We konden het gekozen bestand niet openen", + "WRONG_FILE_FORMAT": "U hebt een niet-ondersteund bestandsformaat gekozen", + "SCAN_BEAN": "Scan pakket", + "CLEAR": "leeg maken", + "BEAN_LOOKS_LIKE_CONSUMED": "Het lijkt erop dat deze bonen op zijn. Wil je ze archiveren?", + "CUPPING_1": "Fruit", + "CUPPING_2": "Citrus", + "CUPPING_3": "Citroen & limonade", + "CUPPING_4": "Limoen", + "CUPPING_5": "Grapefruit", + "CUPPING_6": "Clementine", + "CUPPING_7": "Mandarijn", + "CUPPING_8": "mandarijn sinaasappel", + "CUPPING_9": "sinasappel", + "CUPPING_10": "Appel\/peer", + "CUPPING_11": "Groene appel", + "CUPPING_12": "Rode appel", + "CUPPING_13": "Meloen", + "CUPPING_14": "Watermeloen", + "CUPPING_15": "Honingdauw meloen", + "CUPPING_16": "Cantaloupe meloen", + "CUPPING_17": "Druif", + "CUPPING_18": "Witte druif", + "CUPPING_19": "Groene druif", + "CUPPING_20": "Rode druif", + "CUPPING_21": "Concord-druif", + "CUPPING_22": "Tropisch fruit", + "CUPPING_23": "Litchi", + "CUPPING_24": "Stervrucht", + "CUPPING_25": "Tamarinde", + "CUPPING_26": "Passievrucht", + "CUPPING_27": "Ananas", + "CUPPING_28": "Mango", + "CUPPING_29": "Papaja", + "CUPPING_30": "Kiwi", + "CUPPING_31": "Banaan", + "CUPPING_32": "Kokosnoot", + "CUPPING_33": "Steenvrucht", + "CUPPING_34": "Perzik", + "CUPPING_35": "Nectarine", + "CUPPING_36": "Abrikoos", + "CUPPING_37": "Pruim", + "CUPPING_38": "Kers", + "CUPPING_39": "Zwarte kers", + "CUPPING_40": "Bes", + "CUPPING_41": "Cranberry", + "CUPPING_42": "Framboos", + "CUPPING_43": "Aardbei", + "CUPPING_44": "Bosbes", + "CUPPING_45": "Rode bes", + "CUPPING_46": "Zwarte bes", + "CUPPING_47": "Gedroogd fruit", + "CUPPING_48": "Gouden rozijn", + "CUPPING_49": "Rozijn", + "CUPPING_50": "Gedroogde vijg", + "CUPPING_51": "Gedroogde dadels", + "CUPPING_52": "Gedroogde Pruim", + "CUPPING_53": "Zoet & gebrand", + "CUPPING_54": "Chocolade", + "CUPPING_55": "Cacaonibs", + "CUPPING_56": "Donkere chocolade", + "CUPPING_57": "Bakkers chocolade", + "CUPPING_58": "Bitterzoete chocolade", + "CUPPING_59": "Cacaopoeder", + "CUPPING_60": "Melkchocolade", + "CUPPING_61": "Noot", + "CUPPING_62": "Walnoot", + "CUPPING_63": "Pinda", + "CUPPING_64": "Cashew", + "CUPPING_65": "Pecannoot", + "CUPPING_66": "Hazelnoot", + "CUPPING_67": "Amandel", + "CUPPING_68": "Graan & Graanproducten", + "CUPPING_69": "Zoet broodgebak", + "CUPPING_70": "Granola", + "CUPPING_71": "Graham-cracker", + "CUPPING_72": "Rogge", + "CUPPING_73": "Tarwe", + "CUPPING_74": "Gerst", + "CUPPING_75": "Vers brood", + "CUPPING_76": "Zoet & Suikerachtig", + "CUPPING_77": "Vanille", + "CUPPING_78": "Noga", + "CUPPING_79": "Honing", + "CUPPING_80": "Boter", + "CUPPING_81": "Room", + "CUPPING_82": "Marshmallow", + "CUPPING_83": "Rietsuiker", + "CUPPING_84": "Bruine suiker", + "CUPPING_85": "Karamel", + "CUPPING_86": "Ahornsiroop", + "CUPPING_87": "Melasse", + "CUPPING_88": "Cola", + "CUPPING_89": "Geroosterd", + "CUPPING_90": "Toast", + "CUPPING_91": "Verbrande suiker", + "CUPPING_92": "Rokerig", + "CUPPING_93": "Koolstof", + "CUPPING_94": "Plantaardig, hartig en kruidig", + "CUPPING_95": "Kruiden", + "CUPPING_96": "Zwarte peper", + "CUPPING_97": "Witte peper", + "CUPPING_98": "Kaneel", + "CUPPING_99": "Koriander", + "CUPPING_100": "Gember", + "CUPPING_101": "Nootmuskaat", + "CUPPING_102": "Kerrie", + "CUPPING_103": "Drop-anijs", + "CUPPING_104": "Kruidnagel", + "CUPPING_105": "Hartig", + "CUPPING_106": "Leerachtig", + "CUPPING_107": "Vleesachtig", + "CUPPING_108": "Sojasaus", + "CUPPING_109": "Zongedroogde tomaat", + "CUPPING_110": "Tomaat", + "CUPPING_111": "Plantaardig aards kruid", + "CUPPING_112": "Grond", + "CUPPING_113": "Vers hout", + "CUPPING_114": "Ceder", + "CUPPING_115": "Tabak", + "CUPPING_116": "Hooi \/ stro", + "CUPPING_117": "Bladgroenten", + "CUPPING_118": "Olijf", + "CUPPING_119": "Groene peper", + "CUPPING_120": "Pompoen", + "CUPPING_121": "Paddestoel", + "CUPPING_122": "Zoete erwt", + "CUPPING_123": "Sneeuwerwt", + "CUPPING_124": "Grassig", + "CUPPING_125": "Dille", + "CUPPING_126": "Salie", + "CUPPING_127": "Munt", + "CUPPING_128": "Groene thee", + "CUPPING_129": "Zwarte thee", + "CUPPING_130": "Hop", + "CUPPING_131": "Bergamot", + "CUPPING_132": "Bloemrijk", + "CUPPING_133": "Bloemen", + "CUPPING_134": "Hibiscus", + "CUPPING_135": "Rozenbottels", + "CUPPING_136": "Lavendel", + "CUPPING_137": "Magnolia", + "CUPPING_138": "Jasmijn kamperfoelie", + "CUPPING_139": "Oranjebloesem", + "CUPPING_140": "Citroengras", + "WATER_SECTION": { + "NAV_WATER": "Water", + "YOU_GOT_NO_ARCHIVED_WATER": "Je hebt nog geen water gearchiveerd", + "YOU_GOT_NO_WATER": "Je hebt nog geen water toegevoegd", + "CATEGORY_INFORMATION": "Water informatie", + "CATEGORY_GENERAL": "Algemeen", + "WATER_BOTTLE_EXPLANATION": "Waterflessen vermelden de concentratie meestal in eenheden van ppm = mg\/L", + "USED_TIMES": "Aantal keren gebruikt", + "AMOUNT": "Gebruikte hoeveelheid", + "WATER": { + "GENERAL_HARDNESS": "Algemene hardheid (GH)", + "TOTAL_ALKALINITY": "Totale alkaliteit (KH)", + "CALCIUM": "Kalium (Ca)", + "MAGNESIUM": "Magnesium (Mg)", + "SODIUM": "Natrium (Na)", + "TDS": "Totaal opgeloste vaste stoffen (TDS)", + "UNITS": "Eenheden", + "PLACE_HOLDER": { + "GENERAL_HARDNESS": "Algemene hardheid", + "TOTAL_ALKALINITY": "Totale alkaliteit", + "CALCIUM": "Kalium (Ca)", + "MAGNESIUM": "Magnesium (Mg)", + "SODIUM": "Natrium (Na)", + "TDS": "Totaal opgeloste vaste stoffen (TDS)", + "NAME": "Voeg waternaam toe", + "NOTES": "Voeg wat notities toe voor je water", + "POTASSIUM": "Kalium (K)", + "CHLORIDE": "Chloride (Cl)", + "SULFATE": "Sulfaat (SO4)" + }, + "WATER_UNIT": { + "UNKNOWN": "Onbekend", + "PPM": "ppm als CaCO3", + "MG_L": "mg\/L", + "MMOL_L": "mmol\/L", + "DH": "°dH" + }, + "POTASSIUM": "Kalium (K)", + "CHLORIDE": "Chloride (Cl)", + "SULFATE": "Sulfaat (SO4)" + } + }, + "BREW_BRIX_CALCULATION": "Graden Brix", + "SET_TDS": "TDS instellen", + "TOTAL_WEIGHT": "Totaal gewicht", + "CALCULATED_WEIGHT": "Berekend gewicht", + "SET_WEIGHT": "Gewicht instellen", + "ADD_FLAVORS_AROMAS_TITLE": "Aroma's \/ Smaken", + "CUSTOM_FLAVORS_AROMAS": "Individueel aroma", + "CUSTOM_FLAVORS_AROMAS_PLACEHOLDER": "Voeg je individuele aroma toe", + "PREDEFINED_FLAVORS_AROMAS": "Veel voorkomende aroma's", + "ADD_AROMA_FLAVOR": "Aroma's\/smaken toevoegen", + "BEAN_WEIGHT_IN_PLACEHOLDER": "Bonen uit de verpakking gehaald", + "VESSEL_PLACEHOLDER": "Naam van het Serveerkan en het leeggewicht ervan", + "GRIND_WEIGHT_PLACEHOLDER": "Gewicht van de gemalen bonen die voor het brouwen worden gebruikt", + "PRESET_BREW_TITLE": "Gebruik laatste brouwsel als voorinstelling", + "CUPPING_BREW_TAB_AROMA": "Aroma", + "CUPPING_BREW_TAB_TASTING": "Systematische cupping", + "WATER_PLACEHOLDER": "Activeer het watergedeelte in het instellingenmenu voor volledige functionaliteit", + "PAGE_SETTINGS_SCALES": "Weegschalen", + "CONNECT": "Verbinden", + "DISCONNECT": "Loskoppelen", + "SCALE": { + "BLUETOOTH_SCAN_RUNNING": "Zoeken naar weegschaal tot 60s", + "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", + "CONNECTION_NOT_ESTABLISHED": "Weegschaal niet gevonden, of verbinding kon niet tot stand worden gebracht", + "CONNECTED_SUCCESSFULLY": "Weegschaal verbonden", + "DISCONNECTED_SUCCESSFULLY": "Weegschaal losgekoppeld", + "DISCONNECTED_UNPLANNED": "Weegschaal onverwachts losgekoppeld", + "REQUEST_PERMISSION": { + "LOCATION": "Om Bluetooth-weegschalen te vinden, heeft de app toegang nodig tot de locatie.", + "BLUETOOTH": "Om bluetooth-weegschalen te vinden, heeft de app toegang tot bluetooth nodig" + }, + "INFORMATION_DESCRIPTION": "Ondersteunde weegschalen zijn: Decent Scale, Acaia, Felicita, Hiroia Jimmy, Skale 2, DiFluid Microbalance, Smartchef Scale, Blackcoffee.io, Bookoo Mini Scale en Eureka Precisa. Let op: Als de Eureka Precisa een negatieve waarde ontvangt, stopt de timer" + }, + "QR": { + "WRONG_QRCODE_DESCRIPTION": "Ongeldige QR-code of onbekende inhoud", + "WRONG_QRCODE_TITLE": "Fout", + "WRONG_LINK_DESCRIPTION": "Ongeldige QR-link", + "WRONG_LINK_TITLE": "Fout", + "SERVER": { + "ERROR_OCCURED": "Er is een fout opgetreden. De QR-code kon niet worden gelezen. Probeer het opnieuw.", + "BEAN_NOT_APPROVED": "Boon is nog niet goedgekeurd, probeer het later nog eens" + }, + "BEAN_SUCCESSFULLY_SCANNED": "Bean succesvol gescand", + "BEAN_SUCCESSFULLY_REFRESHED": "Boon succesvol bijgewerkt", + "IMAGES_GETTING_DOWNLOADED": "Afbeeldingen downloaden" + }, + "RETRY_CONNECT": "Verbinding opnieuw proberen", + "SMART_SCALE_STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de weegschaal verbonden, zelfs als de app op de achtergrond draait", + "BREW_FLOW_WEIGHT": "Gewicht", + "BREW_FLOW_WEIGHT_PER_SECOND": "Stroom (afgevlakt)", + "ROAST_TYPE_UNKNOWN": "onbekend", + "ROAST_TYPE_CINNAMON_ROAST": "Cinnamon Branding", + "ROAST_TYPE_AMERICAN_ROAST": "Amerikaans Branding", + "ROAST_TYPE_NEW_ENGLAND_ROAST": "Nieuw-Engeland Branding", + "ROAST_TYPE_HALF_CITY_ROAST": "Half City Branding", + "ROAST_TYPE_MODERATE_LIGHT_ROAST": "Matig-lichte branding", + "ROAST_TYPE_CITY_ROAST": "City Branding", + "ROAST_TYPE_CITY_PLUS_ROAST": "City+ Branding", + "ROAST_TYPE_FULL_CITY_ROAST": "Full City Branding", + "ROAST_TYPE_FULL_CITY_PLUS_ROAST": "Full City + Branding", + "ROAST_TYPE_ITALIAN_ROAST": "Ialiaanse Branding", + "ROAST_TYPE_VIEANNA_ROAST": "Weense Branding", + "ROAST_TYPE_FRENCH_ROAST": "Franse Branding", + "ROAST_TYPE_CUSTOM_ROAST": "Aangepast", + "BEAN_MIX_UNKNOWN": "onbekend", + "BEAN_MIX_SINGLE_ORIGIN": "Single Origin", + "BEAN_MIX_BLEND": "Melange", + "BEAN_ROASTING_TYPE_FILTER": "Filter", + "BEAN_ROASTING_TYPE_ESPRESSO": "Espresso", + "BEAN_ROASTING_TYPE_OMNI": "Omni", + "BEAN_ROASTING_TYPE_UNKNOWN": "Onbekend", + "SMART_SCALE_LOG": "Activeer logbestanden voor slimme weegschaal (alleen voor foutopsporing)", + "TOAST_PREPARATION_TOOL_EDITED_SUCCESSFULLY": "Voorbereidingstool bewerkt", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE": "Bluetooth-weegschaal", + "PAGE_SETTINGS_TAB_GENERAL": "Algemeen", + "SMART_SCALE_TARE_ON_BREW": "Tarraweegschaal op nieuw brouwsel", + "SMART_SCALE_TARE_ON_START_TIMER": "Tarra weegschaal bij het starten van de timer", + "PAGE_SETTINGS_BREW_RATING_STEPS": "Beoordelingsstappen", + "BREW_AVG_FLOW_WEIGHT_PER_SECOND": "Ø Stroom", + "CUSTOM_LIST_VIEW_PARAMETERS": "Parameters voor lijstweergave", + "NAV_LIST_VIEW_CUSTOM_PARAMETERS": "Parameters voor lijstweergave", + "PAGE_LIST_VIEW_CUSTOM_PARAMETERS_DESCRIPTION": "Bepaal welke parameters moeten worden weergegeven op de tegels van de lijstweergave", + "BREW_DATA_VESSEL_NAME_WEIGHT": "Serveerkan Naam\/Gewicht", + "IGNORE_NEGATIVE_VALUES": "Negeer negatieve gewichtswaarden", + "IGNORE_ANOMALY_VALUES": "Negeer afwijkende waarden", + "IGNORE_ANOMALY_VALUES_TOOLTIP": "Bijvoorbeeld: Een kopje rond bewegen op de weegschaal", + "TOAST_BEAN_FAVOURITE_ADDED": "Favoriet toegevoegd", + "TOAST_BEAN_FAVOURITE_REMOVED": "Favoriet verwijderd", + "QR_CODE_SCANNER_INFORMATION_TITLE": "QR-code", + "QR_CODE_SCANNER_INFORMATION_DESCRIPTION": "Alle gescande boneninformatie komt rechtstreeks van de branderij. Mocht u onjuiste of misleidende informatie aantreffen, laat het mij dan weten via e-mail: info@beanconqueror.com.", + "DONT_SHOW_AGAIN": "Niet meer weergeven", + "ARCHIVED_TOOLS": "Gearchiveerd gereedschap", + "UNARCHIVE": "Herstel", + "PAGE_SETTINGS_HIDE_ARCHIVED_BREWS_DASHBOARD": "Toon gearchiveerde brouwsels op dashboard", + "PAGE_SETTINGS_HIDE_ARCHIVED_BREWS_DASHBOARD_DESCRIPTION": "Moeten gearchiveerde brouwsels op de startpagina worden weergegeven?", + "COPY": "Kopiëren", + "TOAST_PREPARATION_METHOD_REPEATED_SUCCESSFULLY": "Bereidingsmethode succesvol gekopieerd", + "PREPARATION_TYPE_CAFEC_FLOWER": "Cafec Flower", + "PREPARATION_TYPE_DECEMBER_DRIPPER": "December Dripper", + "PREPARATION_TYPE_DECENT_ESPRESSO": "Decent Espresso", + "PREPARATION_TYPE_HARIO_SWITCH": "Hario Switch", + "PREPARATION_TYPE_HARIO_WOODNECK": "Hario Woodneck", + "PREPARATION_TYPE_RATIO_SIX_COFFEE_BREWER": "Ratio Six-koffiezetapparaat", + "PREPARATION_TYPE_ROK": "ROK", + "PREPARATION_TYPE_TORNADO_DUO": "Tornado-duo", + "PREPARATION_TYPE_TRICOLATE": "Tricolate", + "QR_CODE_REFRESH_DATA_MESSAGE": "Alle informatie voor deze boon wordt overschreven, doorgaan?", + "POPOVER_QR_CODE_REFRESH": "Gegevens opnieuw laden", + "BREW_FLOW_WEIGHT_REALTIME": "Stroom (realtime)", + "SMART_SCALE_STOP_TIMER_ON_BREW": "Stop de timer van de weegschaal bij een nieuw brouwsel", + "SMART_SCALE_RESET_TIMER_ON_BREW": "Reset de weegschaaltimer bij een nieuw brouwsel", + "BREW_PRESSURE_FLOW": "Druk", + "BREW_TEMPERATURE_REALTIME": "Temperatuur", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_SHOW_GRAPHS_FILTER": "Grafieken weergeven voor filter", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_SHOW_GRAPHS_ESPRESSO": "Toon grafieken voor espresso", + "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE": "Drukapparaat", + "PAGE_SETTINGS_TAB_BLUETOOTH_TEMPERATURE": "Temperatuur apparaat", + "PRESSURE_LOG": "Activeer logbestanden voor drukapparaat", + "PRESSURE_THRESHOLD_ACTIVE": "Starttimer met vooraf gedefinieerde druk", + "PRESSURE_THRESHOLD_BAR": "Drempelwaarde druk", + "TIMER_MILLISECONDS": "MS", + "PAGE_SETTINGS_BREW_ENABLE_MILLISECONDS": "Milliseconden?", + "PAGE_SETTINGS_BREW_ENABLE_MILLISECONDS_DESCRIPTION": "Gebruik milliseconden om uw brouwsels nog nauwkeuriger te analyseren", + "PAGE_SETTINGS_BEAN_RATING": "Bonen beoordeling", + "PAGE_SETTINGS_BEAN_RATING_TOOLTIP": "Is de standaard '0 tot 5' niet de juiste beoordeling voor u? U kunt in plaats daarvan een '0 tot 100'-schaal gebruiken", + "PAGE_SETTINGS_BEAN_RATING_STEPS": "Stappen voor het beoordelen van bonen", + "COFFEE_GRAMS_BREWED": "grammen gebrouwen", + "SMART_SCALE_MAXIMIZE_ON_START_TIMER": "Maximaliseer realtime-grafiek bij het starten van de timer", + "PRESSURE": { + "CONNECTION_NOT_ESTABLISHED": "Drukapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", + "CONNECTED_SUCCESSFULLY": "Drukapparaat aangesloten", + "DISCONNECTED_SUCCESSFULLY": "Drukapparaat losgekoppeld", + "DISCONNECTED_UNPLANNED": "Drukapparaat onverwachts losgekoppeld", + "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd het drukapparaat aangesloten, zelfs als de app op de achtergrond draait", + "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: Popsicle, Pressensor, Smart Espresso Profiler, Bookoo Espresso Monitor", + "BLUETOOTH_SCAN_RUNNING": "Zoeken naar drukapparaat gedurende maximaal 60 seconden", + "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", + "REQUEST_PERMISSION": { + "LOCATION": "Om drukapparaten te vinden, heeft de app toegang nodig tot de locatie.", + "BLUETOOTH": "Om drukapparaten te vinden, heeft de app toegang tot Bluetooth nodig" + } + }, + "POPOVER_BLUETOOTH_ACTION_RECONNECT_SCALE": "Weegschaal opnieuw verbinden", + "POPOVER_BLUETOOTH_ACTION_RECONNECT_PRESSURE_DEVICE": "Drukapparaat opnieuw aansluiten", + "POPOVER_SHOW_BREWS": "Toon brouwsels", + "LAST_USED_GRIND_SIZE_SETTING": "Laatste maalstand", + "LAST_USED_BEAN": "Laatste boon", + "PAGE_SETTINGS_BREW_MILLISECONDS_DECIMAL_PLACES_DESCRIPTION": "Hoeveel decimalen moeten er worden weergegeven?", + "SMART_SCALE_COMMAND_DELAY": "Opdracht vertraging", + "SMART_SCALE_COMMAND_DELAY_TOOLTIP": "Hoeveel tijd moet er verstrijken tussen elk bluetooth-commando?", + "SUPPORT_ME": "Donatie", + "PAGE_SETTINGS_BREW_DISPLAY_BEAN_IMAGE": "Bonenafbeeldingen op brouwsels weergeven?", + "PAGE_SETTINGS_BREW_DISPLAY_BEAN_IMAGE_DESCRIPTION": "Als er een bonenafbeelding bestaat, wordt deze gebruikt in plaats van de afbeelding van de bereidingsmethode", + "DOWNLOAD_XLSX": "Excel downloaden", + "DOWNLOAD_JSON": "JSON downloaden", + "NAV_BEAN_PARAMS": "Boon Parameters", + "BEAN_DATA_ROAST_NAME_TYPE": "Brand graad", + "ENABLE_BEAN_SORT_INFORMATION": "Variëteit-informatie inschakelen", + "BEAN_SORT_MIX": "Bonenmix", + "PAGE_MANAGE_BEAN_PARAMETERS_DESCRIPTION": "Markeer welke parameters moeten worden weergegeven bij het bewerken van bean-informatie.", + "PAGE_BEAN_LIST_VIEW_CUSTOM_PARAMETERS_DESCRIPTION": "Bepaal de parameters die moeten worden weergegeven in lijstweergaven voor bonen", + "BEAN_DATA_NAME_TOOLTIP": "De naam van de bonen", + "BEAN_DATA_ROASTER_TOOLTIP": "Wie is de brander", + "BEAN_DATA_BUY_DATE_TOOLTIP": "Wanneer heb je de bonen gekocht?", + "BEAN_DATA_ROASTING_DATE_TOOLTIP": "Wat is de branddatum van de bonen?", + "BEAN_DATA_ROASTING_TYPE_TOOLTIP": "Voor welke bereidingswijze is deze boon geroosterd, bijvoorbeeld Filter", + "BEAN_DATA_ROAST_NAME_TOOLTIP": "Wat is de brandingsgraad van de bonen?", + "BEAN_DATA_ROAST_NAME_TYPE_TOOLTIP": "Welk type branding (Cinnamon, New England, etc.)", + "BREW_DATA_RATING_TOOLTIP": "Je waardering", + "BEAN_SORT_MIX_TOOLTIP": "Zijn de bonen een melange?", + "BEAN_DATA_WEIGHT_TOOLTIP": "Hoeveel wegen de bonen?", + "BEAN_DATA_COST_TOOLTIP": "Hoeveel hebben de bonen gekost?", + "BEAN_DATA_AROMATICS_TOOLTIP": "Welke aroma's\/smaken hebben de bonen?", + "BEAN_DATA_CUPPING_POINTS_TOOLTIP": "Hoeveel cupping-punten heeft de boon?", + "BEAN_DATA_DECAFFEINATED_TOOLTIP": "Is het cafeïnevrij?", + "BEAN_DATA_URL_TOOLTIP": "URL naar de winkel", + "BEAN_DATA_EAN_TOOLTIP": "Het EAN\/artikelnummer", + "NOTES_TOOLTIP": "Aantekeningen gemaakt", + "BREW_DATA_ATTACHMENTS_TOOLTIP": "Foto's toevoegen?", + "ENABLE_BEAN_SORT_INFORMATION_TOOLTIP": "Meer informatie over de bonen: waar komen ze vandaan, wanneer zijn ze geoogst, etc.", + "BEAN_DATA_COUNTRY_TOOLTIP": "Uit welk land komen de bonen?", + "BEAN_DATA_REGION_TOOLTIP": "Uit welke regio komen de bonen?", + "BEAN_DATA_FARM_TOOLTIP": "Van welke boerderij komen de bonen?", + "BEAN_DATA_FARMER_TOOLTIP": "Wie verbouwde deze bonen", + "BEAN_DATA_ELEVATION_TOOLTIP": "Op welke hoogte groeiden de bonen?", + "BEAN_DATA_PROCESSING_TOOLTIP": "Hoe zijn de bonen verwerkt (natuurlijk, gewassen, enz.)", + "BEAN_DATA_VARIETY_TOOLTIP": "De Koffieboon Variëteit (SL28 bv.)", + "BEAN_DATA_HARVEST_TIME_TOOLTIP": "In welk jaar\/maand werden deze bonen geoogst?", + "BEAN_DATA_PERCENTAGE_TOOLTIP": "Hoeveel procent van deze bonen zit er in de zak?", + "BEAN_DATA_CERTIFICATION_TOOLTIP": "Welke certificeringen hebben de bonen (bijvoorbeeld fairtrade)", + "BEAN_DATA_PURCHASING_PRICE_TOOLTIP": "Wat was de aankoopprijs van de koffiebrander", + "BEAN_DATA_FOB_PRICE_TOOLTIP": "Wat was de Free-On-Board (FOB) prijs toen de brander het kocht?", + "BEAN_PARAMETER_CUSTOMIZE_TITLE": "Pas de informatie aan die u voor bonen wilt gebruiken", + "BEAN_PARAMETER_CUSTOMIZE_DESCRIPTION": "Er kan veel informatie over de bonen worden ingevoerd of gebruikt. Kies zelf de parameters die u wilt invullen en welke u wilt weergeven", + "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_TITLE": "Timer resetten!", + "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_DESCRIPTION": "Omdat je een Bluetooth-apparaat hebt aangesloten, moet je eerst je timer resetten voordat je kunt beginnen.", + "BREW_FILTER_JUST_CHART_DATA": "Alleen grafieken", + "SCALE_RESET_TRIGGERED_DESCRIPTION": "De bluetooth weegschaal wil zowel de app-timer als de brouwgrafiek resetten, wil je doorgaan?", + "SCALE_RESET_TRIGGERED_TITLE": "Opnieuw instellen?", + "NAV_REPEAT_PARAMETERS": "Herhalingsparameters definiëren", + "PAGE_REPEAT_PARAMETERS_DESCRIPTION": "Markeer welke parameters vooraf moeten worden ingesteld wanneer u een specifieke brouwbeurt herhaalt", + "CUSTOM_REPEAT_PARAMETERS": "Herhalen", + "CUSTOM_REPEAT_PARAMETERS_DESCRIPTION": "Aangepaste herhaling activeren?", + "PAGE_SETTINGS_USE_NUERMIC_KEYBOARD_FOR_GRIND_SIZE": "Numeriek toetsenbord voor maalinstelling?", + "PAGE_SETTINGS_USE_NUERMIC_KEYBOARD_FOR_GRIND_SIZE_DESCRIPTION": "Wilt u een numeriek toetsenbord gebruiken voor de maalinstelling, in plaats van het hele toetsenbord?", + "PREPARATION_DEVICE": { + "TYPE": { + "NONE": "Geen", + "XENIA": "Xenia", + "METICULOUS": "Meticulous" + }, + "URL": "URL-adres", + "CHOOSE_DEVICE": "Kies apparaat", + "CONNECTION": { + "UNSUCCESFULLY": "Er kon geen verbinding met de machine worden gemaakt", + "SUCCESFULLY": "Verbinding met machine was succesvol" + }, + "TYPE_XENIA": { + "TITLE": "Xenia machine", + "PRESS_START_SCRIPT": "Start script bij start", + "FIRST_DRIP_SCRIPT": "Start script bij eerste druppel", + "SCRIPT_AT_WEIGHT": "Gewicht voor scriptuitvoering", + "SCRIPT_LIST_GENERAL_0": "Niets", + "SCRIPT_LIST_GENERAL_1": "Espresso, 25 seconden", + "SCRIPT_LIST_GENERAL_2": "Espresso, eindeloos", + "SCRIPT_LIST_GENERAL_STOP": "Schot stoppen", + "CHOOSE_SCRIPT_AT_WEIGHT": "Kies script voor gewicht bereikt", + "ERROR_NOT_ALL_SCRIPTS_FOUND": "Een of meer scripts konden niet worden gevonden, ze zijn gereset", + "ERROR_CONNECTION_COULD_NOT_BE_ESTABLISHED": "De verbinding met de xenia espressomachine kon niet tot stand worden gebracht. Controleer of u zich op het juiste netwerk (LAN) bevindt, of u het juiste IP-adres hebt ingevoerd, etc.", + "CHECKING_CONNECTION_TO_PORTAFILTER": "Verbinding met Xenia wordt gecontroleerd", + "GRABING_SCRIPTS": "Scripts laden vanuit Xenia", + "BREW_BY_WEIGHT_ACTIVE": "Brouwen op gewicht actief" + }, + "API_VERSION": "Api-versie", + "RESIDUAL_LAG_TIME": "Resterende vertragingstijd", + "RESIDUAL_LAG_TIME_DESCRIPTION": "Stel de tijd in die overeenkomt met het resterende water. Met een naakte portafilter heb je een lagere tijd nodig, met een tuit een hogere. Hoe langzamer uw weegschaal het gewicht rapporteert, hoe meer tijd u nodig heeft", + "TYPE_METICULOUS": { + "TITLE": "Meticulous machine", + "NO_PROFILE": "Geen profiel", + "CHOOSE_PROFILE": "Profiel kiezen", + "SHOT_STARTED": "Brouwen gestart", + "SHOT_ENDED": "Brouwen gestopt" + } + }, + "DEVICE_CONNECTION": "Apparaatverbinding", + "PREPARATION_DEVICE_CONNECTION": "Apparaatverbinding", + "MANUAL_EXPORT_TO_VISUALIZER": "Exporteren naar Visualizer", + "ONLY_FAVOURITES": "Alleen favorieten", + "TEMPERATURE": { + "CONNECTION_NOT_ESTABLISHED": "Temperatuurapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", + "CONNECTED_SUCCESSFULLY": "Temperatuurapparaat aangesloten", + "DISCONNECTED_SUCCESSFULLY": "Temperatuurapparaat losgekoppeld", + "DISCONNECTED_UNPLANNED": "Temperatuurapparaat onverwachts losgekoppeld", + "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de thermometer verbonden, zelfs als de app op de achtergrond staat", + "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: ETI Ltd BLE-thermometers (ThermaQ Blue, BlueTherm, enz.), Combustion Inc., Meater (niet Meater+ of Meater 2)", + "BLUETOOTH_SCAN_RUNNING": "Zoeken naar temperatuurapparaat gedurende maximaal 60 seconden", + "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", + "REQUEST_PERMISSION": { + "LOCATION": "Om temperatuurmeters te vinden, heeft de app toegang nodig tot de locatie.", + "BLUETOOTH": "Om temperatuurapparaten te vinden, heeft de app toegang tot Bluetooth nodig" + }, + "LOG": "Logbestanden voor temperatuurapparaat activeren", + "THRESHOLD_ACTIVE": "Start timer met vooraf ingestelde temperatuur", + "THRESHOLD_TEMP": "Drempel temperatuur" + }, + "POPOVER_BLUETOOTH_ACTION_RECONNECT_TEMPERATURE_DEVICE": "Temperatuurapparaat opnieuw aansluiten", + "PRESSURE_DEVICE_JUST_VISIBLE_ON_ESPRESSO": "Drukapparaat is alleen bruikbaar bij de bereidingswijze 'Espresso'", + "PRESSURE_MESSAGE_AFTER_CONNECTION": "Bekend gedrag (in analyse): Houd er rekening mee dat het langer kan duren om verbinding te maken nadat u uw telefoon opnieuw hebt opgestart of wanneer u de app langere tijd niet hebt gebruikt. Na deze tijd zou het verbindingsprobleem opgelost moeten zijn.", + "SMART_SCALE_ACAIA_HEARTBEAT_TIMER": "Hartslagtimer - Speciaal voor Acaia Scales", + "SMART_SCALE_ACAIA_HEARTBEAT_TIMER_TOOLTIP": "Alleen gebruikt voor Acaia-weegschalen! - Oudere Acaia-weegschalen hebben een hartslagsignaal nodig. Als u problemen ondervindt, probeer dan de hartslag op een hogere frequentie in te stellen.", + "SHARE_BEAN_URL": "Delen als URL", + "SHARE_BEAN_IMAGE": "Delen als afbeelding", + "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE": "Espresso - Automatisch stoppen met brouwen", + "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE_DESCRIPTION": "Deze instelling wordt alleen gebruikt voor brouwsels van het type 'espresso'. Het brouwsel wordt automatisch gestopt wanneer er geen flow wordt gedetecteerd.", + "BREW_DATA_BREW_QUANTITY_TOOLTIP_BREW_RATIO": "De zetverhouding wordt berekend met deze waarde voor alle brouwsels, maar niet voor type 'espresso'.", + "BREW_DATA_BREW_BEVERAGE_QUANTITY_TOOLTIP_BREW_RATIO": "De zetverhouding wordt alleen met deze waarde berekend voor brouwsels van het type 'espresso'", + "SMART_SCALE_DID_NOT_SEND_ANY_WEIGHT_DESCRIPTION": "Het lijkt erop dat de bluetooth weegschaal niet goed is aangesloten. Dit gebeurt meestal op iOS-apparaten met Acaia weegschalen, sluit de weegschaal opnieuw aan en zorg ervoor dat de gewichtstegel wordt bijgewerkt.", + "SMART_SCALE_DID_NOT_SEND_ANY_WEIGHT_TITLE": "Geen gewichtswaarden?", + "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE_MIN_FLOW_DESCRIPTION": "De stroomsnelheid waarbij het zetten moet worden gestopt. Het zetten wordt pas gestopt als er minimaal 5 seconden zijn verstreken, er 5 gram in de kop zit of als u het gewicht van de gemalen koffie hebt ingevoerd - er is minimaal een zetverhouding van 1:1 bereikt (bijv.: 18 g erin, 18 g eruit). Nadat aan deze voorwaarden is voldaan, wordt de hier ingestelde minimale stroomsnelheid gecontroleerd", + "ONLY_BEST_BREWS": "Alleen de beste brouwsels", + "POPOVER_BEST_BREW": "Beste brouwsel", + "PAGE_SETTINGS_BEST_BREW": "Beste brouwsels activeren", + "PAGE_SETTINGS_BEST_BREW_DESCRIPTION": "Markeer je beste brouwsel voor een specifieke boon. Elke boon kan één beste brouwsel hebben in plaats van meerdere favorieten.", + "PAGE_SETTINGS_TAB_BLUETOOTH_REFRACTOMETER": "Refractometer apparaat", + "REFRACTOMETER": { + "CONNECTION_NOT_ESTABLISHED": "Refractometerapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", + "CONNECTED_SUCCESSFULLY": "Refractometerapparaat aangesloten", + "DISCONNECTED_SUCCESSFULLY": "Refractometerapparaat losgekoppeld", + "DISCONNECTED_UNPLANNED": "Refractometerapparaat onverwachts losgekoppeld", + "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de refractometer verbonden, zelfs als de app op de achtergrond draait", + "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: DiFluid R2", + "BLUETOOTH_SCAN_RUNNING": "Zoeken naar refractometer-apparaat gedurende maximaal 60 seconden", + "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", + "REQUEST_PERMISSION": { + "LOCATION": "Om refractometerapparaten te vinden, heeft de app toegang nodig tot de locatie.", + "BLUETOOTH": "Om refractometerapparaten te vinden, heeft de app toegang tot Bluetooth nodig" + }, + "LOG": "Activeer logbestanden voor refractometerapparaat", + "READ_END": "Test voltooid - resultaat ontvangen" + }, + "COPIED_TO_CLIPBOARD_SUCCESSFULLY": "Toegevoegd aan klembord", + "COPIED_TO_CLIPBOARD_UNSUCCESSFULLY": "Kan niet worden toegevoegd aan het klembord", + "PAGE_SETTINGS_LANGUAGE_FRENCH": "Frans", + "ANDROID_EXTERNAL_FILE_ACCESS_NOT_POSSIBLE_TITLE": "Gegevens kunnen niet worden opgeslagen vanwege Android-beperkingen", + "ANDROID_EXTERNAL_FILE_ACCESS_NEEDED_DESCRIPTION": "Je Android-telefoon ondersteunt geen externe bestandssystemen, dus je moet het ZIP-bestand downloaden zonder mediabestanden. Ga voor meer informatie naar https:\/\/beanconqueror.com\/faq.", + "PAGE_SETTINGS_SECURITY_CHECK_WHEN_GOING_BACK": "Beveiligingsbericht voor afsluiten?", + "PAGE_SETTINGS_SECURITY_CHECK_WHEN_GOING_BACK_DESCRIPTION": "Controleer of de gegevens zijn gewijzigd bij het toevoegen\/bewerken van bonen of brouwsels; als dat het geval is, wordt er een veiligheidswaarschuwing weergegeven bij het teruggaan.", + "PAGE_BEANS_DISCARD_CONFIRM": "Boon informatie is gewijzigd. Weet je zeker dat je de pagina wilt verlaten zonder op te slaan?", + "PAGE_BREW_DISCARD_CONFIRM": "De brouw informatie is gewijzigd. Weet je zeker dat je de pagina wilt verlaten zonder op te slaan?", + "NO_ENTRIES_FOUND": "Geen vermeldingen gevonden", + "POPOVER_BEANS_OPTION_REPEAT": "Herhaal laatste brouwsel", + "REPEAT_LAST_BREW": "Herhaal laatste brouwsel", + "REPEAT_BEST_BREW": "Herhaal beste brouwsel", + "PAGE_SETTINGS_VISUALIZER_SECTION": "Visualizer", + "VISUALIZER": { + "ACTIVATE": "Visualizer activeren", + "CHOOSE_SERVER": "Server kiezen", + "CONNECTION": { + "UNSUCCESSFULLY": "Er kon geen verbinding tot stand worden gebracht.", + "SUCCESSFULLY": "Verbinding kon tot stand worden gebracht." + }, + "SERVER": { + "VISUALIZER": "Visualizer-server", + "CUSTOM": "Aangepaste server" + }, + "SHOT": { + "UPLOAD_SUCCESSFULLY": "Brouwen geüpload naar visualizer.", + "UPLOAD_UNSUCCESSFULLY": "Brouwen kon niet worden geüpload naar de Visualizer." + }, + "URL": "Server-URL", + "USERNAME": "Gebruikersnaam", + "PASSWORD": "Wachtwoord", + "UPLOAD_AUTOMATIC": "Elke brouwsessie automatisch uploaden?", + "UPLOAD_AUTOMATIC_TOOLTIP": "Zorg ervoor dat u een actieve internetverbinding hebt wanneer u uw brouwsel opslaat.", + "UPLOAD_ALL": "Alle brouwsels uploaden", + "NOT_ALL_SHOTS_UPLOADED": "Niet alle brouwsels konden worden geüpload", + "ALL_SHOTS_UPLOADED": "Alle brouwsels zijn geüpload" + }, + "SMART_SCALE_AUTO_START_LISTENING": "Timer automatisch starten?", + "SMART_SCALE_AUTO_START_LISTENING_DESCRIPTION": "Start de timer automatisch bij het bereiken van de volgende gewichtswaarde", + "CHOOSE_REFERENCE_GRAPH": "Referentiegrafiek selecteren", + "RESET": "Opnieuw instellen", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_AXIS": "Definieer de beginassen van de grafiek", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_AXIS_DESCRIPTION": "Stel de begingrootte van de assen in voor zowel filter- als espressokoffie.", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_FILTER_WEIGHT": "Filter - Gewicht", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_FILTER_FLOW": "Filter - Doorstroming", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_ESPRESSO_WEIGHT": "Espresso - Gewicht", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_ESPRESSO_FLOW": "Espresso - Doorstroming", + "SMART_SCALE_IGNORE_INCOMING_WEIGHT": "Negeer huidige gewichtsoverdracht ", + "SMART_SCALE_IGNORE_INCOMING_WEIGHT_TOOLTIP": "Er verschijnt een nieuwe knop in het brouwgedeelte, die nieuwe gewichtswaarden van de bluetooth weegschaal zal negeren.", + "BREWS_ACTIVE": "Actieve brouwsels", + "BREWS_ARCHIVED": "Gearchiveerde brouwsels", + "GRAPHS": "Grafieken", + "GRAPH_SECTION": { + "NAV_GRAPH": "Grafieken", + "NO_ARCHIVED_ENTRIES": "Geen gearchiveerde vermeldingen", + "NO_ENTRIES": "Geen vermeldingen", + "SECTION_HAS_BEEN_ACTIVATED": "Grafieksectie is geactiveerd" + }, + "TOAST_GRAPH_ARCHIVED_SUCCESSFULLY": "Grafiek gearchiveerd", + "TOAST_GRAPH_DELETED_SUCCESSFULLY": "Grafiek verwijderd", + "TOAST_GRAPH_EDITED_SUCCESSFULLY": "Grafiek bewerkt", + "TOAST_GRAPH_ADD_SUCCESSFULLY": "Grafiek toegevoegd", + "NAV_GRAPH_SECTION": "Grafieken", + "DELETE_GRAPH_QUESTION": "Wilt u deze grafiek verwijderen?", + "PAGE_SETTINGS_SHOW_ARCHIVED_GRAPHS": "Gearchiveerde grafieken weergeven", + "PAGE_SETTINGS_SHOW_GRAPH_SECTION": "Grafieksectie activeren", + "EDIT_GRAPH": "Grafiek bewerken", + "ADD_GRAPH": "Grafiek toevoegen", + "GRAPH": { + "PLACE_HOLDER": { + "NAME": "Grafiek naam", + "NOTES": "Notities" + }, + "UPLOAD": "Grafiek uploaden", + "DELETE": "Grafiek verwijderen", + "UPLOAD_DESCRIPTION": "Importeer een .JSON-bestand dat u kunt downloaden in de brew-detailweergave. U kunt ook gedeelde grafieken van de community importeren die van het type .JSON zijn." + }, + "SHOW_VISUALIZER": "Visualiseerder weergeven", + "NO_BREWS_FOUND": "Geen brouwsels gevonden", + "NO_GRAPHS_FOUND": "Geen grafieken gevonden", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_AXIS": "Definieer de maximale tijdsas van de grafiek", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_DESCRIPTION": "Stel het maximum aantal seconden in op de tijd-as voor zowel filterkoffie als espresso.", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_FILTER_AXIS_NORMAL_SCREEN": "Filter - Normaal scherm", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_FILTER_AXIS_FULL_SCREEN_SCREEN": "Filter - Volledig scherm", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_ESPRESSO_AXIS_NORMAL_SCREEN": "Espresso - Normaal scherm", + "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_ESPRESSO_AXIS_FULL_SCREEN_SCREEN": "Espresso - Volledig scherm", + "PAGE_SETTINGS_DATE_FORMAT": "Datum notatie", + "PAGE_SETTINGS_LANGUAGE_FRANCE": "Frans", + "PAGE_SETTINGS_LANGUAGE_INDONESIA": "Indonesisch", + "EXTRACTION_CHART_TITLE": "Extractie grafiek", + "PAGE_SETTINGS_SHOW_BACKUP_ISSUES": "Back-up problemen weergeven", + "PAGE_SETTINGS_SHOW_BACKUP_ISSUES_DESCRIPTION": "Geef een pop-up weer als er geen back-ups naar het bestandssysteem kunnen worden geschreven", + "AUTOMATIC_BACKUP_DID_FAIL": "Automatische back-up werkte niet, zorg ervoor dat u werkende back-ups hebt! Deze informatie kan worden uitgeschakeld in de instellingen", + "INTERNAL_BACKUP_DID_FAIL": "Interne back-up werkte niet, zorg ervoor dat u werkende back-ups hebt! Deze informatie kan worden uitgeschakeld in de instellingen", + "ZIP_BACKUP_FILE_COULD_NOT_BE_BUILD": "ZIP-bestand kon niet worden opgeslagen! Deze informatie kan worden uitgeschakeld in de instellingen", + "SEND_LOGS": "Logboeken verzenden", + "POPOVER_BLUETOOTH_ACTION_RECONNECT_REFRACTOMETER": "Sluit refractometer apparaat opnieuw aan", + "PAGE_SETTINGS_LANGUAGE_ITALIAN": "Italiaans", + "PAGE_SETTINGS_LANGUAGE_POLISH": "Pools", + "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_GENERAL_DESCRIPTION": "Je moet eerst je timer resetten voordat je kunt beginnen.", + "SMART_SCALE_FIRST_DRIP_THRESHOLD": "Eerste druppel drempel", + "SMART_SCALE_FIRST_DRIP_THRESHOLD_TOOLTIP": "Bij welk weegschaalgewicht moet de eerste druppel worden geteld? Standaard: >= 0,1g", + "PAGE_SETTINGS_BREW_TIMER_START_DELAY_ACTIVE": "Zetvertraging starten", + "PAGE_SETTINGS_BREW_TIMER_START_DELAY_ACTIVE_DESCRIPTION": "Stel een vertragingstijd in die een laadspinner weergeeft totdat het brouwen begint", + "STARTING_IN": "Beginnend in ... {{time}}", + "IOS_DATABASE_ISSUE_TITLE": "ATTENTIE !!!!! - DATABASEVERBINDING VERLOREN", + "IOS_DATABASE_ISSUE_DESCRIPTION": "Het spijt ons u te moeten meedelen dat de verbinding met de database is verbroken. Dit probleem is het gevolg van een onopgeloste bug in het systeem van Apple, waarover Beanconqueror geen controle heeft. Om mogelijk gegevensverlies te voorkomen, verzoeken wij u vriendelijk de Beanconqueror-applicatie onmiddellijk geforceerd af te sluiten en opnieuw te openen.", + "RELOAD_APP": "Herstart de app", + "WATER_TYPE_ADD_CUSTOM": "Water op maat", + "WATER_TYPE_THIRD_WAVE_WATER_CLASSIC_LIGHT_ROAST_PROFILE": "Third Wave Water - Klassiek licht geroosterd profiel", + "WATER_TYPE_THIRD_WAVE_WATER_MEDIUM_ROAST_PROFILE": "Third Wave Water - Middel geroosterd profiel", + "WATER_TYPE_THIRD_WAVE_WATER_DARK_ROAST_PROFILE": "Third Wave Water - Donker geroosterd profiel", + "WATER_TYPE_THIRD_WAVE_WATER_ESPRESSO_MACHINE_PROFILE": "Third Wave Water - Espressomachine Profiel", + "WATER_TYPE_THIRD_WAVE_WATER_COLD_BREW_PROFILE": "Third Wave Water - koud brouwprofiel", + "WATER_TYPE_THIRD_WAVE_WATER_LOW_ACID_PROFILE": "Third Wave Water - Laag Zuurprofiel", + "ADD_WATER": "Voeg water toe", + "EXTRACTION_CHART_LABEL_STRONG_UNDEREXTRACTED": "STERK
onderextractie", + "EXTRACTION_CHART_LABEL_STRONG": "Strong
", + "EXTRACTION_CHART_LABEL_STRONG_HARSH": "STERK
ruw", + "EXTRACTION_CHART_LABEL_UNDEREXTRACTED": "ondergeëxtraheerd", + "EXTRACTION_CHART_LABEL_IDEAL": "IDEAAL", + "EXTRACTION_CHART_LABEL_HARSH": "ruw", + "EXTRACTION_CHART_LABEL_WEAK_UNDEREXTRACTED": "ZWAK
onderextractie", + "EXTRACTION_CHART_LABEL_WEAK": "ZWAK
", + "EXTRACTION_CHART_LABEL_WEAK_HARSH": "ZWAK
ruw", + "PAGE_SETTINGS_TEXT_TO_SPEECH_SECTION": "Tekst naar spraak", + "TEXT_TO_SPEECH": { + "ACTIVATE": "Activeer tekst naar spraak", + "BREW_STARTED": "Brouwen gestart", + "BREW_ENDED": "Einde brouwen", + "TIME": "Tijd", + "SPEAK_EVERY_MS": "Spreek elke geselecteerde milliseconde", + "FOLLOWING_NUMBERS_WILL_BE_TEST_SPOKEN": "De volgende nummers worden als test uitgesproken", + "TEST_SPEAK": "Start test spraak", + "PITCH": "Toonhoogte", + "RATE": "beoordeling" + }, + "PAGE_SETTINGS_HAPTIC_FEEDBACK_SECTION": "Haptische feedback", + "HAPTIC_FEEDBACK": { + "ACTIVATE": "Activeer haptische feedback", + "BREW_STARTED": "Trillen bij het starten van het brouwen", + "BREW_STOPPED": "Trillen bij het stoppen van het brouwen", + "TARE": "Trillen bij tarra van de weegschaal" + }, + "CONNECTED": "Verbonden", + "DISCONNECTED": "Losgekoppeld", + "EXPERIMENTAL_FEATURE_DISCLAIMER": "Dit is een experimentele functie", + "SHOW_HOURS": "Toon uren", + "SHOW_MINUTES": "Toon Minuten", + "BEANS_UNARCHIVE": "uit het archief halen", + "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Boon is uit het archief gehaald", + "WATER_TYPE_PURE_COFFEE_WATER": "Zuiver Koffiewater", + "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", + "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", + "SORT_PREPARATION_TOOLS": "Sorteer bereidingsmiddelen", + "PREPARATION_TYPE_METICULOUS": "Meticulous", + "EXPORT_CAUTION": "Exporteren exporteert alleen de database, geen afbeeldingen, geen stromingsprofielen . Als deze nodig zijn, ga dan naar Gitbook voor meer informatie", + "POPOVER_FREEZE_COFFEE_BEAN": "Bevries koffieboon", + "POPOVER_UNFREEZE_COFFEE_BEAN": "Koffieboon ontdooien", + "BEAN_POPOVER_EDIT_FREEZE_DATE": "invries datum bewerken", + "BEAN_POPOVER_EDIT_UNFREEZE_DATE": "ontdooi datum bewerken", + "BEAN_POPOVER_LEFT_UNFROZEN": "Niet ingevroren", + "BEAN_POPOVER_FREEZE_PARTIAL_BAG": "Gedeelte zak invriezen (g)", + "FROZEN_BEANS": "Bevroren", + "BEAN_TAB_FROZEN_INFORMATION": "Bevroren notities", + "BEAN_POPOVER_FROZEN_BAGS": "Bevroren zakken", + "BEAN_POPOVER_FROZEN_DELETE_BEAN_MESSAGE": "Je gaat de hele zak invriezen en we hebben geen brouwsels gevonden die ermee gemaakt zijn, wil je de originele zak verwijderen?", + "CREATE_FROZEN_BEANS": "creëer bonen", + "BEAN_POPOVER_COPY_ATTACHMENTS": "Kopieer bijlagen", + "BEAN_POPOVER_COPY_ATTACHMENTS_DESCRIPTION": "Het kopiëren van bijlagen is aan het begin van deze functie gedeactiveerd", + "BEAN_DATA_FROZEN_DATE": "Invries datum", + "BEAN_DATA_UNFROZEN_DATE": "ontdooi datum", + "PAGE_BEANS_LIST_YOU_GOT_NO_FROZEN_BEANS": "Je hebt geen ingevroren bonen", + "BEAN_DATA_FROZEN_ID": "Ingevroren id", + "PAGE_SETTINGS_MANAGE_FEATURES": "Functies beheren", + "ACTIVE_BEAN_FREEZING_FEATURE": "Activeer het invriezen van bonen", + "NAV_FROZEN_BEANS_LIST": "Lijst met ingevroren bonen", + "BEAN_BREW_LIST_VIEW_PARAMETERS": "Boon informatie voor brouwen", + "BEAN_AGE_BY_BREW_DATE": "Leeftijd van de bonen op brouwdatum", + "BEAN_POPOVER_FROZEN_BEAN_WILL_BE_ARCHIVED_NOW_MESSAGE": "Je diepvrieszakken hebben als resultaat dat je originele zak geen gewicht meer heeft, maar je hebt er wel mee gebrouwen, dus beoordeel en stuur naar het archief.", + "BEAN_POPOVER_YOU_CANT_FREEZE_WITH_ZERO_WEIGHT_LEFT": "Je kunt niet bevriezen, want het restgewicht van je zak is nul", + "BEAN_DATA_BEST_DATE": "Beste Bonen Datum", + "BEAN_DATA_BEST_DATE_TOOLTIP": "Wanneer is de beste datum om de bonen te gebruiken?", + "BEAN_DATA_OPEN_DATE": "Openingsdatum van de zak", + "BEAN_DATA_OPEN_DATE_TOOLTIP": "Wanneer heb je de zak bonen geopend?", + "BEAN_FREEZING_STORAGE_TYPE_UNKNOWN": "Onbekend", + "BEAN_FREEZING_STORAGE_TYPE_COFFEE_BAG": "Koffiezak", + "BEAN_FREEZING_STORAGE_TYPE_COFFEE_JAR": "Koffie pot", + "BEAN_FREEZING_STORAGE_TYPE_ZIP_LOCK": "Ritssluiting", + "BEAN_FREEZING_STORAGE_TYPE_VACUUM_SEALED": "Vacuüm verzegeld", + "BEAN_FREEZING_STORAGE_TYPE_TUBE": "Buis", + "BEAN_DATA_FROZEN_STORAGE_TYPE": "Vriezer opslagtype", + "PAGE_SETTINGS_BREW_RATING_CHANGED_BREWS_NOT_VISIBLE": "U heeft de maximale beoordeling van uw brouwsels gewijzigd, maar u heeft uw brouwsels al hoger beoordeeld dan uw werkelijke maximum. Deze worden dus niet weergegeven bij de normale filterinstellingen.", + "PAGE_SETTINGS_BEAN_RATING_CHANGED_BEANS_NOT_VISIBLE": "U heeft de maximale beoordeling voor bonen gewijzigd, maar u heeft bonen al hoger beoordeeld dan uw werkelijke maximum. Ze worden dus niet weergegeven met de normale filterinstellingen.", + "BEAN_DATA_FROZEN_NOTE": "Bevroren notities", + "IGNORE_NEGATIVE_VALUES_DESCRIPTION": "Als je dit activeert, loopt de grafiek één seconde achter", + "IGNORE_ANOMALY_VALUES_DESCRIPTION": "Als je dit activeert, loopt de grafiek één seconde achter", + "SAVE_LOGFILES_TO_NOTES_FROM_MACHINE": "Bewaar de machine logs bij het opslaan van een brouwsel" +} \ No newline at end of file diff --git a/src/assets/i18n/pl.json b/src/assets/i18n/pl.json index ca541d8e..23e94e5e 100644 --- a/src/assets/i18n/pl.json +++ b/src/assets/i18n/pl.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Pokaż minuty", "BEANS_UNARCHIVE": "Cofnij archiwizację", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Ziarno nie zostało zarchiwizowane", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Wersja 7.4.0: Co nowego", - "DESCRIPTION": [ - "Ziarna<\/b>", - "Teraz możliwe jest zamrożenie ziaren kawy, aktywując tę funkcję w ustawieniach.", - "Dodano najlepszą i otwartą datę dla fasoli, należy aktywować ten parametr", - "Ziarna można teraz dodawać bezpośrednio z przeglądu wyboru.", - "", - "Termometr<\/b>", - "Wsparcie Combustion Inc. Termometr - Dziękujemy za urządzenie!", - "Wsparcie dla termometru Meater (nie Meater 2 lub Meater +) - dzięki Yannick!", - "", - "Sekcja wodna<\/b>", - "Dodano czystą wodę kawową", - "Dodana woda empiryczna", - "", - "Narzędzia przygotowawcze<\/b>", - "Posortuj teraz swoje narzędzia przygotowawcze", - "", - "Młynek<\/b>", - "Obrazy młynka są teraz wyświetlane w przeglądzie wyboru", - "", - "Ustawienia<\/b>", - "Komunikat bezpieczeństwa, jeśli zmieniono ocenę dla naparów lub ziaren, a maksymalna ocena jest niższa niż już oceniony wpis.", - "", - "Inne<\/b>", - "Przywrócono bezpośrednie ustawianie ostrości w sekundach podczas otwierania timera.", - "Kilka zmian technicznych w kodzie", - "Drobne poprawki" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Czysta woda kawowa", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "woda empiryczna GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "woda empiryczna SPRING", diff --git a/src/assets/i18n/tr.json b/src/assets/i18n/tr.json index cfb0c409..f2e49174 100644 --- a/src/assets/i18n/tr.json +++ b/src/assets/i18n/tr.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "Dakikayı göster", "BEANS_UNARCHIVE": "Arşivden çıkar", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Çekirdek arşivden çıkarıldı", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "Sürüm 7.4.0: Yenilikler", - "DESCRIPTION": [ - " Fasulye <\/b>", - "Artık kahve çekirdeklerinizi dondurmak mümkün, bu özelliği ayarlardan etkinleştirin", - "Çekirdek için en iyi ve açık tarih eklendi, bu parametreyi etkinleştirmeniz gerekir", - "Çekirdekler artık doğrudan seçime genel bakıştan eklenebilir", - "", - "Termometre<\/b>", - "Combustion Inc. Termometre Desteği - Cihaz için teşekkürler!", - "Meater Termometre desteği (Meater 2 veya Meater + değil) - Yannick'e teşekkürler!", - "", - "Su Bölümü<\/b>", - "Saf Kahve Suyu Eklendi", - "Ampirik su eklendi", - "", - "Hazırlık Araçları<\/b>", - "Hazırlık araçlarınızı şimdi sıralayın", - "", - "Öğütücü<\/b>", - "Öğütücü görüntüleri artık seçim genel görünümünde gösteriliyor", - "", - "Ayarlar<\/b>", - "Demleme veya çekirdek derecelendirmesini değiştirdiyseniz ve maksimum değer, halihazırda derecelendirilmiş bir girişten düşükse güvenlik mesajı", - "", - "Diğer<\/b>", - "Zamanlayıcıyı açarken doğrudan saniye odağı geri döndürüldü", - "Koddaki bazı teknik değişiklikler", - "Küçük değişiklikler" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Saf Kahve Suyu", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "ampirik su GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "ampirik su SPRING", diff --git a/src/assets/i18n/zh.json b/src/assets/i18n/zh.json index b7c5bd63..bca45dc7 100644 --- a/src/assets/i18n/zh.json +++ b/src/assets/i18n/zh.json @@ -1273,39 +1273,6 @@ "SHOW_MINUTES": "显示分钟", "BEANS_UNARCHIVE": "取消归档", "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "咖啡豆已经取消归档", - "UPDATE_TEXT_TITLE_TITLE": { - "7.4.0": { - "TITLE": "版本7.4.0:有什么新功能?", - "DESCRIPTION": [ - "豆子<\/b>", - "现在可以将您的咖啡豆冷冻保存,您可以在设置中激活这个功能", - "为咖啡豆添加了最佳和开封日期,您需要激活此参数", - "现在可以直接从选择概览中添加豆子", - "空的", - "温度计<\/b>", - "支持 Combustion Inc. 温度计 - 感谢提供设备!", - "支持 Meater 温度计(不支持 Meater 2 或 Meater +) - 感谢 Yannick!", - "空的", - "水分区<\/b>", - "添加Pure Coffee Water", - "添加Empirical水", - "空的", - "准备工具<\/b>", - "整理您的准备工具", - "空的", - "磨豆机<\/b>", - "磨豆机的图片现在在选择概览中显示", - "空的", - "设置<\/b>", - "如果您更改了冲泡或咖啡豆的评分,并且最高评分低于已评分条目的评分,则显示安全提示信息", - "空的", - "其他<\/b>", - "在打开计时器时,恢复到以秒数计时为准", - "代码中的一些技术修改", - "小调整" - ] - } - }, "WATER_TYPE_PURE_COFFEE_WATER": "Pure Coffee Water", "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", From d8b849d3f55999ebbbcf363c8add0e2ff3a92c3e Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Wed, 28 Aug 2024 22:00:59 +0200 Subject: [PATCH 11/19] #780 - Adding dutch as language --- src/app/app.component.ts | 2 + src/app/settings/settings.page.html | 1 + src/assets/i18n/en.json | 3 +- src/assets/i18n/nl_NL.json | 1323 ----------------- .../brew-information.component.ts | 1 - 5 files changed, 5 insertions(+), 1325 deletions(-) delete mode 100644 src/assets/i18n/nl_NL.json diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5c9e5762..f06ed532 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -506,6 +506,8 @@ export class AppComponent implements AfterViewInit { settingLanguage = 'fr'; } else if (systemLanguage === 'id') { settingLanguage = 'id'; + } else if (systemLanguage === 'nl') { + settingLanguage = 'nl'; } else { settingLanguage = 'en'; } diff --git a/src/app/settings/settings.page.html b/src/app/settings/settings.page.html index fc663f98..dcd95cff 100644 --- a/src/app/settings/settings.page.html +++ b/src/app/settings/settings.page.html @@ -88,6 +88,7 @@

{{"EXPORT" | translate}}

{{"PAGE_SETTINGS_LANGUAGE_FRANCE" | translate}} {{"PAGE_SETTINGS_LANGUAGE_INDONESIA" | translate}} {{"PAGE_SETTINGS_LANGUAGE_POLISH" | translate}} + {{"PAGE_SETTINGS_LANGUAGE_DUTCH" | translate}} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 682833e5..4bf29546 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1340,5 +1340,6 @@ "BEAN_POPUP_YOU_DONT_SEE_EVERYTHING_DESCRIPTION": "You're adding a bean which has variety information in it, but those parameters are not activated. Do you want to activate them now?", "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS": "Define the axes for the pressure graph", "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_DESCRIPTION": "Set the starting and end size of the axes for pressure", - "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_RANGE": "Pressure axes" + "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_RANGE": "Pressure axes", + "PAGE_SETTINGS_LANGUAGE_DUTCH": "Dutch" } diff --git a/src/assets/i18n/nl_NL.json b/src/assets/i18n/nl_NL.json deleted file mode 100644 index 31e2cd3e..00000000 --- a/src/assets/i18n/nl_NL.json +++ /dev/null @@ -1,1323 +0,0 @@ -{ - "NAV_MENU": "Menu", - "NAV_HOME": "Thuis", - "NAV_SETTINGS": "Instellingen", - "NAV_BREWS": "Brouwsels", - "NAV_BEANS": "Bonen", - "NAV_PREPARATION": "Methoden", - "NAV_MILL": "Malers", - "NAV_ABOUT_US": "Over ons", - "NAV_CONTACT": "Contact", - "NAV_PRIVACY": "Privacy", - "NAV_CREDITS": "Credits", - "NAV_TERMS": "Algemene voorwaarden", - "NAV_THANKS": "Bedankt!", - "NAV_LICENCES": "OSS-licenties", - "NAV_STATISTICS": "Statistieken", - "NAV_IMPRESSUM": "Impressum", - "NAV_COOKIE": "Cookies", - "NAV_LOGS": "Logboeken", - "NAV_BREW_PARAMS": "Brouwparameters", - "NAV_INFORMATION_TO_APP": "Over Beanconqueror", - "NAV_WATER_SECTION": "Water", - "NAV_HELPER": "Calculaties", - "POPOVER_BREWS_OPTION_REPEAT": "Herhalen", - "POPOVER_BREWS_OPTION_DETAIL": "Details", - "DETAIL": "Details", - "POPOVER_BREWS_OPTION_EDIT": "Bewerking", - "POPOVER_BREWS_OPTION_DELETE": "Verwijder", - "POPOVER_BREWS_OPTION_PHOTO_GALLERY": "Fotogalerij", - "POPOVER_BREWS_OPTION_CUPPING": "Cupping", - "POPOVER_BREWS_OPTION_MAP_COORDINATES": "Toon op kaart", - "POPOVER_BREWS_OPTION_FAST_REPEAT": "Snel brouwen herhalen", - "PAGE_BREWS_NO_ENTRIES": "Nog geen brouwsels toegevoegd", - "PAGE_BREWS_NO_ARCHIVED_ENTRIES": "Je hebt nog geen brouwsels gearchiveerd", - "CANT_START_NEW_BREW_TITLE": "Er ontbreekt hier iets...", - "CANT_START_NEW_BREW_DESCRIPTION": "Om te beginnen, maak een beschrijving voor één type bonen, één zetmethode en één grinder. Gebruik het menu om naar de verschillende categorieën te navigeren om deze informatie toe te voegen.", - "PAGE_HOME_WELCOME_GREETINGS": "Leuk dat je er bent!", - "PAGE_HOME_TOTAL_BREW": "Brouwen", - "PAGE_HOME_TOTAL_BREWS": "Brouwsels", - "PAGE_HOME_BEAN_EXPLORED": "Bonen onderzocht", - "PAGE_HOME_BEANS_EXPLORED": "Bonen onderzocht", - "PAGE_HOME_LAST_BREWS": "Laatste brouwsels", - "PAGE_HOME_LAST_BREW": "Laatste brouwsel", - "PAGE_HOME_DIFFERENT_PREPARATION_METHODS": "Verschillende bereidingsmethoden", - "PAGE_HOME_DIFFERENT_MILLS": "Verschillende malers", - "PAGE_HOME_SUPPORTER": "App Supporter", - "PAGE_HOME_START_BREW": "Begin met brouwen", - "PAGE_BEANS_LIST_OBTAINABLE": "Beschikbaar", - "PAGE_BEANS_LIST_YOU_GOT_NO_FRESH_BEANS": "Je hebt geen verse bonen meer!", - "PAGE_BEANS_LIST_YOU_GOT_NO_FINISHED_BEANS": "Je hebt geen gearchiveerde bonen.", - "PAGE_MILL_LIST_NO_MILL_EXISTING": "Je hebt nog geen grinders toegevoegd.", - "PAGE_PREPARATION_LIST_NO_PREPARATION_EXISTING": "Je hebt nog geen zetmethodes toegevoegd.", - "PAGE_CONTACT_SUGGESTIONS_QUESTIONS_WISHES": "Suggesties, vragen, bugs of verzoeken?", - "PAGE_THANKS_THANKS_FOR_YOUR_SUPPORT": "Bedankt voor je steun!", - "PAGE_SETTINGS_LANGUAGE": "Taalinstellingen", - "PAGE_SETTINGS_LANGUAGE_GERMAN": "Duits", - "PAGE_SETTINGS_LANGUAGE_ENGLISH": "Engels", - "PAGE_SETTINGS_LANGUAGE_SPANISH": "Spaans", - "PAGE_SETTINGS_LANGUAGE_TURKISH": "Turks", - "PAGE_SETTINGS_LANGUAGE_CHINESE": "Chinees", - "PAGE_SETTINGS_GENERAL_SETTINGS": "Algemene instellingen", - "PAGE_SETTINGS_TRANSFER": "Gegevens overdragen", - "PAGE_SETTINGS_PRESET_LAST_BREW": "Vooraf ingestelde waarden?", - "PAGE_SETTINGS_DISPLAY": "Weergave", - "PAGE_SETTINGS_DISPLAY_SINGLE_PAGE": "Eén pagina", - "PAGE_SETTINGS_DISPLAY_PAGING": "Paging", - "PAGE_SETTINGS_STARTUP_VIEW": "Startpagina", - "PAGE_SETTINGS_ANALYTICS_INFORMATION": "Analytics", - "PAGE_SETTINGS_ANALYTICS_INFORMATION_TOOLTIP": "Druk op i voor meer informatie", - "PAGE_SETTINGS_TRACK_BREW_COORDINATES": "Geolocatie van brouwsel opslaan", - "PAGE_SETTINGS_FAST_REPEAT": "Snel herhalen", - "PAGE_SETTINGS_TRACK_CAFFEINE_CONSUMPTION": "bewaar cafeïneconsumptie", - "PAGE_SETTINGS_WAKE_LOCK": "Houd het display actief tijdens het brouwen", - "PAGE_SETTINGS_CURRENCY": "Valuta", - "PAGE_STATISTICS_DIFFERENT_PREPARATION_METHOD": "Bereidingsmethoden", - "PAGE_STATISTICS_TOTAL_GROUND_BEANS": "Totaal gemalen bonen", - "PAGE_STATISTICS_MONEY_SPENT_FOR_COFFEE": "Geld uitgegeven aan bonen", - "PAGE_STATISTICS_DRUNKEN_BREWS": "Totaal aantal brouwsels", - "PAGE_STATISTICS_BREW_PROCESSES": "Totaal brouwsels", - "PAGE_STATISTICS_DRUNKEN_QUANTITY": "Verbruikte hoeveelheid", - "PAGE_STATISTICS_BEAN_WEIGHT_USED": "Totaal gemalen bonen", - "PAGE_BREW_TEXT_INFORMATION_FROM_ROASTER": "Informatie over de brander", - "PAGE_ABOUT_NO_VERSION_AVAILABLE": "Geen Versie beschikbaar", - "PAGE_ABOUT_APP_VERSION": "App Versie", - "PAGE_LICENCES_WEBSITE": "Website", - "BEAN_DATA_ROAST_NAME": "Mate van branding", - "BEAN_DATA_CUSTOM_ROAST_NAME": "Aangepaste mate van branding", - "BEAN_DATA_ROASTING_DATE": "Brand datum", - "BEAN_DATA_ROASTER": "Brander", - "BEAN_DATA_VARIETY": "Variëteit", - "BEAN_DATA_PROCESSING": "Verwerking", - "BEAN_DATA_COUNTRY": "Land", - "BEAN_DATA_MIX": "Melange", - "BEAN_DATA_AROMATICS": "Smaakprofiel", - "BEAN_DATA_WEIGHT": "Gewicht", - "BEAN_DATA_COST": "kosten", - "BEAN_DATA_NAME": "Naam", - "BEAN_DATA_REGION": "Regio", - "BEAN_DATA_FARM": "Boerderij", - "BEAN_DATA_FARMER": "Boer", - "BEAN_DATA_ELEVATION": "Elevatie", - "BEAN_DATA_HARVEST_TIME": "Geoogst", - "BEAN_DATA_PERCENTAGE": "Percentage", - "BEAN_DATA_CERTIFICATION": "Bonencertificering", - "BEAN_DATA_ROASTING_TYPE": "type branding", - "BEAN_DATA_DECAFFEINATED": "Cafeïnevrij", - "BEAN_DATA_URL": "Website", - "BEAN_DATA_EAN": "EAN \/ Artikelnummer", - "BEAN_DATA_PURCHASING_PRICE": "Aankoopprijs", - "BEAN_DATA_FOB_PRICE": "FOB-prijs", - "BEAN_DATA_CUPPING_POINTS": "Cupping-punten", - "BREW_DATA_CUSTOM_BREW_TIME": "Aangepaste brouwtijd", - "BREW_CREATION_DATE": "Aanmaakdatum", - "REPEAT": "Herhalen", - "EDIT": "Bewerken", - "DELETE": "Verwijderen", - "FINISHED": "Archief", - "NOTES": "Notities", - "ADD_PHOTO": "Foto toevoegen", - "CANCEL": "Annuleren", - "GENERATE": "Genereren", - "SAVE": "Opslaan", - "ADD_SOMETHING": "Toevoegen", - "CONTACT": "Contact", - "NAME": "Naam", - "IMPORT": "import", - "EXPORT": "Export", - "VIEW": "Weergave", - "ARCHIVE": "archief", - "CURRENT": "huidig", - "BACK": "Terug", - "CLOSE": "sluiten", - "DAY": "Dag", - "BREW_DATA_TEMPERATURE_TIME": "Temperatuur Tijd", - "BREW_DATA_SURF_TIME": "Surftijd", - "BREW_DATA_TIME": "Tijd", - "BREW_DATA_GRIND_SIZE": "Maalinstelling", - "BREW_DATA_GRIND_WEIGHT": "Gemalen koffie (gr)", - "BREW_DATA_IN_OUT_BR": "In\/Uit (BR)", - "BREW_DATA_NOTES": "Notities", - "BREW_DATA_PREPARATION_METHOD": "Bereidingswijze", - "BREW_DATA_MILL": "Maler", - "BREW_DATA_MILL_SPEED": "Maalsnelheid (rpm)", - "BREW_DATA_MILL_TIMER": "Maaltijd", - "BREW_DATA_BREW_QUANTITY": "Hoeveelheid water", - "BREW_DATA_BEAN_TYPE": "Boon type", - "BREW_DATA_BREW_TEMPERATURE": "Brouwtemperatuur", - "BREW_DATA_PRESSURE_PROFILE": "Profiel", - "BREW_DATA_COFFEE_TYPE": "Type koffie", - "BREW_DATA_COFFEE_CONCENTRATION": "Koffie Concentratie", - "BREW_DATA_COFFEE_FIRST_DRIP_TIME": "Eerste druppeltijd", - "BREW_DATA_COFFEE_BLOOMING_TIME": "Bloeitijd \/ Pre-infusie", - "BREW_DATA_ATTACHMENTS": "Bijlagen \/ Foto's", - "BREW_DATA_RATING": "Beoordeling", - "BREW_DATA_CALCULATED_COFFEE_BREW_TIME": "Koffiezettijd", - "BREW_DATA_TDS": "Totaal opgeloste vaste stoffen %", - "BREW_DATA_CALCULATED_EXTRACTION_YIELD": "Extractie Opbrengst %", - "BREW_INFORMATION_BREW_RATIO": "Brouw Verhouding", - "BREW_INFORMATION_BEAN_AGE": "Boon leeftijd", - "BREW_INFORMATION_BREW_QUANTITY_TYPE_NAME": "Hoeveelheidstype", - "BREW_DATA_TDS_EY": "TDS \/ %EY", - "BREW_DATA_BREW_BEVERAGE_QUANTITY": "Hoeveelheid drank", - "BREW_DATA_PREPARATION_METHOD_TOOL": "bereidings gereedschappen", - "BREW_DATA_WATER": "Water", - "BREW_DATA_BEAN_WEIGHT_IN": "Bonengewicht (g)", - "BREW_DATA_VESSEL": "Serveerkan", - "BREW_DATA_VESSEL_WEIGHT": "Serveerkan gewicht", - "BREW_DATA_VESSEL_NAME": "Serveerkan naam", - "BREW_DATA_FLAVOR": "Smaak", - "BREW_DATA_FLOW_PROFILE": "Stroom", - "ONE_DAY": "Dag", - "DAYS": "Dagen", - "ONE_HOUR": "uur", - "HOURS": "uren", - "ONE_MINUTE": "minuut", - "MINUTES": "minuten", - "WITHOUT_COFFEE": "zonder koffie", - "NOT_FOUND": "Niet gevonden", - "INVALID_FILE_FORMAT": "Ongeldig bestandsformaat", - "FILE_NOT_FOUND_INFORMATION": "Bestand niet gevonden", - "ERROR_ON_FILE_READING": "Fout bij het lezen van bestandsgegevens", - "IMPORT_SUCCESSFULLY": "Importeren succesvol", - "IMPORT_UNSUCCESSFULLY_DATA_NOT_CHANGED": "Import mislukt, er zijn geen gegevens gewijzigd", - "INVALID_FILE_DATA": "Ongeldige bestandsinhoud", - "DOWNLOADED": "Gedownload", - "FILE_DOWNLOADED_SUCCESSFULLY": "Bestand ' {{fileName}} ' is succesvol gedownload naar uw downloadmap!", - "NO": "Nee", - "YES": "Ja", - "SURE_QUESTION": "Weet je het zeker?", - "DELETE_BREW_QUESTION": "Brouwsel verwijderen?", - "DELETE_BEAN_QUESTION": "Boon verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", - "DELETE_GREEN_BEAN_QUESTION": "Groene bonen verwijderen? Alle bijbehorende geroosterde bonen, evenals brouwsels worden verwijderd!", - "DELETE_MILL_QUESTION": "Grinder verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", - "DELETE_PREPARATION_METHOD_QUESTION": "Bereidingswijze verwijderen? Alle bijbehorende brouwsels worden ook verwijderd!", - "DELETE_PREPARATION_TOOL_QUESTION": "Bereidingstool verwijderen? Alle brouwsels die aan deze tool zijn gekoppeld, worden bijgewerkt.", - "APP_COULD_NOT_STARTED_CORRECTLY_BECAUSE_MISSING_FILESYSTEM": "App kon niet correct worden gestart vanwege ontbrekend bestandssysteem", - "CARE": "Zorg", - "ERROR_OCCURED": "Er is een fout opgetreden", - "CSV_FILE_NOT_DOWNLOADED": "CSV-bestand kon niet worden gedownload!", - "CSV_FILE_DOWNLOADED_SUCCESSFULLY": "CSV-bestand ' {{fileName}} ' is succesvol gedownload naar uw downloadmap!", - "ADD_BREW": "Voeg brouwsel toe", - "CHOOSE": "Kies", - "CHOOSE_PHOTO_OR_LIBRARY": "Maak een foto of kies uit de fotogalerij.", - "RECORD": "Maak een foto", - "PAGE_BEAN_INFORMATION": "Boon informatie", - "PAGE_BEAN_INFORMATION_GOOD_BREWS": "Goed", - "PAGE_BEAN_INFORMATION_BAD_BREWS": "Slecht", - "PAGE_BEAN_INFORMATION_COUNT_BREWS": "Totaal aantal brouwsels", - "INFORMATION": "Informatie", - "PAGE_BEAN_BREW_CHART_TITLE": "Brouwoverzicht voor deze boon", - "PAGE_BEAN_INFORMATION_AWESOME_BREWS": "Geweldig", - "PAGE_BEAN_INFORMATION_NORMAL_BREWS": "Normaal", - "PAGE_BEAN_INFORMATION_NOT_RATED_BREWS": "Niet beoordeeld", - "PAGE_PREPARATION_INFORMATION_BREWS_DONE": "Brouwsels met deze bereidingswijze", - "PAGE_PREPARATION_INFORMATION_BREWED_QUANTITY": "Gebrouwen hoeveelheid", - "PAGE_PREPARATION_INFORMATION_GRIND_WEIGHT": "Verbruikt gewicht van bonen", - "PAGE_PREPARATION_INFORMATION_TIME_SPENT_BREWING": "Totale bereidingstijd", - "PAGE_PREPARATION_INFORMATION": "Informatie over de bereiding", - "SECONDS": "Seconden", - "PAGE_MILL_INFORMATION": "Maler informatie", - "PAGE_MILL_INFORMATION_BREWS_DONE": "Brouwsels met deze maler", - "PAGE_MILL_INFORMATION_GRIND_WEIGHT": "Verbruikt gewicht van bonen", - "PAGE_HELPER_WATER_HARDNESS": "Waterhardheid", - "PAGE_HELPER_WATER_HARDNESS_CA_CONTENTS": "Calciumgehalte mg\/l", - "PAGE_HELPER_WATER_HARDNESS_MG_CONTENTS": "Magnesiumgehalte mg\/l", - "PAGE_HELPER_WATER_HARDNESS_GERMAN_HARDNESS": "Duitse hardheidsgraad", - "PAGE_HELPER_WATER_HARDNESS_TOTAL_HARDNESS": "Totale hardheid", - "PAGE_HELPER_BREW_RATIO": "Brouw Verhouding", - "PAGE_HELPER_BREW_RATIO_GROUND_COFFEE": "Gemalen koffie (gr)", - "PAGE_HELPER_BREW_RATIO_WATER": "Vloeistof (gr\/ml)", - "PAGE_HELPER_BREW_RATIO_CALCULATED": "Berekende brouwverhouding", - "PAGE_SETTINGS_SHOW_ARCHIVED_BREWS": "Gearchiveerde brouwsels weergeven", - "PAGE_SETTINGS_SHOW_ARCHIVED_BEANS": "Gearchiveerde bonen weergeven", - "PAGE_SETTINGS_SHOW_ARCHIVED_GREEN_BEANS": "Toon gearchiveerde groene bonen", - "CUPPING_SCORE": "Score", - "CUPPING_SCORE_DRY_FRAGRANCE": "Droge geur", - "CUPPING_SCORE_WET_AROMA": "Nat aroma", - "CUPPING_SCORE_BRIGHTNESS": "Helderheid", - "CUPPING_SCORE_FLAVOR": "Smaak", - "CUPPING_SCORE_BODY": "Body", - "CUPPING_SCORE_FINISH": "Afwerking", - "CUPPING_SCORE_SWEETNESS": "Zoetheid", - "CUPPING_SCORE_CLEAN_CUP": "Clean Cup", - "CUPPING_SCORE_COMPLEXITY": "Complexiteit", - "CUPPING_SCORE_UNIFORMITY": "Uniformiteit", - "CUPPING_SCORE_CUPPERS_CORRECTION": "Cuppers-correctie", - "CUPPING_SCORE_DRY_FRAGRANCE_TOOLTIP": "Verwijst naar het aroma van de droge gemalen koffie voordat er heet water aan wordt toegevoegd.", - "CUPPING_SCORE_WET_AROMA_TOOLTIP": "De geur van nat koffiedik, nadat er heet water aan is toegevoegd.", - "CUPPING_SCORE_BRIGHTNESS_TOOLTIP": "Zuurgraad is de smaak van scherpe hoge tonen in de koffie, veroorzaakt door een set van chlorogeen, citroenzuur, kininezuur, azijnzuur en andere, voornamelijk waargenomen in de voorkant van de mond en op de tong. (Het is een goede kwaliteit; niet gerelateerd aan bitterheid in koffie, en niet direct verantwoordelijk voor maagklachten). Zuurgraad wordt gewaardeerd door veel kopers, en is direct gerelateerd aan de kwaliteit van de kop, aangezien zuurgraad het product is van aanplantingen op grote hoogte.", - "CUPPING_SCORE_FLAVOR_TOOLTIP": "Dit is de algehele indruk in de mond, inclusief alle andere beoordelingen. Er zijn 4 \"primaire smaak\"-groeperingen (zuur, zoet, zout, bitter) en veel \"secundaire smaken\".", - "CUPPING_SCORE_BODY_TOOLTIP": "Vaak \"mondgevoel\" genoemd, is body het gevoel van gewicht en dikte van de gezette koffie, veroorzaakt door het percentage oplosbare vaste stoffen in de kop, inclusief alle organische verbindingen die worden geëxtraheerd (de zetmethode en de hoeveelheid gemalen koffie die wordt gebruikt, hebben hier grote invloed op). We beoordelen Body op een lagere schaal omdat licht gebodyde koffiesoorten zeker niet slecht zijn en in sommige origines past de lichtere body het beste bij het algehele karakter van de kop.", - "CUPPING_SCORE_FINISH_TOOLTIP": "De aanhoudende of opkomende smaken die komen nadat de mond is schoongemaakt. Dit omvat de tijd dat de koffie je mond verlaat tot minuten daarna...een reden dat je veel cuppers zult vinden die hun nasmaakscores herzien terwijl ze een minuut of twee later nog steeds een positieve smaak ervaren.", - "CUPPING_SCORE_SWEETNESS_TOOLTIP": "Zoetheid is bijna altijd een gewenste kwaliteit in koffie, zelfs als het op eufemistische wijze wordt beschreven, zoals \"rustieke zoetheid\" of \"bitterzoetheid\". U zult merken dat verfijnde zoetheid (denk aan Europees gebak, fijn snoepgoed, witte suiker, pure zoetheid) hoog scoort, evenals complexe zoetheid van fruitsuikers (fructose). Moutige zoetheid (maltose) is minder traditioneel, maar wel wenselijk en honing kan variëren van heel puur en schoon tot complex, rustiek, bijna gistachtig. Kortom, als zoetheid een sleutel is tot de kop, zal het goed worden beoordeeld.", - "CUPPING_SCORE_CLEAN_CUP_TOOLTIP": "Let op dat \"clean cup\" niet letterlijk betekent dat er geen vuil op de koffie zit. Het gaat alleen om smaak en rauwe, funky koffies die \"onrein\" zijn en de smaak kan ook heel wenselijk zijn, zoals nat-gepelde Indonesische koffies uit Sumatra, of droog verwerkte Ethiopische en Jemenitische types.", - "CUPPING_SCORE_COMPLEXITY_TOOLTIP": "Complexiteit complimenteert de scores voor \"smaak\" en \"afwerking\", om een veelheid of gelaagdheid van veel smaken te communiceren. Het betekent dat er veel te ontdekken valt in de kop. Aan de andere kant kunnen simpele koffies een opluchting zijn na overmatige blootstelling aan veel krachtige, intense, complexe koffies.", - "CUPPING_SCORE_UNIFORMITY_TOOLTIP": "Uniformiteit verwijst naar verschillen tussen kopjes. Koffiesoorten die met een droog proces zijn bereid, kunnen van nature minder uniform zijn dan koffiesoorten die met een nat proces zijn bereid. We zouden nooit een partij met fantastische smaken vermijden als deze af en toe afwijkt. Dit wordt gescoord tijdens het cuppingprotocol, waarbij meerdere kopjes worden gemaakt van elke partij die wordt beoordeeld.", - "CUPPING_SCORE_CUPPERS_CORRECTION_TOOLTIP": "Dit is aangepast van het SCAA-systeem en de Cup of Excellence-score (soms noemen ze het \"Overall Points\"). Het stelt een cupper in staat om ervoor te zorgen dat de totale score de algehele indruk van de cup correct weergeeft. U zou deze aanpak kunnen bekritiseren en het \"vervalsen\" van het totaal kunnen beschouwen. In zekere zin zou u gelijk hebben ... maar het zou veel erger zijn om de categoriescores te veranderen om het gewenste totaal te bereiken (om een koffie een 9 te geven voor zuurgraad terwijl u weet dat het een 7 is), of omgekeerd om een koffie die absoluut een 90 verdient, op 84 te laten eindigen. Het specifieke Cupper's Correction-nummer doet er niet toe, of het nu een 5 of een 8 is ... het idee is dat de totale score een correcte indruk geeft van de kwaliteit van de koffie.", - "CUPPING_SCORE_TOOLTIP": "100-95 = Verbazingwekkend, 90-94 = Uitstekend, 85-89 = Zeer goed, 80-84 = Goed, 75-79 = Redelijk, 70-74 = Slecht", - "DETAIL_BREW": "Brouw details", - "DETAIL_BEAN": "Boon details", - "DETAIL_MILL": "Maler details", - "DETAIL_PREPARATION": "Bereidings details", - "EDIT_BREW": "Bewerk brouwsel", - "ADD_BEAN": "Boon toevoegen", - "EDIT_BEAN": "Bewerken boon", - "ADD_PREPARATION": "Bereidingsmethode toevoegen", - "EDIT_PREPARATION": "Bewerk bereidingsmethode", - "ADD_MILL": "Voeg maler toe", - "EDIT_MILL": "Maler bewerken", - "USE_FILTER": "Filter toepassen", - "RESET_FILTER": "Filter resetten", - "COFFEE_GRAMS_GRINDED": "Gram gemalen", - "BEANS_USED": "Bonen geconsumeerd", - "BREW_HEADER_BEFORE_BREW": "Voor het brouwen", - "BREW_HEADER_WHILE_BREW": "Tijdens het brouwen", - "BREW_HEADER_AFTER_BREW": "Na het brouwen", - "BREW_HEADER_CUPPING": "Proeven", - "BEANS_CONSUMED": "Archieveer", - "NAV_MANAGE_PARAMETERS": "Parameters beheren", - "NAV_SORT_PARAMETERS": "Sorteer parameters", - "NAV_DEFAULT_PARAMETERS": "Standaardparameters definiëren", - "PAGE_SORT_PARAMETERS_DESCRIPTION": "Versleep parameters om te bepalen in welke volgorde ze worden weergegeven.", - "PAGE_MANAGE_PARAMETERS_DESCRIPTION": "Geef aan welke parameters moeten worden weergegeven bij het bewerken van brouwinformatie.", - "PAGE_DEFAULT_PARAMETERS_DESCRIPTION": "Markeer welke parameters standaard moeten worden ingesteld op de laatst gebruikte waarde.", - "SORT_PARAMETERS_BEFORE": "Voor het brouwen", - "SORT_PARAMETERS_MEANWHILE": "Tijdens het brouwen", - "SORT_PARAMETERS_AFTER": "Na het brouwen", - "MORE_INFORMATION": "Meer informatie", - "UNDERSTOOD": "Begrepen", - "WELCOME_PAGE_ACTIVATE_ANALYTICS_TITLE": "Analyse en tracking", - "WELCOME_PAGE_ACTIVATE_ANALYTICS_DESCRIPTION": "We willen de app, de website en onze toekomstige diensten voor u voortdurend verbeteren. Om dit te doen, moeten we wat gegevens bijhouden over hoe u de app en de functies ervan gebruikt. Maar we beloven dat we nooit persoonlijke gegevens zullen bijhouden. Om deze beloften waar te maken, gebruiken we Matomo, een open source service gericht op gegevensbeveiliging en privacy die op onze eigen server wordt gehost - dit zorgt ervoor dat alleen wij eigenaar zijn van de gegevens. Onze website biedt alle informatie over de parameters die we bijhouden en bovendien kunt u de broncode bekijken die 100% open source is. Heeft u vragen? Neem dan gerust contact met ons op.", - "ANALYTICS_INFORMATION_TITLE": "Analyse en tracking", - "ANALYTICS_INFORMATION_DESCRIPTION": "Zoals u weet, is de veiligheid van uw gegevens en uw privacy onze topprioriteit. Daarom zijn we overgestapt van Google Analytics naar de open source service Matomo, die zich richt op gegevensbeveiliging en privacy. Deze service wordt gehost op onze eigen server. Dit betekent dat wij volledig eigenaar zijn van de gegevens. De bijgehouden parameters zijn niet gewijzigd en we beloven nog steeds dat we nooit persoonlijke gegevens zullen bijhouden. Op onze website vindt u alle informatie over de parameters die we bijhouden. Bovendien kunt u de broncode bekijken, die 100% open source is. Heeft u vragen? Neem dan gerust contact met ons op.", - "ACTIVATE": "Activeren", - "DO_NOT_ACTIVE": "Niet activeren", - "WELCOME_PAGE_BEAN_TITLE": "Boon", - "WELCOME_PAGE_BEAN_DESCRIPTION": "Koffie zetten zonder bonen is een beetje lastig. Voeg je eerste boon toe om te beginnen!", - "WELCOME_PAGE_BEAN_ADD": "Boon toevoegen", - "SKIP": "Overslaan", - "WELCOME_PAGE_PREPARATION_TITLE": "Bereidingswijze", - "WELCOME_PAGE_PREPARATION_DESCRIPTION": "V60, Aeropress, Espresso - er zijn veel manieren om koffie te zetten. Voeg er minstens één toe.", - "WELCOME_PAGE_PREPARATION_ADD": "Bereidingswijze toevoegen", - "WELCOME_PAGE_MILL_TITLE": "Maler", - "WELCOME_PAGE_MILL_DESCRIPTION": "Bijna klaar, maar je hebt iets nodig om je bonen te malen! Voeg minstens één maler toe.", - "WELCOME_PAGE_MILL_ADD": "Voeg Maler toe", - "WELCOME_PAGE_TITLE": "Welkom!", - "WELCOME_PAGE_BEAN_HEADLINE": "Eerste boon", - "WELCOME_PAGE_PREPARATION_HEADLINE": "Bereidingswijze toevoegen", - "WELCOME_PAGE_MILL_HEADLINE": "Eerste Maler", - "WELCOME_PAGE_LETS_START_HEADLINE": "Nu kunnen we beginnen met brouwen!", - "WELCOME_PAGE_LETS_START_TITLE": "Nu kunnen we beginnen met brouwen!", - "WELCOME_PAGE_LETS_START_DESCRIPTION": "Gefeliciteerd, je bent klaar om de beste koffie van je leven te zetten. Veel plezier en verspreid de liefde voor goede koffie!", - "PREPARATION_TYPE": "Bereidingsmethode", - "PREPARATION_TYPE_NAME": "Naam", - "ARCHIVED": "Gearchiveerd", - "PAGE_SETTINGS_SHOW_ARCHIVED_PREPARATIONS": "Toon gearchiveerde bereidingsmethoden", - "PAGE_SETTINGS_SHOW_ARCHIVED_MILLS": "Toon gearchiveerde malers", - "PAGE_MILL_LIST_NO_ARCHIVED_MILL_EXISTING": "Er zijn nog geen malers gearchiveerd.", - "PAGE_PREPARATION_LIST_NO_ARCHIVED_PREPARATION_EXISTING": "Je hebt geen gearchiveerde bereidingswijzen.", - "TOAST_BREW_ADDED_SUCCESSFULLY": "Brouwsel succesvol toegevoegd", - "TOAST_BREW_REPEATED_SUCCESSFULLY": "Brouwsel succesvol herhaald", - "TOAST_BEAN_ADDED_SUCCESSFULLY": "Boon succesvol toegevoegd", - "TOAST_MILL_ADDED_SUCCESSFULLY": "Maler succesvol toegevoegd", - "TOAST_PREPARATION_ADDED_SUCCESSFULLY": "Bereidingswijze succesvol toegevoegd", - "TOAST_WATER_ADDED_SUCCESSFULLY": "Water succesvol toegevoegd", - "TOAST_BREW_DELETED_SUCCESSFULLY": "Brouwsel is verwijderd", - "TOAST_BEAN_DELETED_SUCCESSFULLY": "Boon is verwijderd", - "TOAST_GREEN_BEAN_DELETED_SUCCESSFULLY": "Groene boon is verwijderd", - "TOAST_MILL_DELETED_SUCCESSFULLY": "Maler is verwijderd", - "TOAST_WATER_DELETED_SUCCESSFULLY": "Water is verwijderd", - "TOAST_PREPARATION_DELETED_SUCCESSFULLY": "Bereidingswijze is verwijderd", - "TOAST_BREW_EDITED_SUCCESSFULLY": "Brouwsel is bewerkt", - "TOAST_BEAN_EDITED_SUCCESSFULLY": "Boon is bewerkt", - "TOAST_MILL_EDITED_SUCCESSFULLY": "Maler is bewerkt", - "TOAST_PREPARATION_EDITED_SUCCESSFULLY": "Bereiding is bewerkt", - "TOAST_WATER_EDITED_SUCCESSFULLY": "Water is bewerkt", - "TOAST_BEAN_ARCHIVED_SUCCESSFULLY": "Boon is gearchiveerd", - "TOAST_MILL_ARCHIVED_SUCCESSFULLY": "Maler is gearchiveerd", - "TOAST_PREPARATION_ARCHIVED_SUCCESSFULLY": "Bereidingsmethode is gearchiveerd", - "TOAST_WATER_ARCHIVED_SUCCESSFULLY": "Water is gearchiveerd", - "BEAN_WEIGHT_ALREADY_USED": "{{gramUsed}} g van {{gramTotal}} g ( {{leftOver}} g)", - "PREPARATION_TYPE_CUSTOM_PREPARATION": "Aangepaste bereidingsmethode", - "PREPARATION_TYPE_AEROPRESS": "Aeropress", - "PREPARATION_TYPE_V60": "V60", - "PREPARATION_TYPE_CHEMEX": "Chemex", - "PREPARATION_TYPE_BIALETTI": "Bialetti", - "PREPARATION_TYPE_PORTAFILTER": "Espresso machine", - "PREPARATION_TYPE_KALITA_WAVE": "Kalita Wave", - "PREPARATION_TYPE_FRENCH_PRESS": "French Press", - "PREPARATION_TYPE_SWANNECK": "Swan Neck", - "PREPARATION_TYPE_DRIPPER": "Dripper", - "PREPARATION_TYPE_DELTER_PRESS": "Delter Press", - "PREPARATION_TYPE_COLD_BREW": "Koud brouwsel", - "PREPARATION_TYPE_AEROPRESS_INVERTED": "Aeropress Omgekeerd", - "PREPARATION_TYPE_TURKISH": "Turks", - "PREPARATION_TYPE_BLUE_DRIPPER": "Blue Dripper", - "PREPARATION_TYPE_ADD_CUSTOM": "Aangepaste methode toevoegen", - "PREPARATION_TYPE_GINA": "Gina", - "PREPARATION_TYPE_KONO": "Kono", - "PREPARATION_TYPE_ORIGAMI": "Origami", - "PREPARATION_TYPE_CAFELAT": "Cafelat", - "PREPARATION_TYPE_OREA": "Orea", - "PREPARATION_TYPE_COLD_DRIP": "Cold Drip", - "PREPARATION_TYPE_HAND_LEVER": "Handmatige hendel", - "PREPARATION_TYPE_FLAIR": "Flair", - "PREPARATION_TYPE_APRIL_BREWER": "April Brewer", - "PREPARATION_TYPE_ESPRO_BLOOM": "Espreo Bloom", - "PREPARATION_TYPE_FELLOW_STAGG": "Fellow Stagg", - "PREPARATION_TYPE_HSIAO_50": "Hsiao 50", - "PREPARATION_TYPE_KARLSBADER_KANNE": "Karlsbader", - "PREPARATION_TYPE_MOCCA_MASTER": "Mocca Master", - "PREPARATION_TYPE_SIPHON": "Sifon", - "CHOOSE_BEANS": "Selecteer bonen", - "CHOOSE_BEAN": "Selecteer boon", - "CHOOSE_WATERS": "Selecteer wateren", - "CHOOSE_WATER": "Selecteer water", - "CHOOSE_PREPARATIONS": "Selecteer bereidingsmethoden", - "CHOOSE_PREPARATION": "Selecteer bereidingsmethode", - "CHOOSE_MILLS": "Selecteer molens", - "CHOOSE_MILL": "Selecteer molen", - "BEAN": { - "PLACE_HOLDER": { - "BEAN_DATA_NAME": "Naam toevoegen", - "BEAN_DATA_ROAST_NAME": "Voeg de mate van branding toe", - "BEAN_DATA_ROASTING_DATE": "Wanneer werden de bonen geroosterd?", - "BEAN_DATA_ROASTER": "Wie heeft de bonen geroosterd?", - "BEAN_DATA_VARIETY": "Voeg de koffievariant toe", - "BEAN_DATA_PROCESSING": "Koffieverwerking, bijvoorbeeld gewassen", - "BEAN_DATA_COUNTRY": "Waar komt de boon vandaan?", - "BEAN_DATA_MIX": "Wat is de melange ratio?", - "BEAN_DATA_AROMATICS": "Voeg smaken toe", - "BEAN_DATA_WEIGHT": "Gewicht van de bonen", - "BEAN_DATA_COST": "Hoeveel hebben de bonen gekost?", - "BEAN_DATA_REGION": "Regio toevoegen", - "BEAN_DATA_FARM": "Voeg de boerderij toe", - "BEAN_DATA_FARMER": "Voeg de boer toe", - "BEAN_DATA_ELEVATION": "Op welke hoogte werden de bonen geteeld", - "BEAN_DATA_HARVEST_TIME": "wanneer zijn de bonen geoogst?", - "BEAN_DATA_BUY_DATE": "Wanneer zijn de bonen gekocht?", - "BEAN_DATA_PERCENTAGE": "Voeg het percentage van deze boon in de melange toe", - "BEAN_DATA_CERTIFICATION": "Voeg de bonencertificering toe (bijv. fairtrade, bio)", - "BEAN_DATA_ROASTING_TYPE": "Voeg brand type toe", - "BEAN_DATA_DECAFFEINATED": "Is deze koffie cafeïnevrij", - "BEAN_DATA_URL": "Voeg de website-url toe", - "BEAN_DATA_EAN": "Voeg het EAN- of artikelnummer toe", - "BEAN_DATA_CUPPING_POINTS": "Voeg de cuppingpunten toe", - "BEAN_DATA_PURCHASING_PRICE": "Voeg de aankoopprijs toe", - "BEAN_DATA_FOB_PRICE": "Voeg de FOB-prijs toe", - "NOTES": "Voeg notities toe over deze bonen", - "CHOOSE_DATA_ROASTER": "Kies een brander", - "CHOOSE_DATA_ROASTING_TYPE": "Kies type branding", - "BEAN_DATA_BEST_DATE": "Wanneer is de beste datum om de bonen te gebruiken?", - "BEAN_DATA_OPEN_DATE": "Wanneer is de zak bonen geopend?", - "FROZEN_NOTES": "Zijn er opmerkingen over de bevroren koffie? Bijvoorbeeld in welke vriezer je het hebt bewaard." - } - }, - "PREPARATION": { - "PLACE_HOLDER": { - "PREPARATION_TYPE_NAME": "Voeg een naam toe", - "NOTES": "Voeg notities toe over deze bereidingsmethode" - } - }, - "MILL": { - "PLACE_HOLDER": { - "NAME": "Voeg een naam toe", - "NOTES": "Voeg notities toe over deze grinder" - } - }, - "BREW": { - "PLACE_HOLDER": { - "BREW_DATA_GRIND_SIZE": "Voer de maalinstelling in", - "BREW_DATA_GRIND_WEIGHT": "Vul de hoeveelheid koffie in (gr)", - "BREW_DATA_BREW_TEMPERATURE": "Voer de brouwtemperatuur in", - "BREW_DATA_PREPARATION_METHOD": "Selecteer bereidingsmethode", - "BREW_DATA_BEAN_TYPE": "Selecteer bonen", - "BREW_DATA_MILL": "Selecteer een molen", - "BREW_DATA_MILL_SPEED": "Voer de maalsnelheid in", - "BREW_DATA_MILL_TIMER": "Voer de maal tijd in", - "BREW_DATA_PRESSURE_PROFILE": "Druk\/stroomprofiel, brouwmethodologie", - "BREW_DATA_TEMPERATURE_TIME": "Voer de tijd in die de machine heeft mogen opwarmen", - "BREW_DATA_COFFEE_BLOOMING_TIME": "Hoe lang is de bloom?", - "BREW_DATA_COFFEE_FIRST_DRIP_TIME": "Wanneer verscheen de eerste druppel?", - "BREW_DATA_BREW_QUANTITY": "Hoeveel water heb je gebruikt om te brouwen?", - "BREW_DATA_COFFEE_TYPE": "Voer de koffiestijl in (bijv. ristretto)", - "BREW_DATA_COFFEE_CONCENTRATION": "Voer de koffie concentratie in", - "BREW_DATA_TDS": "Wat was de gemeten hoeveelheid opgeloste vaste stoffen (TDS)?", - "BREW_DATA_NOTES": "Voeg notities toe over dit brouwsel", - "BREW_DATA_BREW_BEVERAGE_QUANTITY": "Voeg totale drank hoeveelheid toe", - "BREW_DATA_PREPARATION_METHOD_TOOL": "Kies je bereiding tools", - "BREW_DATA_WATER": "Kies het gebruikte water", - "BREW_DATA_BEAN_WEIGHT_IN": "Welk gewicht aan bonen heb je gebruikt?" - } - }, - "ROASTED_BEFORE": "Geroosterd voor", - "DAY_OLD": "dag oud", - "DAYS_OLD": "dagen oud", - "BEANS_AMOUNT_USED": "Verbruikt", - "CUPPING_BREW": "Proeven", - "COFFEE_DRUNKEN_QUANTITY": "Koffie dronken", - "IMAGE_DELETED": "Afbeelding is verwijderd", - "IMAGE_NOT_DELETED": "Afbeelding kon niet worden verwijderd", - "EXTERNAL_STORAGE_NOT_SUPPORTED": "Sorry, externe opslag wordt niet ondersteund", - "BEANS_ARCHIVED": "Gearchiveerd", - "TAB_ARCHIVE": "Archief", - "TODAY": "Vandaag", - "PLEASE_WAIT": "Even geduld aub...", - "PREPARATION_STYLE_POUR_OVER": "Pourover", - "PREPARATION_STYLE_ESPRESSO": "Espresso", - "PREPARATION_STYLE_FULL_IMMERSION": "Immersie", - "PREPARATION_STYLE_PERCOLATION": "Percolatie", - "PREPARATION_TYPE_STYLE": "Bereidingsstijl", - "PAGE_SETTINGS_FAST_REPEAT_DESCRIPTION": "Activeert een nieuw menu-item - hiermee kun je een brouwsel kopieren.", - "PAGE_SETTINGS_TRACK_BREW_COORDINATES_DESCRIPTION": "Sla geolocatie gegevens op voor elk brouwsel.", - "PAGE_SETTINGS_TRACK_CAFFEINE_CONSUMPTION_DESCRIPTION": "Bewaar de hoeveelheid geconsumeerde cafeïne", - "UPDATE_TITLE": "Wat is er nieuw?", - "NEXT": "Volgende", - "CUSTOM_PARAMETERS": "Parameters aanpassen", - "CUSTOM_DEFAULT_PARAMETERS": "Standaard", - "CUSTOM_MANAGE_PARAMETERS": "Beheer", - "CUSTOM_SORT_PARAMETERS": "Sorteer", - "BREW_PARAMETER_CUSTOMIZE_TITLE": "Aangepaste parameters voor elke bereidingsmethode", - "BREW_PARAMETER_CUSTOMIZE_DESCRIPTION": "Wilt u voor elke bereidingsmethode aangepaste parameters kiezen? Navigeer naar \"Methoden\", open het menu van de specifieke bereidingsmethode en kies \"Parameters aanpassen\". Daar kunt u kiezen welke parameters voor deze bereiding worden gebruikt!", - "BREW_DATA_BREW_QUANTITY_TOOLTIP": "Hoeveelheid water (niet bruikbaar voor espresso)", - "BREW_DATA_COFFEE_FIRST_DRIP_TIME_TOOLTIP": "Eerste druppel tijd van de koffie (alleen espresso)", - "BREW_DATA_PREPARATION_METHOD_TOOLTIP": "Voorbereiding (alleen aanpasbaar indien actief)", - "PAGE_SETTINGS_GENERAL": "Algemene instellingen", - "EDIT_PREPARATION_CUSTOM_PARAMETERS": "Parameters aanpassen", - "ENABLE_PREPARATION_CUSTOM_PARAMETERS": "Aangepaste parameters gebruiken", - "BEAN_ADD_ANOTHER_SORT": "Voeg een andere boon type toe", - "BEAN_SORT": "Boon Type", - "BEAN_SORT_INFORMATION": "Informatie over de variëteit", - "BEAN_SORT_MORE_INFORMATION": "Meer informatie", - "NAVIGATE_TO_PREPARATION_METHODS": "Navigeer naar bereidingsmethoden", - "PREPARATION_TOOLS": "bereidingsmiddelen", - "PREPARATION_TOOLS_INFORMATION": "Voeg verschillende mandjes toe, WDT-gereedschappen voor uw espressomachine; stoffen, papieren of gaasfilters voor uw filterkoffie, enz.", - "PREPARATION_TOOLS_PLACEHOLDER": "Papieren of stoffen filter, VST 20g, 14g mandje, enz.", - "PREPARATION_PARAMETERS_CUSTOMIZED": "Aangepaste parameters", - "BEANS_WEIGHT_AVAILABLE": "Beschikbare bonen", - "SORT_ORDER": "Sorteervolgorde wijzigen", - "ASCENDING": "Oplopend", - "DESCENDING": "Aflopend", - "SORT_AFTER": "Sorteren na", - "BEAN_SORT_NAME_OF_BEAN": "Boon naam", - "BEAN_SORT_ROASTER": "Brander", - "BEAN_SORT_ROASTING_DATE": "Datum van roosteren", - "BEAN_TAB_ROAST_INFORMATION": "Geroosterde informatie", - "BEAN_TAB_GENERAL_INFORMATION": "Algemeen", - "BEAN_TAB_SORT_INFORMATION": "Informatie over de variëteit", - "PAGE_SETTINGS_MANAGE_ARCHIVE": "Archief beheren", - "LAST_USE": "Laatst gebruikt", - "SEARCH": "Zoeken", - "OVERVIEW": "Overzicht", - "BEAN_HEADER_ADDITIONALE_INFORMATION": "Aanvullende informatie", - "THREE_DEE_TOUCH_ACTION_BREW": "Brouw", - "THREE_DEE_TOUCH_ACTION_BEAN": "Boon", - "THREE_DEE_TOUCH_ACTION_PREPARATION": "Bereidingsmethode", - "THREE_DEE_TOUCH_ACTION_MILL": "Koffiemolen", - "PAGE_CREDITS_NOT_EXISTING": "Geen inhoud", - "TIMER_HOUR": "Uren", - "TIMER_MINUTES": "Minuten", - "TIMER_SECONDS": "Seconden", - "EXCEL": { - "BEAN": { - "CREATION_DATE": "Aanmaakdatum", - "ID": "Bonen-ID" - }, - "PREPARATION": { - "CREATION_DATE": "Aanmaakdatum", - "ID": "bereidingsmiddelen" - }, - "GRINDER": { - "CREATION_DATE": "Aanmaakdatum", - "ID": "Molen-ID" - } - }, - "EXCEL_EXPORT": "Excel-export", - "HEALTH_KIT_QUESTION_TITLE": "cafeïneconsumptie opslaan", - "HEALTH_KIT_QUESTION_MESSAGE": "Na activering wordt de geschatte cafeïne van elk brouwsel automatisch opgeslagen in Apple Health.", - "NAV_ROASTING_SECTION": "Bonen roosteren", - "ROASTING_SECTION": { - "NAV_GREEN_BEANS": "Groene bonen", - "NAV_ROASTING_MACHINE": "Roostermachine", - "ROASTING_MACHINE": { - "TOTAL_ROAST_QUANTITY": "Totaalgewicht geroosterd", - "TOTAL_ROAST_COUNT": "Aantal brandingen" - }, - "GREEN_BEAN": { - "ADD": "Toevoegen", - "EDIT": "Bewerking", - "DETAIL": "Groene bonen details", - "ROASTABLE": "Roosterbaar", - "NO_ROASTS_YET": "Nog geen gebrande bonen" - }, - "BEAN": { - "DROP_TEMPERATURE": "Eindtemperatuur van de gebrande boon", - "ROAST_LENGTH": "brand lengte", - "ROASTER_MACHINE": "Roostermachine", - "GREEN_BEAN_WEIGHT": "Gewicht van groene bonen", - "OUTSIDE_TEMPERATURE": "Omgevingstemperatuur", - "HUMIDITY": "Vochtigheid", - "FIRST_CRACK_MINUTE": "eerst kraak minuut", - "FIRST_CRACK_TEMPERATURE": "eerste kraak temperatuur", - "SECOND_CRACK_MINUTE": "Tweede kraak minuut", - "SECOND_CRACK_TEMPERATURE": "tweede kraak temperatuur", - "PLACE_HOLDER": { - "DROP_TEMPERATURE": "Eindtemperatuur van de gebrande boon", - "ROAST_LENGTH": "brand lengte", - "ROASTER_MACHINE": "Roostermachine", - "GREEN_BEAN_WEIGHT": "Gewicht van groene bonen", - "OUTSIDE_TEMPERATURE": "Omgevingstemperatuur", - "HUMIDITY": "Vochtigheid", - "FIRST_CRACK_MINUTE": "Eerste kraak minuut", - "FIRST_CRACK_TEMPERATURE": "Eerste kraak temperatuur", - "SECOND_CRACK_TEMPERATURE": "Tweede kraak temperatuur", - "SECOND_CRACK_MINUTE": "Tweede kraak minuut" - } - } - }, - "PAGE_SETTINGS_MANAGE_SECTIONS": "Meer secties", - "PAGE_SETTINGS_SHOW_ROASTING_SECTION": "Activeer brandersectie", - "PAGE_SETTINGS_SHOW_WATER_SECTION": "Activeer water sectie", - "PAGE_SETTINGS_SHOW_CUPPING_SECTION": "Activeer cupping-sectie", - "BEAN_DATA_BUY_DATE": "Aankoopdatum", - "BEAN_SORT_CREATION_DATE": "Aanmaakdatum", - "BEAN_SORT_PURCHASE_DATE": "Aankoopdatum", - "BEAN_ROAST_COUNT": "Roost aantal", - "TRANSFER_ROAST": "Geroosterd", - "BEAN_TAB_LINKED_ROASTS": "Geroosterd", - "BEAN_DATA_WEIGHT_AFTER_ROASTING": "Gewicht na het roosteren", - "TOAST_GREEN_BEAN_ADDED_SUCCESSFULLY": "Groene bonen toegevoegd", - "TOAST_GREEN_BEAN_EDITED_SUCCESSFULLY": "Groene boon bewerkt", - "TOAST_GREEN_BEAN_ARCHIVED_SUCCESSFULLY": "Groene bonen gearchiveerd", - "TOAST_ROASTING_MACHINE_ADDED_SUCCESSFULLY": "Roostermachine toegevoegd", - "TOAST_ROASTING_MACHINE_EDITED_SUCCESSFULLY": "Brandmachine bewerkt", - "TOAST_ROASTING_MACHINE_ARCHIVED_SUCCESSFULLY": "Brander gearchiveerd", - "DELETE_ROASTING_MACHINE_QUESTION": "Brander verwijderen? Alle gebrande bonen waarnaar verwezen wordt, worden bijgewerkt en niet verwijderd.", - "TOAST_ROASTING_MACHINE_DELETED_SUCCESSFULLY": "Brander verwijderd", - "EDIT_ROASTING_MACHINE": "Bewerk", - "DETAIL_ROASTING_MACHINE": "Details van de brander", - "DELETE_WATER_QUESTION": "Water verwijderen? Alle gerefereerde brouwsels worden bijgewerkt en niet verwijderd", - "ROASTING_MACHINE": { - "PLACE_HOLDER": { - "NAME": "Voeg een naam toe", - "NOTES": "Opmerkingen toevoegen voor deze brander" - } - }, - "NAV_ROASTING_MACHINE": "koffierooster machines", - "PAGE_ROASTING_MACHINE_LIST_NO_MACHINES_EXISTING": "U hebt geen koffiebrander toegevoegd", - "PAGE_ROASTING_MACHINE_LIST_NO_ARCHIVED_MACHINES_EXISTING": "je hebt geen koffiebrander gearchiveerd", - "CHOOSE_ROASTING_MACHINES": "koffiebrander", - "CHOOSE_ROASTING_MACHINE": "koffiebrander", - "POPOVER_BREWS_OPTION_TOGGLE_FAVOURITE": "Favoriet", - "TOAST_BREW_FAVOURITE_ADDED": "Favoriet toegevoegd", - "TOAST_BREW_FAVOURITE_REMOVED": "Favoriet verwijderd", - "BREW_FILTER_JUST_FAVOURITE": "Favorieten", - "STATISTICS_PREPARATION_USAGES": "Bereidingsmethode gebruik", - "STATISTICS_PREPARATION_TIMELINE_USAGES": "Gebruiksgeschiedenis bereidingsmethode", - "STATISTICS_GRINDER_TIMELINE_USAGES": "Gebruiksgeschiedenis van de Maler", - "ACCEPT": "Accepteer", - "STATISTIC_TAB_GENERAL": "Algemeen", - "STATISTIC_TAB_BREWS": "Brouwsels", - "STATISTIC_TAB_BEANS": "Bonen", - "STATISTIC_TAB_PREPARATIONS": "Voorbereidingen", - "STATISTIC_TAB_GRINDERS": "Malers", - "PAGE_STATISTICS_BREW_PER_DAYPROCESSES": "Brouwsels per dag", - "PAGE_STATISTICS_BREW_TIME": "Brouwtijd", - "PAGE_STATISTICS_PHOTOS_TAKEN": "Foto's gemaakt", - "PAGE_SETTINGS_IMAGE_QUALITY": "afbeelding kwaliteit", - "PAGE_SETTINGS_IMAGE_QUALITY_TOOLTIP": "Bepaal in welke kwaliteit uw afbeeldingen moeten worden opgeslagen. Dit kan uw dataverbruik verlagen.", - "PAGE_SETTINGS_BREW_RATING": "Brouw beoordeling", - "PAGE_SETTINGS_BREW_RATING_TOOLTIP": "Is de standaard '-1 tot 5' niet de juiste beoordeling voor u? U kunt in plaats daarvan een '-1 tot 100' schaal gebruiken", - "UPDATE_ENTRY_OF": "Update item {{index}} van {{count}}", - "WEBSITE": "Website", - "SHARE": "Deel", - "ANDROID_FILE_ACCESS_NEEDED_TITLE": "Toegang tot gedeeld bestand vereist", - "ANDROID_FILE_ACCESS_NEEDED_DESCRIPTION": "Om de app volledig te laten werken, vragen we u om bestandstoegang te autoriseren. Anders ontstaan er problemen bij het gebruik van de app. Dit is specifiek nodig voor het automatische back-upsysteem.", - "COULD_NOT_ACCESS_FILE": "We konden het gekozen bestand niet openen", - "WRONG_FILE_FORMAT": "U hebt een niet-ondersteund bestandsformaat gekozen", - "SCAN_BEAN": "Scan pakket", - "CLEAR": "leeg maken", - "BEAN_LOOKS_LIKE_CONSUMED": "Het lijkt erop dat deze bonen op zijn. Wil je ze archiveren?", - "CUPPING_1": "Fruit", - "CUPPING_2": "Citrus", - "CUPPING_3": "Citroen & limonade", - "CUPPING_4": "Limoen", - "CUPPING_5": "Grapefruit", - "CUPPING_6": "Clementine", - "CUPPING_7": "Mandarijn", - "CUPPING_8": "mandarijn sinaasappel", - "CUPPING_9": "sinasappel", - "CUPPING_10": "Appel\/peer", - "CUPPING_11": "Groene appel", - "CUPPING_12": "Rode appel", - "CUPPING_13": "Meloen", - "CUPPING_14": "Watermeloen", - "CUPPING_15": "Honingdauw meloen", - "CUPPING_16": "Cantaloupe meloen", - "CUPPING_17": "Druif", - "CUPPING_18": "Witte druif", - "CUPPING_19": "Groene druif", - "CUPPING_20": "Rode druif", - "CUPPING_21": "Concord-druif", - "CUPPING_22": "Tropisch fruit", - "CUPPING_23": "Litchi", - "CUPPING_24": "Stervrucht", - "CUPPING_25": "Tamarinde", - "CUPPING_26": "Passievrucht", - "CUPPING_27": "Ananas", - "CUPPING_28": "Mango", - "CUPPING_29": "Papaja", - "CUPPING_30": "Kiwi", - "CUPPING_31": "Banaan", - "CUPPING_32": "Kokosnoot", - "CUPPING_33": "Steenvrucht", - "CUPPING_34": "Perzik", - "CUPPING_35": "Nectarine", - "CUPPING_36": "Abrikoos", - "CUPPING_37": "Pruim", - "CUPPING_38": "Kers", - "CUPPING_39": "Zwarte kers", - "CUPPING_40": "Bes", - "CUPPING_41": "Cranberry", - "CUPPING_42": "Framboos", - "CUPPING_43": "Aardbei", - "CUPPING_44": "Bosbes", - "CUPPING_45": "Rode bes", - "CUPPING_46": "Zwarte bes", - "CUPPING_47": "Gedroogd fruit", - "CUPPING_48": "Gouden rozijn", - "CUPPING_49": "Rozijn", - "CUPPING_50": "Gedroogde vijg", - "CUPPING_51": "Gedroogde dadels", - "CUPPING_52": "Gedroogde Pruim", - "CUPPING_53": "Zoet & gebrand", - "CUPPING_54": "Chocolade", - "CUPPING_55": "Cacaonibs", - "CUPPING_56": "Donkere chocolade", - "CUPPING_57": "Bakkers chocolade", - "CUPPING_58": "Bitterzoete chocolade", - "CUPPING_59": "Cacaopoeder", - "CUPPING_60": "Melkchocolade", - "CUPPING_61": "Noot", - "CUPPING_62": "Walnoot", - "CUPPING_63": "Pinda", - "CUPPING_64": "Cashew", - "CUPPING_65": "Pecannoot", - "CUPPING_66": "Hazelnoot", - "CUPPING_67": "Amandel", - "CUPPING_68": "Graan & Graanproducten", - "CUPPING_69": "Zoet broodgebak", - "CUPPING_70": "Granola", - "CUPPING_71": "Graham-cracker", - "CUPPING_72": "Rogge", - "CUPPING_73": "Tarwe", - "CUPPING_74": "Gerst", - "CUPPING_75": "Vers brood", - "CUPPING_76": "Zoet & Suikerachtig", - "CUPPING_77": "Vanille", - "CUPPING_78": "Noga", - "CUPPING_79": "Honing", - "CUPPING_80": "Boter", - "CUPPING_81": "Room", - "CUPPING_82": "Marshmallow", - "CUPPING_83": "Rietsuiker", - "CUPPING_84": "Bruine suiker", - "CUPPING_85": "Karamel", - "CUPPING_86": "Ahornsiroop", - "CUPPING_87": "Melasse", - "CUPPING_88": "Cola", - "CUPPING_89": "Geroosterd", - "CUPPING_90": "Toast", - "CUPPING_91": "Verbrande suiker", - "CUPPING_92": "Rokerig", - "CUPPING_93": "Koolstof", - "CUPPING_94": "Plantaardig, hartig en kruidig", - "CUPPING_95": "Kruiden", - "CUPPING_96": "Zwarte peper", - "CUPPING_97": "Witte peper", - "CUPPING_98": "Kaneel", - "CUPPING_99": "Koriander", - "CUPPING_100": "Gember", - "CUPPING_101": "Nootmuskaat", - "CUPPING_102": "Kerrie", - "CUPPING_103": "Drop-anijs", - "CUPPING_104": "Kruidnagel", - "CUPPING_105": "Hartig", - "CUPPING_106": "Leerachtig", - "CUPPING_107": "Vleesachtig", - "CUPPING_108": "Sojasaus", - "CUPPING_109": "Zongedroogde tomaat", - "CUPPING_110": "Tomaat", - "CUPPING_111": "Plantaardig aards kruid", - "CUPPING_112": "Grond", - "CUPPING_113": "Vers hout", - "CUPPING_114": "Ceder", - "CUPPING_115": "Tabak", - "CUPPING_116": "Hooi \/ stro", - "CUPPING_117": "Bladgroenten", - "CUPPING_118": "Olijf", - "CUPPING_119": "Groene peper", - "CUPPING_120": "Pompoen", - "CUPPING_121": "Paddestoel", - "CUPPING_122": "Zoete erwt", - "CUPPING_123": "Sneeuwerwt", - "CUPPING_124": "Grassig", - "CUPPING_125": "Dille", - "CUPPING_126": "Salie", - "CUPPING_127": "Munt", - "CUPPING_128": "Groene thee", - "CUPPING_129": "Zwarte thee", - "CUPPING_130": "Hop", - "CUPPING_131": "Bergamot", - "CUPPING_132": "Bloemrijk", - "CUPPING_133": "Bloemen", - "CUPPING_134": "Hibiscus", - "CUPPING_135": "Rozenbottels", - "CUPPING_136": "Lavendel", - "CUPPING_137": "Magnolia", - "CUPPING_138": "Jasmijn kamperfoelie", - "CUPPING_139": "Oranjebloesem", - "CUPPING_140": "Citroengras", - "WATER_SECTION": { - "NAV_WATER": "Water", - "YOU_GOT_NO_ARCHIVED_WATER": "Je hebt nog geen water gearchiveerd", - "YOU_GOT_NO_WATER": "Je hebt nog geen water toegevoegd", - "CATEGORY_INFORMATION": "Water informatie", - "CATEGORY_GENERAL": "Algemeen", - "WATER_BOTTLE_EXPLANATION": "Waterflessen vermelden de concentratie meestal in eenheden van ppm = mg\/L", - "USED_TIMES": "Aantal keren gebruikt", - "AMOUNT": "Gebruikte hoeveelheid", - "WATER": { - "GENERAL_HARDNESS": "Algemene hardheid (GH)", - "TOTAL_ALKALINITY": "Totale alkaliteit (KH)", - "CALCIUM": "Kalium (Ca)", - "MAGNESIUM": "Magnesium (Mg)", - "SODIUM": "Natrium (Na)", - "TDS": "Totaal opgeloste vaste stoffen (TDS)", - "UNITS": "Eenheden", - "PLACE_HOLDER": { - "GENERAL_HARDNESS": "Algemene hardheid", - "TOTAL_ALKALINITY": "Totale alkaliteit", - "CALCIUM": "Kalium (Ca)", - "MAGNESIUM": "Magnesium (Mg)", - "SODIUM": "Natrium (Na)", - "TDS": "Totaal opgeloste vaste stoffen (TDS)", - "NAME": "Voeg waternaam toe", - "NOTES": "Voeg wat notities toe voor je water", - "POTASSIUM": "Kalium (K)", - "CHLORIDE": "Chloride (Cl)", - "SULFATE": "Sulfaat (SO4)" - }, - "WATER_UNIT": { - "UNKNOWN": "Onbekend", - "PPM": "ppm als CaCO3", - "MG_L": "mg\/L", - "MMOL_L": "mmol\/L", - "DH": "°dH" - }, - "POTASSIUM": "Kalium (K)", - "CHLORIDE": "Chloride (Cl)", - "SULFATE": "Sulfaat (SO4)" - } - }, - "BREW_BRIX_CALCULATION": "Graden Brix", - "SET_TDS": "TDS instellen", - "TOTAL_WEIGHT": "Totaal gewicht", - "CALCULATED_WEIGHT": "Berekend gewicht", - "SET_WEIGHT": "Gewicht instellen", - "ADD_FLAVORS_AROMAS_TITLE": "Aroma's \/ Smaken", - "CUSTOM_FLAVORS_AROMAS": "Individueel aroma", - "CUSTOM_FLAVORS_AROMAS_PLACEHOLDER": "Voeg je individuele aroma toe", - "PREDEFINED_FLAVORS_AROMAS": "Veel voorkomende aroma's", - "ADD_AROMA_FLAVOR": "Aroma's\/smaken toevoegen", - "BEAN_WEIGHT_IN_PLACEHOLDER": "Bonen uit de verpakking gehaald", - "VESSEL_PLACEHOLDER": "Naam van het Serveerkan en het leeggewicht ervan", - "GRIND_WEIGHT_PLACEHOLDER": "Gewicht van de gemalen bonen die voor het brouwen worden gebruikt", - "PRESET_BREW_TITLE": "Gebruik laatste brouwsel als voorinstelling", - "CUPPING_BREW_TAB_AROMA": "Aroma", - "CUPPING_BREW_TAB_TASTING": "Systematische cupping", - "WATER_PLACEHOLDER": "Activeer het watergedeelte in het instellingenmenu voor volledige functionaliteit", - "PAGE_SETTINGS_SCALES": "Weegschalen", - "CONNECT": "Verbinden", - "DISCONNECT": "Loskoppelen", - "SCALE": { - "BLUETOOTH_SCAN_RUNNING": "Zoeken naar weegschaal tot 60s", - "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", - "CONNECTION_NOT_ESTABLISHED": "Weegschaal niet gevonden, of verbinding kon niet tot stand worden gebracht", - "CONNECTED_SUCCESSFULLY": "Weegschaal verbonden", - "DISCONNECTED_SUCCESSFULLY": "Weegschaal losgekoppeld", - "DISCONNECTED_UNPLANNED": "Weegschaal onverwachts losgekoppeld", - "REQUEST_PERMISSION": { - "LOCATION": "Om Bluetooth-weegschalen te vinden, heeft de app toegang nodig tot de locatie.", - "BLUETOOTH": "Om bluetooth-weegschalen te vinden, heeft de app toegang tot bluetooth nodig" - }, - "INFORMATION_DESCRIPTION": "Ondersteunde weegschalen zijn: Decent Scale, Acaia, Felicita, Hiroia Jimmy, Skale 2, DiFluid Microbalance, Smartchef Scale, Blackcoffee.io, Bookoo Mini Scale en Eureka Precisa. Let op: Als de Eureka Precisa een negatieve waarde ontvangt, stopt de timer" - }, - "QR": { - "WRONG_QRCODE_DESCRIPTION": "Ongeldige QR-code of onbekende inhoud", - "WRONG_QRCODE_TITLE": "Fout", - "WRONG_LINK_DESCRIPTION": "Ongeldige QR-link", - "WRONG_LINK_TITLE": "Fout", - "SERVER": { - "ERROR_OCCURED": "Er is een fout opgetreden. De QR-code kon niet worden gelezen. Probeer het opnieuw.", - "BEAN_NOT_APPROVED": "Boon is nog niet goedgekeurd, probeer het later nog eens" - }, - "BEAN_SUCCESSFULLY_SCANNED": "Bean succesvol gescand", - "BEAN_SUCCESSFULLY_REFRESHED": "Boon succesvol bijgewerkt", - "IMAGES_GETTING_DOWNLOADED": "Afbeeldingen downloaden" - }, - "RETRY_CONNECT": "Verbinding opnieuw proberen", - "SMART_SCALE_STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de weegschaal verbonden, zelfs als de app op de achtergrond draait", - "BREW_FLOW_WEIGHT": "Gewicht", - "BREW_FLOW_WEIGHT_PER_SECOND": "Stroom (afgevlakt)", - "ROAST_TYPE_UNKNOWN": "onbekend", - "ROAST_TYPE_CINNAMON_ROAST": "Cinnamon Branding", - "ROAST_TYPE_AMERICAN_ROAST": "Amerikaans Branding", - "ROAST_TYPE_NEW_ENGLAND_ROAST": "Nieuw-Engeland Branding", - "ROAST_TYPE_HALF_CITY_ROAST": "Half City Branding", - "ROAST_TYPE_MODERATE_LIGHT_ROAST": "Matig-lichte branding", - "ROAST_TYPE_CITY_ROAST": "City Branding", - "ROAST_TYPE_CITY_PLUS_ROAST": "City+ Branding", - "ROAST_TYPE_FULL_CITY_ROAST": "Full City Branding", - "ROAST_TYPE_FULL_CITY_PLUS_ROAST": "Full City + Branding", - "ROAST_TYPE_ITALIAN_ROAST": "Ialiaanse Branding", - "ROAST_TYPE_VIEANNA_ROAST": "Weense Branding", - "ROAST_TYPE_FRENCH_ROAST": "Franse Branding", - "ROAST_TYPE_CUSTOM_ROAST": "Aangepast", - "BEAN_MIX_UNKNOWN": "onbekend", - "BEAN_MIX_SINGLE_ORIGIN": "Single Origin", - "BEAN_MIX_BLEND": "Melange", - "BEAN_ROASTING_TYPE_FILTER": "Filter", - "BEAN_ROASTING_TYPE_ESPRESSO": "Espresso", - "BEAN_ROASTING_TYPE_OMNI": "Omni", - "BEAN_ROASTING_TYPE_UNKNOWN": "Onbekend", - "SMART_SCALE_LOG": "Activeer logbestanden voor slimme weegschaal (alleen voor foutopsporing)", - "TOAST_PREPARATION_TOOL_EDITED_SUCCESSFULLY": "Voorbereidingstool bewerkt", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE": "Bluetooth-weegschaal", - "PAGE_SETTINGS_TAB_GENERAL": "Algemeen", - "SMART_SCALE_TARE_ON_BREW": "Tarraweegschaal op nieuw brouwsel", - "SMART_SCALE_TARE_ON_START_TIMER": "Tarra weegschaal bij het starten van de timer", - "PAGE_SETTINGS_BREW_RATING_STEPS": "Beoordelingsstappen", - "BREW_AVG_FLOW_WEIGHT_PER_SECOND": "Ø Stroom", - "CUSTOM_LIST_VIEW_PARAMETERS": "Parameters voor lijstweergave", - "NAV_LIST_VIEW_CUSTOM_PARAMETERS": "Parameters voor lijstweergave", - "PAGE_LIST_VIEW_CUSTOM_PARAMETERS_DESCRIPTION": "Bepaal welke parameters moeten worden weergegeven op de tegels van de lijstweergave", - "BREW_DATA_VESSEL_NAME_WEIGHT": "Serveerkan Naam\/Gewicht", - "IGNORE_NEGATIVE_VALUES": "Negeer negatieve gewichtswaarden", - "IGNORE_ANOMALY_VALUES": "Negeer afwijkende waarden", - "IGNORE_ANOMALY_VALUES_TOOLTIP": "Bijvoorbeeld: Een kopje rond bewegen op de weegschaal", - "TOAST_BEAN_FAVOURITE_ADDED": "Favoriet toegevoegd", - "TOAST_BEAN_FAVOURITE_REMOVED": "Favoriet verwijderd", - "QR_CODE_SCANNER_INFORMATION_TITLE": "QR-code", - "QR_CODE_SCANNER_INFORMATION_DESCRIPTION": "Alle gescande boneninformatie komt rechtstreeks van de branderij. Mocht u onjuiste of misleidende informatie aantreffen, laat het mij dan weten via e-mail: info@beanconqueror.com.", - "DONT_SHOW_AGAIN": "Niet meer weergeven", - "ARCHIVED_TOOLS": "Gearchiveerd gereedschap", - "UNARCHIVE": "Herstel", - "PAGE_SETTINGS_HIDE_ARCHIVED_BREWS_DASHBOARD": "Toon gearchiveerde brouwsels op dashboard", - "PAGE_SETTINGS_HIDE_ARCHIVED_BREWS_DASHBOARD_DESCRIPTION": "Moeten gearchiveerde brouwsels op de startpagina worden weergegeven?", - "COPY": "Kopiëren", - "TOAST_PREPARATION_METHOD_REPEATED_SUCCESSFULLY": "Bereidingsmethode succesvol gekopieerd", - "PREPARATION_TYPE_CAFEC_FLOWER": "Cafec Flower", - "PREPARATION_TYPE_DECEMBER_DRIPPER": "December Dripper", - "PREPARATION_TYPE_DECENT_ESPRESSO": "Decent Espresso", - "PREPARATION_TYPE_HARIO_SWITCH": "Hario Switch", - "PREPARATION_TYPE_HARIO_WOODNECK": "Hario Woodneck", - "PREPARATION_TYPE_RATIO_SIX_COFFEE_BREWER": "Ratio Six-koffiezetapparaat", - "PREPARATION_TYPE_ROK": "ROK", - "PREPARATION_TYPE_TORNADO_DUO": "Tornado-duo", - "PREPARATION_TYPE_TRICOLATE": "Tricolate", - "QR_CODE_REFRESH_DATA_MESSAGE": "Alle informatie voor deze boon wordt overschreven, doorgaan?", - "POPOVER_QR_CODE_REFRESH": "Gegevens opnieuw laden", - "BREW_FLOW_WEIGHT_REALTIME": "Stroom (realtime)", - "SMART_SCALE_STOP_TIMER_ON_BREW": "Stop de timer van de weegschaal bij een nieuw brouwsel", - "SMART_SCALE_RESET_TIMER_ON_BREW": "Reset de weegschaaltimer bij een nieuw brouwsel", - "BREW_PRESSURE_FLOW": "Druk", - "BREW_TEMPERATURE_REALTIME": "Temperatuur", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_SHOW_GRAPHS_FILTER": "Grafieken weergeven voor filter", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_SHOW_GRAPHS_ESPRESSO": "Toon grafieken voor espresso", - "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE": "Drukapparaat", - "PAGE_SETTINGS_TAB_BLUETOOTH_TEMPERATURE": "Temperatuur apparaat", - "PRESSURE_LOG": "Activeer logbestanden voor drukapparaat", - "PRESSURE_THRESHOLD_ACTIVE": "Starttimer met vooraf gedefinieerde druk", - "PRESSURE_THRESHOLD_BAR": "Drempelwaarde druk", - "TIMER_MILLISECONDS": "MS", - "PAGE_SETTINGS_BREW_ENABLE_MILLISECONDS": "Milliseconden?", - "PAGE_SETTINGS_BREW_ENABLE_MILLISECONDS_DESCRIPTION": "Gebruik milliseconden om uw brouwsels nog nauwkeuriger te analyseren", - "PAGE_SETTINGS_BEAN_RATING": "Bonen beoordeling", - "PAGE_SETTINGS_BEAN_RATING_TOOLTIP": "Is de standaard '0 tot 5' niet de juiste beoordeling voor u? U kunt in plaats daarvan een '0 tot 100'-schaal gebruiken", - "PAGE_SETTINGS_BEAN_RATING_STEPS": "Stappen voor het beoordelen van bonen", - "COFFEE_GRAMS_BREWED": "grammen gebrouwen", - "SMART_SCALE_MAXIMIZE_ON_START_TIMER": "Maximaliseer realtime-grafiek bij het starten van de timer", - "PRESSURE": { - "CONNECTION_NOT_ESTABLISHED": "Drukapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", - "CONNECTED_SUCCESSFULLY": "Drukapparaat aangesloten", - "DISCONNECTED_SUCCESSFULLY": "Drukapparaat losgekoppeld", - "DISCONNECTED_UNPLANNED": "Drukapparaat onverwachts losgekoppeld", - "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd het drukapparaat aangesloten, zelfs als de app op de achtergrond draait", - "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: Popsicle, Pressensor, Smart Espresso Profiler, Bookoo Espresso Monitor", - "BLUETOOTH_SCAN_RUNNING": "Zoeken naar drukapparaat gedurende maximaal 60 seconden", - "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", - "REQUEST_PERMISSION": { - "LOCATION": "Om drukapparaten te vinden, heeft de app toegang nodig tot de locatie.", - "BLUETOOTH": "Om drukapparaten te vinden, heeft de app toegang tot Bluetooth nodig" - } - }, - "POPOVER_BLUETOOTH_ACTION_RECONNECT_SCALE": "Weegschaal opnieuw verbinden", - "POPOVER_BLUETOOTH_ACTION_RECONNECT_PRESSURE_DEVICE": "Drukapparaat opnieuw aansluiten", - "POPOVER_SHOW_BREWS": "Toon brouwsels", - "LAST_USED_GRIND_SIZE_SETTING": "Laatste maalstand", - "LAST_USED_BEAN": "Laatste boon", - "PAGE_SETTINGS_BREW_MILLISECONDS_DECIMAL_PLACES_DESCRIPTION": "Hoeveel decimalen moeten er worden weergegeven?", - "SMART_SCALE_COMMAND_DELAY": "Opdracht vertraging", - "SMART_SCALE_COMMAND_DELAY_TOOLTIP": "Hoeveel tijd moet er verstrijken tussen elk bluetooth-commando?", - "SUPPORT_ME": "Donatie", - "PAGE_SETTINGS_BREW_DISPLAY_BEAN_IMAGE": "Bonenafbeeldingen op brouwsels weergeven?", - "PAGE_SETTINGS_BREW_DISPLAY_BEAN_IMAGE_DESCRIPTION": "Als er een bonenafbeelding bestaat, wordt deze gebruikt in plaats van de afbeelding van de bereidingsmethode", - "DOWNLOAD_XLSX": "Excel downloaden", - "DOWNLOAD_JSON": "JSON downloaden", - "NAV_BEAN_PARAMS": "Boon Parameters", - "BEAN_DATA_ROAST_NAME_TYPE": "Brand graad", - "ENABLE_BEAN_SORT_INFORMATION": "Variëteit-informatie inschakelen", - "BEAN_SORT_MIX": "Bonenmix", - "PAGE_MANAGE_BEAN_PARAMETERS_DESCRIPTION": "Markeer welke parameters moeten worden weergegeven bij het bewerken van bean-informatie.", - "PAGE_BEAN_LIST_VIEW_CUSTOM_PARAMETERS_DESCRIPTION": "Bepaal de parameters die moeten worden weergegeven in lijstweergaven voor bonen", - "BEAN_DATA_NAME_TOOLTIP": "De naam van de bonen", - "BEAN_DATA_ROASTER_TOOLTIP": "Wie is de brander", - "BEAN_DATA_BUY_DATE_TOOLTIP": "Wanneer heb je de bonen gekocht?", - "BEAN_DATA_ROASTING_DATE_TOOLTIP": "Wat is de branddatum van de bonen?", - "BEAN_DATA_ROASTING_TYPE_TOOLTIP": "Voor welke bereidingswijze is deze boon geroosterd, bijvoorbeeld Filter", - "BEAN_DATA_ROAST_NAME_TOOLTIP": "Wat is de brandingsgraad van de bonen?", - "BEAN_DATA_ROAST_NAME_TYPE_TOOLTIP": "Welk type branding (Cinnamon, New England, etc.)", - "BREW_DATA_RATING_TOOLTIP": "Je waardering", - "BEAN_SORT_MIX_TOOLTIP": "Zijn de bonen een melange?", - "BEAN_DATA_WEIGHT_TOOLTIP": "Hoeveel wegen de bonen?", - "BEAN_DATA_COST_TOOLTIP": "Hoeveel hebben de bonen gekost?", - "BEAN_DATA_AROMATICS_TOOLTIP": "Welke aroma's\/smaken hebben de bonen?", - "BEAN_DATA_CUPPING_POINTS_TOOLTIP": "Hoeveel cupping-punten heeft de boon?", - "BEAN_DATA_DECAFFEINATED_TOOLTIP": "Is het cafeïnevrij?", - "BEAN_DATA_URL_TOOLTIP": "URL naar de winkel", - "BEAN_DATA_EAN_TOOLTIP": "Het EAN\/artikelnummer", - "NOTES_TOOLTIP": "Aantekeningen gemaakt", - "BREW_DATA_ATTACHMENTS_TOOLTIP": "Foto's toevoegen?", - "ENABLE_BEAN_SORT_INFORMATION_TOOLTIP": "Meer informatie over de bonen: waar komen ze vandaan, wanneer zijn ze geoogst, etc.", - "BEAN_DATA_COUNTRY_TOOLTIP": "Uit welk land komen de bonen?", - "BEAN_DATA_REGION_TOOLTIP": "Uit welke regio komen de bonen?", - "BEAN_DATA_FARM_TOOLTIP": "Van welke boerderij komen de bonen?", - "BEAN_DATA_FARMER_TOOLTIP": "Wie verbouwde deze bonen", - "BEAN_DATA_ELEVATION_TOOLTIP": "Op welke hoogte groeiden de bonen?", - "BEAN_DATA_PROCESSING_TOOLTIP": "Hoe zijn de bonen verwerkt (natuurlijk, gewassen, enz.)", - "BEAN_DATA_VARIETY_TOOLTIP": "De Koffieboon Variëteit (SL28 bv.)", - "BEAN_DATA_HARVEST_TIME_TOOLTIP": "In welk jaar\/maand werden deze bonen geoogst?", - "BEAN_DATA_PERCENTAGE_TOOLTIP": "Hoeveel procent van deze bonen zit er in de zak?", - "BEAN_DATA_CERTIFICATION_TOOLTIP": "Welke certificeringen hebben de bonen (bijvoorbeeld fairtrade)", - "BEAN_DATA_PURCHASING_PRICE_TOOLTIP": "Wat was de aankoopprijs van de koffiebrander", - "BEAN_DATA_FOB_PRICE_TOOLTIP": "Wat was de Free-On-Board (FOB) prijs toen de brander het kocht?", - "BEAN_PARAMETER_CUSTOMIZE_TITLE": "Pas de informatie aan die u voor bonen wilt gebruiken", - "BEAN_PARAMETER_CUSTOMIZE_DESCRIPTION": "Er kan veel informatie over de bonen worden ingevoerd of gebruikt. Kies zelf de parameters die u wilt invullen en welke u wilt weergeven", - "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_TITLE": "Timer resetten!", - "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_DESCRIPTION": "Omdat je een Bluetooth-apparaat hebt aangesloten, moet je eerst je timer resetten voordat je kunt beginnen.", - "BREW_FILTER_JUST_CHART_DATA": "Alleen grafieken", - "SCALE_RESET_TRIGGERED_DESCRIPTION": "De bluetooth weegschaal wil zowel de app-timer als de brouwgrafiek resetten, wil je doorgaan?", - "SCALE_RESET_TRIGGERED_TITLE": "Opnieuw instellen?", - "NAV_REPEAT_PARAMETERS": "Herhalingsparameters definiëren", - "PAGE_REPEAT_PARAMETERS_DESCRIPTION": "Markeer welke parameters vooraf moeten worden ingesteld wanneer u een specifieke brouwbeurt herhaalt", - "CUSTOM_REPEAT_PARAMETERS": "Herhalen", - "CUSTOM_REPEAT_PARAMETERS_DESCRIPTION": "Aangepaste herhaling activeren?", - "PAGE_SETTINGS_USE_NUERMIC_KEYBOARD_FOR_GRIND_SIZE": "Numeriek toetsenbord voor maalinstelling?", - "PAGE_SETTINGS_USE_NUERMIC_KEYBOARD_FOR_GRIND_SIZE_DESCRIPTION": "Wilt u een numeriek toetsenbord gebruiken voor de maalinstelling, in plaats van het hele toetsenbord?", - "PREPARATION_DEVICE": { - "TYPE": { - "NONE": "Geen", - "XENIA": "Xenia", - "METICULOUS": "Meticulous" - }, - "URL": "URL-adres", - "CHOOSE_DEVICE": "Kies apparaat", - "CONNECTION": { - "UNSUCCESFULLY": "Er kon geen verbinding met de machine worden gemaakt", - "SUCCESFULLY": "Verbinding met machine was succesvol" - }, - "TYPE_XENIA": { - "TITLE": "Xenia machine", - "PRESS_START_SCRIPT": "Start script bij start", - "FIRST_DRIP_SCRIPT": "Start script bij eerste druppel", - "SCRIPT_AT_WEIGHT": "Gewicht voor scriptuitvoering", - "SCRIPT_LIST_GENERAL_0": "Niets", - "SCRIPT_LIST_GENERAL_1": "Espresso, 25 seconden", - "SCRIPT_LIST_GENERAL_2": "Espresso, eindeloos", - "SCRIPT_LIST_GENERAL_STOP": "Schot stoppen", - "CHOOSE_SCRIPT_AT_WEIGHT": "Kies script voor gewicht bereikt", - "ERROR_NOT_ALL_SCRIPTS_FOUND": "Een of meer scripts konden niet worden gevonden, ze zijn gereset", - "ERROR_CONNECTION_COULD_NOT_BE_ESTABLISHED": "De verbinding met de xenia espressomachine kon niet tot stand worden gebracht. Controleer of u zich op het juiste netwerk (LAN) bevindt, of u het juiste IP-adres hebt ingevoerd, etc.", - "CHECKING_CONNECTION_TO_PORTAFILTER": "Verbinding met Xenia wordt gecontroleerd", - "GRABING_SCRIPTS": "Scripts laden vanuit Xenia", - "BREW_BY_WEIGHT_ACTIVE": "Brouwen op gewicht actief" - }, - "API_VERSION": "Api-versie", - "RESIDUAL_LAG_TIME": "Resterende vertragingstijd", - "RESIDUAL_LAG_TIME_DESCRIPTION": "Stel de tijd in die overeenkomt met het resterende water. Met een naakte portafilter heb je een lagere tijd nodig, met een tuit een hogere. Hoe langzamer uw weegschaal het gewicht rapporteert, hoe meer tijd u nodig heeft", - "TYPE_METICULOUS": { - "TITLE": "Meticulous machine", - "NO_PROFILE": "Geen profiel", - "CHOOSE_PROFILE": "Profiel kiezen", - "SHOT_STARTED": "Brouwen gestart", - "SHOT_ENDED": "Brouwen gestopt" - } - }, - "DEVICE_CONNECTION": "Apparaatverbinding", - "PREPARATION_DEVICE_CONNECTION": "Apparaatverbinding", - "MANUAL_EXPORT_TO_VISUALIZER": "Exporteren naar Visualizer", - "ONLY_FAVOURITES": "Alleen favorieten", - "TEMPERATURE": { - "CONNECTION_NOT_ESTABLISHED": "Temperatuurapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", - "CONNECTED_SUCCESSFULLY": "Temperatuurapparaat aangesloten", - "DISCONNECTED_SUCCESSFULLY": "Temperatuurapparaat losgekoppeld", - "DISCONNECTED_UNPLANNED": "Temperatuurapparaat onverwachts losgekoppeld", - "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de thermometer verbonden, zelfs als de app op de achtergrond staat", - "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: ETI Ltd BLE-thermometers (ThermaQ Blue, BlueTherm, enz.), Combustion Inc., Meater (niet Meater+ of Meater 2)", - "BLUETOOTH_SCAN_RUNNING": "Zoeken naar temperatuurapparaat gedurende maximaal 60 seconden", - "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", - "REQUEST_PERMISSION": { - "LOCATION": "Om temperatuurmeters te vinden, heeft de app toegang nodig tot de locatie.", - "BLUETOOTH": "Om temperatuurapparaten te vinden, heeft de app toegang tot Bluetooth nodig" - }, - "LOG": "Logbestanden voor temperatuurapparaat activeren", - "THRESHOLD_ACTIVE": "Start timer met vooraf ingestelde temperatuur", - "THRESHOLD_TEMP": "Drempel temperatuur" - }, - "POPOVER_BLUETOOTH_ACTION_RECONNECT_TEMPERATURE_DEVICE": "Temperatuurapparaat opnieuw aansluiten", - "PRESSURE_DEVICE_JUST_VISIBLE_ON_ESPRESSO": "Drukapparaat is alleen bruikbaar bij de bereidingswijze 'Espresso'", - "PRESSURE_MESSAGE_AFTER_CONNECTION": "Bekend gedrag (in analyse): Houd er rekening mee dat het langer kan duren om verbinding te maken nadat u uw telefoon opnieuw hebt opgestart of wanneer u de app langere tijd niet hebt gebruikt. Na deze tijd zou het verbindingsprobleem opgelost moeten zijn.", - "SMART_SCALE_ACAIA_HEARTBEAT_TIMER": "Hartslagtimer - Speciaal voor Acaia Scales", - "SMART_SCALE_ACAIA_HEARTBEAT_TIMER_TOOLTIP": "Alleen gebruikt voor Acaia-weegschalen! - Oudere Acaia-weegschalen hebben een hartslagsignaal nodig. Als u problemen ondervindt, probeer dan de hartslag op een hogere frequentie in te stellen.", - "SHARE_BEAN_URL": "Delen als URL", - "SHARE_BEAN_IMAGE": "Delen als afbeelding", - "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE": "Espresso - Automatisch stoppen met brouwen", - "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE_DESCRIPTION": "Deze instelling wordt alleen gebruikt voor brouwsels van het type 'espresso'. Het brouwsel wordt automatisch gestopt wanneer er geen flow wordt gedetecteerd.", - "BREW_DATA_BREW_QUANTITY_TOOLTIP_BREW_RATIO": "De zetverhouding wordt berekend met deze waarde voor alle brouwsels, maar niet voor type 'espresso'.", - "BREW_DATA_BREW_BEVERAGE_QUANTITY_TOOLTIP_BREW_RATIO": "De zetverhouding wordt alleen met deze waarde berekend voor brouwsels van het type 'espresso'", - "SMART_SCALE_DID_NOT_SEND_ANY_WEIGHT_DESCRIPTION": "Het lijkt erop dat de bluetooth weegschaal niet goed is aangesloten. Dit gebeurt meestal op iOS-apparaten met Acaia weegschalen, sluit de weegschaal opnieuw aan en zorg ervoor dat de gewichtstegel wordt bijgewerkt.", - "SMART_SCALE_DID_NOT_SEND_ANY_WEIGHT_TITLE": "Geen gewichtswaarden?", - "SMART_SCALE_ESPRESSO_STOP_ON_NO_WEIGHT_CHANGE_MIN_FLOW_DESCRIPTION": "De stroomsnelheid waarbij het zetten moet worden gestopt. Het zetten wordt pas gestopt als er minimaal 5 seconden zijn verstreken, er 5 gram in de kop zit of als u het gewicht van de gemalen koffie hebt ingevoerd - er is minimaal een zetverhouding van 1:1 bereikt (bijv.: 18 g erin, 18 g eruit). Nadat aan deze voorwaarden is voldaan, wordt de hier ingestelde minimale stroomsnelheid gecontroleerd", - "ONLY_BEST_BREWS": "Alleen de beste brouwsels", - "POPOVER_BEST_BREW": "Beste brouwsel", - "PAGE_SETTINGS_BEST_BREW": "Beste brouwsels activeren", - "PAGE_SETTINGS_BEST_BREW_DESCRIPTION": "Markeer je beste brouwsel voor een specifieke boon. Elke boon kan één beste brouwsel hebben in plaats van meerdere favorieten.", - "PAGE_SETTINGS_TAB_BLUETOOTH_REFRACTOMETER": "Refractometer apparaat", - "REFRACTOMETER": { - "CONNECTION_NOT_ESTABLISHED": "Refractometerapparaat niet gevonden, of verbinding kon niet tot stand worden gebracht", - "CONNECTED_SUCCESSFULLY": "Refractometerapparaat aangesloten", - "DISCONNECTED_SUCCESSFULLY": "Refractometerapparaat losgekoppeld", - "DISCONNECTED_UNPLANNED": "Refractometerapparaat onverwachts losgekoppeld", - "STAY_CONNECTED_ON_APP_MINIMIZE": "Houd de refractometer verbonden, zelfs als de app op de achtergrond draait", - "INFORMATION_DESCRIPTION": "Ondersteunde apparaten zijn: DiFluid R2", - "BLUETOOTH_SCAN_RUNNING": "Zoeken naar refractometer-apparaat gedurende maximaal 60 seconden", - "BLUETOOTH_NOT_ENABLED": "Bluetooth niet geactiveerd, activeer het om het goed te laten werken", - "REQUEST_PERMISSION": { - "LOCATION": "Om refractometerapparaten te vinden, heeft de app toegang nodig tot de locatie.", - "BLUETOOTH": "Om refractometerapparaten te vinden, heeft de app toegang tot Bluetooth nodig" - }, - "LOG": "Activeer logbestanden voor refractometerapparaat", - "READ_END": "Test voltooid - resultaat ontvangen" - }, - "COPIED_TO_CLIPBOARD_SUCCESSFULLY": "Toegevoegd aan klembord", - "COPIED_TO_CLIPBOARD_UNSUCCESSFULLY": "Kan niet worden toegevoegd aan het klembord", - "PAGE_SETTINGS_LANGUAGE_FRENCH": "Frans", - "ANDROID_EXTERNAL_FILE_ACCESS_NOT_POSSIBLE_TITLE": "Gegevens kunnen niet worden opgeslagen vanwege Android-beperkingen", - "ANDROID_EXTERNAL_FILE_ACCESS_NEEDED_DESCRIPTION": "Je Android-telefoon ondersteunt geen externe bestandssystemen, dus je moet het ZIP-bestand downloaden zonder mediabestanden. Ga voor meer informatie naar https:\/\/beanconqueror.com\/faq.", - "PAGE_SETTINGS_SECURITY_CHECK_WHEN_GOING_BACK": "Beveiligingsbericht voor afsluiten?", - "PAGE_SETTINGS_SECURITY_CHECK_WHEN_GOING_BACK_DESCRIPTION": "Controleer of de gegevens zijn gewijzigd bij het toevoegen\/bewerken van bonen of brouwsels; als dat het geval is, wordt er een veiligheidswaarschuwing weergegeven bij het teruggaan.", - "PAGE_BEANS_DISCARD_CONFIRM": "Boon informatie is gewijzigd. Weet je zeker dat je de pagina wilt verlaten zonder op te slaan?", - "PAGE_BREW_DISCARD_CONFIRM": "De brouw informatie is gewijzigd. Weet je zeker dat je de pagina wilt verlaten zonder op te slaan?", - "NO_ENTRIES_FOUND": "Geen vermeldingen gevonden", - "POPOVER_BEANS_OPTION_REPEAT": "Herhaal laatste brouwsel", - "REPEAT_LAST_BREW": "Herhaal laatste brouwsel", - "REPEAT_BEST_BREW": "Herhaal beste brouwsel", - "PAGE_SETTINGS_VISUALIZER_SECTION": "Visualizer", - "VISUALIZER": { - "ACTIVATE": "Visualizer activeren", - "CHOOSE_SERVER": "Server kiezen", - "CONNECTION": { - "UNSUCCESSFULLY": "Er kon geen verbinding tot stand worden gebracht.", - "SUCCESSFULLY": "Verbinding kon tot stand worden gebracht." - }, - "SERVER": { - "VISUALIZER": "Visualizer-server", - "CUSTOM": "Aangepaste server" - }, - "SHOT": { - "UPLOAD_SUCCESSFULLY": "Brouwen geüpload naar visualizer.", - "UPLOAD_UNSUCCESSFULLY": "Brouwen kon niet worden geüpload naar de Visualizer." - }, - "URL": "Server-URL", - "USERNAME": "Gebruikersnaam", - "PASSWORD": "Wachtwoord", - "UPLOAD_AUTOMATIC": "Elke brouwsessie automatisch uploaden?", - "UPLOAD_AUTOMATIC_TOOLTIP": "Zorg ervoor dat u een actieve internetverbinding hebt wanneer u uw brouwsel opslaat.", - "UPLOAD_ALL": "Alle brouwsels uploaden", - "NOT_ALL_SHOTS_UPLOADED": "Niet alle brouwsels konden worden geüpload", - "ALL_SHOTS_UPLOADED": "Alle brouwsels zijn geüpload" - }, - "SMART_SCALE_AUTO_START_LISTENING": "Timer automatisch starten?", - "SMART_SCALE_AUTO_START_LISTENING_DESCRIPTION": "Start de timer automatisch bij het bereiken van de volgende gewichtswaarde", - "CHOOSE_REFERENCE_GRAPH": "Referentiegrafiek selecteren", - "RESET": "Opnieuw instellen", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_AXIS": "Definieer de beginassen van de grafiek", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_AXIS_DESCRIPTION": "Stel de begingrootte van de assen in voor zowel filter- als espressokoffie.", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_FILTER_WEIGHT": "Filter - Gewicht", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_FILTER_FLOW": "Filter - Doorstroming", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_ESPRESSO_WEIGHT": "Espresso - Gewicht", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_ESPRESSO_FLOW": "Espresso - Doorstroming", - "SMART_SCALE_IGNORE_INCOMING_WEIGHT": "Negeer huidige gewichtsoverdracht ", - "SMART_SCALE_IGNORE_INCOMING_WEIGHT_TOOLTIP": "Er verschijnt een nieuwe knop in het brouwgedeelte, die nieuwe gewichtswaarden van de bluetooth weegschaal zal negeren.", - "BREWS_ACTIVE": "Actieve brouwsels", - "BREWS_ARCHIVED": "Gearchiveerde brouwsels", - "GRAPHS": "Grafieken", - "GRAPH_SECTION": { - "NAV_GRAPH": "Grafieken", - "NO_ARCHIVED_ENTRIES": "Geen gearchiveerde vermeldingen", - "NO_ENTRIES": "Geen vermeldingen", - "SECTION_HAS_BEEN_ACTIVATED": "Grafieksectie is geactiveerd" - }, - "TOAST_GRAPH_ARCHIVED_SUCCESSFULLY": "Grafiek gearchiveerd", - "TOAST_GRAPH_DELETED_SUCCESSFULLY": "Grafiek verwijderd", - "TOAST_GRAPH_EDITED_SUCCESSFULLY": "Grafiek bewerkt", - "TOAST_GRAPH_ADD_SUCCESSFULLY": "Grafiek toegevoegd", - "NAV_GRAPH_SECTION": "Grafieken", - "DELETE_GRAPH_QUESTION": "Wilt u deze grafiek verwijderen?", - "PAGE_SETTINGS_SHOW_ARCHIVED_GRAPHS": "Gearchiveerde grafieken weergeven", - "PAGE_SETTINGS_SHOW_GRAPH_SECTION": "Grafieksectie activeren", - "EDIT_GRAPH": "Grafiek bewerken", - "ADD_GRAPH": "Grafiek toevoegen", - "GRAPH": { - "PLACE_HOLDER": { - "NAME": "Grafiek naam", - "NOTES": "Notities" - }, - "UPLOAD": "Grafiek uploaden", - "DELETE": "Grafiek verwijderen", - "UPLOAD_DESCRIPTION": "Importeer een .JSON-bestand dat u kunt downloaden in de brew-detailweergave. U kunt ook gedeelde grafieken van de community importeren die van het type .JSON zijn." - }, - "SHOW_VISUALIZER": "Visualiseerder weergeven", - "NO_BREWS_FOUND": "Geen brouwsels gevonden", - "NO_GRAPHS_FOUND": "Geen grafieken gevonden", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_AXIS": "Definieer de maximale tijdsas van de grafiek", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_DESCRIPTION": "Stel het maximum aantal seconden in op de tijd-as voor zowel filterkoffie als espresso.", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_FILTER_AXIS_NORMAL_SCREEN": "Filter - Normaal scherm", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_FILTER_AXIS_FULL_SCREEN_SCREEN": "Filter - Volledig scherm", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_ESPRESSO_AXIS_NORMAL_SCREEN": "Espresso - Normaal scherm", - "PAGE_SETTINGS_TAB_BLUETOOTH_SCALE_GRAPHS_TIME_ESPRESSO_AXIS_FULL_SCREEN_SCREEN": "Espresso - Volledig scherm", - "PAGE_SETTINGS_DATE_FORMAT": "Datum notatie", - "PAGE_SETTINGS_LANGUAGE_FRANCE": "Frans", - "PAGE_SETTINGS_LANGUAGE_INDONESIA": "Indonesisch", - "EXTRACTION_CHART_TITLE": "Extractie grafiek", - "PAGE_SETTINGS_SHOW_BACKUP_ISSUES": "Back-up problemen weergeven", - "PAGE_SETTINGS_SHOW_BACKUP_ISSUES_DESCRIPTION": "Geef een pop-up weer als er geen back-ups naar het bestandssysteem kunnen worden geschreven", - "AUTOMATIC_BACKUP_DID_FAIL": "Automatische back-up werkte niet, zorg ervoor dat u werkende back-ups hebt! Deze informatie kan worden uitgeschakeld in de instellingen", - "INTERNAL_BACKUP_DID_FAIL": "Interne back-up werkte niet, zorg ervoor dat u werkende back-ups hebt! Deze informatie kan worden uitgeschakeld in de instellingen", - "ZIP_BACKUP_FILE_COULD_NOT_BE_BUILD": "ZIP-bestand kon niet worden opgeslagen! Deze informatie kan worden uitgeschakeld in de instellingen", - "SEND_LOGS": "Logboeken verzenden", - "POPOVER_BLUETOOTH_ACTION_RECONNECT_REFRACTOMETER": "Sluit refractometer apparaat opnieuw aan", - "PAGE_SETTINGS_LANGUAGE_ITALIAN": "Italiaans", - "PAGE_SETTINGS_LANGUAGE_POLISH": "Pools", - "BREW_CANT_START_BECAUSE_TIMER_NOT_RESETTED_GENERAL_DESCRIPTION": "Je moet eerst je timer resetten voordat je kunt beginnen.", - "SMART_SCALE_FIRST_DRIP_THRESHOLD": "Eerste druppel drempel", - "SMART_SCALE_FIRST_DRIP_THRESHOLD_TOOLTIP": "Bij welk weegschaalgewicht moet de eerste druppel worden geteld? Standaard: >= 0,1g", - "PAGE_SETTINGS_BREW_TIMER_START_DELAY_ACTIVE": "Zetvertraging starten", - "PAGE_SETTINGS_BREW_TIMER_START_DELAY_ACTIVE_DESCRIPTION": "Stel een vertragingstijd in die een laadspinner weergeeft totdat het brouwen begint", - "STARTING_IN": "Beginnend in ... {{time}}", - "IOS_DATABASE_ISSUE_TITLE": "ATTENTIE !!!!! - DATABASEVERBINDING VERLOREN", - "IOS_DATABASE_ISSUE_DESCRIPTION": "Het spijt ons u te moeten meedelen dat de verbinding met de database is verbroken. Dit probleem is het gevolg van een onopgeloste bug in het systeem van Apple, waarover Beanconqueror geen controle heeft. Om mogelijk gegevensverlies te voorkomen, verzoeken wij u vriendelijk de Beanconqueror-applicatie onmiddellijk geforceerd af te sluiten en opnieuw te openen.", - "RELOAD_APP": "Herstart de app", - "WATER_TYPE_ADD_CUSTOM": "Water op maat", - "WATER_TYPE_THIRD_WAVE_WATER_CLASSIC_LIGHT_ROAST_PROFILE": "Third Wave Water - Klassiek licht geroosterd profiel", - "WATER_TYPE_THIRD_WAVE_WATER_MEDIUM_ROAST_PROFILE": "Third Wave Water - Middel geroosterd profiel", - "WATER_TYPE_THIRD_WAVE_WATER_DARK_ROAST_PROFILE": "Third Wave Water - Donker geroosterd profiel", - "WATER_TYPE_THIRD_WAVE_WATER_ESPRESSO_MACHINE_PROFILE": "Third Wave Water - Espressomachine Profiel", - "WATER_TYPE_THIRD_WAVE_WATER_COLD_BREW_PROFILE": "Third Wave Water - koud brouwprofiel", - "WATER_TYPE_THIRD_WAVE_WATER_LOW_ACID_PROFILE": "Third Wave Water - Laag Zuurprofiel", - "ADD_WATER": "Voeg water toe", - "EXTRACTION_CHART_LABEL_STRONG_UNDEREXTRACTED": "STERK
onderextractie", - "EXTRACTION_CHART_LABEL_STRONG": "Strong
", - "EXTRACTION_CHART_LABEL_STRONG_HARSH": "STERK
ruw", - "EXTRACTION_CHART_LABEL_UNDEREXTRACTED": "ondergeëxtraheerd", - "EXTRACTION_CHART_LABEL_IDEAL": "IDEAAL", - "EXTRACTION_CHART_LABEL_HARSH": "ruw", - "EXTRACTION_CHART_LABEL_WEAK_UNDEREXTRACTED": "ZWAK
onderextractie", - "EXTRACTION_CHART_LABEL_WEAK": "ZWAK
", - "EXTRACTION_CHART_LABEL_WEAK_HARSH": "ZWAK
ruw", - "PAGE_SETTINGS_TEXT_TO_SPEECH_SECTION": "Tekst naar spraak", - "TEXT_TO_SPEECH": { - "ACTIVATE": "Activeer tekst naar spraak", - "BREW_STARTED": "Brouwen gestart", - "BREW_ENDED": "Einde brouwen", - "TIME": "Tijd", - "SPEAK_EVERY_MS": "Spreek elke geselecteerde milliseconde", - "FOLLOWING_NUMBERS_WILL_BE_TEST_SPOKEN": "De volgende nummers worden als test uitgesproken", - "TEST_SPEAK": "Start test spraak", - "PITCH": "Toonhoogte", - "RATE": "beoordeling" - }, - "PAGE_SETTINGS_HAPTIC_FEEDBACK_SECTION": "Haptische feedback", - "HAPTIC_FEEDBACK": { - "ACTIVATE": "Activeer haptische feedback", - "BREW_STARTED": "Trillen bij het starten van het brouwen", - "BREW_STOPPED": "Trillen bij het stoppen van het brouwen", - "TARE": "Trillen bij tarra van de weegschaal" - }, - "CONNECTED": "Verbonden", - "DISCONNECTED": "Losgekoppeld", - "EXPERIMENTAL_FEATURE_DISCLAIMER": "Dit is een experimentele functie", - "SHOW_HOURS": "Toon uren", - "SHOW_MINUTES": "Toon Minuten", - "BEANS_UNARCHIVE": "uit het archief halen", - "TOAST_BEAN_UNARCHIVED_SUCCESSFULLY": "Boon is uit het archief gehaald", - "WATER_TYPE_PURE_COFFEE_WATER": "Zuiver Koffiewater", - "WATER_TYPE_EMPIRICAL_WATER_GLACIAL": "empirical water GLACIAL", - "WATER_TYPE_EMPIRICAL_WATER_SPRING": "empirical water SPRING", - "SORT_PREPARATION_TOOLS": "Sorteer bereidingsmiddelen", - "PREPARATION_TYPE_METICULOUS": "Meticulous", - "EXPORT_CAUTION": "Exporteren exporteert alleen de database, geen afbeeldingen, geen stromingsprofielen . Als deze nodig zijn, ga dan naar Gitbook voor meer informatie", - "POPOVER_FREEZE_COFFEE_BEAN": "Bevries koffieboon", - "POPOVER_UNFREEZE_COFFEE_BEAN": "Koffieboon ontdooien", - "BEAN_POPOVER_EDIT_FREEZE_DATE": "invries datum bewerken", - "BEAN_POPOVER_EDIT_UNFREEZE_DATE": "ontdooi datum bewerken", - "BEAN_POPOVER_LEFT_UNFROZEN": "Niet ingevroren", - "BEAN_POPOVER_FREEZE_PARTIAL_BAG": "Gedeelte zak invriezen (g)", - "FROZEN_BEANS": "Bevroren", - "BEAN_TAB_FROZEN_INFORMATION": "Bevroren notities", - "BEAN_POPOVER_FROZEN_BAGS": "Bevroren zakken", - "BEAN_POPOVER_FROZEN_DELETE_BEAN_MESSAGE": "Je gaat de hele zak invriezen en we hebben geen brouwsels gevonden die ermee gemaakt zijn, wil je de originele zak verwijderen?", - "CREATE_FROZEN_BEANS": "creëer bonen", - "BEAN_POPOVER_COPY_ATTACHMENTS": "Kopieer bijlagen", - "BEAN_POPOVER_COPY_ATTACHMENTS_DESCRIPTION": "Het kopiëren van bijlagen is aan het begin van deze functie gedeactiveerd", - "BEAN_DATA_FROZEN_DATE": "Invries datum", - "BEAN_DATA_UNFROZEN_DATE": "ontdooi datum", - "PAGE_BEANS_LIST_YOU_GOT_NO_FROZEN_BEANS": "Je hebt geen ingevroren bonen", - "BEAN_DATA_FROZEN_ID": "Ingevroren id", - "PAGE_SETTINGS_MANAGE_FEATURES": "Functies beheren", - "ACTIVE_BEAN_FREEZING_FEATURE": "Activeer het invriezen van bonen", - "NAV_FROZEN_BEANS_LIST": "Lijst met ingevroren bonen", - "BEAN_BREW_LIST_VIEW_PARAMETERS": "Boon informatie voor brouwen", - "BEAN_AGE_BY_BREW_DATE": "Leeftijd van de bonen op brouwdatum", - "BEAN_POPOVER_FROZEN_BEAN_WILL_BE_ARCHIVED_NOW_MESSAGE": "Je diepvrieszakken hebben als resultaat dat je originele zak geen gewicht meer heeft, maar je hebt er wel mee gebrouwen, dus beoordeel en stuur naar het archief.", - "BEAN_POPOVER_YOU_CANT_FREEZE_WITH_ZERO_WEIGHT_LEFT": "Je kunt niet bevriezen, want het restgewicht van je zak is nul", - "BEAN_DATA_BEST_DATE": "Beste Bonen Datum", - "BEAN_DATA_BEST_DATE_TOOLTIP": "Wanneer is de beste datum om de bonen te gebruiken?", - "BEAN_DATA_OPEN_DATE": "Openingsdatum van de zak", - "BEAN_DATA_OPEN_DATE_TOOLTIP": "Wanneer heb je de zak bonen geopend?", - "BEAN_FREEZING_STORAGE_TYPE_UNKNOWN": "Onbekend", - "BEAN_FREEZING_STORAGE_TYPE_COFFEE_BAG": "Koffiezak", - "BEAN_FREEZING_STORAGE_TYPE_COFFEE_JAR": "Koffie pot", - "BEAN_FREEZING_STORAGE_TYPE_ZIP_LOCK": "Ritssluiting", - "BEAN_FREEZING_STORAGE_TYPE_VACUUM_SEALED": "Vacuüm verzegeld", - "BEAN_FREEZING_STORAGE_TYPE_TUBE": "Buis", - "BEAN_DATA_FROZEN_STORAGE_TYPE": "Vriezer opslagtype", - "PAGE_SETTINGS_BREW_RATING_CHANGED_BREWS_NOT_VISIBLE": "U heeft de maximale beoordeling van uw brouwsels gewijzigd, maar u heeft uw brouwsels al hoger beoordeeld dan uw werkelijke maximum. Deze worden dus niet weergegeven bij de normale filterinstellingen.", - "PAGE_SETTINGS_BEAN_RATING_CHANGED_BEANS_NOT_VISIBLE": "U heeft de maximale beoordeling voor bonen gewijzigd, maar u heeft bonen al hoger beoordeeld dan uw werkelijke maximum. Ze worden dus niet weergegeven met de normale filterinstellingen.", - "BEAN_DATA_FROZEN_NOTE": "Bevroren notities", - "IGNORE_NEGATIVE_VALUES_DESCRIPTION": "Als je dit activeert, loopt de grafiek één seconde achter", - "IGNORE_ANOMALY_VALUES_DESCRIPTION": "Als je dit activeert, loopt de grafiek één seconde achter", - "SAVE_LOGFILES_TO_NOTES_FROM_MACHINE": "Bewaar de machine logs bij het opslaan van een brouwsel" -} \ No newline at end of file diff --git a/src/components/brew-information/brew-information.component.ts b/src/components/brew-information/brew-information.component.ts index a1455d89..209b94c7 100644 --- a/src/components/brew-information/brew-information.component.ts +++ b/src/components/brew-information/brew-information.component.ts @@ -401,7 +401,6 @@ export class BrewInformationComponent implements OnInit { htmlToImage .toPng(this.cardEl.nativeElement) .then((_dataURL) => { - console.log(_dataURL); // On iOS we need to do this a second time, because the rendering doesn't render everything (strange thing) setTimeout(() => { htmlToImage From 82669b37d28ef4eed53487e5d45d7b6840aaf10a Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Fri, 30 Aug 2024 23:03:44 +0200 Subject: [PATCH 12/19] Changes --- src/app/brew/brew-add/brew-add.component.html | 4 +- .../brew/brew-edit/brew-edit.component.html | 4 +- ...reparation-connected-device.component.html | 4 +- .../preparation-connected-device.component.ts | 8 ++ .../beanconqueror-preparation-sanremo-you.svg | 35 +++++++++ .../beanconqueror-sanremo-you-logo.svg | 73 ++++++++++++------- src/assets/i18n/en.json | 6 +- src/classes/preparation/preparation.ts | 2 + .../sanremo/sanremoYOUDevice.ts | 7 +- src/classes/settings/settings.ts | 4 +- .../brew-brewing-graph.component.ts | 32 +++++--- ...-brewing-preparation-device.component.html | 13 ++++ ...ew-brewing-preparation-device.component.ts | 3 + .../sanremo/sanremoYOUMode.ts | 4 + .../sanremoYOU/iSanremoYOUParams.ts | 3 + 15 files changed, 156 insertions(+), 46 deletions(-) create mode 100644 src/assets/custom-ion-icons/beanconqueror-preparation-sanremo-you.svg create mode 100755 src/enums/preparationDevice/sanremo/sanremoYOUMode.ts diff --git a/src/app/brew/brew-add/brew-add.component.html b/src/app/brew/brew-add/brew-add.component.html index b74ee3c5..1ebe900a 100644 --- a/src/app/brew/brew-add/brew-add.component.html +++ b/src/app/brew/brew-add/brew-add.component.html @@ -21,11 +21,11 @@ - + - + diff --git a/src/app/brew/brew-edit/brew-edit.component.html b/src/app/brew/brew-edit/brew-edit.component.html index 462b5e87..3531024c 100644 --- a/src/app/brew/brew-edit/brew-edit.component.html +++ b/src/app/brew/brew-edit/brew-edit.component.html @@ -11,11 +11,11 @@ - + - + diff --git a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.html b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.html index 071f6557..85fca6bc 100644 --- a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.html +++ b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.html @@ -50,7 +50,7 @@

{{"PREPARATION_DEVICE.RESIDUAL_LAG_TIME" | translate }}  - @@ -96,7 +96,7 @@

{{"PREPARATION_DEVICE.RESIDUAL_LAG_TIME" | translate }}  - diff --git a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts index f6c2ce88..a4b55d94 100644 --- a/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts +++ b/src/app/preparation/preparation-connected-device/preparation-connected-device.component.ts @@ -14,6 +14,9 @@ import { UISettingsStorage } from '../../../services/uiSettingsStorage'; import { Settings } from '../../../classes/settings/settings'; import { environment } from '../../../environments/environment'; import { PREPARATION_TYPES } from '../../../enums/preparations/preparationTypes'; +import { SanremoYOUParams } from '../../../classes/preparationDevice/sanremo/sanremoYOUDevice'; +import { MeticulousParams } from '../../../classes/preparationDevice/meticulous/meticulousDevice'; +import { XeniaParams } from '../../../classes/preparationDevice/xenia/xeniaDevice'; @Component({ selector: 'app-preparation-connected-device', @@ -58,13 +61,18 @@ export class PreparationConnectedDeviceComponent { if (this.data.type === PREPARATION_TYPES.METICULOUS) { this.data.connectedPreparationDevice.type = PreparationDeviceType.METICULOUS; + this.data.connectedPreparationDevice.customParams = + new MeticulousParams(); } if (this.data.type === PREPARATION_TYPES.XENIA) { this.data.connectedPreparationDevice.type = PreparationDeviceType.XENIA; + this.data.connectedPreparationDevice.customParams = new XeniaParams(); } if (this.data.type === PREPARATION_TYPES.SANREMO_YOU) { this.data.connectedPreparationDevice.type = PreparationDeviceType.SANREMO_YOU; + this.data.connectedPreparationDevice.customParams = + new SanremoYOUParams(); } } } diff --git a/src/assets/custom-ion-icons/beanconqueror-preparation-sanremo-you.svg b/src/assets/custom-ion-icons/beanconqueror-preparation-sanremo-you.svg new file mode 100644 index 00000000..2bee8008 --- /dev/null +++ b/src/assets/custom-ion-icons/beanconqueror-preparation-sanremo-you.svg @@ -0,0 +1,35 @@ + + + + diff --git a/src/assets/custom-ion-icons/beanconqueror-sanremo-you-logo.svg b/src/assets/custom-ion-icons/beanconqueror-sanremo-you-logo.svg index 076d07b5..65a29f37 100644 --- a/src/assets/custom-ion-icons/beanconqueror-sanremo-you-logo.svg +++ b/src/assets/custom-ion-icons/beanconqueror-sanremo-you-logo.svg @@ -2,34 +2,55 @@ - - + + + diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 4bf29546..9e83e5a9 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1067,7 +1067,11 @@ }, "TYPE_SANREMO_YOU": { "TITLE": "Sanremo YOU Machine", - "STOP_AT_WEIGHT": "Stop at weight" + "STOP_AT_WEIGHT": "Stop at weight", + "SELECT_MODE": "Select mode", + "MODE_LISTENING": "Listening", + "MODE_CONTROL": "Control" + } }, "DEVICE_CONNECTION": "Device connection", diff --git a/src/classes/preparation/preparation.ts b/src/classes/preparation/preparation.ts index d6d35f76..299f7a2c 100755 --- a/src/classes/preparation/preparation.ts +++ b/src/classes/preparation/preparation.ts @@ -254,6 +254,8 @@ export class Preparation implements IPreparation { return 'beanconqueror-preparation-tricolate'; case PREPARATION_TYPES.METICULOUS: return 'beanconqueror-preparation-meticulous'; + case PREPARATION_TYPES.SANREMO_YOU: + return 'beanconqueror-preparation-sanremo-you'; default: return 'beanconqueror-preparation-custom'; } diff --git a/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts b/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts index c36b1dad..4cf6023f 100644 --- a/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts +++ b/src/classes/preparationDevice/sanremo/sanremoYOUDevice.ts @@ -3,6 +3,7 @@ import { HttpClient } from '@angular/common/http'; import { Preparation } from '../../preparation/preparation'; import { ISanremoYOUParams } from '../../../interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams'; +import { SanremoYOUMode } from '../../../enums/preparationDevice/sanremo/sanremoYOUMode'; declare var cordova; export class SanremoYOUDevice extends PreparationDevice { public scriptList: Array<{ INDEX: number; TITLE: string }> = []; @@ -176,8 +177,10 @@ export class SanremoYOUDevice extends PreparationDevice { export class SanremoYOUParams implements ISanremoYOUParams { public stopAtWeight: number = 0; - public residualLagTime: number = 1.35; + public residualLagTime: number = 0.9; + public selectedMode: SanremoYOUMode = SanremoYOUMode.LISTENING; constructor() { - this.residualLagTime = 1.35; + this.residualLagTime = 0.9; + this.selectedMode = SanremoYOUMode.LISTENING; } } diff --git a/src/classes/settings/settings.ts b/src/classes/settings/settings.ts index 3a4839c1..1adf7cb1 100755 --- a/src/classes/settings/settings.ts +++ b/src/classes/settings/settings.ts @@ -387,8 +387,8 @@ export class Settings implements ISettings { }; this.graph_pressure = { - upper: 0, - lower: 9, + lower: 0, + upper: 9, }; this.brew_rating = 5; diff --git a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts index c0aa6771..eb7f588c 100644 --- a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts +++ b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts @@ -63,6 +63,7 @@ import { UIGraphStorage } from '../../../services/uiGraphStorage.service'; import regression from 'regression'; import { TextToSpeechService } from '../../../services/textToSpeech/text-to-speech.service'; import { SanremoYOUDevice } from '../../../classes/preparationDevice/sanremo/sanremoYOUDevice'; +import { SanremoYOUMode } from '../../../enums/preparationDevice/sanremo/sanremoYOUMode'; declare var Plotly; @@ -1052,6 +1053,9 @@ export class BrewBrewingGraphComponent implements OnInit { fixedrange: true, range: [suggestedMinPressure, suggestedMaxPressure], }; + if (suggestedMaxPressure <= 10) { + layout['yaxis4']['dtick'] = 1; + } } const temperatureDevice = this.bleManager.getTemperatureDevice(); if ( @@ -1787,7 +1791,9 @@ export class BrewBrewingGraphComponent implements OnInit { this.brewComponent?.brewBrewingPreparationDeviceEl?.getPreparationDeviceType() === PreparationDeviceType.SANREMO_YOU && _event !== 'sanremo_you' && - this.machineStopScriptWasTriggered === false + this.machineStopScriptWasTriggered === false && + this.data.preparationDeviceBrew.params.selectedMode === + SanremoYOUMode.CONTROLLING ) { this.machineStopScriptWasTriggered = true; this.uiLog.log(`Sanremo YOU - Pause button pressed, stop shot`); @@ -2320,13 +2326,19 @@ export class BrewBrewingGraphComponent implements OnInit { ) { const prepDeviceCall: SanremoYOUDevice = this.brewComponent .brewBrewingPreparationDeviceEl.preparationDevice as SanremoYOUDevice; - prepDeviceCall.startShot().catch((_msg) => { - this.uiLog.log('We could not start shot on sanremo: ' + _msg); - this.uiToast.showInfoToast( - 'We could not start shot on sanremo: ' + _msg, - false - ); - }); + + if ( + this.data.preparationDeviceBrew?.params.selectedMode === + SanremoYOUMode.CONTROLLING + ) { + prepDeviceCall.startShot().catch((_msg) => { + this.uiLog.log('We could not start shot on sanremo: ' + _msg); + this.uiToast.showInfoToast( + 'We could not start shot on sanremo: ' + _msg, + false + ); + }); + } if ( this.settings.bluetooth_scale_maximize_on_start_timer === true && @@ -3012,7 +3024,9 @@ export class BrewBrewingGraphComponent implements OnInit { } } else if ( this.brewComponent.brewBrewingPreparationDeviceEl.getPreparationDeviceType() === - PreparationDeviceType.SANREMO_YOU + PreparationDeviceType.SANREMO_YOU && + this.data.preparationDeviceBrew.params.selectedMode === + SanremoYOUMode.CONTROLLING ) { /**We call this function before the if, because we still log the data**/ const thresholdHit = this.calculateBrewByWeight( diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html index 1c314521..0c923610 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.html @@ -83,10 +83,23 @@ {{"PREPARATION_DEVICE.TYPE_SANREMO_YOU.TITLE" | translate }} + + + + {{"PREPARATION_DEVICE.TYPE_SANREMO_YOU.MODE_LISTENING" | translate}} + + + {{"PREPARATION_DEVICE.TYPE_SANREMO_YOU.MODE_CONTROL" | translate}} + + + + + diff --git a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts index f84204e2..cb340e75 100644 --- a/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts +++ b/src/components/brews/brew-brewing-preparation-device/brew-brewing-preparation-device.component.ts @@ -44,6 +44,7 @@ import { SanremoYOUDevice, SanremoYOUParams, } from '../../../classes/preparationDevice/sanremo/sanremoYOUDevice'; +import { SanremoYOUMode } from '../../../enums/preparationDevice/sanremo/sanremoYOUMode'; @Component({ selector: 'brew-brewing-preparation-device', templateUrl: './brew-brewing-preparation-device.component.html', @@ -433,4 +434,6 @@ export class BrewBrewingPreparationDeviceComponent implements OnInit { } }, 50); } + + protected readonly SanremoYOUMode = SanremoYOUMode; } diff --git a/src/enums/preparationDevice/sanremo/sanremoYOUMode.ts b/src/enums/preparationDevice/sanremo/sanremoYOUMode.ts new file mode 100755 index 00000000..c66e9caa --- /dev/null +++ b/src/enums/preparationDevice/sanremo/sanremoYOUMode.ts @@ -0,0 +1,4 @@ +export enum SanremoYOUMode { + LISTENING = 'LISTENING', + CONTROLLING = 'CONTROLLING', +} diff --git a/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts b/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts index a04a7335..f753a638 100644 --- a/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts +++ b/src/interfaces/preparationDevices/sanremoYOU/iSanremoYOUParams.ts @@ -1,4 +1,7 @@ +import { SanremoYOUMode } from '../../../enums/preparationDevice/sanremo/sanremoYOUMode'; + export interface ISanremoYOUParams { stopAtWeight: number; residualLagTime: number; + selectedMode: SanremoYOUMode; } From b2f49023a60b5f78745b95feb5d67f17265c6d7e Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Sat, 31 Aug 2024 22:03:00 +0200 Subject: [PATCH 13/19] Adding download button to download import files --- src/app/settings/settings.page.html | 8 ++++++-- src/app/settings/settings.page.ts | 6 ++++++ src/assets/i18n/en.json | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/app/settings/settings.page.html b/src/app/settings/settings.page.html index dcd95cff..cd21b706 100644 --- a/src/app/settings/settings.page.html +++ b/src/app/settings/settings.page.html @@ -59,14 +59,18 @@

{{"EXPORT" | translate}}

{{"EXCEL_EXPORT" | translate}} - + {{"IMPORT_ROASTED_BEANS_EXCEL" | translate}} - + {{"IMPORT_GREEN_BEANS_EXCEL" | translate}} + + {{"DOWNLOAD_IMPORT_EXCEL_TEMPLATES" | translate}} + + diff --git a/src/app/settings/settings.page.ts b/src/app/settings/settings.page.ts index fcae3d57..787af73a 100644 --- a/src/app/settings/settings.page.ts +++ b/src/app/settings/settings.page.ts @@ -1287,6 +1287,12 @@ export class SettingsPage { } } + public downloadImportExcelTemplates() { + this.uiHelper.openExternalWebpage( + 'https://beanconqueror.gitbook.io/beanconqueror/resources/files' + ); + } + public importBeansExcel(_type: string = 'roasted'): void { if (this.platform.is('cordova')) { this.uiAnalytics.trackEvent( diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 9e83e5a9..952181d8 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1345,5 +1345,6 @@ "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS": "Define the axes for the pressure graph", "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_DESCRIPTION": "Set the starting and end size of the axes for pressure", "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_RANGE": "Pressure axes", - "PAGE_SETTINGS_LANGUAGE_DUTCH": "Dutch" + "PAGE_SETTINGS_LANGUAGE_DUTCH": "Dutch", + "DOWNLOAD_IMPORT_EXCEL_TEMPLATES": "Download import templates" } From 41c42973d5fab5dc01e67ccbf14992ef36c291da Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Sat, 31 Aug 2024 23:17:44 +0200 Subject: [PATCH 14/19] #783 - Make pressure graph resizeable --- .../graph-detail/graph-detail.component.ts | 12 ++++++ .../brew-brewing-graph.component.ts | 42 +++++++++++-------- .../graph-display-card.component.ts | 11 +++++ 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/app/graph-section/graph/graph-detail/graph-detail.component.ts b/src/app/graph-section/graph/graph-detail/graph-detail.component.ts index a0ead927..113e182f 100644 --- a/src/app/graph-section/graph/graph-detail/graph-detail.component.ts +++ b/src/app/graph-section/graph/graph-detail/graph-detail.component.ts @@ -174,6 +174,16 @@ export class GraphDetailComponent implements OnInit { }, }; + const graph_pressure_settings = this.settings.graph_pressure; + const suggestedMinPressure: number = graph_pressure_settings.lower; + let suggestedMaxPressure = graph_pressure_settings.upper; + try { + if (this.pressureTrace?.y.length > 0) { + suggestedMaxPressure = Math.max(...this.pressureTrace.y); + suggestedMaxPressure = Math.ceil(suggestedMaxPressure + 1); + } + } catch (ex) {} + layout['yaxis4'] = { title: '', titlefont: { color: '#05C793' }, @@ -183,6 +193,7 @@ export class GraphDetailComponent implements OnInit { side: 'right', showgrid: false, position: 0.93, + range: [suggestedMinPressure, suggestedMaxPressure], visible: true, }; @@ -348,6 +359,7 @@ export class GraphDetailComponent implements OnInit { } } } + if ( this.flow_profile_raw?.pressureFlow && this.flow_profile_raw.pressureFlow.length > 0 diff --git a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts index eb7f588c..60e98e2e 100644 --- a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts +++ b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts @@ -1053,9 +1053,6 @@ export class BrewBrewingGraphComponent implements OnInit { fixedrange: true, range: [suggestedMinPressure, suggestedMaxPressure], }; - if (suggestedMaxPressure <= 10) { - layout['yaxis4']['dtick'] = 1; - } } const temperatureDevice = this.bleManager.getTemperatureDevice(); if ( @@ -1116,6 +1113,16 @@ export class BrewBrewingGraphComponent implements OnInit { }, }; + const graph_pressure_settings = this.settings.graph_pressure; + const suggestedMinPressure = graph_pressure_settings.lower; + let suggestedMaxPressure = graph_pressure_settings.upper; + try { + if (this.pressureTrace?.y.length > 0) { + suggestedMaxPressure = Math.max(...this.pressureTrace.y); + suggestedMaxPressure = Math.ceil(suggestedMaxPressure + 1); + } + } catch (ex) {} + layout['yaxis4'] = { title: '', titlefont: { color: '#05C793' }, @@ -1125,7 +1132,7 @@ export class BrewBrewingGraphComponent implements OnInit { side: 'right', showgrid: false, position: 0.93, - range: [0, 12], + range: [suggestedMinPressure, suggestedMaxPressure], visible: true, }; @@ -1588,6 +1595,18 @@ export class BrewBrewingGraphComponent implements OnInit { newLayoutIsNeeded = true; } } + if (this.pressureTrace?.y?.length > 0) { + // #783 + const lastPressureData: number = + this.pressureTrace.y[this.pressureTrace.y.length - 1]; + if (lastPressureData > this.lastChartLayout.yaxis4.range[1]) { + this.lastChartLayout.yaxis4.range[1] = Math.ceil( + lastPressureData + 1 + ); + newLayoutIsNeeded = true; + } + } + if (newLayoutIsNeeded) { Plotly.relayout( this.profileDiv.nativeElement, @@ -1596,18 +1615,7 @@ export class BrewBrewingGraphComponent implements OnInit { } }, 25); } else { - const delay = moment(new Date()) - .startOf('day') - .add('seconds', 0) - .toDate() - .getTime(); - const delayedTime: number = moment(new Date()) - .startOf('day') - .add('seconds', this.brewComponent.timer.getSeconds() + 5) - .toDate() - .getTime(); - this.lastChartLayout.xaxis.range = [delay, delayedTime]; - Plotly.relayout(this.profileDiv.nativeElement, this.lastChartLayout); + // Not needed anymore } } catch (ex) {} }); @@ -2134,7 +2142,7 @@ export class BrewBrewingGraphComponent implements OnInit { ); weight = weight + genRand(0.1, 2, 2); pressure = Math.floor( - (crypto.getRandomValues(new Uint8Array(1))[0] / Math.pow(2, 8)) * 11 + (crypto.getRandomValues(new Uint8Array(1))[0] / Math.pow(2, 8)) * 16 ); temperature = Math.floor( (crypto.getRandomValues(new Uint8Array(1))[0] / Math.pow(2, 8)) * 90 diff --git a/src/components/graph-display-card/graph-display-card.component.ts b/src/components/graph-display-card/graph-display-card.component.ts index 9896b7fb..4fd0b40e 100644 --- a/src/components/graph-display-card/graph-display-card.component.ts +++ b/src/components/graph-display-card/graph-display-card.component.ts @@ -159,6 +159,16 @@ export class GraphDisplayCardComponent implements OnInit { }, }; + const graph_pressure_settings = this.settings.graph_pressure; + const suggestedMinPressure: number = graph_pressure_settings.lower; + let suggestedMaxPressure = graph_pressure_settings.upper; + try { + if (this.pressureTrace?.y.length > 0) { + suggestedMaxPressure = Math.max(...this.pressureTrace.y); + suggestedMaxPressure = Math.ceil(suggestedMaxPressure + 1); + } + } catch (ex) {} + layout['yaxis4'] = { title: '', titlefont: { color: '#05C793' }, @@ -168,6 +178,7 @@ export class GraphDisplayCardComponent implements OnInit { side: 'right', fixedrange: true, showgrid: false, + range: [suggestedMinPressure, suggestedMaxPressure], position: 0.93, visible: true, }; From d78ad04780d673faa3058e3164fcbfc9f121578a Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Sun, 1 Sep 2024 21:53:15 +0200 Subject: [PATCH 15/19] #784 - Fixing sorting of preparation tools --- .../preparation-sort-tools.component.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app/preparation/preparation-sort-tools/preparation-sort-tools.component.ts b/src/app/preparation/preparation-sort-tools/preparation-sort-tools.component.ts index ad1c717f..d0eac0ff 100644 --- a/src/app/preparation/preparation-sort-tools/preparation-sort-tools.component.ts +++ b/src/app/preparation/preparation-sort-tools/preparation-sort-tools.component.ts @@ -2,6 +2,7 @@ import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; import { Preparation } from '../../../classes/preparation/preparation'; import { ModalController } from '@ionic/angular'; +import { UIHelper } from '../../../services/uiHelper'; @Component({ selector: 'app-preparation-sort-tools', @@ -20,7 +21,8 @@ export class PreparationSortToolsComponent implements OnInit { @Input() public preparation: Preparation; constructor( private readonly modalController: ModalController, - private readonly changeDetectorRef: ChangeDetectorRef + private readonly changeDetectorRef: ChangeDetectorRef, + private readonly uiHelper: UIHelper ) {} public ngOnInit() { @@ -40,13 +42,12 @@ export class PreparationSortToolsComponent implements OnInit { reorderVar.splice(ev.detail.to, 0, reorderVar.splice(ev.detail.from, 1)[0]); - const swapElements = (myArray, index1, index2) => { - [myArray[index1], myArray[index2]] = [myArray[index2], myArray[index1]]; - }; - - swapElements(this.preparation.tools, ev.detail.from, ev.detail.to); + this.preparation.tools.splice( + ev.detail.to, + 0, + this.preparation.tools.splice(ev.detail.from, 1)[0] + ); - // console.log(this.settings.brew_order); // Finish the reorder and position the item in the DOM based on // where the gesture ended. This method can also be called directly // by the reorder group From 12bf334852e531bfad35c05bd045e8c26e211fb8 Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Sun, 1 Sep 2024 22:22:54 +0200 Subject: [PATCH 16/19] Remove things. --- src/components/brew-information/brew-information.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/brew-information/brew-information.component.html b/src/components/brew-information/brew-information.component.html index a60b6043..7d174be6 100644 --- a/src/components/brew-information/brew-information.component.html +++ b/src/components/brew-information/brew-information.component.html @@ -1,5 +1,5 @@
- + From bcb114919158d5597aea1a4319ed4b5ff3857fa5 Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Sun, 1 Sep 2024 23:33:05 +0200 Subject: [PATCH 17/19] #785 - Make it possible to slide cards to show graph --- src/app/app.scss | 27 +- .../brew-information.component.html | 407 +++++++++--------- .../brew-information.component.scss | 10 + .../brew-information.component.ts | 38 ++ .../graph-display-card.component.ts | 6 +- .../photo-add/photo-add.component.html | 2 +- .../photo-view/photo-view.component.html | 2 +- .../photo-popover.component.html | 2 +- .../update-popover.component.html | 2 +- .../welcome-popover.component.html | 2 +- 10 files changed, 283 insertions(+), 215 deletions(-) diff --git a/src/app/app.scss b/src/app/app.scss index a2c6f01c..e760198f 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -944,24 +944,27 @@ swiper-container { --swiper-scrollbar-drag-bg-color: rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.5); } -swiper-slide { - display: flex; - position: relative; +swiper-container.swiper { + swiper-slide { + display: flex; + position: relative; - flex-direction: column; - flex-shrink: 0; - align-items: center; - justify-content: center; + flex-direction: column; + flex-shrink: 0; + align-items: center; + justify-content: center; - width: 100%; - height: 100%; + width: 100%; + height: 100%; - font-size: 18px; + font-size: 18px; - text-align: center; - box-sizing: border-box; + text-align: center; + box-sizing: border-box; + } } + swiper-slide img { width: auto; max-width: 100%; diff --git a/src/components/brew-information/brew-information.component.html b/src/components/brew-information/brew-information.component.html index 7d174be6..f4869a3e 100644 --- a/src/components/brew-information/brew-information.component.html +++ b/src/components/brew-information/brew-information.component.html @@ -1,247 +1,260 @@ -
- - - - - - - - -
- -
-
- -
- -
-
- - - - - - - - - {{ brew.config.unix_timestamp | formatDate:[settings?.date_format] }}{{ brew.config.unix_timestamp | formatDate:["HH:mm"] }} - - - - - - - - - -
- - () - - {{ bean?.name }} ({{ bean?.roaster }}) -
-
- + + + + + + + + + + +
+ +
+
+ +
+ +
+
+ + + + + + + + + {{ brew.config.unix_timestamp | formatDate:[settings?.date_format] }}{{ brew.config.unix_timestamp | formatDate:["HH:mm"] }} + + + + + + + + + +
+ + () + + {{ bean?.name }} ({{ bean?.roaster }}) +
+
+ - - - - + + + + - {{ this.uiHelper.toFixedIfNecessary(brew.rating, 2) }} - -
-
-
-
-
- - -
-
-
-
- - - + {{ this.uiHelper.toFixedIfNecessary(brew.rating, 2) }} + + + +
+
+
+ + +
+
+
+
+ + + - {{ "BREW_DATA_PREPARATION_METHOD" | translate }} -
- {{ preparation?.name }} -
- {{ "BREW_DATA_PREPARATION_METHOD" | translate }} +
+ {{ preparation?.name }} +
+ - {{ "BREW_DATA_MILL" |translate }} -
- {{ mill?.name }} -
- - {{ "BREW_DATA_IN_OUT_BR" | translate }} -
- - {{ brew?.grind_weight | number : '.0-2' }}gr - / {{ brew.brew_quantity | number : '.0-2' }}{{ brewQuantityEnum[brew?.brew_quantity_type] }} ({{ brew?.getBrewRatio() }} - ) - - - {{ brew?.grind_weight | number : '.0-2' }}gr - / {{ brew.brew_beverage_quantity | number : '.0-2' }}{{ brewQuantityEnum[brew?.brew_beverage_quantity_type] }} ({{ brew?.getBrewRatio() }} - ) - -
- {{ "BREW_DATA_MILL" |translate }} +
+ {{ mill?.name }} +
+ + {{ "BREW_DATA_IN_OUT_BR" | translate }} +
+ + {{ brew?.grind_weight | number : '.0-2' }}gr + / {{ brew.brew_quantity | number : '.0-2' }}{{ brewQuantityEnum[brew?.brew_quantity_type] }} ({{ brew?.getBrewRatio() }} + ) + + + {{ brew?.grind_weight | number : '.0-2' }}gr + / {{ brew.brew_beverage_quantity | number : '.0-2' }}{{ brewQuantityEnum[brew?.brew_beverage_quantity_type] }} ({{ brew?.getBrewRatio() }} + ) + +
+ - {{ 'BREW_DATA_TIME' | translate }} -
- {{ brew?.getFormattedTotalCoffeeBrewTime() }} -
- 0 && uiBrewHelper.fieldVisible(settings.visible_list_view_parameters.mill_speed, preparation?.visible_list_view_parameters.mill_speed, preparation?.use_custom_parameters))" size='6'> - {{ 'BREW_DATA_GRIND_SIZE' | translate }} -
- {{ brew?.grind_size }} @ {{ brew?.mill_speed }} -
- - {{ 'BREW_DATA_TDS_EY' | translate }} -
- {{ brew?.tds }}, %{{ brew?.getExtractionYield() }} -
- 0 && brew?.brew_beverage_quantity>0' size='6'> + {{ 'BREW_DATA_TDS_EY' | translate }} +
+ {{ brew?.tds }}, %{{ brew?.getExtractionYield() }} +
+ - {{ 'BREW_DATA_BREW_TEMPERATURE' | translate }} -
- {{ brew?.brew_temperature }} -
- - {{ 'BREW_DATA_PRESSURE_PROFILE' | translate }} -
- {{ brew?.pressure_profile }} -
- {{ 'BREW_DATA_PRESSURE_PROFILE' | translate }} +
+ {{ brew?.pressure_profile }} +
+ - {{ "BREW_DATA_BEAN_WEIGHT_IN" | translate }} -
- {{ brew?.bean_weight_in }} -
- {{ "BREW_DATA_BEAN_WEIGHT_IN" | translate }} +
+ {{ brew?.bean_weight_in }} +
+ - {{ "BREW_DATA_MILL_TIMER" | translate }} -
- {{ brew?.mill_timer }} -
- +
+ {{ brew?.mill_timer }} +
+ - {{ "BREW_DATA_VESSEL_NAME_WEIGHT" | translate }} -
- {{ brew?.vessel_name }} / {{ brew?.vessel_weight }} -
- {{ "BREW_DATA_VESSEL_NAME_WEIGHT" | translate }} +
+ {{ brew?.vessel_name }} / {{ brew?.vessel_weight }} +
+ - {{ "BREW_DATA_TEMPERATURE_TIME" | translate }} -
- {{ brew?.getFormattedTotalCoffeeTemperatureTime() }} -
- {{ "BREW_DATA_TEMPERATURE_TIME" | translate }} +
+ {{ brew?.getFormattedTotalCoffeeTemperatureTime() }} +
+ - {{ "BREW_DATA_COFFEE_BLOOMING_TIME" | translate }} -
- {{ brew?.getFormattedTotalCoffeeBloomingTime() }} -
- {{ "BREW_DATA_COFFEE_BLOOMING_TIME" | translate }} +
+ {{ brew?.getFormattedTotalCoffeeBloomingTime() }} +
+ - {{ "BREW_DATA_COFFEE_FIRST_DRIP_TIME" | translate }} -
- {{ brew?.getFormattedTotalCoffeeFirstDripTime() }} -
- +
+ {{ brew?.getFormattedTotalCoffeeFirstDripTime() }} +
+ - {{ "BREW_DATA_WATER" | translate }} -
- {{ brew?.getWater().name }} -
- +
+ {{ brew?.getWater().name }} +
+ - {{ "BREW_DATA_COFFEE_TYPE" | translate }} -
- {{ brew?.coffee_type }} -
- +
+ {{ brew?.coffee_type }} +
+ - {{ "BREW_DATA_COFFEE_CONCENTRATION" | translate }} -
- {{ brew?.coffee_concentration }} -
- {{ "BREW_DATA_COFFEE_CONCENTRATION" | translate }} +
+ {{ brew?.coffee_concentration }} +
+ - {{ "BREW_INFORMATION_BEAN_AGE" | translate }} -
- {{ brew?.getCalculatedBeanAge() }} -
- {{ "BREW_INFORMATION_BEAN_AGE" | translate }} +
+ {{ brew?.getCalculatedBeanAge() }} +
+ - {{ "BREW_DATA_PREPARATION_METHOD_TOOL" | translate }} -
- {{ brew?.getPreparationToolName(uuid) }} - -
-
- - {{ 'BREW_DATA_FLAVOR' | translate }} -
- {{ getCuppedBrewFlavors() }} -
- +
+ {{ brew?.getPreparationToolName(uuid) }} + +
+
+ + {{ 'BREW_DATA_FLAVOR' | translate }} +
+ {{ getCuppedBrewFlavors() }} +
+ - {{ "BREW_DATA_NOTES" | translate }} -
- -
{{ brew?.note }}
-
-
+ {{ "BREW_DATA_NOTES" | translate }} +
+ +
{{ brew?.note }}
+
+
+ +
+
+
+
+ + + + + + + + + + - - - -
{ event.stopPropagation(); event.stopImmediatePropagation(); diff --git a/src/components/graph-display-card/graph-display-card.component.ts b/src/components/graph-display-card/graph-display-card.component.ts index 4fd0b40e..4334b623 100644 --- a/src/components/graph-display-card/graph-display-card.component.ts +++ b/src/components/graph-display-card/graph-display-card.component.ts @@ -31,6 +31,7 @@ export class GraphDisplayCardComponent implements OnInit { @Input() public meticulousHistoryData: HistoryListingEntry; @Input() public chartWidth: number; + @Input() public chartHeight: number; public flow_profile_raw: BrewFlow = new BrewFlow(); @@ -97,7 +98,10 @@ export class GraphDisplayCardComponent implements OnInit { chartWidth = this.chartWidth; } - const chartHeight: number = 150; + let chartHeight: number = 150; + if (this.chartHeight) { + chartHeight = this.chartHeight; + } let tickFormat = '%S'; diff --git a/src/components/photo-add/photo-add.component.html b/src/components/photo-add/photo-add.component.html index c2975a83..099304c2 100644 --- a/src/components/photo-add/photo-add.component.html +++ b/src/components/photo-add/photo-add.component.html @@ -2,7 +2,7 @@  {{"ADD_PHOTO" | translate}}
- + diff --git a/src/components/photo-view/photo-view.component.html b/src/components/photo-view/photo-view.component.html index eec87872..9b25041d 100644 --- a/src/components/photo-view/photo-view.component.html +++ b/src/components/photo-view/photo-view.component.html @@ -1,5 +1,5 @@
- + diff --git a/src/popover/photo-popover/photo-popover.component.html b/src/popover/photo-popover/photo-popover.component.html index ecb0bc64..feb076c2 100644 --- a/src/popover/photo-popover/photo-popover.component.html +++ b/src/popover/photo-popover/photo-popover.component.html @@ -10,7 +10,7 @@
- + diff --git a/src/popover/update-popover/update-popover.component.html b/src/popover/update-popover/update-popover.component.html index 5cb174de..376a1bb6 100644 --- a/src/popover/update-popover/update-popover.component.html +++ b/src/popover/update-popover/update-popover.component.html @@ -1,6 +1,6 @@ - +
diff --git a/src/popover/welcome-popover/welcome-popover.component.html b/src/popover/welcome-popover/welcome-popover.component.html index 97da5ca4..4098a24a 100644 --- a/src/popover/welcome-popover/welcome-popover.component.html +++ b/src/popover/welcome-popover/welcome-popover.component.html @@ -30,7 +30,7 @@ - +
From c8e1ee7917b6b910f87645221e229021f32db7af Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Mon, 2 Sep 2024 20:49:22 +0200 Subject: [PATCH 18/19] #785 - Show graph in slider is now rightly extending + paddings --- .../brew-popover-actions.component.html | 4 ++++ .../graph-detail/graph-detail.component.ts | 19 +++++++++---------- src/assets/i18n/en.json | 3 ++- src/classes/devices/bokooScale.ts | 10 ++++++++++ .../brew-information.component.html | 6 +++--- .../brew-information.component.scss | 5 +++++ .../brew-information.component.ts | 13 +++++++++++-- .../brew-brewing-graph.component.ts | 6 ++++++ .../graph-display-card.component.ts | 1 - src/enums/brews/brewAction.ts | 1 + src/services/uiGraphHelper.ts | 10 ++++++++++ 11 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/app/brew/brew-popover-actions/brew-popover-actions.component.html b/src/app/brew/brew-popover-actions/brew-popover-actions.component.html index 02819e3e..79e2f04b 100644 --- a/src/app/brew/brew-popover-actions/brew-popover-actions.component.html +++ b/src/app/brew/brew-popover-actions/brew-popover-actions.component.html @@ -55,6 +55,10 @@ {{"SHOW_VISUALIZER" | translate}} + + + + {{"SHOW_GRAPH" | translate}} diff --git a/src/app/graph-section/graph/graph-detail/graph-detail.component.ts b/src/app/graph-section/graph/graph-detail/graph-detail.component.ts index 113e182f..8999fb49 100644 --- a/src/app/graph-section/graph/graph-detail/graph-detail.component.ts +++ b/src/app/graph-section/graph/graph-detail/graph-detail.component.ts @@ -11,7 +11,6 @@ import BeanconquerorFlowTestDataDummy from '../../../../assets/BeanconquerorFlow import { BrewFlow } from '../../../../classes/brew/brewFlow'; import { Settings } from '../../../../classes/settings/settings'; import { TranslateService } from '@ngx-translate/core'; -import { Graph } from '../../../../classes/graph/graph'; import { IGraph } from '../../../../interfaces/graph/iGraph'; import GRAPH_TRACKING from '../../../../data/tracking/graphTracking'; import { UIAnalytics } from '../../../../services/uiAnalytics'; @@ -19,6 +18,7 @@ import { UIHelper } from '../../../../services/uiHelper'; import { ModalController, Platform } from '@ionic/angular'; import { UIFileHelper } from '../../../../services/uiFileHelper'; import { UISettingsStorage } from '../../../../services/uiSettingsStorage'; +import { IBrew } from '../../../../interfaces/brew/iBrew'; declare var Plotly; @Component({ selector: 'app-graph-detail', @@ -44,9 +44,9 @@ export class GraphDetailComponent implements OnInit { @ViewChild('profileDiv', { read: ElementRef, static: true }) public profileDiv: ElementRef; - public data: Graph = new Graph(); - @Input() private graph: IGraph; + @Input() private brew: IBrew; + @Input() private flowProfileData: any; constructor( @@ -68,8 +68,9 @@ export class GraphDetailComponent implements OnInit { GRAPH_TRACKING.ACTIONS.DETAIL ); if (this.graph) { - this.data = this.uiHelper.copyData(this.graph); - await this.readFlowProfile(); + await this.readFlowProfile(this.graph.flow_profile); + } else if (this.brew) { + await this.readFlowProfile(this.brew.flow_profile); } else { this.flow_profile_raw = this.uiHelper.cloneData(this.flowProfileData); } @@ -408,13 +409,11 @@ export class GraphDetailComponent implements OnInit { }, 100); } - private async readFlowProfile() { + private async readFlowProfile(_path) { if (this.platform.is('cordova')) { - if (this.graph.flow_profile !== '') { + if (_path !== '') { try { - const jsonParsed = await this.uiFileHelper.getJSONFile( - this.graph.flow_profile - ); + const jsonParsed = await this.uiFileHelper.getJSONFile(_path); this.flow_profile_raw = jsonParsed; } catch (ex) {} } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 952181d8..f8b9d034 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1346,5 +1346,6 @@ "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_DESCRIPTION": "Set the starting and end size of the axes for pressure", "PAGE_SETTINGS_TAB_BLUETOOTH_PRESSURE_GRAPHS_AXIS_RANGE": "Pressure axes", "PAGE_SETTINGS_LANGUAGE_DUTCH": "Dutch", - "DOWNLOAD_IMPORT_EXCEL_TEMPLATES": "Download import templates" + "DOWNLOAD_IMPORT_EXCEL_TEMPLATES": "Download import templates", + "SHOW_GRAPH": "Graph anzeigen" } diff --git a/src/classes/devices/bokooScale.ts b/src/classes/devices/bokooScale.ts index ad314498..a2052073 100644 --- a/src/classes/devices/bokooScale.ts +++ b/src/classes/devices/bokooScale.ts @@ -49,6 +49,16 @@ export class BookooScale extends BluetoothScale { await this.write(new Uint8Array([0x03, 0x0a, 0x01, 0x00, 0x00, 0x08])); } + public async tareAndStartTimerModeAuto() { + this.weight.smoothed = 0; + this.weight.actual = 0; + this.weight.oldSmoothed = 0; + this.weight.old = 0; + this.setWeight(0); + + await this.write(new Uint8Array([0x03, 0x0a, 0x07, 0x00, 0x00, 0x00])); + } + public override disconnectTriggered(): void { this.logger.log('Disconnecting...'); this.deattachNotification(); diff --git a/src/components/brew-information/brew-information.component.html b/src/components/brew-information/brew-information.component.html index f4869a3e..5d02bbf9 100644 --- a/src/components/brew-information/brew-information.component.html +++ b/src/components/brew-information/brew-information.component.html @@ -2,7 +2,7 @@ - + - - + + diff --git a/src/components/brew-information/brew-information.component.scss b/src/components/brew-information/brew-information.component.scss index 693bf49f..03b0008a 100644 --- a/src/components/brew-information/brew-information.component.scss +++ b/src/components/brew-information/brew-information.component.scss @@ -9,6 +9,7 @@ max-height:60px!important; } ion-card.brew-layout { + width:100%; margin-top:0px; margin-bottom:0px; margin-left:10px; @@ -54,6 +55,7 @@ top: -5px; } } + ion-card.dashboard-layout { @@ -151,6 +153,9 @@ width: 100%; height: 100%; } + .add-bottom-spacing{ + margin-bottom:20px; + } } diff --git a/src/components/brew-information/brew-information.component.ts b/src/components/brew-information/brew-information.component.ts index 637b9a0c..abe007b8 100644 --- a/src/components/brew-information/brew-information.component.ts +++ b/src/components/brew-information/brew-information.component.ts @@ -36,9 +36,10 @@ import * as htmlToImage from 'html-to-image'; import { UIFileHelper } from '../../services/uiFileHelper'; import { BrewFlow } from '../../classes/brew/brewFlow'; -import { UIBeanStorage } from '../../services/uiBeanStorage'; + import { UIBeanHelper } from '../../services/uiBeanHelper'; import { VisualizerService } from '../../services/visualizerService/visualizer-service.service'; +import { UIGraphHelper } from '../../services/uiGraphHelper'; declare var window; @Component({ selector: 'brew-information', @@ -93,7 +94,8 @@ export class BrewInformationComponent implements OnInit { private readonly platform: Platform, private readonly uiFileHelper: UIFileHelper, private readonly uiBeanHelper: UIBeanHelper, - private readonly visualizerService: VisualizerService + private readonly visualizerService: VisualizerService, + private readonly uiGraphHelper: UIGraphHelper ) {} public ngOnInit() { @@ -140,6 +142,10 @@ export class BrewInformationComponent implements OnInit { this.brewAction.emit([BREW_ACTION.DETAIL, this.brew]); } + public async showBrewGraph() { + await this.uiGraphHelper.detailBrewGraph(this.brew); + } + public getElementOffsetWidth() { if (this.brewInformationContainer?.nativeElement?.offsetWidth) { return this.brewInformationContainer?.nativeElement?.offsetWidth - 50; @@ -391,6 +397,9 @@ export class BrewInformationComponent implements OnInit { case BREW_ACTION.SHOW_VISUALIZER: await this.showVisualizerShot(); break; + case BREW_ACTION.SHOW_GRAPH: + await this.showBrewGraph(); + break; default: break; } diff --git a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts index 60e98e2e..74e5bcfe 100644 --- a/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts +++ b/src/components/brews/brew-brewing-graph/brew-brewing-graph.component.ts @@ -64,6 +64,7 @@ import regression from 'regression'; import { TextToSpeechService } from '../../../services/textToSpeech/text-to-speech.service'; import { SanremoYOUDevice } from '../../../classes/preparationDevice/sanremo/sanremoYOUDevice'; import { SanremoYOUMode } from '../../../enums/preparationDevice/sanremo/sanremoYOUMode'; +import { BookooScale } from '../../../classes/devices/bokooScale'; declare var Plotly; @@ -2393,6 +2394,11 @@ export class BrewBrewingGraphComponent implements OnInit { await this.timerReset(undefined); await this.brewComponent.timer.resetWithoutEmit(false); + if (scale.getScaleType() === ScaleType.BOKOOSCALE) { + //const bookooScale: BookooScale = scale as BookooScale; + //await bookooScale.tareAndStartTimerModeAuto(); + } + this.brewComponent.timer.checkChanges(); this.checkChanges(); diff --git a/src/components/graph-display-card/graph-display-card.component.ts b/src/components/graph-display-card/graph-display-card.component.ts index 4334b623..023557a7 100644 --- a/src/components/graph-display-card/graph-display-card.component.ts +++ b/src/components/graph-display-card/graph-display-card.component.ts @@ -227,7 +227,6 @@ export class GraphDisplayCardComponent implements OnInit { try { Plotly.purge(this.profileDiv.nativeElement); } catch (ex) {} - const graphSettings = this.settings.graph.FILTER; this.weightTrace = { x: [], diff --git a/src/enums/brews/brewAction.ts b/src/enums/brews/brewAction.ts index 96dc6f74..3cc746fa 100755 --- a/src/enums/brews/brewAction.ts +++ b/src/enums/brews/brewAction.ts @@ -14,4 +14,5 @@ export enum BREW_ACTION { RATING = 'RATING', TOGGLE_BEST_BREW = 'TOGGLE_BEST_BREW', SHOW_VISUALIZER = 'SHOW_VISUALIZER', + SHOW_GRAPH = 'SHOW_GRAPH', } diff --git a/src/services/uiGraphHelper.ts b/src/services/uiGraphHelper.ts index 75fe2582..aa464a23 100644 --- a/src/services/uiGraphHelper.ts +++ b/src/services/uiGraphHelper.ts @@ -16,6 +16,7 @@ import { FileEntry } from '@awesome-cordova-plugins/file'; import { UILog } from './uiLog'; import { UIFileHelper } from './uiFileHelper'; import BeanconquerorFlowTestDataDummy from '../assets/BeanconquerorFlowTestDataFourth.json'; +import { Brew } from '../classes/brew/brew'; /** * Handles every helping functionalities @@ -70,6 +71,15 @@ export class UIGraphHelper { await modal.present(); await modal.onWillDismiss(); } + public async detailBrewGraph(_brew: Brew) { + const modal = await this.modalController.create({ + component: GraphDetailComponent, + id: GraphDetailComponent.COMPONENT_ID, + componentProps: { brew: _brew }, + }); + await modal.present(); + await modal.onWillDismiss(); + } public async detailGraphRawData(_flowData: any) { const modal = await this.modalController.create({ From de977c03a3670caac388cd0a1af14487fe0702bb Mon Sep 17 00:00:00 2001 From: Lars Saalbach Date: Mon, 2 Sep 2024 22:03:11 +0200 Subject: [PATCH 19/19] #785 - Show graph in slider is now rightly extending + paddings --- .../brew-information.component.html | 5 +- .../brew-information.component.scss | 5 +- .../brew-information.component.ts | 63 +++++++++---------- .../welcome-popover.component.ts | 6 -- 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/components/brew-information/brew-information.component.html b/src/components/brew-information/brew-information.component.html index 5d02bbf9..85e0b065 100644 --- a/src/components/brew-information/brew-information.component.html +++ b/src/components/brew-information/brew-information.component.html @@ -246,9 +246,10 @@ - + + - + diff --git a/src/components/brew-information/brew-information.component.scss b/src/components/brew-information/brew-information.component.scss index 03b0008a..6ec6155b 100644 --- a/src/components/brew-information/brew-information.component.scss +++ b/src/components/brew-information/brew-information.component.scss @@ -151,13 +151,16 @@ position: relative; width: 100%; - height: 100%; + + height: auto; } + .add-bottom-spacing{ margin-bottom:20px; } + } diff --git a/src/components/brew-information/brew-information.component.ts b/src/components/brew-information/brew-information.component.ts index abe007b8..3537da56 100644 --- a/src/components/brew-information/brew-information.component.ts +++ b/src/components/brew-information/brew-information.component.ts @@ -10,7 +10,7 @@ import { } from '@angular/core'; import { Brew } from '../../classes/brew/brew'; import { UISettingsStorage } from '../../services/uiSettingsStorage'; -import { ModalController, Platform } from '@ionic/angular'; +import { MenuController, ModalController, Platform } from '@ionic/angular'; import { BREW_ACTION } from '../../enums/brews/brewAction'; import { BrewPopoverActionsComponent } from '../../app/brew/brew-popover-actions/brew-popover-actions.component'; import { Bean } from '../../classes/bean/bean'; @@ -53,14 +53,16 @@ export class BrewInformationComponent implements OnInit { @ViewChild('card', { read: ElementRef }) public cardEl: ElementRef; + public slideOpts = { + allowTouchMove: false, + speed: 400, + slide: 4, + }; + @ViewChild('swiper', { static: false }) public brewInformationSlider: | ElementRef | undefined; - @ViewChild('ionCardParent', { static: false }) public ionCardParent: - | ElementRef - | any; - @ViewChild('brewInformationContainer', { read: ElementRef, static: false }) public brewInformationContainer: ElementRef; @@ -77,6 +79,9 @@ export class BrewInformationComponent implements OnInit { public settings: Settings = null; + public informationContainerHeight: number = undefined; + public informationContainerWidth: number = undefined; + constructor( private readonly uiSettingsStorage: UISettingsStorage, public readonly uiBrewHelper: UIBrewHelper, @@ -95,7 +100,8 @@ export class BrewInformationComponent implements OnInit { private readonly uiFileHelper: UIFileHelper, private readonly uiBeanHelper: UIBeanHelper, private readonly visualizerService: VisualizerService, - private readonly uiGraphHelper: UIGraphHelper + private readonly uiGraphHelper: UIGraphHelper, + private readonly menu: MenuController ) {} public ngOnInit() { @@ -104,6 +110,25 @@ export class BrewInformationComponent implements OnInit { this.bean = this.brew.getBean(); this.preparation = this.brew.getPreparation(); this.mill = this.brew.getMill(); + + setTimeout(() => { + /**We calculcate the information here, to avoid expression-changed in angular, because it always triggered while scrolling cause of calucation functions**/ + this.informationContainerHeight = + this.brewInformationContainer?.nativeElement?.offsetHeight - 50; + this.informationContainerWidth = + this.brewInformationContainer?.nativeElement?.offsetWidth - 50; + + /**If we slide on a bigger tablet, somehow ionic triggering the menu when sliding from right to left, thats why we need to attach us to touchstart/end and to ignore the slide...**/ + this.brewInformationSlider?.nativeElement.swiper.on( + 'touchStart', + () => { + this.menu.swipeGesture(false); + } + ); + this.brewInformationSlider?.nativeElement.swiper.on('touchEnd', () => { + this.menu.swipeGesture(true); + }); + }, 150); } } @@ -146,32 +171,6 @@ export class BrewInformationComponent implements OnInit { await this.uiGraphHelper.detailBrewGraph(this.brew); } - public getElementOffsetWidth() { - if (this.brewInformationContainer?.nativeElement?.offsetWidth) { - return this.brewInformationContainer?.nativeElement?.offsetWidth - 50; - } - return 0; - } - public getElementOffsetHeight() { - if (this.brewInformationContainer?.nativeElement?.offsetHeight) { - return this.brewInformationContainer?.nativeElement?.offsetHeight - 50; - } - return 0; - } - - public getElementHeight() { - if (this.ionCardParent?.el.offsetHeight) { - return this.ionCardParent?.el.offsetHeight; - } - return 200; - } - public getElementWidth() { - if (this.ionCardParent?.el.offsetWidth) { - return this.ionCardParent?.el.offsetWidth; - } - return 200; - } - public async showBrewActions(event): Promise { event.stopPropagation(); event.stopImmediatePropagation(); diff --git a/src/popover/welcome-popover/welcome-popover.component.ts b/src/popover/welcome-popover/welcome-popover.component.ts index 38c67d8a..25145648 100644 --- a/src/popover/welcome-popover/welcome-popover.component.ts +++ b/src/popover/welcome-popover/welcome-popover.component.ts @@ -12,12 +12,6 @@ import { UIPreparationHelper } from '../../services/uiPreparationHelper'; styleUrls: ['./welcome-popover.component.scss'], }) export class WelcomePopoverComponent implements OnInit { - public slideOpts = { - allowTouchMove: false, - speed: 400, - slide: 4, - }; - public slide: number = 1; @ViewChild('slider', { static: false }) public welcomeSlider: | ElementRef