search page

This commit is contained in:
Sercan Yemen 2017-08-01 17:12:26 +03:00
parent 4d477561b7
commit 59e58ce4f8
17 changed files with 652 additions and 14 deletions

View File

@ -32,6 +32,7 @@ import {
MdTableModule, MdTableModule,
MdTabsModule, MdTabsModule,
} from '@angular/material'; } from '@angular/material';
import { CdkTableModule } from '@angular/cdk';
@NgModule({ @NgModule({
imports: [ imports: [
@ -65,7 +66,8 @@ import {
MdTableModule, MdTableModule,
MdTabsModule, MdTabsModule,
MdToolbarModule, MdToolbarModule,
MdTooltipModule MdTooltipModule,
CdkTableModule
], ],
exports: [ exports: [
MdAutocompleteModule, MdAutocompleteModule,
@ -98,7 +100,8 @@ import {
MdTableModule, MdTableModule,
MdTabsModule, MdTabsModule,
MdToolbarModule, MdToolbarModule,
MdTooltipModule MdTooltipModule,
CdkTableModule
], ],
}) })
export class MaterialModule export class MaterialModule

View File

@ -159,6 +159,9 @@ md-icon.status {
padding: 0 8px; padding: 0 8px;
.pagination-item { .pagination-item {
display: flex;
align-items: center;
justify-content: center;
min-width: 48px; min-width: 48px;
min-height: 56px; min-height: 56px;
line-height: 56px; line-height: 56px;

View File

@ -8,6 +8,7 @@ import { ProfileFakeDb } from './profile';
import { ContactsFakeDb } from './contacts'; import { ContactsFakeDb } from './contacts';
import { InvoiceFakeDb } from './invoice'; import { InvoiceFakeDb } from './invoice';
import { FileManagerFakeDb } from './file-manager'; import { FileManagerFakeDb } from './file-manager';
import { SearchFakeDb } from './search';
export class FuseFakeDbService implements InMemoryDbService export class FuseFakeDbService implements InMemoryDbService
{ {
@ -30,7 +31,9 @@ export class FuseFakeDbService implements InMemoryDbService
'profile-about' : ProfileFakeDb.about, 'profile-about' : ProfileFakeDb.about,
'contacts' : ContactsFakeDb.contacts, 'contacts' : ContactsFakeDb.contacts,
'invoice' : InvoiceFakeDb.invoice, 'invoice' : InvoiceFakeDb.invoice,
'file-manager' : FileManagerFakeDb.files 'file-manager' : FileManagerFakeDb.files,
'search-classic' : SearchFakeDb.classic,
'search-table' : SearchFakeDb.table
}; };
} }
} }

View File

@ -0,0 +1,139 @@
export class SearchFakeDb
{
public static classic = [
{
'title' : 'Dynamically Procrastinate B2C',
'url' : 'ourwebaddress.com/articles/procrastinate',
'excerpt': 'Collaboratively administrate empowered markets via plug-and-play networks. Dynamically procrastinate B2C users after installed base benefits.'
},
{
'title' : 'Cross Media',
'url' : 'ourwebaddress.com/articles/cross-media',
'excerpt': 'Efficiently unleash cross-media information without cross-media value. Quickly maximize timely deliverables for real-time schemas.'
},
{
'title' : 'Synergize',
'url' : 'ourwebaddress.com/articles/synergize',
'excerpt': 'Completely synergize resource taxing relationships via premier niche markets. Professionally cultivate one-to-one customer service with robust ideas.'
},
{
'title' : 'Parallel Platforms',
'url' : 'ourwebaddress.com/articles/parallel-paltforms',
'excerpt': 'Objectively innovate empowered manufactured products whereas parallel platforms. Holisticly predominate extensible testing procedures for reliable supply chains.'
},
{
'title' : 'Growth Strategies',
'url' : 'ourwebaddress.com/articles/growth-strategies',
'excerpt': 'Proactively envisioned multimedia based expertise and cross-media growth strategies. Holistically pontificate installed base portals after maintainable products.'
},
{
'title' : 'Methodologies',
'url' : 'ourwebaddress.com/articles/methodologies',
'excerpt': 'Phosfluorescently engage worldwide methodologies with web-enabled technology. Completely pursue scalable customer service through sustainable potentialities.'
},
{
'title' : 'E-tailers',
'url' : 'ourwebaddress.com/articles/e-trailers',
'excerpt': 'Collaboratively administrate turnkey channels whereas virtual e-tailers. Objectively seize scalable metrics whereas proactive e-services.'
},
{
'title' : 'Web Readiness',
'url' : 'ourwebaddress.com/articles/web-readiness',
'excerpt': 'Credibly innovate granular internal or organic sources whereas high standards in web-readiness. Dramatically synthesize integrated schemas with optimal networks.'
}
];
public static table = [
{
'name' : 'Airi Satou',
'position' : 'Accountant',
'office' : 'Tokyo',
'age' : '33',
'startDate': '2008/11/28',
'salary' : '162700',
'email' : 'a.satou@mail.com'
},
{
'name' : 'Angellica Ramos',
'position' : 'Chief Executive Officer (CEO)',
'office' : 'London',
'age' : '47',
'startDate': '2009/10/09',
'salary' : '1200000',
'email' : 'a.ramos@mail.com'
},
{
'name' : 'Ashton Cox',
'position' : 'Hunior Technical Author',
'office' : 'San Fransisco',
'age' : '66',
'startDate': '2009/01/12',
'salary' : '86000',
'email' : 'a.cox@mail.com'
},
{
'name' : 'Bradley Greer',
'position' : 'Software Engineer',
'office' : 'London',
'age' : '41',
'startDate': '2012/10/13',
'salary' : '132000',
'email' : 'b.greer@mail.com'
},
{
'name' : 'Brenden Wagner',
'position' : 'Software Engineer',
'office' : 'San Fransisco',
'age' : '28',
'startDate': '2011/06/07',
'salary' : '206850',
'email' : 'b.wagner@mail.com'
},
{
'name' : 'Brielle Williamson',
'position' : 'Integration Specialist',
'office' : 'New York',
'age' : '61',
'startDate': '2012/12/02',
'salary' : '372000',
'email' : 'b.williamson@mail.com'
},
{
'name' : 'Bruno Nash',
'position' : 'Software Engineer',
'office' : 'London',
'age' : '38',
'startDate': '2011/05/03',
'salary' : '163500',
'email' : 'b.nash@mail.com'
},
{
'name' : 'Caesar Vance',
'position' : 'Pre-Sales Support',
'office' : 'New York',
'age' : '21',
'startDate': '2011/12/12',
'salary' : '106450',
'email' : 'c.vance@mail.com'
},
{
'name' : 'Cara Stevens',
'position' : 'Sales Assistant',
'office' : 'New York',
'age' : '46',
'startDate': '2011/12/06',
'salary' : '145600',
'email' : 'c.stevens@mail.com'
},
{
'name' : 'Cedric Kelly',
'position' : 'Senior Javascript Developer',
'office' : 'Edinburg',
'age' : '22',
'startDate': '2012/03/29',
'salary' : '433060',
'email' : 'c.kelly@mail.com'
}
];
}

View File

@ -27,18 +27,18 @@
</ngx-datatable-column> </ngx-datatable-column>
<ngx-datatable-column name="Name" prop="name"> <ngx-datatable-column name="Name" prop="name" [width]="200">
</ngx-datatable-column> </ngx-datatable-column>
<ngx-datatable-column name="Type" prop="type"> <ngx-datatable-column name="Type" prop="type" [width]="200">
</ngx-datatable-column> </ngx-datatable-column>
<ngx-datatable-column name="Owner" prop="owner"> <ngx-datatable-column name="Owner" prop="owner" [width]="200">
</ngx-datatable-column> </ngx-datatable-column>
<ngx-datatable-column name="Size" prop="size"> <ngx-datatable-column name="Size" prop="size" [width]="200">
</ngx-datatable-column> </ngx-datatable-column>
<ngx-datatable-column name="Last Modified" prop="modified"> <ngx-datatable-column name="Last Modified" prop="modified" [width]="200">
</ngx-datatable-column> </ngx-datatable-column>
</ngx-datatable> </ngx-datatable>

View File

@ -13,12 +13,15 @@ import { ComingSoonComponent } from './coming-soon/coming-soon.component';
import { Error404Component } from './errors/404/error-404.component'; import { Error404Component } from './errors/404/error-404.component';
import { Error500Component } from './errors/500/error-500.component'; import { Error500Component } from './errors/500/error-500.component';
import { InvoiceModernComponent } from './invoices/modern/modern.component'; import { InvoiceModernComponent } from './invoices/modern/modern.component';
import { MaintenanceComponent } from './maintenance/maintenance.component';
import { ProfileComponent } from './profile/profile.component';
import { ProfileModule } from './profile/profile.module';
import { ProfileService } from './profile/profile.service';
import { InvoiceCompactComponent } from './invoices/compact/compact.component'; import { InvoiceCompactComponent } from './invoices/compact/compact.component';
import { InvoiceService } from './invoices/invoice.service'; import { InvoiceService } from './invoices/invoice.service';
import { MaintenanceComponent } from './maintenance/maintenance.component';
import { ProfileModule } from './profile/profile.module';
import { ProfileComponent } from './profile/profile.component';
import { ProfileService } from './profile/profile.service';
import { SearchModule } from './search/search.module';
import { SearchComponent } from './search/search.component';
import { SearchService } from './search/search.service';
const routes = [ const routes = [
{ {
@ -85,6 +88,13 @@ const routes = [
resolve : { resolve : {
profile: ProfileService profile: ProfileService
} }
},
{
path : 'pages/search',
component: SearchComponent,
resolve : {
search: SearchService
}
} }
]; ];
@ -92,7 +102,8 @@ const routes = [
imports : [ imports : [
SharedModule, SharedModule,
RouterModule.forChild(routes), RouterModule.forChild(routes),
ProfileModule ProfileModule,
SearchModule
], ],
declarations: [ declarations: [
LoginComponent, LoginComponent,
@ -111,7 +122,8 @@ const routes = [
], ],
providers : [ providers : [
InvoiceService, InvoiceService,
ProfileService ProfileService,
SearchService
] ]
}) })
export class PagesModule export class PagesModule

