Skip to content
Permalink
Browse files

More bootstrap 4 updates to the project.

Also:
- switch the ng-bootstrap
- use ng-bootstrap typeahead in album editor
  • Loading branch information...
RickStrahl committed Apr 8, 2019
1 parent 7f1d83b commit fc0ac35f964ff2818c4c5f2bfcd992550926361d
@@ -244,6 +244,12 @@ Websurge-Request-Name: Script

------------------------------------------------------------------

GET http://localhost:5005/api/artistlookup?search=S HTTP/1.1
Accept-Encoding: gzip,deflate
Websurge-Request-Name: Artist Lookup (Typeahead)

------------------------------------------------------------------


----- Start WebSurge Options -----

@@ -254,7 +260,7 @@ Websurge-Request-Name: Script
"CaptureMinimalResponseData": false,
"MaxResponseSize": 0,
"ReplaceQueryStringValuePairs": null,
"ReplaceDomain": "localhost/albumviewer",
"ReplaceDomain": "localhost:5000",
"ReplaceCookieValue": null,
"ReplaceAuthorization": null,
"Username": null,
@@ -27,7 +27,7 @@ The **ASP.NET Core** Backend demonstrates:
The sample also includes a few Server Side Rendered MVC pages for browsing and viewing of albums and artists. I'll be adding the edit pages at a later point.

Version supported:
* **.NET Core 2.2.0**
* **.NET Core 2.2**
* **2.2 SDK or later**
* **Visual Studio 2017.7 or later**

@@ -44,8 +44,8 @@ The **Angular** front end application demonstrates:
* Angular CLI Project

Version supported:
* **Angular 6.0.3**
* **Angular CLI 6.0.3**
* **Angular 7.2.12**
* **Angular CLI 6.2.5**


### Getting Started
@@ -39,25 +39,18 @@
}
],
"styles": [
{"input": "src/css/albumviewer.css"},
{"input": "node_modules/bootstrap/dist/css/bootstrap.css"},
{"input": "node_modules/bootstrap/dist/css/bootstrap-theme.css"},
{"input": "node_modules/font-awesome/css/font-awesome.css"},
{"input": "node_modules/toastr/build/toastr.css"}
{"input": "node_modules/bootstrap/dist/css/bootstrap.css"},
{"input": "node_modules/font-awesome/css/font-awesome.css" },
{"input": "node_modules/toastr/build/toastr.css" },
{"input": "src/css/albumviewer.css" }
],
"scripts": [
{
"input": "node_modules/jquery/dist/jquery.js"
},
{
"input": "node_modules/toastr/toastr.js"
},
{
"input": "node_modules/bootstrap/dist/js/bootstrap.js"
},
{
"input": "node_modules/bootstrap-3-typeahead/bootstrap3-typeahead.js"
}
}
]
},
"configurations": {
@@ -161,4 +154,4 @@
}
}
}
}
}
@@ -16,30 +16,31 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^6.1.10",
"@angular/common": "^6.1.10",
"@angular/compiler": "^6.1.10",
"@angular/core": "^6.1.10",
"@angular/forms": "^6.1.10",
"@angular/http": "^6.1.10",
"@angular/platform-browser": "^6.1.10",
"@angular/platform-browser-dynamic": "^6.1.10",
"@angular/router": "^6.1.10",
"@angular/animations": "^7.2.12",
"@angular/common": "^7.2.12",
"@angular/compiler": "^7.2.12",
"@angular/core": "^7.2.12",
"@angular/forms": "^7.2.12",
"@angular/http": "^7.2.12",
"@angular/platform-browser": "^7.2.12",
"@angular/platform-browser-dynamic": "^7.2.12",
"@angular/router": "^7.2.12",
"@ng-bootstrap/ng-bootstrap": "^4.1.1",
"bootstrap": "^4.3.1",
"core-js": "^2.5.4",
"rxjs": "^6.3.3",
"zone.js": "^0.8.26",
"bootstrap": "^3.3.7",
"bootstrap-3-typeahead": "^4.0.2",
"font-awesome": "^4.7.0",
"jquery": "^3.2.1",
"toastr": "^2.1.2"
"rxjs": "^6.4.0",
"toastr": "^2.1.2",
"tslib": "^1.9.0",
"zone.js": "^0.8.29"
},
"devDependencies": {
"@angular/compiler-cli": "^6.1.10",
"@angular-devkit/build-angular": "~0.6.6",
"typescript": "~2.9.2",
"@angular/cli": "~6.2.5",
"@angular/language-service": "^6.1.10",
"@angular/compiler-cli": "^7.2.12",
"@angular-devkit/build-angular": "~0.13.0",
"typescript": "~3.2.4",
"@angular/cli": "~7.3.8",
"@angular/language-service": "^7.2.12",
"@types/jasmine": "~2.8.6",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~8.9.4",
@@ -55,4 +56,4 @@
"ts-node": "~5.0.1",
"tslint": "~5.9.1"
}
}
}
@@ -1,12 +1,12 @@
<div class="container" >

