feat(aio): add about component and data

This commit is contained in:
Ward Bell 2017-03-30 16:51:51 -07:00 committed by Pete Bacon Darwin
parent ad639d783f
commit 97deb01b1f
12 changed files with 269 additions and 8 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,14 @@
<div class="grid-fluid l-space-bottom-8">
<h3 class="title center">Building For the Future</h3>
<p>
Angular is built by a team of engineers who share a passion for
making web development feel effortless. We believe that writing
beautiful apps should be joyful and fun. We're building a
platform for the future.
</p>
</div>
<div class="grid-fluid l-space-bottom-6">
<h3 class="title center">Current Contributors</h3>
<aio-contributor-list></aio-contributor-list>
</div>

View File

@ -0,0 +1,25 @@
import { Component, OnInit } from '@angular/core';
import { Contributor } from './contributors.model';
import { ContributorService } from './contributor.service';
@Component({
selector: `aio-contributor-list`,
template: `
<section *ngFor="let group of groups" class="grid-fluid">
<h4 class="title">{{group}}</h4>
<aio-contributor *ngFor="let person of contributorGroups[group]" [person]="person"></aio-contributor>
</section>`
})
export class ContributorListComponent implements OnInit {
contributorGroups = new Map<string, Contributor[]>();
groups: string[];
constructor(private contributorService: ContributorService) { }
ngOnInit() {
this.contributorService.contributors.subscribe(cgs => {
this.groups = ['Lead', 'Google', 'Community'];
this.contributorGroups = cgs;
});
}
}

View File

@ -0,0 +1,36 @@
import { Component, Input } from '@angular/core';
import { Contributor } from './contributors.model';
@Component({
selector: 'aio-contributor',
template: `
<header>
<img src="{{pictureBase}}{{person.picture || noPicture}}" alt="name" width="240" height="208">
<h3>{{person.name}}</h3>
<button *ngIf="person.bio" aria-label="View Bio" (click)="showBio=!showBio">View Bio</button>
<!-- TODO: get the twitter/website icons and get rid of text -->
<a *ngIf="person.twitter" href="https://twitter.com/{{person.twitter}}">
<span class="icon-twitter">twitter</span>
</a>
<a *ngIf="person.website" href="{{person.website}}">
<span class="icon-publ">website</span>
</a>
<p>{{person.bio}}</p>
<header>
<!-- TODO: This should be modal and float over the width of page -->
<article *ngIf="showBio">
<h3>{{person.name}}</h3>
<p>{{person.bio}}</p>
<article>
`
})
export class ContributorComponent {
@Input() person: Contributor;
showBio = false;
noPicture = '_no-one.png';
pictureBase = 'content/images/bios/';
}

View File

@ -0,0 +1,44 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/publishLast';
import { Logger } from 'app/shared/logger.service';
import { Contributor } from './contributors.model';
const contributorsPath = 'content/contributors.json';
@Injectable()
export class ContributorService {
contributors: Observable<Map<string, Contributor[]>>;
constructor(private http: Http, private logger: Logger) {
this.contributors = this.getContributors();
}
private getContributors() {
const contributors = this.http.get(contributorsPath)
.map(res => res.json())
.map(contribs => {
const contribGroups = new Map<string, Contributor[]>();
Object.keys(contribs).forEach(key => {
const contributor = contribs[key];
const group = contributor.group;
const contribGroup = contribGroups[group];
if (contribGroup) {
contribGroup.push(contributor);
} else {
contribGroups[group] = [contributor];
}
});
return contribGroups;
})
.publishLast();
contributors.connect();
return contributors;
}
}

View File

@ -0,0 +1,8 @@
export class Contributor {
group: string;
name: string;
picture?: string;
website?: string;
twitter?: string;
bio?: string;
}

View File