View File

@ -0,0 +1,32 @@
<div id="search" class="page-layout simple tabbed">
<!-- HEADER -->
<div class="header md-accent-bg p-24" fxLayout="column" fxLayoutAlign="center center" fxLayout.gt-sm="row"
fxLayoutAlign.gt-sm="space-between end">
<md-input-container class="w-100-p">
<input mdInput name="search" placeholder="Search...">
</md-input-container>
</div>
<!-- / HEADER -->
<!-- CONTENT -->
<div class="content">
<md-tab-group md-dynamic-height="true">
<md-tab label="Classic">
<fuse-search-classic></fuse-search-classic>
</md-tab>
<md-tab label="Table">
<fuse-search-table></fuse-search-table>
</md-tab>
</md-tab-group>
</div>
<!-- / CONTENT -->
</div>

View File

@ -0,0 +1,70 @@
@import "src/app/core/scss/fuse";
:host {
#search {
.header {
@include media-breakpoint('xs') {
padding: 16px;
}
.search {
position: relative;
max-width: 780px;
.search-icon {
margin: 0 -24px 0 0;
}
.search-input {
padding: 0 0 0 48px;
background: none;
font-size: 24px;
line-height: 48px;
height: 48px;
color: #FFFFFF;
border-bottom: 2px solid rgba(255, 255, 255, 0.3);
transition: border-color 300ms ease;
&:focus {
border-color: rgba(255, 255, 255, 1);
}
&::-webkit-input-placeholder {
color: #FFFFFF;
}
}
}
}
.content {
.result-info {
padding-bottom: 16px;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
.md-title {
padding-right: 8px;
}
.pager {
@include media-breakpoint('xs'){
margin-top: 16px;
}
.page-info {
font-weight: 500;
margin: 0 8px 0 0;
}
}
}
.simple-pagination {
margin: 32px 0;
}
}
}
}