<div class="btn-group" style="margin-bottom: 10px;">
<a routerLink="/albums" class="btn btn-sm btn-default"><i class="fa fa-list"></i> Albums</a>
<a [routerLink]="['/album/edit',album.Id]" class="btn btn-sm btn-default"><i class="fa fa-edit"></i> Edit</a>
<a [href]="album.AmazonUrl" class="btn btn-sm btn-default"><i class="fa fa-dollar"></i> Buy</a>

<a [href]="album.SpotifyUrl" class="btn btn-sm btn-default"><i class="fa fa-volume-up"></i> Listen</a>
<button (click)="deleteAlbum(album)" class="btn btn-sm btn-default"><i class="fa fa-remove"></i> Delete</button>
<div class="container" >
<div class="btn-group" role="group" style="margin-bottom: 10px;" aria-label="Album Navigation">
<a routerLink="/albums" class="btn btn-sm btn-primary"><i class="fa fa-list"></i> Albums</a>
<a [routerLink]="['/album/edit',album.Id]" class="btn btn-sm btn-primary"><i class="fa fa-edit"></i> Edit</a>
<a [href]="album.AmazonUrl" class="btn btn-sm btn-primary"><i class="fa fa-dollar"></i> Buy</a>

<a [href]="album.SpotifyUrl" class="btn btn-sm btn-primary"><i class="fa fa-volume-up"></i> Listen</a>
<button (click)="deleteAlbum(album)" class="btn btn-sm btn-primary"><i class="fa fa-remove"></i> Delete</button>
</div>

<div class="separator"></div>
@@ -1,9 +1,9 @@
<div class="container" >
<div class="container" >

<div *ngIf="album.Id !== 0" class="btn-group" style="margin-bottom: 10px;">
<a routerLink="/albums" class="btn btn-sm btn-default"><i class="fa fa-list"></i> List</a>
<a [routerLink]="['/album',album.Id]" class="btn btn-sm btn-default"><i class="fa fa-eye"></i> View</a>
<a [href]="album.AmazonUrl" class="btn btn-sm btn-default"><i class="fa fa-dollar"></i> Buy</a>
<div *ngIf="album.Id !== 0" class="btn-group" role="group" style="margin-bottom: 10px;">
<a routerLink="/albums" class="btn btn-sm btn-primary"><i class="fa fa-list"></i> List</a>
<a [routerLink]="['/album',album.Id]" class="btn btn-sm btn-primary"><i class="fa fa-eye"></i> View</a>
<a [href]="album.AmazonUrl" class="btn btn-sm btn-primary"><i class="fa fa-dollar"></i> Buy</a>
</div>

<div class="separator"></div>
@@ -22,19 +22,23 @@
[(ngModel)]="album.Title" autofocus />

</div>
<div class="form-group">
<label for="BandName">Band Name:</label>
<input type="text" class="form-control input-sm typeahead" id="BandName"
required
autocomplete="off"
data-provide="typeahead"
placeholder="Band Name"
name="ArtistName"
[(ngModel)]="album.Artist.ArtistName" />


</div>
<div class="form-group">
<div class="form-group">
<label for="typeahead-basic">Band Name (Auto):</label>
<input id="typeahead-basic" type="text"
name="SearchText"
class="form-control"
[(ngModel)]="album.Artist.ArtistName"
[ngbTypeahead]="search"
[resultFormatter]="resultFormatBandListValue"
[inputFormatter]="inputFormatBandListValue"
#instance="ngbTypeahead"
/>
</div>


<div class="form-group">
<label for="Description">Album Description:</label>
<textarea class="form-control input-sm" id="Description"
placeholder="Album description or review"
@@ -47,7 +51,11 @@

<div class="form-group">
<div class="input-group">
<span class="input-group-addon" title="Image Url"><i class="fa fa-image fa-fw"></i></span>
<span class="input-group-prepend" title="Image Url">
<span class="input-group-text">
<i class="fa fa-image fa-fw"></i>
</span>
</span>
<input type="text" class="form-control input-sm" id="ImageUrl"
required
name="ImageUrl"
@@ -58,7 +66,11 @@