@ -1,9 +1,9 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { PrettyPrinter } from './code/pretty-printer.service'; import { ContributorService } from './contributor/contributor.service';
import { CopierService } from 'app/shared/copier.service'; import { CopierService } from 'app/shared/copier.service';
import { PrettyPrinter } from './code/pretty-printer.service';
// Any components that we want to use inside embedded components must be declared or imported here // Any components that we want to use inside embedded components must be declared or imported here
// It is not enough just to import them inside the AppModule // It is not enough just to import them inside the AppModule
@ -16,6 +16,8 @@ import { CodeComponent } from './code/code.component';
import { ApiListComponent } from './api/api-list.component'; import { ApiListComponent } from './api/api-list.component';
import { CodeExampleComponent } from './code/code-example.component'; import { CodeExampleComponent } from './code/code-example.component';
import { CodeTabsComponent } from './code/code-tabs.component'; import { CodeTabsComponent } from './code/code-tabs.component';
import { ContributorListComponent } from './contributor/contributor-list.component';
import { ContributorComponent } from './contributor/contributor.component';
import { DocTitleComponent } from './doc-title.component'; import { DocTitleComponent } from './doc-title.component';
import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example/live-example.component'; import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example/live-example.component';
@ -23,7 +25,8 @@ import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example/l
* such as CodeExampleComponent, LiveExampleComponent,... * such as CodeExampleComponent, LiveExampleComponent,...
*/ */
export const embeddedComponents: any[] = [ export const embeddedComponents: any[] = [
ApiListComponent, CodeExampleComponent, DocTitleComponent, CodeTabsComponent, LiveExampleComponent ApiListComponent, CodeExampleComponent, CodeTabsComponent,
ContributorListComponent, DocTitleComponent, LiveExampleComponent
]; ];
/** Injectable class w/ property returning components that can be embedded in docs */ /** Injectable class w/ property returning components that can be embedded in docs */
@ -36,12 +39,14 @@ export class EmbeddedComponents {
declarations: [ declarations: [
embeddedComponents, embeddedComponents,
CodeComponent, CodeComponent,
ContributorComponent,
EmbeddedPlunkerComponent EmbeddedPlunkerComponent
], ],
providers: [ providers: [
ContributorService,
CopierService,
EmbeddedComponents, EmbeddedComponents,
PrettyPrinter, PrettyPrinter
CopierService
], ],
entryComponents: [ embeddedComponents ] entryComponents: [ embeddedComponents ]
}) })

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,128 @@
$unit: 8px;
$metal: #536E7A;
$snow: #FFFFFF;
$steel: #253238;
aio-contributor-list {
.grid-fluid {
margin: 0 auto;
margin-bottom: 6 * 8px;
*zoom: 1;
}
.grid-fluid aio-contributor {
display: inline;
float: left;
margin-right: 1.04167%;
margin-left: 1.04167%;
width: 22.91667%;
margin-bottom: 6 * 8px;
}
.grid-fluid:after, .grid-fluid:before {
content: '.';
clear: both;
display: block;
overflow: hidden;
visibility: hidden;
font-size: 0;
line-height: 0;
width: 0;
height: 0;
}
@media handheld and (max-width: 480px), screen and (max-width: 480px), screen and (max-width: 900px) {
/* line 6, ../scss/_responsive.scss */
.grid-fluid{
width: auto;
}
}
@media handheld and (max-width: 480px), screen and (max-width: 480px), screen and (max-width: 900px) {
.grid-fluid{
margin-left: 20px;
margin-right: 20px;
float: none;
display: block;
width: auto;
}
}
}
aio-contributor {
margin: 0px 0px ($unit * 4) 0px;
position: relative;
cursor: pointer;
box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26);
background: $snow;
transition: all .3s;
padding: 10px;
&:hover {
transform: translate3d(0,-3px,0);
box-shadow: 0px 8px 16px 0 rgba(0, 0, 0, 0.4);
nav {
opacity: 1;
}
}
// HEADER
header {
position: relative;
overflow: hidden;
border-radius: 2px 2px 0px 0px;
nav {
transition: opacity .5s;
position: absolute;
bottom: 3px;
left: 0;
right: 0;
z-index: 1;
padding: $unit;
background: rgba($steel, .4);
opacity: 0;
button {
font-size: 14px;
color: $snow;
text-transform: uppercase;
opacity: .87;
background: none;
border: none;
}
a {
color: $snow;
font-size: 20px;
text-decoration: none;
opacity: .87;
margin-right: $unit;
float: right;
}
}
}
// MAIN CONTENT
h3 {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: $metal;
text-transform: uppercase;
font-size: 18px;
margin-bottom: $unit;
}
p {
white-space: nowrap;
overflow: hidden;
cursor: pointer;
font-size: 14px;
line-height: 24px;
margin: 0;
text-overflow: ellipsis;
}
}

View File

@ -4,6 +4,7 @@
@import 'hamburger'; @import 'hamburger';
@import 'code'; @import 'code';
@import 'contributor';
@import 'alert'; @import 'alert';
@import 'filetree'; @import 'filetree';
@import 'images'; @import 'images';

View File

@ -151,7 +151,7 @@ module.exports =
}, },
{ {
basePath: CONTENTS_PATH, basePath: CONTENTS_PATH,
include: CONTENTS_PATH + '/marketing/contributor.json', include: CONTENTS_PATH + '/marketing/contributors.json',
fileReader: 'jsonFileReader' fileReader: 'jsonFileReader'
}, },
]; ];
@ -286,7 +286,7 @@ module.exports =
outputPathTemplate: '${path}.json' outputPathTemplate: '${path}.json'
}, },
{docTypes: ['navigation-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, {docTypes: ['navigation-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'},
{docTypes: ['contributor-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'} {docTypes: ['contributors-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}
]; ];
}) })