Skip to content

Commit

Permalink
remaining CRUD operations
Browse files Browse the repository at this point in the history
  • Loading branch information
David Domigues committed Sep 23, 2021
1 parent 66bf27f commit 0f1adc9
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 43 deletions.
10 changes: 0 additions & 10 deletions src/app/app-routing.module.ts

This file was deleted.

67 changes: 46 additions & 21 deletions src/app/app.component.ts
@@ -1,52 +1,77 @@
import { Component } from '@angular/core';
import { MapInfoWindow, MapMarker } from '@angular/google-maps';
import { BehaviorSubject } from 'rxjs';

import { MarkerForm } from './components/marker-form.component';
import { MarkersService } from './markers.service';
import { MarkerData } from './models/marker-data';

@Component({
selector: 'app-root',
styleUrls: ['./app.component.scss'],
template: `
<google-map [options]="options" width="100vw" height="100vh" (mapClick)="onClick($event)">
<google-map [options]="options" width="100vw" height="100vh" (mapClick)="onAddMarker($event, info, markerForm)">
<!-- MARKERS -->
<map-marker
#marker="mapMarker"
*ngFor="let data of markersService.markers$ | async"
[position]="data"
[options]="markerOptions"
(mapClick)="onOpenInfo(marker, info, data, paragraph, image)"
*ngFor="let data of markers$ | async; trackBy: trackFn"
[position]="{ lat: +data.lat, lng: +data.long }"
(mapClick)="onViewMarker(marker, info, data, markerForm)"
></map-marker>
<!-- INFO -->
<!-- MARKER FORM -->
<map-info-window #info="mapInfoWindow">
<p #paragraph></p>
<img #image alt="" />
<marker-form #markerForm (submitted)="onRefresh()"></marker-form>
</map-info-window>
</google-map>
<pre>
{{ markersService.markers$ | async | json }}
<!-- <pre>
{{ markers$ | async | json }}
</pre
>
> -->
`,
})
export class AppComponent {
refresh = new BehaviorSubject(null);
markers$ = this.mrkrService.getMarkers(this.refresh);

options: google.maps.MapOptions = {
center: { lat: 40.4378698, lng: -3.8196208 },
center: { lat: 42, lng: -1 },
zoom: 6,
};

markerOptions: google.maps.MarkerOptions = { draggable: false };
markerPositions: google.maps.LatLngLiteral[] = [];
constructor(private mrkrService: MarkersService) {}

onAddMarker(event: google.maps.MapMouseEvent, infoWindow: MapInfoWindow, markerForm: MarkerForm) {
const position = event.latLng.toJSON();

markerForm.form.reset();
markerForm.form.patchValue({
lat: position.lat,
long: position.lng,
});

constructor(public markersService: MarkersService) {}
infoWindow.options = { position };
infoWindow.open();
}

onViewMarker(marker: MapMarker, infoWindow: MapInfoWindow, mrkData: MarkerData, markerForm: MarkerForm) {
this.mrkrService.getMarkersById(mrkData.id).subscribe((data) => {
markerForm.form.reset();
markerForm.form.patchValue(data);
infoWindow.open(marker);
});
}

onClick(event: google.maps.MapMouseEvent) {
this.markerPositions.push(event.latLng.toJSON());
ngAfterViewInit() {
setTimeout(() => {
const dismissButton: HTMLButtonElement = document.querySelector('.dismissButton');
dismissButton && dismissButton.click();
}, 1000);
}

onOpenInfo(marker: MapMarker, infoWindow: MapInfoWindow, mrkData: MarkerData, paragraph: HTMLParagraphElement, image: HTMLImageElement) {
image.src = mrkData.image_url;
paragraph.innerText = mrkData.content;
infoWindow.open(marker);
onRefresh() {
this.refresh.next(null);
}

trackFn = (idx, { id }) => id;
}
8 changes: 5 additions & 3 deletions src/app/app.module.ts
@@ -1,14 +1,16 @@
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { GoogleMapsModule } from '@angular/google-maps';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { MarkerForm } from './components/marker-form.component';

@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AppRoutingModule, HttpClientModule, GoogleMapsModule],
declarations: [AppComponent, MarkerForm],
imports: [BrowserModule, HttpClientModule, CommonModule, GoogleMapsModule, ReactiveFormsModule],
bootstrap: [AppComponent],
})
export class AppModule {}
59 changes: 59 additions & 0 deletions src/app/components/marker-form.component.scss
@@ -0,0 +1,59 @@
.form-fields {
display: grid;
gap: 5px;
grid-template-columns: 75px auto;

b {
text-align: right;
line-height: 20px;
}

input,
textarea {
width: 100%;
box-sizing: border-box;
border: none;
border-bottom: 2px solid #e2bdbd;

&:focus-visible {
outline: none;
border-bottom: 2px solid #b79191;
}
}
}

