This commit is contained in:
Jan 2020-10-03 01:22:11 +02:00
commit 403277c6df
17 changed files with 17241 additions and 0 deletions

50
.gitignore vendored Normal file
View file

@ -0,0 +1,50 @@
.DS_STORE
/dist/
/bazel-out
/integration/bazel/bazel-*
*.log
node_modules
# Include when developing application packages.
pubspec.lock
.c9
.idea/
.devcontainer/*
!.devcontainer/README.md
!.devcontainer/recommended-devcontainer.json
!.devcontainer/recommended-Dockerfile
.settings/
.vscode/launch.json
.vscode/settings.json
.vscode/tasks.json
*.swo
modules/.settings
modules/.vscode
.vimrc
.nvimrc
# Don't check in secret files
*secret.js
# Ignore npm/yarn debug log
npm-debug.log
yarn-error.log
# build-analytics
.build-analytics
# rollup-test output
/modules/rollup-test/dist/
# User specific bazel settings
.bazelrc.user
# User specific ng-dev settings
.ng-dev.user*
.notes.md
baseline.json
# Ignore .history for the xyz.local-history VSCode extension
.history

129
angular.json Normal file
View file

@ -0,0 +1,129 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"app": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/app",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "app:build"
},
"configurations": {
"production": {
"browserTarget": "app:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "app:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "app:serve"
},
"configurations": {
"production": {
"devServerTarget": "app:serve:production"
}
}
}
}
}},
"defaultProject": "app"
}

16620
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

55
package.json Normal file
View file

@ -0,0 +1,55 @@
{
"name": "async-huddle-stories",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^10.0.0",
"@angular/common": "^10.0.0",
"@angular/compiler": "^10.0.0",
"@angular/core": "^10.0.0",
"@angular/forms": "^10.0.0",
"@angular/localize": "10.1.4",
"@angular/platform-browser": "^10.0.0",
"@angular/platform-browser-dynamic": "^10.0.0",
"@angular/router": "^10.0.0",
"@ng-bootstrap/ng-bootstrap": "7.0.0",
"bootstrap": "4.5.2",
"core-js": "3.6.4",
"rxjs": "6.5.4",
"tslib": "1.13.0",
"zone.js": "0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1000.0",
"@angular/cli": "^10.0.0",
"@angular/compiler-cli": "^10.0.0",
"@angular/language-service": "^10.0.0",
"@types/core-js": "0.9.46",
"@types/jasmine": "~2.8.3",
"@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~2.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~4.1.0",
"tslint": "~5.9.1",
"typescript": "3.9.7"
},
"keywords": [],
"description": ""
}

View file

@ -0,0 +1,80 @@
<nav class="navbar navbar-light bg-light">
<a class="navbar-brand" href="#" style="margin: 0 auto;">ASYNC HUDDLE</a>
</nav>
<div class="container">
<div class="row">
<div *ngFor="let user of users" class="col p-3">
<div class="text-center" (click)="playStory(user)">
<div
class="storyImage"
style="background-image: url({{user.image}})"
[ngClass]="{'hasStory': user.story_link && user.submit_time}"
></div>
<p class="mt-2 mb-0"><strong>{{user.name}}</strong></p>
<p><small>{{user.submit_time | date :'dd.MM. HH:mm' }}</small></p>
</div>
</div>
</div>
</div>
<ng-template #content let-modal>
<div class="modal-body d-flex flex-column">
<div class="btn-group mb-2" role="group" aria-label="Basic example">
<button type="button" class="btn btn-secondary" (click)="prevUser(modal)">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M18 17L10 12L18 7V17Z" fill="currentColor" />
<path d="M6 7H9V17H6V7Z" fill="currentColor" />
</svg>
</button>
<button
type="button"
class="btn btn-secondary"
(click)="modal.dismiss('Cross click')"
>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6.2253 4.81108C5.83477 4.42056 5.20161 4.42056 4.81108 4.81108C4.42056 5.20161 4.42056 5.83477 4.81108 6.2253L10.5858 12L4.81114 17.7747C4.42062 18.1652 4.42062 18.7984 4.81114 19.1889C5.20167 19.5794 5.83483 19.5794 6.22535 19.1889L12 13.4142L17.7747 19.1889C18.1652 19.5794 18.7984 19.5794 19.1889 19.1889C19.5794 18.7984 19.5794 18.1652 19.1889 17.7747L13.4142 12L19.189 6.2253C19.5795 5.83477 19.5795 5.20161 19.189 4.81108C18.7985 4.42056 18.1653 4.42056 17.7748 4.81108L12 10.5858L6.2253 4.81108Z"
fill="currentColor"
/>
</svg>
</button>
<button type="button" class="btn btn-secondary" (click)="nextUser(modal)">
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M6 17L14 12L6 7V17Z" fill="currentColor" />
<path d="M18 7H15V12V17H18V7Z" fill="currentColor" />
</svg>
</button>
</div>
<p class="text-center m-0">
<strong
>{{selectedUser.name}} -
<small
>{{selectedUser.submit_time | date :'dd.MM. HH:mm' }}</small
></strong
>
</p>
<video
[src]="selectedUser.story_link"
(ended)="nextUser(modal)"
autoplay
></video>
</div>
</ng-template>

View file

@ -0,0 +1,50 @@
.storyImage {
width: 200px;
height: 200px;
border-radius: 50%;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
margin: 0 auto;
}
.storyImage.hasStory:before {
content: "";
position: relative;
right: 1%;
bottom: 1%;
z-index: -1;
border-radius: inherit;
background: -webkit-gradient(
linear,
left top,
right top,
from(red),
to(orange)
);
background: linear-gradient(to right, red, orange);
width: 205px;
height: 205px;
margin: 0 auto;
display: block;
}
.modal-body {
height: 90vh;
}
.modal-body video {
width: 100%;
height: auto;
overflow-y: hidden;
}
.modal-body .close {
margin: 0 auto;
}
.modal-body .control {
position: absolute;
top: 20px;
}
.modal-body .control.right {
right: 20px;
}
.modal-body .control.left {
left: 20px;
}

90
src/app/app.component.ts Normal file
View file

@ -0,0 +1,90 @@
import { Component, ViewChild } from "@angular/core";
import { NgbModal, NgbModalRef } from "@ng-bootstrap/ng-bootstrap";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class AppComponent {
@ViewChild("content") content;
@ViewChild("activeStory") video;
users = [
{
name: "Jan",
image: "https://www.supercardating.com/doc/image.rhtm/profile-pic2.jpg",
submit_time: 1601655386668,
story_link:
"https://v16.tikbrowse.com/4bfe44985e5cf9126d53e74f10412e25/5f7806ee/video/tos/useast2a/tos-useast2a-pve-0068/a2d6b9c57b7b4050bcb674fe43592a82/?a=1988&br=2584&bt=1292&cr=0&cs=0&cv=1&dr=0&ds=3&er=&l=202010022306170101890492251369CD84&lr=tiktok_m&mime_type=video_mp4&qs=0&rc=ajczZGlrb3RqdTMzZjczM0ApOzM4Njw5NmU5NzU5ZzY2ZWdsbGBzcHFkX2xfLS0tMTZzczU2NTBhX14zLzEwY2NfNGE6Yw%3D%3D&vl=&vr="
},
{
name: "Bob",
image:
"https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse1.mm.bing.net%2Fth%3Fid%3DOIP.4oYqJqInuQd2TAlPPdggLgHaHa%26pid%3DApi&f=1",
submit_time: null,
story_link:
"https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4"
},
{
name: "Angela",
image:
"https://writestylesonline.com/wp-content/uploads/2019/01/What-To-Wear-For-Your-Professional-Profile-Picture-or-Headshot.jpg",
submit_time: 1601655386668,
story_link:
"https://minio.carl.jgerstbe.de/public/Idee%20Erstellen-12.m4v?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=jgerstbe%2F20201002%2F%2Fs3%2Faws4_request&X-Amz-Date=20201002T213319Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=d44fd8d773506e5052da5e90b8bb7587629864416deeaff979432143f188ea61"
}
];
selectedUser;
constructor(private modalService: NgbModal) {}
playStory(user) {
if (!user.submit_time || !user.story_link) {
return;
}
this.modalService.open(this.content, { centered: true });
this.selectedUser = user;
}
prevUser(modal: NgbModalRef) {
let index: number = this.users.findIndex(
(u) => u.name === this.selectedUser.name
);
if (index < 1) {
modal.close();
return;
}
while (
!this.users[index - 1].story_link ||
!this.users[index - 1].submit_time
) {
index--;
if (index === 0) {
modal.close();
return;
}
}
this.selectedUser = this.users[index - 1];
}
nextUser(modal: NgbModalRef) {
let index: number = this.users.findIndex(
(u) => u.name === this.selectedUser.name
);
if (index === -1 || index === this.users.length - 1) {
modal.close();
return;
}
while (
!this.users[index + 1].story_link ||
!this.users[index + 1].submit_time
) {
if (index === -1 || index === this.users.length - 1) {
modal.close();
return;
}
index++;
}
this.selectedUser = this.users[index + 1];
}
}

13
src/app/app.module.ts Normal file
View file

@ -0,0 +1,13 @@
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { AppComponent } from "./app.component";
import { NgbModalModule } from "@ng-bootstrap/ng-bootstrap";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, NgbModalModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}

View file

@ -0,0 +1,3 @@
export const environment = {
production: true
};

View file

@ -0,0 +1,8 @@
// The file contents for the current environment will overwrite these during build.
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.
export const environment = {
production: false
};

21
src/index.html Normal file
View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Angular</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<!-- <link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
crossorigin="anonymous"
/> -->
</head>
<body>
<app-root></app-root>
</body>
</html>

13
src/main.ts Normal file
View file

@ -0,0 +1,13 @@
import { enableProdMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { AppModule } from "./app/app.module";
import { environment } from "./environments/environment";
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.log(err));

60
src/polyfills.ts Normal file
View file

@ -0,0 +1,60 @@
/**
* 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 Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';
/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import "core-js/proposals/reflect-metadata";
/**
* Required to support Web Animations `@angular/platform-browser/animations`.
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
**/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import "zone.js/dist/zone"; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/

6
src/styles.scss Normal file
View file

@ -0,0 +1,6 @@
/* You can add global styles to this file, and also import other style files */
html,
body {
font-family: sans-serif;
}

5
src/typings.d.ts vendored Normal file
View file

@ -0,0 +1,5 @@
/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
id: string;
}

19
tsconfig.app.json Normal file
View file

@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.ts",
"src/**/*.d.ts"
],
"exclude": [
"src/**/*.spec.ts"
]
}

19
tsconfig.json Normal file
View file

@ -0,0 +1,19 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"module": "es2020",
"lib": [
"es2018",
"dom"
]
}
}