Website updates
This commit is contained in:
		
							
								
								
									
										28
									
								
								src/App.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/App.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import Foot from '@/components/foot.vue';
 | 
			
		||||
import Profile from '@/components/profile.vue';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<!-- Spacer -->
 | 
			
		||||
	<div class="w-100" style="height: min(75vh, 500px)"></div>
 | 
			
		||||
 | 
			
		||||
	<!-- Content -->
 | 
			
		||||
	<div class="cap-width mb-3 bg-white">
 | 
			
		||||
		<!-- Header -->
 | 
			
		||||
		<header class="p-3 mx-auto" style="background: #732222">
 | 
			
		||||
			<profile style="transform: translateY(-33%)" />
 | 
			
		||||
		</header>
 | 
			
		||||
 | 
			
		||||
		<!-- Body -->
 | 
			
		||||
		<main class="p-3">
 | 
			
		||||
			<router-view></router-view>
 | 
			
		||||
		</main>
 | 
			
		||||
 | 
			
		||||
		<!-- Footer -->
 | 
			
		||||
		<foot />
 | 
			
		||||
	</div>
 | 
			
		||||
 | 
			
		||||
	<!-- Spacer -->
 | 
			
		||||
	<div class="d-none d-sm-block w-100" style="height: 40px"></div>
 | 
			
		||||
</template>
 | 
			
		||||
@@ -1,36 +0,0 @@
 | 
			
		||||
import {HttpClientModule} from '@angular/common/http';
 | 
			
		||||
import {BrowserModule} from '@angular/platform-browser';
 | 
			
		||||
import {NgModule} from '@angular/core';
 | 
			
		||||
import {ContactFormComponent} from './components/contact-form/contact-form.component';
 | 
			
		||||
import {ProjectsComponent} from './components/projects/projects.component';
 | 
			
		||||
import {HomeComponent} from './views/home/home.component';
 | 
			
		||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
 | 
			
		||||
import {MaterialModule} from './material.module';
 | 
			
		||||
import {FormsModule} from '@angular/forms';
 | 
			
		||||
import {TypewriterComponent} from './components/typewriter/typewriter.component';
 | 
			
		||||
import {SlideShowComponent} from './components/slideShow/slideShow.component';
 | 
			
		||||
import {AppComponent} from './views/app/app.component';
 | 
			
		||||
import {AppRouting} from './app.routing';
 | 
			
		||||
import {ConsoleComponent} from './components/console/console.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
        AppComponent,
 | 
			
		||||
        ConsoleComponent,
 | 
			
		||||
		ContactFormComponent,
 | 
			
		||||
        HomeComponent,
 | 
			
		||||
		ProjectsComponent,
 | 
			
		||||
        SlideShowComponent,
 | 
			
		||||
        TypewriterComponent
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        AppRouting,
 | 
			
		||||
        BrowserModule,
 | 
			
		||||
        BrowserAnimationsModule,
 | 
			
		||||
        FormsModule,
 | 
			
		||||
		HttpClientModule,
 | 
			
		||||
        MaterialModule,
 | 
			
		||||
    ],
 | 
			
		||||
    bootstrap: [AppComponent]
 | 
			
		||||
})
 | 
			
		||||
export class AppModule { }
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
import {NgModule} from '@angular/core';
 | 
			
		||||
import {RouterModule} from '@angular/router';
 | 
			
		||||
import {HomeComponent} from './views/home/home.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [
 | 
			
		||||
        RouterModule.forRoot([
 | 
			
		||||
            {path: '', component: HomeComponent},
 | 
			
		||||
            {path: '**', redirectTo: ''}
 | 
			
		||||
        ])
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [RouterModule]
 | 
			
		||||
})
 | 
			
		||||
export class AppRouting {}
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
<div class="p-3 d-flex flex-column justify-content-end console overflow-hidden" [style.height]="height">
 | 
			
		||||
    <div>
 | 
			
		||||
        <h4 class="m-0" *ngFor="let o of output">{{o}}</h4>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="mt-2">
 | 
			
		||||
        <h4 class="m-0">
 | 
			
		||||
			{{prompt}} <typewriter class="pl-2" [text]="input" (done)="done()"></typewriter>
 | 
			
		||||
		</h4>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