View File

@ -0,0 +1,20 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector : 'fuse-search',
templateUrl: './search.component.html',
styleUrls : ['./search.component.scss']
})
export class SearchComponent implements OnInit
{
constructor()
{
}
ngOnInit()
{
}
}

View File

@ -0,0 +1,26 @@
import { NgModule } from '@angular/core';
import { SharedModule } from '../../../core/modules/shared.module';
import { SearchClassicComponent } from './tabs/classic/classic.component';
import { SearchTableComponent } from './tabs/table/table.component';
import { SearchComponent } from './search.component';
@NgModule({
declarations: [
SearchComponent,
SearchClassicComponent,
SearchTableComponent
],
imports : [
SharedModule
],
exports : [
SearchComponent,
SearchClassicComponent,
SearchTableComponent
]
})
export class SearchModule
{
}

View File

@ -0,0 +1,72 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Http } from '@angular/http';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class SearchService implements Resolve<any>
{
classic: any;
table: any;
classicOnChanged: BehaviorSubject<any> = new BehaviorSubject({});
tableOnChanged: BehaviorSubject<any> = new BehaviorSubject({});
constructor(private http: Http)
{
}
/**
* Resolve
* @param {ActivatedRouteSnapshot} route
* @param {RouterStateSnapshot} state
* @returns {Observable<any> | Promise<any> | any}
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any
{
return new Promise((resolve, reject) => {
Promise.all([
this.getClassic(),
this.getTable()
]).then(
() => {
resolve();
},
reject
);
});
}
/**
* Get classic
*/
getClassic(): Promise<any[]>
{
return new Promise((resolve, reject) => {
this.http.get('api/search-classic')
.subscribe(classic => {
this.classic = classic.json().data;
this.classicOnChanged.next(this.classic);
resolve(this.classic);
}, reject);
});
}
/**
* Get table
*/
getTable(): Promise<any[]>
{
return new Promise((resolve, reject) => {
this.http.get('api/search-table')
.subscribe(table => {
this.table = table.json().data;
this.tableOnChanged.next(this.table);
resolve(this.table);
}, reject);
});
}
}

View File

