The site is more or less working. Some weirdness with animations though

This commit is contained in:
Cameron
2018-10-20 20:11:33 -04:00
parent c6f5c3d86e
commit 67c314924f
48 changed files with 1337 additions and 71 deletions

View File

@@ -1,20 +1,6 @@
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
<app-toolbar></app-toolbar>
</div>
<h2>Here are some links to help you start: </h2>
<ul>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>
<main [@routerTransition]="getState(o)">
<router-outlet #o="outlet"></router-outlet>
</main>

View File

@@ -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!');
}));
});

View File

@@ -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
}
}

View File

@@ -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 {
}

View File

@@ -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;
}

View File

@@ -0,0 +1,25 @@
<div
style="background: url(../../assets/terminal-background.jpg) repeat-y;width: 100%; height: 100%; background-size: contain">
<div class="center-column" style="position: absolute; z-index: 1; margin-top: 2em">
<h2>Social Media</h2>
<div style="display: flex; justify-content: center; width: 100%">
<div class="icon-layout" (click)="linkedInClicked()">
<img src="../../assets/linked-in.png" class="icon">
<span class="icon-text">LinkedIn</span>
</div>
<div class="icon-layout" (click)="githubClicked()">
<img src="../../assets/github.png" class="icon">
<span class="icon-text">GitHub</span>
</div>
<div class="icon-layout" (click)="emailClicked()">
<img src="../../assets/gmail.png" class="icon">
<span class="icon-text">Email</span>
</div>
</div>
<p class="subtitle">Contact me to connect, collaborate or just to chat.</p>
</div>
<div style="background: white; height: 100%; opacity: 0.78"></div>
</div>

View File

@@ -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<ContactComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ContactComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContactComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -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")
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,23 @@
<div class="home-container">
<div class="overlay" style="position: absolute;">
<img src="../../assets/CubeSpace.jpg" class="image">
</div>
<div class="center-column" style="height: 100%">
<div style="width: 100%; margin: 0 auto; position: absolute">
<img src="../../assets/cameron-headshot.jpg" style="width: 27%; margin: 2em 0 1em 0">
<h1 class="overlay-text">Cameron Cordes</h1>
<p
class="thin-subtitle" style="color: white;">
Android and iOS Developer</p>
<p class="body-text">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.</p>
<p class="body-text">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.</p>
</div>
</div>
</div>

View File

@@ -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<HomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HomeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -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() {
}
}

View File

@@ -0,0 +1,8 @@
import { ProjectKeywordPipe } from './project-keyword.pipe';
describe('ProjectKeywordPipe', () => {
it('create an instance', () => {
const pipe = new ProjectKeywordPipe();
expect(pipe).toBeTruthy();
});
});

View File

@@ -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 = '<b>' + value.substring(keywordIndex, keywordIndex + keyword.length) + '</b>';
value = value.replace(keyword, boldKeyword);
}
});
return value;
}
}

View File

@@ -0,0 +1,6 @@
export class ProjectItem {
title: String;
applicationType: String;
description: String
imgLocation: String
}

View File

@@ -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();
});
});

View File

@@ -0,0 +1,51 @@
import {Injectable} from '@angular/core';
import {ProjectItem} from "./project-item";
@Injectable({
providedIn: 'root'
})
export class ProjectService {
constructor() {
}
getProjects(): Promise<Array<ProjectItem>> {
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"
}
];

View File

@@ -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%;
}
}

View File

@@ -0,0 +1,9 @@
<div class="center-column">
<div class="project-item" *ngFor="let project of projects">
<h4>{{project.title}}</h4>
<img src={{project.imgLocation}} width="50%">
<p class="subtitle" style="margin: 0">{{project.applicationType}}</p>
<p class="thin-subtitle" [innerHTML]="project.description | projectKeyword"></p>
</div>
<div style="height: 4em"></div>
</div>

View File

@@ -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<ProjectsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ProjectsComponent, ProjectKeywordPipe]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProjectsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -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<ProjectItem>;
constructor(private projectService: ProjectService) {
}
ngOnInit(): void {
this.getProjects()
}
getProjects() {
return this.projectService.getProjects().then(projects => this.projects = projects)
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,74 @@
<div id="page-wrap">
<img src="../../assets/cthulu.png" alt="Photo of Cthulu" id="pic"/>
<div id="contact-info" class="vcard">
<!-- Microformats! -->
<h1 class="fn">Cameron Ryan Kenneth Cordes</h1>
<p>
Cell: <span class="tel">330-421-6010</span><br/>
Email: <a class="email" href="mailto:cameronc.dev@gmail.com">cameronc.dev@gmail.com</a>
</p>
</div>
<div id="objective">
</div>
<div class="clear"></div>
<dl>
<dd class="clear"></dd>
<dt>Education</dt>
<dd>
<h2>Baldwin Wallace University</h2>
<p><strong>Major:</strong> Computer Science<br/>
<strong>Minor:</strong> Math</p>
</dd>
<dd class="clear"></dd>
<dt>Skills</dt>
<dd>
<h2>Computer skills</h2>
<p>Windows, Linux, OSX, Android Studio, Visual Studio, XCode, Microsoft productivity software (Word, Excel, etc).</p>
</dd>
<dd class="clear"></dd>
<dt>Experience</dt>
<dd>
<h2>Progressive Insurance <span>Mobile Developer Jan 2018 - Present</span></h2>
<ul>
<li>Inspired and won highest peasant death competition among servants</li>
<li>Helped coordinate managers to grow cult following</li>
<li>Provided untimely deaths to all who opposed</li>
</ul>
<h2>Hyland Software <span>Developer II - Westlake, OH - 2016 - 2018</span></h2>
<ul>
<li>Developed a camera interface and photo viewer using Android Camera API for a consistent method of capturing photos and reviewing them</li>
<li>Wrote an image downloading module with in memory caching</li>
<li>Started an initiative to use the Model View Presenter pattern to enable more testable code</li>
</ul>
</dd>
<dd class="clear"></dd>
<dt>Hobbies</dt>
<dd>Music, Movies, Motorcycles, Homebrewing, Travel</dd>
<dd class="clear"></dd>
<dt>References</dt>
<dd>Available on request</dd>
<dd class="clear"></dd>
</dl>
<div class="clear"></div>
</div>

View File

@@ -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<ResumeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ResumeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ResumeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -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() {
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,8 @@
<mat-sidenav-container>
<mat-toolbar>
<span routerLink="/home" routerLinkActive="active">Home</span>
<span routerLink="/resume" routerLinkActive="active">Resume</span>
<span routerLink="/projects" routerLinkActive="active">Projects</span>
<span routerLink="/contact" routerLinkActive="active">Contact</span>
</mat-toolbar>
</mat-sidenav-container>

View File

@@ -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<ToolbarComponent>;
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");
});
});

View File

@@ -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() {
}
}