img {
width: 20vw;
margin: 4px auto;
display: block;
}

button {
border: none;
color: white;
padding: 8px;
text-align: center;
font-size: 14px;
cursor: pointer;
width: 50%;

&[type='submit'] {
background: #4caf50;

&:disabled {
background: #4caf509c;
}

&:active {
background: #4caf50e0;
}
}

&[type='button'] {
background: #fb3324;

&:active {
background: #fb3324ab;
}
}
}
59 changes: 59 additions & 0 deletions src/app/components/marker-form.component.ts
@@ -0,0 +1,59 @@
import { Component, EventEmitter, Output } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { MapInfoWindow } from '@angular/google-maps';

import { MarkersService } from './../markers.service';

@Component({
selector: 'marker-form',
styleUrls: ['marker-form.component.scss'],
template: `
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div class="form-fields">
<b> Title: </b>
<input formControlName="title" required />
<b> Content: </b>
<textarea rows="5" formControlName="content" required></textarea>
<b> Image URL: </b>
<input #image formControlName="image_url" />
</div>
<img [src]="image.value" alt="insert a valid image URL" />
<button type="submit" [disabled]="form.invalid">SUBMIT</button>
<button *ngIf="markerId" type="button" (click)="onDelete()">DELETE</button>
</form>
`,
})
export class MarkerForm {
form = new FormGroup({
id: new FormControl(),
title: new FormControl(),
content: new FormControl(),
image_url: new FormControl(),
lat: new FormControl(),
long: new FormControl(),
});

@Output() submitted = new EventEmitter();

get markerId() {
return this.form.get('id').value;
}

constructor(private infoWindow: MapInfoWindow, private mrkService: MarkersService) {}

onSubmit() {
this.mrkService.submitMarker(this.form.getRawValue()).subscribe((next) => {
this.submitted.emit(next);
this.infoWindow.close();
});
}

onDelete() {
this.mrkService.deleteMarker(this.markerId).subscribe((next) => {
this.submitted.emit(next);
this.infoWindow.close();
});
}
}
29 changes: 24 additions & 5 deletions src/app/markers.service.ts
@@ -1,12 +1,31 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { iif, Subject } from 'rxjs';
import { switchMap } from 'rxjs/operators';

import { MarkerData } from './models/marker-data';

@Injectable({ providedIn: 'root' })
export class MarkersService {
markers$ = this.http
.get('http://localhost:3000/api/v1/posts')
.pipe(map((markers: any[]) => markers.map((m) => ({ ...m, lat: +m.lat, lng: +m.long }))));

constructor(private http: HttpClient) {}

getMarkers(refreshSignal: Subject<null>) {
return refreshSignal.pipe(switchMap(() => this.http.get('http://localhost:3000/api/v1/posts')));
}

getMarkersById(id: number) {
return this.http.get(`http://localhost:3000/api/v1/posts/${id}`);
}

submitMarker(body: Partial<MarkerData>) {
return iif(
() => !!body.id,
this.http.put(`http://localhost:3000/api/v1/posts/${body.id}`, body),
this.http.post('http://localhost:3000/api/v1/posts', body)
);
}

deleteMarker(id: number) {
return this.http.delete(`http://localhost:3000/api/v1/posts/${id}`);
}
}
3 changes: 1 addition & 2 deletions src/app/models/marker-data.ts
Expand Up @@ -2,10 +2,9 @@ export interface MarkerData {
id: number;
title: string;
content: string;
lat: number;
lat: string;
long: string;
image_url: string;
created_at: string;
updated_at: string;
lng: number;
}
2 changes: 1 addition & 1 deletion src/index.html
Expand Up @@ -7,7 +7,7 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC-r04m8RqFPzNsAx3HkhUA5MHlBh7MhyE"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDXEKkvJ1Tcei5T5SyJQUdaVtrejJzlka0"></script>
</head>

<body>
Expand Down
4 changes: 3 additions & 1 deletion src/styles.scss
@@ -1,6 +1,8 @@
html,
body {
height: 100%;
}
body {
margin: 0;
font-family: Ubuntu-Regular;
font-family: Roboto, 'Helvetica Neue', sans-serif;
}

0 comments on commit 0f1adc9

Please sign in to comment.