@ -0,0 +1,93 @@
<div class="classic-tab p-24">
<div class="result-info" fxLayout="row" fxLayoutAlign="space-between center" fxLayout.xs="column"
fxLayoutAlign.xs="start start">
<span class="result-count h3 secondary-text">
<span>54</span>
<span>Results</span>
</span>
<div class="pager" fxLayout="row" fxLayoutAlign="start center">
<span class="secondary-text">
<span>Results:&nbsp;</span>
</span>
<span class="page-info">
<span>1</span>
<span>-</span>
<span>10</span>
<span>of</span>
<span>54</span>
</span>
<button md-icon-button aria-label="Previous page">
<md-icon>chevron_left</md-icon>
</button>
<button md-icon-button aria-label="Next page">
<md-icon>chevron_right</md-icon>
</button>
</div>
</div>
<div class="results">
<div class="result-item" *ngFor="let item of classic">
<div class="title blue-fg">{{item.title}}</div>
<div class="url green-fg">{{item.url}}</div>
<div class="excerpt">{{item.excerpt}}</div>
</div>
</div>
<div class="simple-pagination">
<button md-button class="pagination-item disabled" disabled="disabled"
aria-label="Go to previous page">
<md-icon>chevron_left</md-icon>
</button>
<button md-button class="pagination-item active" [disableRipple]="true" aria-label="Go to page 1">
<span>1</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 2">
<span>2</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 3">
<span>3</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 4">
<span>4</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 5">
<span>5</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 6">
<span>6</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 7">
<span>7</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 8">
<span>8</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 9">
<span>9</span>
</button>
<button md-button class="pagination-item" aria-label="Go to page 10">
<span>10</span>
</button>
<button md-button class="pagination-item" aria-label="Go to next page">
<md-icon>chevron_right</md-icon>
</button>
</div>
</div>

View File

@ -0,0 +1,53 @@
@import "src/app/core/scss/fuse";
:host {
.classic-tab {
.result-info {
padding-bottom: 16px;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
.pager {
.page-info {
font-weight: 500;
margin: 0 8px 0 0;
}
}
}
.results {
.result-item {
margin-top: 32px;
max-width: 512px;
.title {
font-size: 17px;
font-weight: 500;
cursor: pointer;
}
.url {
margin-bottom: 4px;
}
.excerpt {
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
&:last-child {
padding-bottom: 32px;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
}
}
.simple-pagination {
margin: 32px 0;
}
}
}

View File

@ -0,0 +1,24 @@
import { Component, OnInit } from '@angular/core';
import { SearchService } from '../../search.service';
@Component({
selector : 'fuse-search-classic',
templateUrl: './classic.component.html',
styleUrls : ['./classic.component.scss']
})
export class SearchClassicComponent implements OnInit
{
classic: any;
constructor(private searchService: SearchService)
{
this.searchService.classicOnChanged.subscribe(classic => {
this.classic = classic;
});
}
ngOnInit()
{
}
}

View File

@ -0,0 +1,36 @@
<div class="table-tab">
<md-table #table [dataSource]="dataSource">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- ID Column -->
<ng-container cdkColumnDef="name">
<md-header-cell *cdkHeaderCellDef>Name</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.name}} </md-cell>
</ng-container>
<!-- Progress Column -->
<ng-container cdkColumnDef="position">
<md-header-cell *cdkHeaderCellDef>Position</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.position}} </md-cell>
</ng-container>
<!-- Name Column -->
<ng-container cdkColumnDef="office">
<md-header-cell *cdkHeaderCellDef>Office</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.office}} </md-cell>
</ng-container>
<!-- Color Column -->
<ng-container cdkColumnDef="salary">
<md-header-cell *cdkHeaderCellDef>Salary</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.salary | currency:'USD':true}} </md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
</md-table>
</div>

View File

@ -0,0 +1,6 @@
@import "src/app/core/scss/fuse";
:host {
}

View File

@ -0,0 +1,46 @@
import { Component, OnInit } from '@angular/core';
import { SearchService } from '../../search.service';
import { DataSource } from '@angular/cdk';
@Component({
selector : 'fuse-search-table',
templateUrl: './table.component.html',
styleUrls : ['./table.component.scss']
})
export class SearchTableComponent implements OnInit
{
table: any;
dataSource: SearchTableDataSource;
displayedColumns = ['name', 'position', 'office', 'salary'];
constructor(private searchService: SearchService)
{
this.searchService.tableOnChanged
.subscribe(table => {
this.table = table;
});
}
ngOnInit()
{
this.dataSource = new SearchTableDataSource(this.searchService);
}
}
export class SearchTableDataSource extends DataSource<any>
{
constructor(private searchService: SearchService)
{
super();
}
connect()
{
return this.searchService.tableOnChanged;
}
disconnect()
{
}
}