<div class="form-group">
<div class="input-group">
<span class="input-group-addon" title="Url where to buy"><i class="fa fa-dollar fa-fw"></i></span>
<span class="input-group-prepend" title="Url where to buy">
<span class="input-group-text">
<i class="fa fa-dollar fa-fw"></i>
</span>
</span>
<input type="text" class="form-control input-sm" id="AmazonUrl"
placeholder="Purchase Url"
name="AmazonUrl"
@@ -68,7 +80,11 @@

<div class="form-group">
<div class="input-group">
<span class="input-group-addon" title="Url where to buy"><i class="fa fa-spotify fa-fw"></i></span>
<div class="input-group-prepend" title="Url where to buy">
<span class="input-group-text">
<i class="fa fa-spotify fa-fw"></i>
</span>
</div>
<input type="text" class="form-control input-sm" id="SpotifyUrl"
placeholder="Listen Url"
name="SpotifyUrl"
@@ -1,17 +1,24 @@
import {Component, OnInit, ElementRef} from '@angular/core';
import {Component, OnInit, ElementRef} from '@angular/core';
import {Album} from "../business/entities";
import {AlbumService} from "./albumService";
import {Router, ActivatedRoute} from "@angular/router";
import {ErrorInfo} from "../common/errorDisplay";
import {AppConfiguration} from "../business/appConfiguration";
import {UserInfo} from "../business/userInfo";
import { UserInfo } from "../business/userInfo";

import { Observable, merge, of } from 'rxjs';
import { debounceTime, map, switchMap, catchError , distinctUntilChanged } from 'rxjs/operators';

//declare var $:any ;
declare var $:any;
declare var toastr:any;
declare var window:any;

import {slideInLeft, slideIn} from "../common/animations";
import { slideInLeft, slideIn } from "../common/animations";

import { HttpClient } from "@angular/common/http";



@Component({
selector: 'album-editor',
@@ -23,13 +30,18 @@ export class AlbumEditor implements OnInit {
private router: Router,
private albumService: AlbumService,
private config:AppConfiguration,
private user:UserInfo) {
private user: UserInfo,
private httpClient: HttpClient) {
}
model: any;

album: Album = new Album();
error: ErrorInfo = new ErrorInfo();
loaded = false;
aniFrame = 'in';
public searchData: any = {};



ngOnInit() {
if (!this.user.isAuthenticated) {
@@ -38,17 +50,15 @@ export class AlbumEditor implements OnInit {
}

this.config.isSearchAllowed = false;
this.bandTypeAhead();



var id = this.route.snapshot.params["id"];
if (id < 1) {
this.loaded = true;
this.album = this.albumService.newAlbum();
return;
}



this.albumService.getAlbum(id)
.subscribe(result => {
@@ -60,10 +70,11 @@ export class AlbumEditor implements OnInit {
});
}


saveAlbum(album) {
return this.albumService.saveAlbum(album)
.subscribe((album: Album) => {
var msg = album.Title + " has been saved."
var msg = album.Title + " has been saved.";
this.error.info(msg);
toastr.success(msg);
window.document.getElementById("MainView").scrollTop = 0;
@@ -82,33 +93,35 @@ export class AlbumEditor implements OnInit {
this.router.navigate(["login"]);
}
});
};

bandTypeAhead() {
var $input:any = $("#BandName");
var config = this.config;

// delay slightly to ensure that the
// typeahead component is loaded when
// doing a full browser refresh
setTimeout( function () {
$input.typeahead({
source: [],
autoselect: true,
minLength: 0
});

$input.keyup( function() {
let s = $(this).val();
let url = config.urls.url("artistLookup") + s;

$.getJSON(url,
(data) => {
$input.data('typeahead').source = data;
});
});

},1000);
};


/**
* Returns a list of Artist Lookup items and pipes them
* into the look up list. Result format is:
* [ {name: "band", id: "band"}]
*
* Called from ngb-TypeAhead with the search term observable
*/
search = (text$: Observable<string>) => {
return text$.pipe(
debounceTime(200),
distinctUntilChanged(),
// switchMap allows returning an observable rather than maps array
switchMap( (searchText) => this.albumService.artistLookup(searchText) ),
catchError(new ErrorInfo().parseObservableResponseError)
);
}

/**
* Used to format the result data from the lookup into the
* display and list values
* @param value For
*/
resultFormatBandListValue(value: any) {
return value.name;
}
inputFormatBandListValue(value: any) {
return value;
}
}

0 comments on commit fc0ac35

Please sign in to comment.
You can’t perform that action at this time.