diff --git a/.gitignore b/.gitignore
index ee5c9d8..7f740ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,34 @@ testem.log
# System Files
.DS_Store
Thumbs.db
+### Angular ###
+### Angular ##
+## compiled output
+/dist
+/tmp
+/app/**/*.js
+/app/**/*.js.map
+
+# dependencies
+/node_modules
+/bower_components
+
+# IDEs and editors
+/.idea
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage/*
+/libpeerconnection.log
+npm-debug.log
+testem.log
+/typings
+
+# e2e
+/e2e/*.js
+/e2e/*.map
+
+#System Files
+.DS_Store
+
diff --git a/README.md b/README.md
deleted file mode 100644
index 08ac6f7..0000000
--- a/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# TestWebsite
-
-This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.2.1.
-
-## Development server
-
-Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
-
-## Code scaffolding
-
-Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
-
-## Build
-
-Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
-
-## Running unit tests
-
-Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
-
-## Running end-to-end tests
-
-Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
-
-## Further help
-
-To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/package-lock.json b/package-lock.json
index d9dc58f..ab85751 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -124,6 +124,14 @@
"tslib": "^1.9.0"
}
},
+ "@angular/cdk": {
+ "version": "6.4.7",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-6.4.7.tgz",
+ "integrity": "sha512-18x0U66fLD5kGQWZ9n3nb75xQouXlWs7kUDaTd8HTrHpT1s2QIAqlLd1KxfrYiVhsEC2jPQaoiae7VnBlcvkBg==",
+ "requires": {
+ "tslib": "^1.7.1"
+ }
+ },
"@angular/cli": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-6.2.1.tgz",
@@ -357,6 +365,23 @@
"integrity": "sha512-L6upXuyO42Z5XhtvbDoDuQEmXEOdSYeGOBmXSxb3ywb/0eh8kHk1Xft+8aaKKtazYjol0t+M+DlZgehqvk4vEA==",
"dev": true
},
+ "@angular/material": {
+ "version": "6.4.7",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-6.4.7.tgz",
+ "integrity": "sha512-SdNx7Xovi24Kw9eU6lkLhY/7f2M7L9F+/uh6XuPr4jbGgCUVVpeeVI5ztZhsZRbj1sN+/r1p5w8u62apWWl5Ww==",
+ "requires": {
+ "parse5": "^5.0.0",
+ "tslib": "^1.7.1"
+ },
+ "dependencies": {
+ "parse5": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+ "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+ "optional": true
+ }
+ }
+ },
"@angular/platform-browser": {
"version": "6.1.7",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-6.1.7.tgz",
@@ -9826,6 +9851,11 @@
"minimalistic-assert": "^1.0.0"
}
},
+ "web-animations-js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.1.tgz",
+ "integrity": "sha1-Om2bwVGWN3qQ+OKAP6UmIWWwRRA="
+ },
"webdriver-js-extender": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.0.0.tgz",
diff --git a/package.json b/package.json
index 8b81a28..ab50756 100644
--- a/package.json
+++ b/package.json
@@ -11,17 +11,20 @@
},
"private": true,
"dependencies": {
- "@angular/animations": "^6.1.0",
+ "@angular/animations": "^6.1.7",
+ "@angular/cdk": "^6.4.7",
"@angular/common": "^6.1.0",
"@angular/compiler": "^6.1.0",
"@angular/core": "^6.1.0",
"@angular/forms": "^6.1.0",
"@angular/http": "^6.1.0",
+ "@angular/material": "^6.4.7",
"@angular/platform-browser": "^6.1.0",
"@angular/platform-browser-dynamic": "^6.1.0",
"@angular/router": "^6.1.0",
"core-js": "^2.5.4",
"rxjs": "~6.2.0",
+ "web-animations-js": "^2.3.1",
"zone.js": "~0.8.26"
},
"devDependencies": {
diff --git a/src/app/app.component.html b/src/app/app.component.html
index fa2706a..33bf6b9 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,20 +1,6 @@
-
-
- Welcome to {{ title }}!
-
-
+
-Here are some links to help you start:
-
-
+
+
+
diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts
index 920742a..e323094 100644
--- a/src/app/app.component.spec.ts
+++ b/src/app/app.component.spec.ts
@@ -1,10 +1,22 @@
-import { TestBed, async } from '@angular/core/testing';
-import { AppComponent } from './app.component';
+import {async, TestBed} from '@angular/core/testing';
+import {AppComponent} from './app.component';
+import {ToolbarComponent} from "./toolbar/toolbar.component";
+import {RouterTestingModule} from "@angular/router/testing";
+import {MatSidenavModule, MatToolbarModule} from "@angular/material";
+import {NoopAnimationsModule} from "@angular/platform-browser/animations";
+
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
+ imports: [
+ RouterTestingModule,
+ MatToolbarModule,
+ MatSidenavModule,
+ NoopAnimationsModule,
+ ],
declarations: [
- AppComponent
+ AppComponent,
+ ToolbarComponent
],
}).compileComponents();
}));
@@ -13,15 +25,4 @@ describe('AppComponent', () => {
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
- it(`should have as title 'TestWebsite'`, async(() => {
- const fixture = TestBed.createComponent(AppComponent);
- const app = fixture.debugElement.componentInstance;
- expect(app.title).toEqual('TestWebsite');
- }));
- it('should render title in a h1 tag', async(() => {
- const fixture = TestBed.createComponent(AppComponent);
- fixture.detectChanges();
- const compiled = fixture.debugElement.nativeElement;
- expect(compiled.querySelector('h1').textContent).toContain('Welcome to TestWebsite!');
- }));
});
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 517d1ac..bd83c7e 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,10 +1,44 @@
-import { Component } from '@angular/core';
+import {Component} from '@angular/core';
+import {RouterOutlet} from "@angular/router";
+import {animate, query, style, transition, trigger} from "@angular/animations";
+
+export const routerTransition = trigger('routerTransition', [
+ // The '* => *' will trigger the animation to change between any two states
+ transition('* => *', [
+ // The query function has three params.
+ // First is the event, so this will apply on entering or when the element is added to the DOM.
+ // Second is a list of styles or animations to apply.
+ // Third we add a config object with optional set to true, this is to signal
+ // angular that the animation may not apply as it may or may not be in the DOM.
+ query(
+ ':enter',
+ [style({opacity: 0})],
+ {optional: true}
+ ),
+ query(
+ ':leave',
+ // here we apply a style and use the animate function to apply the style over 0.3 seconds
+ [style({opacity: 1}), animate('0.3s', style({opacity: 0}))],
+ {optional: true}
+ ),
+ query(
+ ':enter',
+ [style({opacity: 0}), animate('0.3s', style({opacity: 1}))],
+ {optional: true}
+ )
+ ])
+]);
@Component({
selector: 'app-root',
+ animations: [routerTransition],
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
- title = 'TestWebsite';
+
+ getState(outlet: RouterOutlet) {
+ return outlet.activatedRouteData.state
+ }
}
+
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index f657163..c8ca02a 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,16 +1,45 @@
-import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
+import {BrowserModule} from '@angular/platform-browser';
+import {NgModule} from '@angular/core';
-import { AppComponent } from './app.component';
+import {AppComponent} from './app.component';
+import {MatSidenavModule, MatToolbarModule} from "@angular/material";
+import {ToolbarComponent} from './toolbar/toolbar.component';
+import {RouterModule, Routes} from "@angular/router";
+import {ResumeComponent} from './resume/resume.component';
+import {ContactComponent} from './contact/contact.component';
+import {HomeComponent} from './home/home.component';
+import {ProjectsComponent} from './projects/projects.component';
+import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
+import { ProjectKeywordPipe } from './project-keyword.pipe';
+
+const appRoutes: Routes = [
+ {path: 'resume', component: ResumeComponent, data: {state: 'resume'}},
+ {path: 'projects', component: ProjectsComponent, data: {state: 'project'}},
+ {path: 'contact', component: ContactComponent, data: {state: 'contact'}},
+ {path: 'home', component: HomeComponent, data: {state: 'home'}},
+ {path: '', pathMatch: 'full', redirectTo: 'home'}
+];
@NgModule({
declarations: [
- AppComponent
+ AppComponent,
+ ToolbarComponent,
+ ResumeComponent,
+ ContactComponent,
+ HomeComponent,
+ ProjectsComponent,
+ ProjectKeywordPipe,
],
imports: [
- BrowserModule
+ RouterModule.forRoot(appRoutes),
+ BrowserModule,
+ BrowserAnimationsModule,
+ MatToolbarModule,
+ MatSidenavModule,
+ RouterModule,
],
providers: [],
bootstrap: [AppComponent]
})
-export class AppModule { }
+export class AppModule {
+}
diff --git a/src/app/contact/contact.component.css b/src/app/contact/contact.component.css
new file mode 100644
index 0000000..b02cee5
--- /dev/null
+++ b/src/app/contact/contact.component.css
@@ -0,0 +1,26 @@
+.icon-text {
+ margin: 0 8px;
+ line-height: 32px
+}
+
+.icon {
+ height: 32px;
+}
+
+.icon-layout {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ margin: 1em .5em 1em .5em;
+ padding: .5em;
+ -webkit-transition: color 300ms;
+ -moz-transition: color 300ms;
+ -ms-transition: color 300ms;
+ -o-transition: color 300ms;
+ transition: color 300ms;
+}
+
+.icon-layout:hover {
+ color: #0FA0CE;
+ cursor: pointer;
+}
diff --git a/src/app/contact/contact.component.html b/src/app/contact/contact.component.html
new file mode 100644
index 0000000..f9934c2
--- /dev/null
+++ b/src/app/contact/contact.component.html
@@ -0,0 +1,25 @@
+
+
+
Social Media
+
+
+
+
+
LinkedIn
+
+
+
+
+
GitHub
+
+
+
+
+
Email
+
+
+
Contact me to connect, collaborate or just to chat.
+
+
+
diff --git a/src/app/contact/contact.component.spec.ts b/src/app/contact/contact.component.spec.ts
new file mode 100644
index 0000000..427633e
--- /dev/null
+++ b/src/app/contact/contact.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ContactComponent } from './contact.component';
+
+describe('ContactComponent', () => {
+ let component: ContactComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ ContactComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ContactComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/contact/contact.component.ts b/src/app/contact/contact.component.ts
new file mode 100644
index 0000000..8d74752
--- /dev/null
+++ b/src/app/contact/contact.component.ts
@@ -0,0 +1,24 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-contact',
+ templateUrl: './contact.component.html',
+ styleUrls: ['./contact.component.css']
+})
+export class ContactComponent {
+
+ constructor() { }
+
+
+ linkedInClicked() {
+ window.open("https://www.linkedin.com/in/cameron-cordes-3b166583/")
+ }
+
+ githubClicked() {
+ window.open("https://github.com/Stampede10343")
+ }
+
+ emailClicked() {
+ window.open("mailto:cameronc.dev@gmail.com")
+ }
+}
diff --git a/src/app/home/home.component.css b/src/app/home/home.component.css
new file mode 100644
index 0000000..bc70c5c
--- /dev/null
+++ b/src/app/home/home.component.css
@@ -0,0 +1,21 @@
+.overlay {
+ background: black;
+ position: relative;
+}
+
+.image {
+ opacity: 0.1;
+ width: 100%;
+ height: auto;
+}
+
+.home-container {
+ background: #2f2f31;
+ height: 100%;
+ width: 100%;
+ position: fixed;
+}
+
+.overlay-text {
+ color: white;
+}
diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
new file mode 100644
index 0000000..c49c8da
--- /dev/null
+++ b/src/app/home/home.component.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
Cameron Cordes
+
+ Android and iOS Developer
+
Hello! I'm Cameron, I am a software developer focusing on mobile Android and iOS
+ applications. I love software development, I enjoy creating things, solving problems and making simple, smart
+ solutions to business problems.
+
I first discovered programming by making bots for the classic Massively Multiplayer Online
+ Role Playing Game Runescape. I learned that you could automate leveling up your skills by writing scripts to do
+ the process for you. So I started reading other peoples scripts, learning the scripting language Pascal. I
+ quickly realized that I could build something that could help myself and others level up their characters in the
+ game and have fun learning and solving problems and thus sparked my love of programming and eventually software
+ development.
+
+
+
diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts
new file mode 100644
index 0000000..490e81b
--- /dev/null
+++ b/src/app/home/home.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HomeComponent } from './home.component';
+
+describe('HomeComponent', () => {
+ let component: HomeComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ HomeComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HomeComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts
new file mode 100644
index 0000000..33fd770
--- /dev/null
+++ b/src/app/home/home.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-home',
+ templateUrl: './home.component.html',
+ styleUrls: ['./home.component.css']
+})
+export class HomeComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/src/app/project-keyword.pipe.spec.ts b/src/app/project-keyword.pipe.spec.ts
new file mode 100644
index 0000000..a4e0584
--- /dev/null
+++ b/src/app/project-keyword.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { ProjectKeywordPipe } from './project-keyword.pipe';
+
+describe('ProjectKeywordPipe', () => {
+ it('create an instance', () => {
+ const pipe = new ProjectKeywordPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/src/app/project-keyword.pipe.ts b/src/app/project-keyword.pipe.ts
new file mode 100644
index 0000000..704dac2
--- /dev/null
+++ b/src/app/project-keyword.pipe.ts
@@ -0,0 +1,21 @@
+import {Pipe, PipeTransform} from '@angular/core';
+
+@Pipe({
+ name: 'projectKeyword'
+})
+export class ProjectKeywordPipe implements PipeTransform {
+ private keywords = ['MySQL', 'Node', 'Express', 'RxJava', 'Dagger 2', 'Model View Presenter', 'Retrofit', 'Realm', 'Room', 'Model-View-View Model'];
+
+ transform(value: String, args?: any): any {
+ this.keywords.forEach(keyword => {
+ let keywordIndex = value.indexOf(keyword);
+ if (keywordIndex != -1) {
+ let boldKeyword = '' + value.substring(keywordIndex, keywordIndex + keyword.length) + ' ';
+ value = value.replace(keyword, boldKeyword);
+ }
+ });
+
+ return value;
+ }
+
+}
diff --git a/src/app/projects/project-item.ts b/src/app/projects/project-item.ts
new file mode 100644
index 0000000..a79ec52
--- /dev/null
+++ b/src/app/projects/project-item.ts
@@ -0,0 +1,6 @@
+export class ProjectItem {
+ title: String;
+ applicationType: String;
+ description: String
+ imgLocation: String
+}
diff --git a/src/app/projects/project.service.spec.ts b/src/app/projects/project.service.spec.ts
new file mode 100644
index 0000000..cf95c43
--- /dev/null
+++ b/src/app/projects/project.service.spec.ts
@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ProjectService } from './project.service';
+
+describe('ProjectService', () => {
+ beforeEach(() => TestBed.configureTestingModule({}));
+
+ it('should be created', () => {
+ const service: ProjectService = TestBed.get(ProjectService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/projects/project.service.ts b/src/app/projects/project.service.ts
new file mode 100644
index 0000000..447ac2e
--- /dev/null
+++ b/src/app/projects/project.service.ts
@@ -0,0 +1,51 @@
+import {Injectable} from '@angular/core';
+import {ProjectItem} from "./project-item";
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ProjectService {
+
+ constructor() {
+ }
+
+ getProjects(): Promise> {
+ return Promise.resolve(projects)
+ }
+}
+
+const projects = [
+ {
+ title: "Secure Notes",
+ applicationType: "Android Application (Kotlin)",
+ description: "Secure Notes is a simple note taking application with security in mind. There is a focus on clean" +
+ " code, Model-View-View Model and loosely coupled components. I built this app to experiment with different" +
+ " Android database libraries (Realm and Room), encryption and security, as well as a single Activity approach to" +
+ " an Android app. (Under development).",
+ imgLocation: "../../assets/note-icon.png"
+ },
+ {
+ title: "CorpsTime",
+ applicationType: "Android Application (Java and Kotlin)",
+ description: "CorpsTime is an Android application to view news, scores and the schedule of Drum Corps International" +
+ " competitions. CorpsTime uses the Model View Presenter pattern and libraries such as Dagger 2, Retrofit and RxJava.",
+ imgLocation: "../../assets/corpstime.png"
+ },
+ {
+ title: "CorpsTime Scraper and API",
+ applicationType: "Express API powered by Node (Javascript)",
+ description: "The CorpsTime scraper and API is the supporting code for the CorpsTime mobile application, written" +
+ " in Javascript using Express, Node, and MySQL to gather and prepare data for the CorpsTime client. The scraper" +
+ " runs nightly during the Drum Corps season to pull data from different websites and store and format it to be" +
+ " later retrieved by the API. The API includes a handful of endpoints to get scores, different competing corps and" +
+ " the upcoming events during the season.",
+ imgLocation: ""
+ },
+ {
+ title: "Android Hues",
+ applicationType: "Android Application (Kotlin)",
+ description: "Android Hues is an Android application to control your Phillips Hue lights at home. Hues uses RxJava," +
+ " Dagger 2 and the Phillips Hue SDK in order to control the color, brightness and power state of your lights.",
+ imgLocation: "../../assets/android-hues.png"
+ }
+];
diff --git a/src/app/projects/projects.component.css b/src/app/projects/projects.component.css
new file mode 100644
index 0000000..67432e9
--- /dev/null
+++ b/src/app/projects/projects.component.css
@@ -0,0 +1,22 @@
+.project-item {
+ width: 40%;
+ margin: 1em 0 1em;
+}
+
+@media (max-width: 768px) {
+ .project-item {
+ width: 75%;
+ }
+}
+
+@media (min-width: 768px) and (max-width: 1080px) {
+ .project-item {
+ width: 60%;
+ }
+}
+
+@media (min-width: 1920px) {
+ .project-item {
+ width: 30%;
+ }
+}
diff --git a/src/app/projects/projects.component.html b/src/app/projects/projects.component.html
new file mode 100644
index 0000000..be4431b
--- /dev/null
+++ b/src/app/projects/projects.component.html
@@ -0,0 +1,9 @@
+
+
+
{{project.title}}
+
+
{{project.applicationType}}
+
+
+
+
diff --git a/src/app/projects/projects.component.spec.ts b/src/app/projects/projects.component.spec.ts
new file mode 100644
index 0000000..939349b
--- /dev/null
+++ b/src/app/projects/projects.component.spec.ts
@@ -0,0 +1,26 @@
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {ProjectsComponent} from './projects.component';
+import {ProjectKeywordPipe} from "../project-keyword.pipe";
+
+describe('ProjectsComponent', () => {
+ let component: ProjectsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ProjectsComponent, ProjectKeywordPipe]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ProjectsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/projects/projects.component.ts b/src/app/projects/projects.component.ts
new file mode 100644
index 0000000..d462148
--- /dev/null
+++ b/src/app/projects/projects.component.ts
@@ -0,0 +1,24 @@
+import {Component, OnInit} from '@angular/core';
+import {ProjectService} from "./project.service";
+import {ProjectItem} from "./project-item";
+
+@Component({
+ selector: 'app-projects',
+ templateUrl: './projects.component.html',
+ styleUrls: ['./projects.component.css'],
+})
+export class ProjectsComponent implements OnInit {
+ projects: Array;
+
+ constructor(private projectService: ProjectService) {
+ }
+
+ ngOnInit(): void {
+ this.getProjects()
+ }
+
+ getProjects() {
+ return this.projectService.getProjects().then(projects => this.projects = projects)
+ }
+
+}
diff --git a/src/app/resume/resume.component.css b/src/app/resume/resume.component.css
new file mode 100644
index 0000000..f33391b
--- /dev/null
+++ b/src/app/resume/resume.component.css
@@ -0,0 +1,103 @@
+* {
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ font: 16px Helvetica, Sans-Serif;
+ line-height: 24px;
+ background: url(../../assets/noise.jpg);
+}
+
+.clear {
+ clear: both;
+}
+
+#page-wrap {
+ width: 800px;
+ margin: 40px auto 60px;
+}
+
+#pic {
+ float: right;
+ margin: -30px 0 0 0;
+}
+
+h1 {
+ margin: 0 0 16px 0;
+ padding: 0 0 16px 0;
+ font-size: 42px;
+ font-weight: bold;
+ letter-spacing: -2px;
+ border-bottom: 1px solid #888;
+}
+
+h2 {
+ font-size: 20px;
+ margin: 0 0 6px 0;
+ position: relative;
+}
+
+h2 span {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ font-style: italic;
+ font-family: Georgia, Serif;
+ font-size: 16px;
+ color: #888;
+ font-weight: normal;
+}
+
+p {
+ margin: 0 0 16px 0;
+}
+
+a {
+ color: #888;
+ text-decoration: none;
+ border-bottom: 1px dotted #888;
+}
+
+a:hover {
+ border-bottom-style: solid;
+ color: black;
+}
+
+ul {
+ margin: 0 0 32px 17px;
+}
+
+#objective {
+ width: 500px;
+ float: left;
+}
+
+#objective p {
+ font-family: Georgia, serif;
+ font-style: italic;
+ color: #666;
+}
+
+dt {
+ font-style: italic;
+ font-weight: bold;
+ font-size: 18px;
+ text-align: right;
+ padding: 0 26px 0 0;
+ width: 150px;
+ float: left;
+ height: 100px;
+ border-right: 2px solid #888;
+}
+
+dd {
+ width: 600px;
+ float: right;
+}
+
+dd.clear {
+ float: none;
+ margin: 0;
+ height: 15px;
+}
diff --git a/src/app/resume/resume.component.html b/src/app/resume/resume.component.html
new file mode 100644
index 0000000..689393e
--- /dev/null
+++ b/src/app/resume/resume.component.html
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Education
+
+ Baldwin Wallace University
+ Major: Computer Science
+ Minor: Math
+
+
+
+
+ Skills
+
+ Computer skills
+ Windows, Linux, OSX, Android Studio, Visual Studio, XCode, Microsoft productivity software (Word, Excel, etc).
+
+
+
+
+ Experience
+
+ Progressive Insurance Mobile Developer Jan 2018 - Present
+
+ Inspired and won highest peasant death competition among servants
+ Helped coordinate managers to grow cult following
+ Provided untimely deaths to all who opposed
+
+
+ Hyland Software Developer II - Westlake, OH - 2016 - 2018
+
+ Developed a camera interface and photo viewer using Android Camera API for a consistent method of capturing photos and reviewing them
+ Wrote an image downloading module with in memory caching
+ Started an initiative to use the Model View Presenter pattern to enable more testable code
+
+
+
+
+
+ Hobbies
+ Music, Movies, Motorcycles, Homebrewing, Travel
+
+
+
+ References
+ Available on request
+
+
+
+
+
+
+
diff --git a/src/app/resume/resume.component.spec.ts b/src/app/resume/resume.component.spec.ts
new file mode 100644
index 0000000..8d4824d
--- /dev/null
+++ b/src/app/resume/resume.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ResumeComponent } from './resume.component';
+
+describe('ResumeComponent', () => {
+ let component: ResumeComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ ResumeComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ResumeComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/resume/resume.component.ts b/src/app/resume/resume.component.ts
new file mode 100644
index 0000000..074042e
--- /dev/null
+++ b/src/app/resume/resume.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-resume',
+ templateUrl: './resume.component.html',
+ styleUrls: ['./resume.component.css']
+})
+export class ResumeComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/src/app/toolbar/toolbar.component.css b/src/app/toolbar/toolbar.component.css
new file mode 100644
index 0000000..07190f4
--- /dev/null
+++ b/src/app/toolbar/toolbar.component.css
@@ -0,0 +1,14 @@
+span {
+ margin-left: 1em;
+ margin-right: 1em;
+ -webkit-transition: color 300ms;
+ -moz-transition: color 300ms;
+ -ms-transition: color 300ms;
+ -o-transition: color 300ms;
+ transition: color 300ms;
+}
+
+span:hover {
+ color: #1DAEDD;
+ cursor: pointer;
+}
diff --git a/src/app/toolbar/toolbar.component.html b/src/app/toolbar/toolbar.component.html
new file mode 100644
index 0000000..1ceea7c
--- /dev/null
+++ b/src/app/toolbar/toolbar.component.html
@@ -0,0 +1,8 @@
+
+
+ Home
+ Resume
+ Projects
+ Contact
+
+
diff --git a/src/app/toolbar/toolbar.component.spec.ts b/src/app/toolbar/toolbar.component.spec.ts
new file mode 100644
index 0000000..d114540
--- /dev/null
+++ b/src/app/toolbar/toolbar.component.spec.ts
@@ -0,0 +1,47 @@
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {ToolbarComponent} from './toolbar.component';
+import {MatSidenavModule, MatToolbarModule} from "@angular/material";
+import {RouterTestingModule} from "@angular/router/testing";
+import {Component} from "@angular/core";
+
+@Component({template: ''})
+class DummyComponent {
+}
+
+describe('ToolbarComponent', () => {
+ let component: ToolbarComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [MatToolbarModule,
+ MatSidenavModule,
+ RouterTestingModule.withRoutes([{path: 'home', component: DummyComponent}])
+ ],
+ declarations: [ToolbarComponent, DummyComponent]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ToolbarComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should contain a material toolbar', () => {
+ expect(fixture.debugElement.children[0].nativeElement.className).toBe("mat-drawer-container mat-sidenav-container")
+ });
+
+ it('should contain 4 links, Home, Resume, Projects, Contact', () => {
+ let debugElements = fixture.debugElement.queryAll((element) => {
+ return element.nativeElement.class == 'span'
+ });
+ expect(debugElements[0].nativeElement).toBe("span");
+ });
+});
diff --git a/src/app/toolbar/toolbar.component.ts b/src/app/toolbar/toolbar.component.ts
new file mode 100644
index 0000000..c2b8120
--- /dev/null
+++ b/src/app/toolbar/toolbar.component.ts
@@ -0,0 +1,12 @@
+import {Component} from '@angular/core';
+
+@Component({
+ selector: 'app-toolbar',
+ templateUrl: './toolbar.component.html',
+ styleUrls: ['./toolbar.component.css']
+})
+export class ToolbarComponent {
+
+ constructor() {
+ }
+}
diff --git a/src/assets/CubeSpace.jpg b/src/assets/CubeSpace.jpg
new file mode 100644
index 0000000..b48d9c1
Binary files /dev/null and b/src/assets/CubeSpace.jpg differ
diff --git a/src/assets/android-hues.png b/src/assets/android-hues.png
new file mode 100644
index 0000000..fbc1e54
Binary files /dev/null and b/src/assets/android-hues.png differ
diff --git a/src/assets/cameron-headshot.jpg b/src/assets/cameron-headshot.jpg
new file mode 100644
index 0000000..84425bf
Binary files /dev/null and b/src/assets/cameron-headshot.jpg differ
diff --git a/src/assets/corpstime.png b/src/assets/corpstime.png
new file mode 100644
index 0000000..b9cebd0
Binary files /dev/null and b/src/assets/corpstime.png differ
diff --git a/src/assets/cthulu.png b/src/assets/cthulu.png
new file mode 100644
index 0000000..29bb89c
Binary files /dev/null and b/src/assets/cthulu.png differ
diff --git a/src/assets/github.png b/src/assets/github.png
new file mode 100644
index 0000000..05cf7bb
Binary files /dev/null and b/src/assets/github.png differ
diff --git a/src/assets/gmail.png b/src/assets/gmail.png
new file mode 100644
index 0000000..4528e3f
Binary files /dev/null and b/src/assets/gmail.png differ
diff --git a/src/assets/linked-in.png b/src/assets/linked-in.png
new file mode 100644
index 0000000..650b8db
Binary files /dev/null and b/src/assets/linked-in.png differ
diff --git a/src/assets/noise.jpg b/src/assets/noise.jpg
new file mode 100644
index 0000000..953903c
Binary files /dev/null and b/src/assets/noise.jpg differ
diff --git a/src/assets/note-icon.png b/src/assets/note-icon.png
new file mode 100644
index 0000000..b07f9c3
Binary files /dev/null and b/src/assets/note-icon.png differ
diff --git a/src/assets/terminal-background.jpg b/src/assets/terminal-background.jpg
new file mode 100644
index 0000000..723120f
Binary files /dev/null and b/src/assets/terminal-background.jpg differ
diff --git a/src/index.html b/src/index.html
index 71465d1..5144296 100644
--- a/src/index.html
+++ b/src/index.html
@@ -2,13 +2,16 @@
- TestWebsite
+
+
+
+ Cameron's Website
-
+
diff --git a/src/normalize.css b/src/normalize.css
new file mode 100644
index 0000000..81c6f31
--- /dev/null
+++ b/src/normalize.css
@@ -0,0 +1,427 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
\ No newline at end of file
diff --git a/src/polyfills.ts b/src/polyfills.ts
index d310405..92a7bdc 100644
--- a/src/polyfills.ts
+++ b/src/polyfills.ts
@@ -51,7 +51,7 @@ import 'core-js/es7/reflect';
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
**/
-// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
diff --git a/src/styles.css b/src/styles.css
index 90d4ee0..94f5eac 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -1 +1,89 @@
/* You can add global styles to this file, and also import other style files */
+@import "~@angular/material/prebuilt-themes/pink-bluegrey.css";
+
+body {
+ margin: 0;
+}
+
+html, body {
+ height: 100%;
+}
+
+h1, h2, h3, p, span {
+ font-family: Roboto, "Helvetica Neue", sans-serif;
+ font-weight: 300;
+}
+
+.body-text {
+ color: white;
+ width: 50%;
+ margin: 1em auto;
+}
+
+@media (min-width: 480px) and (max-width: 768px) {
+ .body-text {
+ font-size: 14px;
+ width: 80%;
+ }
+
+ .very-thin-subtitle {
+ font-size: 14px;
+ }
+
+ .thin-subtitle {
+ font-size: 14px;
+ }
+
+ .subtitle {
+ font-size: 14px;
+ }
+}
+
+@media (min-width: 768px){
+ .body-text {
+ font-size: 16px;
+ }
+
+ .very-thin-subtitle {
+ font-size: 16px;
+ }
+
+ .thin-subtitle {
+ font-size: 16px;
+ }
+
+ .subtitle {
+ font-size: 16px;
+ }
+}
+
+.very-thin-subtitle {
+ font-family: Montserrat, serif;
+ font-weight: 200;
+}
+
+.thin-subtitle {
+ font-family: Montserrat, serif;
+ font-weight: 300;
+}
+
+.subtitle {
+ font-family: Montserrat, serif;
+ font-weight: 400;
+}
+
+.dark-background {
+ background: #555555;
+}
+
+.center-column {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+ text-align: center
+}
+
+.active {
+ color: #1DAEDD;
+}