Skip to content

Commit

Permalink
Add GEOLOCATION component
Browse files Browse the repository at this point in the history
  • Loading branch information
fttx committed Nov 3, 2023
1 parent 21e64f2 commit 6b9e505
Show file tree
Hide file tree
Showing 20 changed files with 196 additions and 5 deletions.
4 changes: 3 additions & 1 deletion electron/src/handlers/connection.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export class ConnectionHandler implements Handler {
ws.send(JSON.stringify(new responseModelUpdateSettings().fromObject({
outputProfiles: this.settingsHandler.outputProfiles,
events: this.getEnabledEvents(),
savedGeoLocations: this.settingsHandler.savedGeoLocations
})));
}
});
Expand Down Expand Up @@ -151,7 +152,8 @@ export class ConnectionHandler implements Handler {
* @deprecated
*/
quantityEnabled: false,
serverUUID: this.settingsHandler.getServerUUID()
serverUUID: this.settingsHandler.getServerUUID(),
savedGeoLocations: this.settingsHandler.savedGeoLocations as { name: string, latitude: number, longitude: number }[]
});

if (request && request.deviceId) {
Expand Down
1 change: 1 addition & 0 deletions electron/src/handlers/scans.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export class ScansHandler implements Handler {
google_sheets: null,
javascript_function: null,
static_text: null,
geolocation: null,
};
// Search if there is a corresponding Output component to assign to the NULL variables
let keys = Object.keys(variables);
Expand Down
4 changes: 3 additions & 1 deletion electron/src/handlers/settings.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ export class SettingsHandler implements Handler {
get onSmartphoneChargeCommand() {
return this.settings.onSmartphoneChargeCommand
}

get savedGeoLocations() {
return this.store.get(Config.STORAGE_SAVED_GEOLOCATIONS, []);
}
async onWsMessage(ws: WebSocket, message: any, req: http.IncomingMessage): Promise<any> {
throw new Error("Method not implemented.");
return message;
Expand Down
3 changes: 3 additions & 0 deletions ionic/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import { MyApp } from './app.component';
import { ComponentEditorImagePage } from '../pages/component-editor/component-editor-image/component-editor-image';
import { ImageViewerPage } from '../pages/image-viewer/image-viewer';
import { ExportOutputTemplatePopoverPage } from '../pages/export-output-template-popover/export-output-template-popover';
import { ComponentEditorGeolocationPage } from '../pages/component-editor/component-editor-geolocation/component-editor-geolocation';

@NgModule({
declarations: [
Expand All @@ -67,6 +68,7 @@ import { ExportOutputTemplatePopoverPage } from '../pages/export-output-template
ComponentEditorAlertPage,
ComponentEditorBarcodePage,
ComponentEditorBeepPage,
ComponentEditorGeolocationPage,
ComponentEditorCsvLookupPage,
ComponentEditorCsvUpdatePage,
ComponentEditorGSheetUpdatePage,
Expand Down Expand Up @@ -138,6 +140,7 @@ import { ExportOutputTemplatePopoverPage } from '../pages/export-output-template
ComponentEditorAlertPage,
ComponentEditorBarcodePage,
ComponentEditorBeepPage,
ComponentEditorGeolocationPage,
ComponentEditorCsvLookupPage,
ComponentEditorCsvUpdatePage,
ComponentEditorGSheetUpdatePage,
Expand Down
9 changes: 9 additions & 0 deletions ionic/src/assets/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,15 @@
"medium": "متوسط",
"fast": "سريع",
"testAudio": "اختبار الصوت",
"savedLocation": "الموقع المحفوظ",
"geoLocationSavedLocations": "المواقع المحفوظة",
"geoLocationDescription": "يحصل على إحداثيات GPS (خط العرض وخط الطول). استخدم &quot;المواقع المحفوظة&quot; للحصول على اسم مخصص بدلاً من الإحداثيات الرقمية في النتيجة. للحصول على معلومات دقيقة عن الموقع، تتعلق باللحظة الدقيقة لاكتساب الباركود، تأكد من وضع مكون الـ GEOLOCATION بعد مكونات الحجب مثل BARCODE.",
"geoLocationAssignNames": "قم بتسمية الإحداثيات بحيث عند مسح الباركود بالقرب من هذه المواقع يتم عرض الاسم بدلاً من الإحداثيات.",
"geoLocationCoordinatesTutorial": "كيف يمكن إيجاد الإحداثيات؟",
"geoLocationNotfound": "لم يتم العثور على مواقع محفوظة",
"geoLocationAddLocation": "أضف موقعاً",
"geoLocationMaxDistanceFromSavedLocation": "المسافة القصوى من الموقع المحفوظ",
"geoLocationMaxDistanceFromSavedLocationDescription": "المسافة القصوى بالكيلومترات من الموقع المحفوظ لعرض اسمه بدلاً من الإحداثيات",
"title": "العنوان",
"message": "الرسالة",
"optionsList": "قائمة الخيارات",
Expand Down
9 changes: 9 additions & 0 deletions ionic/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,15 @@
"medium": "Medium",
"fast": "Fast",
"testAudio": "Test audio",
"savedLocation": "Saved location ",
"geoLocationSavedLocations": "Saved locations",
"geoLocationDescription": "Collect GPS coordinates (latitude and longitude). Use &quot;Saved locations&quot; to output a custom location name instead. To get accurate location information, that is reffering at moment of the the barcode acquisition, make sure to put the GEOLOCATION component after blocking components such as BARCODE.",
"geoLocationAssignNames": "Assign names to coordinates so that when scanning barcodes near that location its name will be outputed instead of coordinates.",
"geoLocationCoordinatesTutorial": "How to find coordinates?",
"geoLocationNotfound":" No Saved locations found'",
"geoLocationAddLocation": "Add location",
"geoLocationMaxDistanceFromSavedLocation": "Max distance from saved location",
"geoLocationMaxDistanceFromSavedLocationDescription": "The maximum distance in kilometers from the saved location to output its name instead of coordinates",
"title": "Title",
"message": "Message",
"optionsList": "Options list",
Expand Down
9 changes: 9 additions & 0 deletions ionic/src/assets/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,15 @@
"medium": "Medio",
"fast": "Rápido",
"testAudio": "Prueba de audio",
"savedLocation": "Ubicación guardada",
"geoLocationSavedLocations": "Ubicaciones guardadas",
"geoLocationDescription": "Obtiene coordenadas GPS (latitud y longitud). Utiliza &quot;Ubicaciones guardadas&quot; para obtener un nombre personalizado en la salida en lugar de las coordenadas numéricas. Para obtener información precisa de la ubicación que se refiera al instante exacto de la captura del código de barras, asegúrate de colocar el componente GEOLOCATION después de componentes que bloquean como BARCODE.",
"geoLocationAssignNames": "Asigna nombres a las coordenadas para que, al escanear códigos de barras cerca de estas ubicaciones, se muestre el nombre en lugar de las coordenadas.",
"geoLocationCoordinatesTutorial": "¿Cómo encontrar las coordenadas?",
"geoLocationNotfound": "No se encontraron ubicaciones guardadas",
"geoLocationAddLocation": "Agregar ubicación",
"geoLocationMaxDistanceFromSavedLocation": "Distancia máxima desde la ubicación guardada",
"geoLocationMaxDistanceFromSavedLocationDescription": "La distancia máxima en kilómetros desde la ubicación guardada para mostrar su nombre en lugar de las coordenadas",
"title": "Título",
"message": "Mensaje",
"optionsList": "Lista de opciones",
Expand Down
9 changes: 9 additions & 0 deletions ionic/src/assets/i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,15 @@
"medium": "Medio",
"fast": "Veloce",
"testAudio": "Test audio",
"savedLocation": "Posizione salvata",
"geoLocationSavedLocations": "Posizioni salvate",
"geoLocationDescription": "Ottiene le coordinate GPS (latitudine e longitudine). Usa &quot;Posizioni salvate&quot; per avere in uscita un nome personalizzato invece delle coordinate numeriche. Per ottenere informazioni precise sulla posizione, che facciano riferimento all'esatto istante di acquisizione del codice a barre, assicurati di inserire il componente GEOLOCATION dopo componenti bloccanti come ad esempio BARCODE.",
"geoLocationAssignNames": "Assegna nomi alle coordinate in modo che, quando si scansionano codici a barre vicino a queste posizioni, venga visualizzato il nome invece delle coordinate.",
"geoLocationCoordinatesTutorial": "Come trovare le coordinate?",
"geoLocationNotfound": "Nessuna posizione salvata",
"geoLocationAddLocation": "Aggiungi posizione",
"geoLocationMaxDistanceFromSavedLocation": "Distanza massima dalla posizione salvata",
"geoLocationMaxDistanceFromSavedLocationDescription": "The maximum distance in kilometers from the saved location to output its name instead of coordinates",
"title": "Titolo",
"message": "Messaggio",
"optionsList": "Elenco delle opzioni",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ComponentEditorVariablePage } from '../../pages/component-editor/compon
import { ComponentEditorWooCommercePage } from '../../pages/component-editor/component-editor-woocommerce/component-editor-woocommerce';
import { UtilsProvider } from '../../providers/utils/utils';
import { ComponentEditorImagePage } from '../../pages/component-editor/component-editor-image/component-editor-image';
import { ComponentEditorGeolocationPage } from '../../pages/component-editor/component-editor-geolocation/component-editor-geolocation';


@Component({
Expand Down Expand Up @@ -64,6 +65,7 @@ export class OutputComponentComponent {
case 'variable': editor = ComponentEditorVariablePage; break;
case 'woocommerce': editor = ComponentEditorWooCommercePage; break;
case 'image': editor = ComponentEditorImagePage; break;
case 'geolocation': editor = ComponentEditorGeolocationPage; break;
}
let modal = this.modalCtrl
.create(editor, { outputBlock: this.outputBlock }, { enableBackdropDismiss: false, showBackdrop: true });
Expand Down
1 change: 1 addition & 0 deletions ionic/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export class Config {
public static STORAGE_SETTINGS = 'storage_settings';
public static STORAGE_LAST_VERSION = 'storage_last_version';
public static STORAGE_LICENSE_EVER_ACTIVATED = 'storage_license_ever_activated';
public static STORAGE_SAVED_GEOLOCATIONS = 'storage_saved_geolocations';

public static GAPIS_CREDENTIALS = {
// 1. Generate credentials: https://console.cloud.google.com/apis/
Expand Down
9 changes: 8 additions & 1 deletion ionic/src/models/output-block.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class OutputBlockModel {
*
* Warning: remeber to update also edit-output-block-pop-over.ts/onHelpClick() method when chaning this field.
*/
type: 'key' | 'text' | 'variable' | 'function' | 'barcode' | 'delay' | 'if' | 'endif' | 'http' | 'run' | 'select_option' | 'image' | 'beep' | 'csv_lookup' | 'csv_update' | 'alert' | 'date_time' | 'woocommerce' | 'google_sheets';
type: 'key' | 'text' | 'variable' | 'function' | 'barcode' | 'delay' | 'if' | 'endif' | 'http' | 'run' | 'select_option' | 'image' | 'beep' | 'csv_lookup' | 'csv_update' | 'alert' | 'date_time' | 'woocommerce' | 'google_sheets' | 'geolocation';
/**
* When true means that the user doesn't want to type or append to files
* the component value but instead he wants to acquire the data, and use it
Expand Down Expand Up @@ -207,6 +207,13 @@ export class OutputBlockModel {
imageHd?: boolean;
outputImagePath?: string;


/**
* Parameter for the GEOLOCATION component
*/
outputMode?: 'coordinates' | 'savedLocation';
maxDistanceFromSavedLocation?: number; // meters

static FindEndIfIndex(outputBlocks: OutputBlockModel[], startFrom = 0): number {
let skip = 0;
for (let i = startFrom; i < outputBlocks.length; i++) {
Expand Down
8 changes: 6 additions & 2 deletions ionic/src/models/response.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ export class responseModelHelo extends responseModel {
outputProfiles: OutputProfileModel[];
events: string[];
serverUUID: string;
savedGeoLocations: { name: string, latitude: number, longitude: number }[];

/**
* @deprecated Use OutputProfiles instead
*/
quantityEnabled: boolean;

public fromObject(obj: ({ version: string, outputProfiles: OutputProfileModel[], quantityEnabled: boolean, events: string[], serverUUID:string })) {
public fromObject(obj: ({ version: string, outputProfiles: OutputProfileModel[], quantityEnabled: boolean, events: string[], serverUUID: string, savedGeoLocations: { name: string, latitude: number, longitude: number }[] })) {
this.outputProfiles = obj.outputProfiles;
if (obj.events) {
this.events = obj.events;
Expand All @@ -58,6 +59,7 @@ export class responseModelHelo extends responseModel {
this.outputProfiles = obj.outputProfiles;
this.quantityEnabled = obj.quantityEnabled;
this.serverUUID = obj.serverUUID;
this.savedGeoLocations = obj.savedGeoLocations || [];
return this;
}
}
Expand Down Expand Up @@ -117,14 +119,16 @@ export class responseModelUpdateSettings extends responseModel {
// Warning: these same settings are also communicated in the HELO response
outputProfiles: OutputProfileModel[];
events: string[];
savedGeoLocations: { name: string, latitude: number, longitude: number }[];

public fromObject(obj: ({ outputProfiles: OutputProfileModel[], events: string[] })) {
public fromObject(obj: ({ outputProfiles: OutputProfileModel[], events: string[], savedGeoLocations: { name: string, latitude: number, longitude: number }[] })) {
this.outputProfiles = obj.outputProfiles;
if (obj.events) {
this.events = obj.events;
} else {
this.events = [];
}
this.savedGeoLocations = obj.savedGeoLocations || [];
return this;
}
}
Expand Down
1 change: 1 addition & 0 deletions ionic/src/models/scan.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class ScanModel {
case 'alert': return ''
case 'woocommerce': return block.value;
case 'google_sheets': return block.value;
case 'geolocation': return block.value;
default: return '';
}
}).join(fieldSeparator).replace(/\s+/g, ' ');
Expand Down
1 change: 1 addition & 0 deletions ionic/src/models/settings.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ export class SettingsModel {
autoUpdate: boolean = true;
onSmartphoneChargeCommand: string = '';
maxScanSessionsNumber: number = 2000; // Update also SettingsPage.MAX_SCAN_SESSION_NUMBER_UNLIMITED
savedGeoLocations:{ name: string, latitude: number, longitude: number }[] = [];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<component-editor [outputBlock]="outputBlock">
<ion-item no-lines text-wrap>
<p [innerHtml]="'geoLocationDescription' | translate"></p>
</ion-item>

<ion-item no-lines>
<ion-label no-lines>{{ 'geoLocationSavedLocations' | translate }}</ion-label>
</ion-item>
<ion-item no-lines text-wrap>
<p>{{ 'geoLocationAssignNames' | translate }}</p>
<p>
<a class="clickable" (click)="electronProvider.shell.openExternal('https://www.loom.com/share/07153366b44c40d9b778396671cada98?sid=c9cd4e33-6653-4541-a42b-566889806cb6')">
{{ 'geoLocationCoordinatesTutorial' | translate }}
</a>
</p>
</ion-item>
<ion-grid class="fields" [hidden]="!savedGeoLocations || !savedGeoLocations.length">
<ion-item no-lines *ngFor="let field of savedGeoLocations; let i = index;">
<ion-row no-padding>
<ion-col>
<input [(ngModel)]="savedGeoLocations[i].name" class="inline-input" type="text" placeholder="Location name" />
</ion-col>
<ion-col col-3>
<input (keyup)="onLatitudeChange(i)" (change)="onLatitudeChange(i)" [(ngModel)]="savedGeoLocations[i].latitude" class="inline-input" type="text" placeholder="0.000000" />
</ion-col>
<ion-col col-3>
<input [(ngModel)]="savedGeoLocations[i].longitude" class="inline-input" type="text" placeholder="0.000000" />
</ion-col>
<ion-col col-1>
<button ion-button small center clear icon-only color="output-block-component-geolocation" class="btn-output-template-action" (click)="deleteSavedLocation(i)">
<ion-icon name="trash"></ion-icon>
</button>
</ion-col>
</ion-row>
</ion-item>
</ion-grid>

<p [hidden]="!(!savedGeoLocations || !savedGeoLocations.length)" text-center>
{{ 'geoLocationNotfound' | translate }}
</p>

<ion-item text-center padding-top no-lines>
<button ion-button small icon-start (click)="addSavedLocation()" color="output-block-component-geolocation">
<ion-icon name="add"></ion-icon>
{{ 'geoLocationAddLocation' | translate }}
</button>
</ion-item>

<ion-item text-wrap [hidden]="!savedGeoLocations || !savedGeoLocations.length">
<label for="_maxDistanceFromSavedLocation">{{ 'geoLocationMaxDistanceFromSavedLocation' | translate }}</label>
<input id="_maxDistanceFromSavedLocation" [(ngModel)]="outputBlock.maxDistanceFromSavedLocation" class="inline-input" type="number" placeholder="0" />
<br>
<p>{{ 'geoLocationMaxDistanceFromSavedLocationDescription' | translate }}</p>
</ion-item>

</component-editor>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
page-component-editor-geolocation {
ion-col {
padding: 0 10px 0 0 !important;

input {
margin-top: 1px !important
}
}

.fields ion-label {
margin: 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Component } from '@angular/core';
import { NavParams } from 'ionic-angular';
import { OutputBlockModel } from '../../../models/output-block.model';
import { ElectronProvider } from '../../../providers/electron/electron';
import { UtilsProvider } from '../../../providers/utils/utils';
import { Config } from '../../../config';

@Component({
selector: 'page-component-editor-geolocation',
templateUrl: 'component-editor-geolocation.html',
})
export class ComponentEditorGeolocationPage {

public outputBlock: OutputBlockModel;
public savedGeoLocations: { name: string, latitude: number, longitude: number }[] = [];

constructor(
public navParams: NavParams,
private utilsProvider: UtilsProvider,
private electronProvider: ElectronProvider,
) {
this.outputBlock = this.navParams.get('outputBlock');

this.savedGeoLocations = this.electronProvider.store.get(Config.STORAGE_SAVED_GEOLOCATIONS, []);
}

ionViewWillUnload() {
this.outputBlock.value = Math.random() + ''; // trigger Save & Apply
// keep only locations that have actual values and that can be converted to numbers
this.savedGeoLocations = this.savedGeoLocations.filter(x => x.latitude && x.longitude && !isNaN(x.latitude) && !isNaN(x.longitude));
// convert to numbers
this.savedGeoLocations = this.savedGeoLocations.map(x => { return { name: x.name, latitude: parseFloat(x.latitude.toString()), longitude: parseFloat(x.longitude.toString()) } });
// save
this.electronProvider.store.set(Config.STORAGE_SAVED_GEOLOCATIONS, this.savedGeoLocations);
}

ionViewDidLoad() {
console.log('ionViewDidLoad ComponentEditorGeolocationPage');
}

async addSavedLocation() {
this.savedGeoLocations = [...this.savedGeoLocations, { name: await this.utilsProvider.text('savedLocation') + (this.savedGeoLocations.length + 1).toString(), latitude: null, longitude: null }];
}

deleteSavedLocation(removeIndex: number) {
this.savedGeoLocations = this.savedGeoLocations.filter((x, index) => index != removeIndex);
}

onLatitudeChange(index: number) {
let latitude = (this.savedGeoLocations[index].latitude || 0).toString();
if (latitude.indexOf(',') > -1) {
let latitudeLongitude = latitude.split(',');
this.savedGeoLocations[index].latitude = parseFloat(latitudeLongitude[0] || '0');
this.savedGeoLocations[index].longitude = parseFloat(latitudeLongitude[1] || '0');
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
<ion-item text-wrap no-lines [hidden]="!enabled" >
<label for="_outputImagePath">{{ 'outputImagePath' | translate }}</label>
<input id="_outputImagePath" [(ngModel)]="outputBlock.outputImagePath" class="inline-input" type="text" placeholder="C&#58;&#92;folder&#92;{{ curlyOpen }} barcode {{ curlyClose }}.jpg" />
<!-- Add Path selector -->
<!-- (also to csv lookup) -->
</ion-item>

<ion-item text-wrap no-lines>
Expand Down
Loading

0 comments on commit 6b9e505

Please sign in to comment.