.console {
 | 
			
		||||
	background-color: #333;
 | 
			
		||||
	color: #00ff00;
 | 
			
		||||
	font-family: monospace !important;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
import {Component, Input, ViewChild} from '@angular/core';
 | 
			
		||||
import {sleep} from '../../misc/utils';
 | 
			
		||||
import {TypewriterComponent} from '../typewriter/typewriter.component';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
	selector: 'console',
 | 
			
		||||
	templateUrl: './console.component.html',
 | 
			
		||||
	styleUrls: ['./console.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class ConsoleComponent {
 | 
			
		||||
	done = () => {};
 | 
			
		||||
	input = '';
 | 
			
		||||
	output: string[] = [];
 | 
			
		||||
	prompt = '>'
 | 
			
		||||
 | 
			
		||||
	@Input() height: string = 'auto';
 | 
			
		||||
 | 
			
		||||
	@ViewChild(TypewriterComponent) typewriter!: TypewriterComponent;
 | 
			
		||||
 | 
			
		||||
	clear() { this.output = []; }
 | 
			
		||||
 | 
			
		||||
	exec(input: string, output: () => any, pause = 1000) {
 | 
			
		||||
		return new Promise<void>(res => {
 | 
			
		||||
			this.done = async () => {
 | 
			
		||||
				await sleep(pause);
 | 
			
		||||
				this.input = '';
 | 
			
		||||
				this.output.push(`${this.prompt} ${input}`);
 | 
			
		||||
				const out = output();
 | 
			
		||||
				if(typeof out == 'string') this.output.push(out);
 | 
			
		||||
				res();
 | 
			
		||||
			};
 | 
			
		||||
			this.input = input;
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
<form>
 | 
			
		||||
	<div *ngIf="success" class="alert alert-success">Email sent!</div>
 | 
			
		||||
	<div *ngIf="error" class="alert alert-danger">Email failed to send</div>
 | 
			
		||||
	<div class="form-group">
 | 
			
		||||
		<label for="emailInput">Email</label>
 | 
			
		||||
		<input type="email" class="form-control" id="emailInput" name="email" placeholder="username@example.com" [(ngModel)]="email">
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="form-group">
 | 
			
		||||
		<label for="subjectInput">Subject</label>
 | 
			
		||||
		<input type="text" class="form-control" id="subjectInput" name="subject" placeholder="Interested in Services" [(ngModel)]="subject">
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="form-group">
 | 
			
		||||
		<label for="messageInput">Message</label>
 | 
			
		||||
		<textarea class="form-control" id="messageInput" name="message" rows="5" [(ngModel)]="message"></textarea>
 | 
			
		||||
	</div>
 | 
			
		||||
	<button type="button" class="btn btn-primary float-right" (click)="send()" [disabled]="loading || !email || !subject || !message">
 | 
			
		||||
		Send
 | 
			
		||||
	</button>
 | 
			
		||||
</form>
 | 
			
		||||
@@ -1,44 +0,0 @@
 | 
			
		||||
import {ChangeDetectorRef, Component} from '@angular/core';
 | 
			
		||||
import {EmailService} from '../../services/email.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
	selector: 'contact-form',
 | 
			
		||||
	templateUrl: './contact-form.component.html'
 | 
			
		||||
})
 | 
			
		||||
export class ContactFormComponent {
 | 
			
		||||
	email = '';
 | 
			
		||||
	error = false;
 | 
			
		||||
	loading = false;
 | 
			
		||||
	message = '';
 | 
			
		||||
	subject = '';
 | 
			
		||||
	success = false;
 | 
			
		||||
 | 
			
		||||
	constructor(private changeRef: ChangeDetectorRef, private emailService: EmailService) { }
 | 
			
		||||
 | 
			
		||||
	async send() {
 | 
			
		||||
		this.error = false;
 | 
			
		||||
		this.success = false;
 | 
			
		||||
		if(this.loading || !this.email || !this.subject || !this.message) return;
 | 
			
		||||
		this.loading = true;
 | 
			
		||||
		this.emailService.send(`ZaksCode: ${this.subject}`, `From: ${this.email}\n\n${this.message}`
 | 
			
		||||
		).then(() => {
 | 
			
		||||
			this.email = '';
 | 
			
		||||
			this.message = '';
 | 
			
		||||
			this.success = true;
 | 
			
		||||
			this.subject = '';
 | 
			
		||||
		}).catch(err => {
 | 
			
		||||
			// Postmail seems to always return an error message
 | 
			
		||||
			if(200 <= err.status && err.status < 300) {
 | 
			
		||||
				this.email = '';
 | 
			
		||||
				this.message = '';
 | 
			
		||||
				this.success = true;
 | 
			
		||||
				this.subject = '';
 | 
			
		||||
			} else {
 | 
			
		||||
				this.error = true;
 | 
			
		||||
			}
 | 
			
		||||
		}).finally(() => {
 | 
			
		||||
			this.loading = false;
 | 
			
		||||
			this.changeRef.detectChanges();
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
<mat-list dense>
 | 
			
		||||
	<ng-container *ngFor="let p of projectsService.all; let first = first">
 | 
			
		||||
		<mat-divider *ngIf="!first"></mat-divider>
 | 
			
		||||
		<mat-list-item>
 | 
			
		||||
			<img *ngIf="p.avatar_url" mat-list-avatar [src]="p.avatar_url" alt="Project icon">
 | 
			
		||||
			<img *ngIf="!p.avatar_url" mat-list-avatar src="/assets/img/git.png" alt="Project icon">
 | 
			
		||||
			<a mat-line [href]="p.web_url" target="_blank">{{p.name}}</a>
 | 
			
		||||
			<div mat-line>{{p.description}}</div>
 | 
			
		||||
		</mat-list-item>
 | 
			
		||||
	</ng-container>
 | 
			
		||||
</mat-list>
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
import {Component} from '@angular/core';
 | 
			
		||||
import {ProjectsService} from '../../services/projects.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
	selector: 'projects',
 | 
			
		||||
	templateUrl: './projects.component.html'
 | 
			
		||||
})
 | 
			
		||||
export class ProjectsComponent {
 | 
			
		||||
	constructor(public projectsService: ProjectsService) { }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
<div id="carouselIndicators" class="carousel slide h-100" data-ride="carousel">
 | 
			
		||||
    <ol class="carousel-indicators">
 | 
			
		||||
        <li *ngFor="let ignore of slides; let i = index" data-target="#carouselIndicators" [attr.data-slide-to]="i"></li>
 | 
			
		||||
    </ol>
 | 
			
		||||
    <div class="carousel-inner">
 | 
			
		||||
        <div *ngFor="let slide of slides" class="carousel-item">
 | 
			
		||||
            <img class="d-block w-100" [src]="slide.image" alt="project.name">
 | 
			
		||||
            <div class="carousel-caption d-none d-md-block">
 | 
			
		||||
                <h5>{{slide.title}}</h5>
 | 
			
		||||
                <p>{{slide.description}}</p>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <a class="carousel-control-prev" href="#carouselIndicators" role="button" data-slide="prev">
 | 
			
		||||
        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
 | 
			
		||||
        <span class="sr-only">Previous</span>
 | 
			
		||||
    </a>
 | 
			
		||||
    <a class="carousel-control-next" href="#carouselIndicators" role="button" data-slide="next">
 | 
			
		||||
        <span class="carousel-control-next-icon" aria-hidden="true"></span>
 | 
			
		||||
        <span class="sr-only">Next</span>
 | 
			
		||||
    </a>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
import {Component, Input} from '@angular/core';
 | 
			
		||||
 | 
			
		||||
export type Slide = {
 | 
			
		||||
	title: string;
 | 
			
		||||
	description: string;
 | 
			
		||||
	image: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'slideshow',
 | 
			
		||||
  templateUrl: 'slideShow.component.html'
 | 
			
		||||
})
 | 
			
		||||
export class SlideShowComponent {
 | 
			
		||||
    @Input() slides: Slide[] = [];
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
.typewriter {
 | 
			
		||||
    & {
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
        margin: 0 auto;
 | 
			
		||||
        letter-spacing: .15em;
 | 
			
		||||
        animation: blink-caret 1s step-end infinite;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @keyframes typing {
 | 
			
		||||
        from { width: 0 }
 | 
			
		||||
        to { width: 100% }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @keyframes blink-caret {
 | 
			
		||||
        from, to { border-right: .15em solid; }
 | 
			
		||||
        50% { border: none; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
import {Component, EventEmitter, Input, Output} from '@angular/core';
 | 
			
		||||
import {Observable, of, timer} from 'rxjs';
 | 
			
		||||
import {filter, map, tap} from 'rxjs/operators';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'typewriter',
 | 
			
		||||
    template: `<span class="typewriter">{{output | async}}</span>`,
 | 
			
		||||
    styleUrls: ['typewriter.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class TypewriterComponent {
 | 
			
		||||
	output?: Observable<string>;
 | 
			
		||||
 | 
			
		||||
    @Input() delay = 1500;
 | 
			
		||||
    @Input() speed = 100;
 | 
			
		||||
    @Input() set text(text: string) {
 | 
			
		||||
		if(!text) {
 | 
			
		||||
			this.output = of('');
 | 
			
		||||
		} else {
 | 
			
		||||
			this.output = timer(this.delay, this.speed).pipe(
 | 
			
		||||
				filter(n => n <= (text.length || 0)),
 | 
			
		||||
				tap(n => {
 | 
			
		||||
					if(n == text.length) this.done.emit();
 | 
			
		||||
				}),
 | 
			
		||||
				map(n => text.slice(0, n))
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Output() done = new EventEmitter<void>();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
import {NgModule} from '@angular/core';
 | 
			
		||||
import {MatButtonModule} from '@angular/material/button';
 | 
			
		||||
import {MatCardModule} from '@angular/material/card';
 | 
			
		||||
import {MatDividerModule} from '@angular/material/divider';
 | 
			
		||||
import {MatFormFieldModule} from '@angular/material/form-field';
 | 
			
		||||
import {MatInputModule} from '@angular/material/input';
 | 
			
		||||
import {MatListModule} from '@angular/material/list';
 | 
			
		||||
 | 
			
		||||
const MODULES = [
 | 
			
		||||
	MatButtonModule,
 | 
			
		||||
	MatCardModule,
 | 
			
		||||
	MatDividerModule,
 | 
			
		||||
	MatFormFieldModule,
 | 
			
		||||
	MatInputModule,
 | 
			
		||||
	MatListModule,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  imports: [MODULES],
 | 
			
		||||
  exports: [MODULES]
 | 
			
		||||
})
 | 
			
		||||
export class MaterialModule {}
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Convert data into a form encoded format.
 | 
			
		||||
 *
 | 
			
		||||
 * @param {any} data - data to convert
 | 
			
		||||
 * @returns {string} - Ecodeded form data
 | 
			
		||||
 */
 | 
			
		||||
export function formEncode(data: any): string {
 | 
			
		||||
	return Object.entries(data).map(([key, value]) =>
 | 
			
		||||
		encodeURIComponent(key) + '=' + encodeURIComponent(<any>value)
 | 
			
		||||
	).join('&');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Use with await to pause the script for a specified amount of time (in miliseconds).
 | 
			
		||||
 *
 | 
			
		||||
 * **Example:**
 | 
			
		||||
 * ```
 | 
			
		||||
 * async () => {
 | 
			
		||||
 *     ...
 | 
			
		||||
 *     await sleep(1000) // Wait 1 second
 | 
			
		||||
 *     ...
 | 
			
		||||
 * }
 | 
			
		||||
 * ```
 | 
			
		||||
 *
 | 
			
		||||
 * @param {number} ms - Time to pause in miliseconds
 | 
			
		||||
 * @returns {Promise<unknown>} - Promise you should await
 | 
			
		||||
 */
 | 
			
		||||
export function sleep(ms: number) {
 | 
			
		||||
	return new Promise(res => setTimeout(res, ms));
 | 
			
		||||
}
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
import {HttpClient} from '@angular/common/http';
 | 
			
		||||
import {Injectable} from '@angular/core';
 | 
			
		||||
import {formEncode} from '../misc/utils';
 | 
			
		||||
 | 
			
		||||
@Injectable({providedIn: 'root'})
 | 
			
		||||
export class EmailService {
 | 
			
		||||
	constructor(private http: HttpClient) { }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Send an email to website admin.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param {string} subject - Email subject line
 | 
			
		||||
	 * @param {string} message - Email body
 | 
			
		||||
	 * @returns {Promise<Object | undefined>} - Response from Postmail API
 | 
			
		||||
	 */
 | 
			
		||||
	send(subject: string, message: string) {
 | 
			
		||||
		return this.http.post('https://postmail.invotes.com/send', formEncode({
 | 
			
		||||
			access_token: 's7uhce84sx6fayy5xlq0nrtx',
 | 
			
		||||
			subject: subject,
 | 
			
		||||
			text: message
 | 
			
		||||
		}), {
 | 
			
		||||
			headers: {'Content-Type': 'application/x-www-form-urlencoded'}
 | 
			
		||||
		}).toPromise();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,47 +0,0 @@
 | 
			
		||||
import {HttpClient} from '@angular/common/http';
 | 
			
		||||
import {Injectable} from '@angular/core';
 | 
			
		||||
 | 
			
		||||
export type Project = {
 | 
			
		||||
	avatar_url: string;
 | 
			
		||||
	created_at: string;
 | 
			
		||||
	default_branch: string;
 | 
			
		||||
	description: string;
 | 
			
		||||
	forks_count: number;
 | 
			
		||||
	http_url_to_repo: string;
 | 
			
		||||
	id: number;
 | 
			
		||||
	last_activity_at: string;
 | 
			
		||||
	name: string;
 | 
			
		||||
	name_with_namespace: string;
 | 
			
		||||
	namespace: {
 | 
			
		||||
		full_path: string;
 | 
			
		||||
		id: number;
 | 
			
		||||
		kind: string;
 | 
			
		||||
		name: string;
 | 
			
		||||
		parent_id: number;
 | 
			
		||||
		path: string;
 | 
			
		||||
		web_url: string;
 | 
			
		||||
	};
 | 
			
		||||
	path: string;
 | 
			
		||||
	path_with_namespace: string;
 | 
			
		||||
	readme_url: string;
 | 
			
		||||
	ssh_url_to_repo: string;
 | 
			
		||||
	star_count: number;
 | 
			
		||||
	tag_list: string[];
 | 
			
		||||
	topics: string[];
 | 
			
		||||
	web_url: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Injectable({providedIn: 'root'})
 | 
			
		||||
export class ProjectsService {
 | 
			
		||||
	all: Project[] = [];
 | 
			
		||||
 | 
			
		||||
	constructor(private http: HttpClient) {
 | 
			
		||||
		this.http.get<Project[]>('https://gitlab.zakscode.com/api/v4/projects').toPromise().then(projects => {
 | 
			
		||||
			this.all = (projects || []).sort((a, b) => {
 | 
			
		||||
				if(a.name > b.name) return 1;
 | 
			
		||||
				if(a.name < b.name) return -1;
 | 
			
		||||
				return 0;
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,27 +0,0 @@
 | 
			
		||||
import {Injectable} from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Injectable({providedIn: 'root'})
 | 
			
		||||
export class QuoteService {
 | 
			
		||||
	readonly quotes = [
 | 
			
		||||
		'When you are a kid you don\'t realize you are also watching your parents grow up',
 | 
			
		||||
		'Some one at Google was like "Yea, just have someone drive down every road on earth!"',
 | 
			
		||||
		'Anxiety is like when video game combat music is playing but you can\'t find the enemy',
 | 
			
		||||
		'Why do kamikaze pilots wear helmets?',
 | 
			
		||||
		'The cake is a lie!',
 | 
			
		||||
		'How are unicorns fake but giraffes real?',
 | 
			
		||||
		'The number of people older than you never goes up',
 | 
			
		||||
		'When you brush your teeth you are cleaning your skeleton',
 | 
			
		||||
		'Pregenancy is like a group project where one person get\'s stuck with all the work',
 | 
			
		||||
		'If the universe wasn\'t infinite it would be even scarier',
 | 
			
		||||
		'Either we are alone in the universe or we are not. both are terrifying'
 | 
			
		||||
	];
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Return random quote
 | 
			
		||||
	 *
 | 
			
		||||
	 * @returns {string} - Quote
 | 
			
		||||
	 */
 | 
			
		||||
	random() {
 | 
			
		||||
		return this.quotes[Math.round(Math.random() * (this.quotes.length - 1))];
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
<router-outlet></router-outlet>
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
import {Component} from '@angular/core';
 | 
			
		||||
import {Title} from '@angular/platform-browser';
 | 
			
		||||
import {ActivatedRoute} from '@angular/router';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'app-root',
 | 
			
		||||
    templateUrl: 'app.component.html'
 | 
			
		||||
})
 | 
			
		||||
export class AppComponent {
 | 
			
		||||
    constructor(private route: ActivatedRoute, private title: Title) {
 | 
			
		||||
        this.route.url.subscribe(() => this.setTitle(''));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	setTitle(title: string) {
 | 
			
		||||
		this.title.setTitle(`Zak's Code${title ? ` - ${title}` : ''}`);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,80 +0,0 @@
 | 
			
		||||
<div class="w-100">
 | 
			
		||||
    <div class="w-100" style="height: calc(100vh - 140px)"></div>
 | 
			
		||||
    <div class="container p-0 bg-white">
 | 
			
		||||
        <div class="px-3" style="background-color: #732222">
 | 
			
		||||
            <mat-card style="max-width: 600px; transform: translateY(-33%)">
 | 
			
		||||
                <mat-card-content class="d-flex p-3">
 | 
			
		||||
                    <div class="d-none d-md-block pr-3">
 | 
			
		||||
                        <img src="assets/img/portrait.jpg" width="150px" height="150px" style="border-radius: 50%" alt="Zakary Timson">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div>
 | 
			
		||||
                        <h1 class="mb-0">Zakary Timson</h1>
 | 
			
		||||
                        <h5 class="text-muted">DEVOPS & SOFTWARE ENGINEER</h5>
 | 
			
		||||
                        <div class="mt-3">
 | 
			
		||||
                            <div><i class="mr-2 fa fa-map-marker-alt"></i> London Ontario, Canada</div>
 | 
			
		||||
                            <div><i class="mr-2 fa fa-envelope"></i> <a href="mailto:zaktimson@gmail.com">zaktimson@gmail.com</a></div>
 | 
			
		||||
							<div><i class="mr-2 fa-brands fa-gitlab"></i> <a href="https://gitlab.zakscode.com/explore/projects" target="_blank">gitlab.zakscode.com</a></div>
 | 
			
		||||
                            <div><i class="mr-2 fa-brands fa-github"></i> <a href="https://github.com/ztimson" target="_blank">github.com/ztimson</a></div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </mat-card-content>
 | 
			
		||||
            </mat-card>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="p-4">
 | 
			
		||||
            <console height="12rem"></console>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="p-4">
 | 
			
		||||
            <h3>About Me</h3>
 | 
			
		||||
            <div>
 | 
			
		||||
				<img alt="Childhood" class="float-right m-3 m-md-0 ml-md-3" src="assets/img/keyboard-in-hand.jpg" height="150px" width="auto" style="border-radius: 50%">
 | 
			
		||||
				<p>
 | 
			
		||||
					Zak was born with a keyboard in hand and was learning his first programming language by thirteen. Nearly
 | 
			
		||||
					entirely self taught, Zak challenged his programming courses through both high-school and college while
 | 
			
		||||
					working in the industry to gain professional experience. He is very passionate about technology and as a
 | 
			
		||||
					lifelong learner it has opened the door to many other hobbies like robotics, space and physics. Some of his
 | 
			
		||||
					personal projects include a full sized arcade machine, home automation and a power wall for a home solar
 | 
			
		||||
					system.
 | 
			
		||||
				</p>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
		<div class="p-4 overflow-hidden">
 | 
			
		||||
			<h3>Resume & References</h3>
 | 
			
		||||
			<div class="d-md-none">
 | 
			
		||||
				<ul class="list-group">
 | 
			
		||||
					<a class="list-group-item list-group-item-action border-primary text-primary" href="https://docs.google.com/document/d/1xP6HASPerXKMJM_x6-PhHVvoYgq-Hym5IRO7g47EX8o/edit?usp=sharing" target="_blank">Resume</a>
 | 
			
		||||
				</ul>
 | 
			
		||||
				<ul class="list-group mt-3">
 | 
			
		||||
					<a class="list-group-item list-group-item-action border-info text-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyNWw0UDFzT0ZTeVU/view?usp=sharing" target="_blank">Manager</a>
 | 
			
		||||
					<a class="list-group-item list-group-item-action border-info text-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyaFBhcXBEaGp6YWc/view?usp=sharing" target="_blank">Contractor</a>
 | 
			
		||||
					<a class="list-group-item list-group-item-action border-info text-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyM0YtTWcxQzk0dEE/view?usp=sharing" target="_blank">Teacher</a>
 | 
			
		||||
					<a class="list-group-item list-group-item-action border-info text-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyX2owd0xURjh3RlE/view?usp=sharing" target="_blank">Principle</a>
 | 
			
		||||
					<a class="list-group-item list-group-item-action border-info text-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyMHdaM1BjZ1MwbWxva2lOY290NElwanN4b2JV/view?usp=sharing" target="_blank">CD Projekt Red</a>
 | 
			
		||||
				</ul>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="d-none d-md-inline-block pt-1">
 | 
			
		||||
				<a class="btn btn-outline-primary" href="https://docs.google.com/document/d/1xP6HASPerXKMJM_x6-PhHVvoYgq-Hym5IRO7g47EX8o/edit?usp=sharing" target="_blank">Resume</a>
 | 
			
		||||
				<div class="ml-3 btn-group" role="group" aria-label="Basic example">
 | 
			
		||||
					<a class="btn btn-outline-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyNWw0UDFzT0ZTeVU/view?usp=sharing" target="_blank">Manager</a>
 | 
			
		||||
					<a class="btn btn-outline-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyaFBhcXBEaGp6YWc/view?usp=sharing" target="_blank">Contractor</a>
 | 
			
		||||
					<a class="btn btn-outline-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyM0YtTWcxQzk0dEE/view?usp=sharing" target="_blank">Teacher</a>
 | 
			
		||||
					<a class="btn btn-outline-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyX2owd0xURjh3RlE/view?usp=sharing" target="_blank">Principle</a>
 | 
			
		||||
					<a class="btn btn-outline-info" href="https://drive.google.com/file/d/0B_iz0vkzXmAyMHdaM1BjZ1MwbWxva2lOY290NElwanN4b2JV/view?usp=sharing" target="_blank">CD Projekt Red</a>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="p-4">
 | 
			
		||||
			<h3>Projects & Repositories</h3>
 | 
			
		||||
			<projects></projects>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="p-4 overflow-hidden">
 | 
			
		||||
			<h3>Contact</h3>
 | 
			
		||||
			<contact-form></contact-form>
 | 
			
		||||
		</div>
 | 
			
		||||
        <footer class="p-1 bg-dark text-center" style="color: grey">
 | 
			
		||||
            Copyright © ZaksCode 2022 | All Rights Reserved
 | 
			
		||||
			<br>
 | 
			
		||||
			Created by <a href="https://zakscode.com">Zak Timson</a>
 | 
			
		||||
        </footer>
 | 
			
		||||
        <div class="d-none d-sm-block skirt"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
import {AfterViewInit, Component, ViewChild} from '@angular/core';
 | 
			
		||||
import {ConsoleComponent} from '../../components/console/console.component';
 | 
			
		||||
import {QuoteService} from '../../services/quote.service';
 | 
			
		||||
import {sleep} from '../../misc/utils';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
	selector: 'home',
 | 
			
		||||
	templateUrl: './home.component.html'
 | 
			
		||||
})
 | 
			
		||||
export class HomeComponent implements AfterViewInit {
 | 
			
		||||
	@ViewChild(ConsoleComponent) console!: ConsoleComponent;
 | 
			
		||||
 | 
			
		||||
	constructor(private quotes: QuoteService) { }
 | 
			
		||||
 | 
			
		||||
	ngAfterViewInit() { this.animateConsole(); }
 | 
			
		||||
 | 
			
		||||
	animateConsole() {
 | 
			
		||||
		setTimeout(async () => {
 | 
			
		||||
			await this.console.exec('bash ./random-thought.sh', () => this.quotes.random());
 | 
			
		||||
			await sleep(10000);
 | 
			
		||||
			await this.console.exec('clear', async () => this.console.clear());
 | 
			
		||||
			this.animateConsole();
 | 
			
		||||
		}, 1000);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 1.9 MiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 83 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 31 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 58 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 123 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 29 KiB  | 
							
								
								
									
										10
									
								
								src/components/icon.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/components/icon.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
	const props = defineProps({
 | 
			
		||||
		class: {type: String, default: ''},
 | 
			
		||||
		name: {type: String, required: true},
 | 
			
		||||
	});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<i :class="props.class + ' fa fa-' + props.name"></i>
 | 
			
		||||
</template>
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
export const environment = {
 | 
			
		||||
  production: true
 | 
			
		||||
};
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
// This file can be replaced during build by using the `fileReplacements` array.
 | 
			
		||||
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
 | 
			
		||||
// The list of file replacements can be found in `angular.json`.
 | 
			
		||||
 | 
			
		||||
export const environment = {
 | 
			
		||||
  production: false
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * For easier debugging in development mode, you can import the following file
 | 
			
		||||
 * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
 | 
			
		||||
 *
 | 
			
		||||
 * This import should be commented out in production mode because it will have a negative impact
 | 
			
		||||
 * on performance if an error is thrown.
 | 
			
		||||
 */
 | 
			
		||||
// import 'zone.js/plugins/zone-error';  // Included with Angular CLI.
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
	<meta charset="utf-8">
 | 
			
		||||
	<title>Zaks Code</title>
 | 
			
		||||
	<base href="/">
 | 
			
		||||
 | 
			
		||||
	<meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
	<meta name=”robots” content=”index,nofollow” />
 | 
			
		||||
	<meta property=”og:type” content=”website” />
 | 
			
		||||
	<meta property=”og:title” content=”Zakary Timson” />
 | 
			
		||||
	<meta property=”og:description” content=”Cloud Architecture & Software Engineering” />
 | 
			
		||||
	<meta property=”og:image” content=”https://zakscode.com/assets/img/ZaksCode.png” />
 | 
			
		||||
	<meta property=”og:url” content=”https://zakscode.com” />
 | 
			
		||||
	<meta property=”og:site_name” content=”ZaksCode” />
 | 
			
		||||
	<meta name=”twitter:title” content=”Zakary Timson” />
 | 
			
		||||
	<meta name=”twitter:description” content=”Cloud Architecture & Software Engineering” />
 | 
			
		||||
	<meta name=”twitter:image” content=”https://zakscode.com/assets/img/ZaksCode.png” />
 | 
			
		||||
 | 
			
		||||
	<link rel="icon" type="image/png" href="assets/img/logo.png">
 | 
			
		||||
 <link rel="preconnect" href="https://fonts.gstatic.com">
 | 
			
		||||
 <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
 | 
			
		||||
 <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<app-root></app-root>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										34
									
								
								src/main.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/main.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
@import url("https://use.fontawesome.com/releases/v6.1.1/css/all.css");
 | 
			
		||||
@import url("https://fonts.googleapis.com/css2?family=Roboto");
 | 
			
		||||
@import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar { width: 10px; }
 | 
			
		||||
::-webkit-scrollbar-track { background: #333; }
 | 
			
		||||
::-webkit-scrollbar-thumb { background: #555; border-radius: 5px }
 | 
			
		||||
::-webkit-scrollbar-thumb:hover { background: #aaa; }
 | 
			
		||||
 | 
			
		||||
html, body {
 | 
			
		||||
	height: 100%;
 | 
			
		||||
	width: 100%;
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	padding: 0;
 | 
			
		||||
 | 
			
		||||
	font-family: Roboto,sans-serif;
 | 
			
		||||
	background: #354B72 url(/cloud.gif) no-repeat fixed right 50% top -10vh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:not(.btn), a:not(.btn):visited {
 | 
			
		||||
	color: #007bff;
 | 
			
		||||
	text-decoration: none;
 | 
			
		||||
 | 
			
		||||
	&:hover {
 | 
			
		||||
		color: #0062ce;
 | 
			
		||||
		text-decoration: underline;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.cap-width {
 | 
			
		||||
	width: min(100%, 1100px);
 | 
			
		||||
	margin-left: auto;
 | 
			
		||||
	margin-right: auto;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/main.ts
									
									
									
									
									
								
							@@ -1,12 +1,9 @@
 | 
			
		||||
import { enableProdMode } from '@angular/core';
 | 
			
		||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 | 
			
		||||
import './main.scss'
 | 
			
		||||
import { createApp } from 'vue'
 | 
			
		||||
import App from './App.vue'
 | 
			
		||||
import router from './router'
 | 
			
		||||
 | 
			
		||||
import { AppModule } from './app/app.module';
 | 
			
		||||
import { environment } from './environments/environment';
 | 
			
		||||
const app = createApp(App)
 | 
			
		||||
 | 
			
		||||
if (environment.production) {
 | 
			
		||||
  enableProdMode();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
platformBrowserDynamic().bootstrapModule(AppModule)
 | 
			
		||||
  .catch(err => console.error(err));
 | 
			
		||||
app.use(router)
 | 
			
		||||
app.mount('#app')
 | 
			
		||||
 
 | 
			
		||||
@@ -1,53 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This file includes polyfills needed by Angular and is loaded before the app.
 | 
			
		||||
 * You can add your own extra polyfills to this file.
 | 
			
		||||
 *
 | 
			
		||||
 * This file is divided into 2 sections:
 | 
			
		||||
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 | 
			
		||||
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 | 
			
		||||
 *      file.
 | 
			
		||||
 *
 | 
			
		||||
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 | 
			
		||||
 * automatically update themselves. This includes recent versions of Safari, Chrome (including
 | 
			
		||||
 * Opera), Edge on the desktop, and iOS and Chrome on mobile.
 | 
			
		||||
 *
 | 
			
		||||
 * Learn more in https://angular.io/guide/browser-support
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***************************************************************************************************
 | 
			
		||||
 * BROWSER POLYFILLS
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * By default, zone.js will patch all possible macroTask and DomEvents
 | 
			
		||||
 * user can disable parts of macroTask/DomEvents patch by setting following flags
 | 
			
		||||
 * because those flags need to be set before `zone.js` being loaded, and webpack
 | 
			
		||||
 * will put import in the top of bundle, so user need to create a separate file
 | 
			
		||||
 * in this directory (for example: zone-flags.ts), and put the following flags
 | 
			
		||||
 * into that file, and then add the following code before importing zone.js.
 | 
			
		||||
 * import './zone-flags';
 | 
			
		||||
 *
 | 
			
		||||
 * The flags allowed in zone-flags.ts are listed here.
 | 
			
		||||
 *
 | 
			
		||||
 * The following flags will work for all browsers.
 | 
			
		||||
 *
 | 
			
		||||
 * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
 | 
			
		||||
 * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
 | 
			
		||||
 * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
 | 
			
		||||
 *
 | 
			
		||||
 *  in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
 | 
			
		||||
 *  with the following flag, it will bypass `zone.js` patch for IE/Edge
 | 
			
		||||
 *
 | 
			
		||||
 *  (window as any).__Zone_enable_cross_context_check = true;
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***************************************************************************************************
 | 
			
		||||
 * Zone JS is required by default for Angular itself.
 | 
			
		||||
 */
 | 
			
		||||
import 'zone.js';  // Included with Angular CLI.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***************************************************************************************************
 | 
			
		||||
 * APPLICATION IMPORTS
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										11
									
								
								src/router/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/router/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
import { createRouter, createWebHistory } from 'vue-router'
 | 
			
		||||
import Home from '@/views/Home.vue'
 | 
			
		||||
 | 
			
		||||
const router = createRouter({
 | 
			
		||||
  history: createWebHistory(import.meta.env.BASE_URL),
 | 
			
		||||
  routes: [
 | 
			
		||||
	  {path: '/', name: 'home', component: Home}
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export default router
 | 
			
		||||
@@ -1,53 +0,0 @@
 | 
			
		||||
@use '@angular/material' as mat;
 | 
			
		||||
 | 
			
		||||
@import url("https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css");
 | 
			
		||||
@import url("https://use.fontawesome.com/releases/v6.1.1/css/all.css");
 | 
			
		||||
@import url("https://fonts.googleapis.com/icon?family=Material+Icons|Roboto:300,400,500");
 | 
			
		||||
 | 
			
		||||
@include mat.core();
 | 
			
		||||
 | 
			
		||||
$zakscode-primary: mat.define-palette(mat.$blue-palette, 900);
 | 
			
		||||
$zakscode-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
 | 
			
		||||
$zakscode-warn: mat.define-palette(mat.$red-palette);
 | 
			
		||||
$zakscode-theme: mat.define-light-theme((
 | 
			
		||||
  color: (
 | 
			
		||||
    primary: $zakscode-primary,
 | 
			
		||||
    accent: $zakscode-accent,
 | 
			
		||||
    warn: $zakscode-warn,
 | 
			
		||||
  )
 | 
			
		||||
));
 | 
			
		||||
@include mat.all-component-themes($zakscode-theme);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar-track {
 | 
			
		||||
	background-color: #354B72;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar {
 | 
			
		||||
	width: 10px;
 | 
			
		||||
	background-color: #354B72;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-scrollbar-thumb {
 | 
			
		||||
	border-radius: 5px;
 | 
			
		||||
	-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.5);
 | 
			
		||||
	background-color: #354B72;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html, body {
 | 
			
		||||
	height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	font-family: Roboto, sans-serif;
 | 
			
		||||
	background: #354B72 url("/assets/img/ZaksCode.gif") no-repeat fixed center;
 | 
			
		||||
	background-position: right 50% top -10vh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.skirt {
 | 
			
		||||
	height: 3rem;
 | 
			
		||||
	width: 100%;
 | 
			
		||||
	background-color: #354B72;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								src/test.ts
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/test.ts
									
									
									
									
									
								
							@@ -1,26 +0,0 @@
 | 
			
		||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
 | 
			
		||||
 | 
			
		||||
import 'zone.js/testing';
 | 
			
		||||
import { getTestBed } from '@angular/core/testing';
 | 
			
		||||
import {
 | 
			
		||||
  BrowserDynamicTestingModule,
 | 
			
		||||
  platformBrowserDynamicTesting
 | 
			
		||||
} from '@angular/platform-browser-dynamic/testing';
 | 
			
		||||
 | 
			
		||||
declare const require: {
 | 
			
		||||
  context(path: string, deep?: boolean, filter?: RegExp): {
 | 
			
		||||
    <T>(id: string): T;
 | 
			
		||||
    keys(): string[];
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// First, initialize the Angular testing environment.
 | 
			
		||||
getTestBed().initTestEnvironment(
 | 
			
		||||
  BrowserDynamicTestingModule,
 | 
			
		||||
  platformBrowserDynamicTesting(),
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
// Then we find all the tests.
 | 
			
		||||
const context = require.context('./', true, /\.spec\.ts$/);
 | 
			
		||||
// And load the modules.
 | 
			
		||||
context.keys().map(context);
 | 
			
		||||
							
								
								
									
										122
									
								
								src/views/Home.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/views/Home.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import Contact from '@/components/contact.vue';
 | 
			
		||||
import Icon from '@/components/icon.vue';
 | 
			
		||||
import Konsole from '@/components/konsole.vue';
 | 
			
		||||
import Projects from '@/components/projects.vue';
 | 
			
		||||
import Refrences from '@/components/refrences.vue';
 | 
			
		||||
 | 
			
		||||
const services: Projects[] = [
 | 
			
		||||
	{name: 'Formula Manager', icon: 'https://git.zakscode.com/avatars/7ec6bfd66b2bf9bad5c43c75a33f9cb3f6609b05c33a31f5d1e524a567cd09c1?size=280', link: 'https://screenprintingsuppliescanada.com/formulation-manager', description: 'Screen Printing Supplies'},
 | 
			
		||||
	{name: 'Map Alliance', icon: 'https://maps.zakscode.com/assets/images/logo.png', link: 'https://maps.zakscode.com', description: 'Online GIS & map editing solution'},
 | 
			
		||||
	{name: 'Phone Reminders', icon: 'https://phone-reminders.com/phone-reminders.png', link: 'https://phone-reminders.com', description: 'Send SMS & Voice call reminders from Google Calendar'},
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const openSource: Projects[] = [
 | 
			
		||||
	{name: 'Formula Manager', icon: 'https://git.zakscode.com/avatars/7ec6bfd66b2bf9bad5c43c75a33f9cb3f6609b05c33a31f5d1e524a567cd09c1?size=280', link: 'https://screenprintingsuppliescanada.com/formulation-manager', description: 'Screen Printing Supplies'},
 | 
			
		||||
	{name: 'Map Alliance', icon: 'https://maps.zakscode.com/assets/images/logo.png', link: 'https://maps.zakscode.com', description: 'Online GIS & map editing solution', source: 'https://google.com'},
 | 
			
		||||
	{name: 'Phone Reminders', icon: 'https://phone-reminders.com/phone-reminders.png', link: 'https://phone-reminders.com', description: 'Send SMS & Voice call reminders from Google Calendar'},
 | 
			
		||||
];
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="p-3">
 | 
			
		||||
		<konsole class="mb-5" style="max-height: 300px" />
 | 
			
		||||
 | 
			
		||||
		<div class="mb-5 pt-5">
 | 
			
		||||
			<h4 class="mb-0 text-center">Plan for Success</h4>
 | 
			
		||||
			<hr class="mb-4">
 | 
			
		||||
			<div class="text-center my-5">
 | 
			
		||||
				<img src="/cycle.svg" alt="Development Cycle" style="width: 100%; max-width: 600px; height: auto;">
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="d-flex">
 | 
			
		||||
				<div class="d-flex flex-column align-items-center border m-3 p-3 text-center" style="flex: 1 0 0;">
 | 
			
		||||
					<div class="m-3 p-3 rounded-circle text-white d-flex align-items-middle justify-content-center" style="background: #6aa84f; height: 50px; width: 50px">
 | 
			
		||||
						<icon name="clipboard"/>
 | 
			
		||||
					</div>
 | 
			
		||||
					<h5>Plan</h5>
 | 
			
		||||
					<p class="text-center">
 | 
			
		||||
						Working with the client we will identify the goals of the project. This includes things like the target audience, use case, features, style, and deployment strategy.
 | 
			
		||||
					</p>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="d-flex flex-column align-items-center border m-3 p-3" style="flex: 1 0 0;">
 | 
			
		||||
					<div class="m-3 p-3 rounded-circle text-white d-flex align-items-middle justify-content-center" style="background: #6d9eeb; height: 50px; width: 50px">
 | 
			
		||||
						<icon name="code"/>
 | 
			
		||||
					</div>
 | 
			
		||||
					<h5>Develop</h5>
 | 
			
		||||
					<p class="text-center">
 | 
			
		||||
						Goals are broken down into tasks and are prioritized. Using CI/CD, tasks are automatically deployed for testing as they are completed.
 | 
			
		||||
					</p>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="d-flex flex-column align-items-center border m-3 p-3" style="flex: 1 0 0;">
 | 
			
		||||
					<div class="m-3 p-3 rounded-circle text-white d-flex align-items-middle justify-content-center" style="background: #e69138; height: 50px; width: 50px">
 | 
			
		||||
						<icon name="message"/>
 | 
			
		||||
					</div>
 | 
			
		||||
					<h5>Feedback</h5>
 | 
			
		||||
					<p class="text-center">
 | 
			
		||||
						Clients are notified with the release notes and can test at their convince. Any critiques can be communicated directly to us or through our ticketing system.
 | 
			
		||||
					</p>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="d-flex flex-column align-items-center border m-3 p-3" style="flex: 1 0 0;">
 | 
			
		||||
					<div class="m-3 p-3 rounded-circle text-white" style="background: #674ea7; height: 50px; width: 50px">
 | 
			
		||||
						<h5 class="m-0">4</h5>
 | 
			
		||||
					</div>
 | 
			
		||||
					<h5>Release</h5>
 | 
			
		||||
					<p class="text-center">
 | 
			
		||||
						Once all goals are complete we will work with you to deploy the product to any location. Once setup, future updates are automatically rolled out.
 | 
			
		||||
					</p>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="d-flex align-items-center">
 | 
			
		||||
				<div>
 | 
			
		||||
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="d-flex flex-column">
 | 
			
		||||
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<div class="mb-5">
 | 
			
		||||
			<h3 class="mb-0">About</h3>
 | 
			
		||||
			<hr class="mb-4">
 | 
			
		||||
			<img alt="Childhood" src="/childhood.jpg" height="150px" width="auto" class="float-end m-3 m-md-0 ml-md-3" style="border-radius: 50%;">
 | 
			
		||||
			<p>
 | 
			
		||||
				Zak Timson is a software engineer with over 10 years of professional experience. Zak has had a love for
 | 
			
		||||
				computers since he was born & taught him self to code at the age of 13. Since then, he has gone to school
 | 
			
		||||
				for computer science & has worked for both small businesses and large corporations as a developer and team lead.
 | 
			
		||||
			</p>
 | 
			
		||||
			<p>
 | 
			
		||||
				Zak specializes in full-stack web development & server infrastructure, and primarily works on large enterprise
 | 
			
		||||
				grade "Software as a service" (SaaS) products. As a software architect & team lead he is able to work with
 | 
			
		||||
				business's to create a road map of their needs, build enterprise grade software solutions that meet those
 | 
			
		||||
				needs & work with clients to host & deliver automatic updates at scale using continuous integration.
 | 
			
		||||
			</p>
 | 
			
		||||
 | 
			
		||||
			<div class="mt-4">
 | 
			
		||||
				<h4 class="mb-3 text-muted">CSV & References</h4>
 | 
			
		||||
				<refrences />
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<div class="mb-5">
 | 
			
		||||
			<h3 class="m-0">Projects</h3>
 | 
			
		||||
			<hr class="mb-4">
 | 
			
		||||
			<div class="mb-4">
 | 
			
		||||
				<h4 class="mb-3 text-muted">Products & Services</h4>
 | 
			
		||||
				<projects :projects="services"/>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div>
 | 
			
		||||
				<h4 class="mb-3 text-muted">Open Source</h4>
 | 
			
		||||
				<projects :projects="openSource"/>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
 | 
			
		||||
		<div>
 | 
			
		||||
			<h3 class="m-0">Contact</h3>
 | 
			
		||||
			<hr class="mb-4">
 | 
			
		||||
			<div>
 | 
			
		||||
				<contact />
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
		Reference in New Issue
	
	Block a user