Compare commits
No commits in common. "master" and "CHAL-1" have entirely different histories.
33
Jenkinsfile
vendored
33
Jenkinsfile
vendored
@ -1,33 +0,0 @@
|
||||
pipeline {
|
||||
agent {
|
||||
docker { image 'elixir:1.9.4' }
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh "elixir -v"
|
||||
dir("challange_accepted") {
|
||||
sh "mix compile && MIX_ENV=test mix compile"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Test') {
|
||||
steps {
|
||||
dir("challange_accepted") {
|
||||
sh "mix test"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build release') {
|
||||
steps {
|
||||
dir("challange_accepted") {
|
||||
sh "mix release"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,2 +1 @@
|
||||
<h1> ChallangeAccepted </h1>
|
||||
Projekt
|
||||
<h1> ChallangeAccepted </h1>
|
@ -1,4 +0,0 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
24
challange_accepted/.gitignore
vendored
24
challange_accepted/.gitignore
vendored
@ -1,24 +0,0 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
challange_accepted-*.tar
|
||||
|
@ -1,21 +0,0 @@
|
||||
# ChallangeAccepted
|
||||
|
||||
**TODO: Add description**
|
||||
|
||||
## Installation
|
||||
|
||||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||
by adding `challange_accepted` to your list of dependencies in `mix.exs`:
|
||||
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:challange_accepted, "~> 0.1.0"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
||||
be found at [https://hexdocs.pm/challange_accepted](https://hexdocs.pm/challange_accepted).
|
||||
|
@ -1,18 +0,0 @@
|
||||
defmodule ChallangeAccepted do
|
||||
@moduledoc """
|
||||
Documentation for ChallangeAccepted.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Hello world.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> ChallangeAccepted.hello()
|
||||
:world
|
||||
|
||||
"""
|
||||
def hello do
|
||||
:world
|
||||
end
|
||||
end
|
@ -1,28 +0,0 @@
|
||||
defmodule ChallangeAccepted.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :challange_accepted,
|
||||
version: "0.1.0",
|
||||
elixir: "~> 1.9",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
@ -1,8 +0,0 @@
|
||||
defmodule ChallangeAcceptedTest do
|
||||
use ExUnit.Case
|
||||
doctest ChallangeAccepted
|
||||
|
||||
test "greets the world" do
|
||||
assert ChallangeAccepted.hello() == :world
|
||||
end
|
||||
end
|
@ -1 +0,0 @@
|
||||
ExUnit.start()
|
@ -1,13 +0,0 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
46
front/.gitignore
vendored
46
front/.gitignore
vendored
@ -1,46 +0,0 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
/bazel-out
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# profiling files
|
||||
chrome-profiler-events*.json
|
||||
speed-measure-plugin*.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
7934
front/package-lock.json
generated
7934
front/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,40 +0,0 @@
|
||||
{
|
||||
"name": "angular-8-registration-login-example",
|
||||
"version": "1.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cornflourblue/angular-8-registration-login-example.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"start": "webpack-dev-server --mode development --open"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular/common": "^8.0.0",
|
||||
"@angular/compiler": "^8.0.0",
|
||||
"@angular/core": "^8.0.0",
|
||||
"@angular/forms": "^8.0.0",
|
||||
"@angular/platform-browser": "^8.0.0",
|
||||
"@angular/platform-browser-dynamic": "^8.0.0",
|
||||
"@angular/router": "^8.0.0",
|
||||
"core-js": "^3.1.3",
|
||||
"rxjs": "^6.3.3",
|
||||
"zone.js": "^0.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.0.7",
|
||||
"angular2-template-loader": "^0.6.2",
|
||||
"css-loader": "^2.1.1",
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"less": "^3.0.4",
|
||||
"less-loader": "^5.0.0",
|
||||
"style-loader": "^0.23.1",
|
||||
"ts-loader": "^6.0.1",
|
||||
"typescript": "^3.1.3",
|
||||
"webpack": "^4.32.2",
|
||||
"webpack-cli": "^3.1.2",
|
||||
"webpack-dev-server": "^3.7.0"
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
<div *ngIf="message" [ngClass]="message.cssClass">{{message.text}}</div>
|
@ -1,32 +0,0 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { AlertService } from '@/_services';
|
||||
|
||||
@Component({ selector: 'alert', templateUrl: 'alert.component.html' })
|
||||
export class AlertComponent implements OnInit, OnDestroy {
|
||||
private subscription: Subscription;
|
||||
message: any;
|
||||
|
||||
constructor(private alertService: AlertService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.subscription = this.alertService.getAlert()
|
||||
.subscribe(message => {
|
||||
switch (message && message.type) {
|
||||
case 'success':
|
||||
message.cssClass = 'alert alert-success';
|
||||
break;
|
||||
case 'error':
|
||||
message.cssClass = 'alert alert-danger';
|
||||
break;
|
||||
}
|
||||
|
||||
this.message = message;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './alert.component';
|
@ -1,4 +0,0 @@
|
||||
// global application styles
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
|
||||
import { AuthenticationService } from '@/_services';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AuthGuard implements CanActivate {
|
||||
constructor(
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService
|
||||
) {}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const currentUser = this.authenticationService.currentUserValue;
|
||||
if (currentUser) {
|
||||
// authorised so return true
|
||||
return true;
|
||||
}
|
||||
|
||||
// not logged in so redirect to login page with the return url
|
||||
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
|
||||
import { AuthenticationService } from '@/_services';
|
||||
|
||||
@Injectable()
|
||||
export class ErrorInterceptor implements HttpInterceptor {
|
||||
constructor(private authenticationService: AuthenticationService) {}
|
||||
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(request).pipe(catchError(err => {
|
||||
if (err.status === 401) {
|
||||
// auto logout if 401 response returned from api
|
||||
this.authenticationService.logout();
|
||||
location.reload(true);
|
||||
}
|
||||
|
||||
const error = err.error.message || err.statusText;
|
||||
return throwError(error);
|
||||
}))
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpRequest, HttpResponse, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { delay, mergeMap, materialize, dematerialize } from 'rxjs/operators';
|
||||
|
||||
// array in local storage for registered users
|
||||
let users = JSON.parse(localStorage.getItem('users')) || [];
|
||||
|
||||
@Injectable()
|
||||
export class FakeBackendInterceptor implements HttpInterceptor {
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
const { url, method, headers, body } = request;
|
||||
|
||||
// wrap in delayed observable to simulate server api call
|
||||
return of(null)
|
||||
.pipe(mergeMap(handleRoute))
|
||||
.pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
|
||||
.pipe(delay(500))
|
||||
.pipe(dematerialize());
|
||||
|
||||
function handleRoute() {
|
||||
switch (true) {
|
||||
case url.endsWith('/users/authenticate') && method === 'POST':
|
||||
return authenticate();
|
||||
case url.endsWith('/users/register') && method === 'POST':
|
||||
return register();
|
||||
case url.endsWith('/users') && method === 'GET':
|
||||
return getUsers();
|
||||
case url.match(/\/users\/\d+$/) && method === 'DELETE':
|
||||
return deleteUser();
|
||||
default:
|
||||
// pass through any requests not handled above
|
||||
return next.handle(request);
|
||||
}
|
||||
}
|
||||
|
||||
// route functions
|
||||
|
||||
function authenticate() {
|
||||
const { username, password } = body;
|
||||
const user = users.find(x => x.username === username && x.password === password);
|
||||
if (!user) return error('Username or password is incorrect');
|
||||
return ok({
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
token: 'fake-jwt-token'
|
||||
})
|
||||
}
|
||||
|
||||
function register() {
|
||||
const user = body
|
||||
|
||||
if (users.find(x => x.username === user.username)) {
|
||||
return error('Username "' + user.username + '" is already taken')
|
||||
}
|
||||
|
||||
user.id = users.length ? Math.max(...users.map(x => x.id)) + 1 : 1;
|
||||
users.push(user);
|
||||
localStorage.setItem('users', JSON.stringify(users));
|
||||
|
||||
return ok();
|
||||
}
|
||||
|
||||
function getUsers() {
|
||||
if (!isLoggedIn()) return unauthorized();
|
||||
return ok(users);
|
||||
}
|
||||
|
||||
function deleteUser() {
|
||||
if (!isLoggedIn()) return unauthorized();
|
||||
|
||||
users = users.filter(x => x.id !== idFromUrl());
|
||||
localStorage.setItem('users', JSON.stringify(users));
|
||||
return ok();
|
||||
}
|
||||
|
||||
// helper functions
|
||||
|
||||
function ok(body?) {
|
||||
return of(new HttpResponse({ status: 200, body }))
|
||||
}
|
||||
|
||||
function error(message) {
|
||||
return throwError({ error: { message } });
|
||||
}
|
||||
|
||||
function unauthorized() {
|
||||
return throwError({ status: 401, error: { message: 'Unauthorised' } });
|
||||
}
|
||||
|
||||
function isLoggedIn() {
|
||||
return headers.get('Authorization') === 'Bearer fake-jwt-token';
|
||||
}
|
||||
|
||||
function idFromUrl() {
|
||||
const urlParts = url.split('/');
|
||||
return parseInt(urlParts[urlParts.length - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const fakeBackendProvider = {
|
||||
// use fake backend in place of Http service for backend-less development
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: FakeBackendInterceptor,
|
||||
multi: true
|
||||
};
|
@ -1,4 +0,0 @@
|
||||
export * from './auth.guard';
|
||||
export * from './error.interceptor';
|
||||
export * from './jwt.interceptor';
|
||||
export * from './fake-backend';
|
@ -1,24 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { AuthenticationService } from '@/_services';
|
||||
|
||||
@Injectable()
|
||||
export class JwtInterceptor implements HttpInterceptor {
|
||||
constructor(private authenticationService: AuthenticationService) {}
|
||||
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
// add authorization header with jwt token if available
|
||||
let currentUser = this.authenticationService.currentUserValue;
|
||||
if (currentUser && currentUser.token) {
|
||||
request = request.clone({
|
||||
setHeaders: {
|
||||
Authorization: `Bearer ${currentUser.token}`
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return next.handle(request);
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
export class Challange {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
currentAmount: number
|
||||
numberOfObservators: number
|
||||
sponsoredBy: string
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
export class Group {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export * from './user';
|
||||
export * from './group';
|
||||
export * from './challange';
|
@ -1,8 +0,0 @@
|
||||
export class User {
|
||||
id: number;
|
||||
username: string;
|
||||
password: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
token: string;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router, NavigationStart } from '@angular/router';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AlertService {
|
||||
private subject = new Subject<any>();
|
||||
private keepAfterRouteChange = false;
|
||||
|
||||
constructor(private router: Router) {
|
||||
// clear alert messages on route change unless 'keepAfterRouteChange' flag is true
|
||||
this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationStart) {
|
||||
if (this.keepAfterRouteChange) {
|
||||
// only keep for a single route change
|
||||
this.keepAfterRouteChange = false;
|
||||
} else {
|
||||
// clear alert message
|
||||
this.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getAlert(): Observable<any> {
|
||||
return this.subject.asObservable();
|
||||
}
|
||||
|
||||
success(message: string, keepAfterRouteChange = false) {
|
||||
this.keepAfterRouteChange = keepAfterRouteChange;
|
||||
this.subject.next({ type: 'success', text: message });
|
||||
}
|
||||
|
||||
error(message: string, keepAfterRouteChange = false) {
|
||||
this.keepAfterRouteChange = keepAfterRouteChange;
|
||||
this.subject.next({ type: 'error', text: message });
|
||||
}
|
||||
|
||||
clear() {
|
||||
// clear by calling subject.next() without parameters
|
||||
this.subject.next();
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { User } from '@/_models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AuthenticationService {
|
||||
private currentUserSubject: BehaviorSubject<User>;
|
||||
public currentUser: Observable<User>;
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')));
|
||||
this.currentUser = this.currentUserSubject.asObservable();
|
||||
}
|
||||
|
||||
public get currentUserValue(): User {
|
||||
return this.currentUserSubject.value;
|
||||
}
|
||||
|
||||
login(username, password) {
|
||||
return this.http.post<any>(`${config.apiUrl}/users/authenticate`, { username, password })
|
||||
.pipe(map(user => {
|
||||
// store user details and jwt token in local storage to keep user logged in between page refreshes
|
||||
localStorage.setItem('currentUser', JSON.stringify(user));
|
||||
this.currentUserSubject.next(user);
|
||||
return user;
|
||||
}));
|
||||
}
|
||||
|
||||
logout() {
|
||||
// remove user from local storage and set current user to null
|
||||
localStorage.removeItem('currentUser');
|
||||
this.currentUserSubject.next(null);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
import { Challange } from '@/_models'
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ChallangesService {
|
||||
challanges: Challange[] = [
|
||||
{ id: "1", name: 'Dwa litry Coli w 20 sekund!', description: 'Czy dasz radę wypić całą butelkę coli w 20 sekund? Zmierz się!', currentAmount: 500, numberOfObservators: 30, sponsoredBy: "Coca-Cola" },
|
||||
{ id: "2", name: 'Zdobądź numer swojej nauczycielki!', description: 'Myślisz, ze dobrze radzisz sobie w kontaktach z płcią przeciwną? Skoro tak, to zdobądź numer swojej nauczycielki / nauczyciela!', currentAmount: 300, numberOfObservators: 50, sponsoredBy: null },
|
||||
{ id: "3", name: 'Stanie na rękach na sedesie!', description: 'Myślisz, ze jesteś zwinny? Jesteś dobrym atletą? Przekonaj nas o tym, wykonując stanie na rękach w zupełnie nieoczywistym miejscu!', currentAmount: 50, numberOfObservators: 15, sponsoredBy: null }
|
||||
]
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
getChallange(challangeId) {
|
||||
return this.challanges.filter(
|
||||
challange => challange.id === challangeId
|
||||
)[0]
|
||||
}
|
||||
|
||||
addChallange(challangeInfo) {
|
||||
console.log(challangeInfo)
|
||||
const id = this.getId()
|
||||
let newChallange: Challange = {id: id, name: challangeInfo.firstName, description: challangeInfo.lastName, sponsoredBy: challangeInfo.username, currentAmount: 0, numberOfObservators: 0}
|
||||
this.challanges.push(newChallange)
|
||||
}
|
||||
|
||||
getId() {
|
||||
const newId = this.challanges[this.challanges.length-1].id + 1
|
||||
return newId
|
||||
}
|
||||
|
||||
addMoneyToChallange(challangeId, amount) {
|
||||
let item = this.getChallange(challangeId)
|
||||
|
||||
let index = this.challanges.indexOf(item)
|
||||
|
||||
let newItem = { id: item.id, name: item.name, description: item.description, currentAmount: item.currentAmount + amount, numberOfObservators: item.numberOfObservators, sponsoredBy: item.sponsoredBy }
|
||||
|
||||
this.challanges[index] = newItem
|
||||
}
|
||||
|
||||
observeChallange(challangeId) {
|
||||
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Group } from '@/_models';
|
||||
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class GroupsService {
|
||||
myGroups: Group[] = [
|
||||
{ id: "1", name: "miszczowie" },
|
||||
{ id: "2", name: "najlepsza grupa ever" },
|
||||
{ id: "3", name: "najlepsiejsi" }
|
||||
]
|
||||
|
||||
allGroups: Group[] = [
|
||||
{ id: "1", name: "miszczowie" },
|
||||
{ id: "2", name: "najlepsza grupa ever" },
|
||||
{ id: "3", name: "najlepsiejsi" },
|
||||
{ id: "4", name: "Super grupa" },
|
||||
{ id: "5", name: "Zwycięzcy" },
|
||||
{ id: "6", name: "Niezwycięzeni" },
|
||||
]
|
||||
|
||||
constructor() {
|
||||
// localStorage.setItem("allGroups", JSON.stringify(this.allGroups))
|
||||
let myGroups = localStorage.getItem("myGroups")
|
||||
let g = myGroups == null ? [] : JSON.parse(myGroups)
|
||||
this.myGroups = g
|
||||
}
|
||||
|
||||
getGroup(groupId) {
|
||||
return this.allGroups.filter(
|
||||
group => group.id === groupId
|
||||
)[0]
|
||||
}
|
||||
|
||||
doIBelong(groupId) {
|
||||
if (this.myGroups == null) {
|
||||
return false
|
||||
}
|
||||
if (this.myGroups.filter(
|
||||
group => group.id === groupId
|
||||
)[0] == null) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
joinGroup(groupId) {
|
||||
const group = this.getGroup(groupId)
|
||||
let myGroups = this.myGroups == null ? [] : this.myGroups
|
||||
myGroups.push(group)
|
||||
this.myGroups = myGroups
|
||||
localStorage.setItem("myGroups", JSON.stringify(myGroups))
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
export * from './alert.service';
|
||||
export * from './authentication.service';
|
||||
export * from './user.service';
|
||||
export * from './groups.service';
|
||||
export * from './challanges.service';
|
@ -1,21 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
import { User } from '@/_models';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UserService {
|
||||
constructor(private http: HttpClient) { }
|
||||
|
||||
getAll() {
|
||||
return this.http.get<User[]>(`${config.apiUrl}/users`);
|
||||
}
|
||||
|
||||
register(user: User) {
|
||||
return this.http.post(`${config.apiUrl}/users/register`, user);
|
||||
}
|
||||
|
||||
delete(id: number) {
|
||||
return this.http.delete(`${config.apiUrl}/users/${id}`);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 offset-sm-3">
|
||||
<h2>Dodaj wyzwanie</h2>
|
||||
<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
|
||||
<div class="form-group">
|
||||
<label for="firstName">Nazwa</label>
|
||||
<input type="text" formControlName="firstName" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.firstName.errors }" />
|
||||
<div *ngIf="submitted && f.firstName.errors" class="invalid-feedback">
|
||||
<div *ngIf="f.firstName.errors.required">Nazwa jest wymagana</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastName">Opis</label>
|
||||
<input type="text" formControlName="lastName" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.lastName.errors }" />
|
||||
<div *ngIf="submitted && f.lastName.errors" class="invalid-feedback">
|
||||
<div *ngIf="f.lastName.errors.required">Opis jest wymagany</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="username">Sponsor (opcjonalnie)</label>
|
||||
<input type="text" formControlName="username" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.username.errors }" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button [disabled]="loading" class="btn btn-primary">
|
||||
<span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
|
||||
Dodaj!
|
||||
</button>
|
||||
<a routerLink="/login" class="btn btn-link">Anuluj</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,46 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { ChallangesService } from '@/_services';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Component({ templateUrl: 'addChallange.component.html' })
|
||||
export class AddChallangeComponent implements OnInit {
|
||||
registerForm: FormGroup;
|
||||
loading = false;
|
||||
submitted = false;
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private challangeService: ChallangesService
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.registerForm = this.formBuilder.group({
|
||||
firstName: ['', Validators.required],
|
||||
lastName: ['', Validators.required],
|
||||
username: ['', Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
get f() { return this.registerForm.controls; }
|
||||
|
||||
|
||||
onSubmit() {
|
||||
this.submitted = true;
|
||||
|
||||
// stop here if form is invalid
|
||||
if (this.registerForm.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
this.challangeService.addChallange(this.registerForm.value)
|
||||
|
||||
this.loading = false
|
||||
this.router.navigate(["/"])
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './addChallange.component';
|
@ -1,15 +0,0 @@
|
||||
<!-- nav -->
|
||||
<nav class="navbar navbar-expand navbar-dark bg-dark" *ngIf="currentUser">
|
||||
<div class="navbar-nav">
|
||||
|
||||
<img style="height: 50px; width: 200px;"
|
||||
src="https://m.media-amazon.com/images/M/MV5BYTY3NDVmZDYtNDg5OS00NTVjLTk0NWItZjhlMTkxMWI1OTRhXkEyXkFqcGdeQXVyNTkzOTM0Nzg@._V1_SX1777_CR0,0,1777,539_AL_.jpg">
|
||||
<a class="nav-item nav-link" routerLink="/">Challenge accepted</a>
|
||||
<a class="nav-item nav-link" routerLink="/groups">Grupy</a>
|
||||
<a class="nav-item nav-link" routerLink="/rank_challanges">Oceniaj wyzwania</a>
|
||||
<a class="nav-item nav-link" (click)="logout()">Logout</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<alert></alert>
|
||||
<router-outlet></router-outlet>
|
@ -1,24 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { AuthenticationService } from './_services';
|
||||
import { User } from './_models';
|
||||
|
||||
import './_content/app.less';
|
||||
|
||||
@Component({ selector: 'app', templateUrl: 'app.component.html' })
|
||||
export class AppComponent {
|
||||
currentUser: User;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService
|
||||
) {
|
||||
this.authenticationService.currentUser.subscribe(x => this.currentUser = x);
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.authenticationService.logout();
|
||||
this.router.navigate(['/login']);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
// used to create fake backend
|
||||
import { fakeBackendProvider } from './_helpers';
|
||||
|
||||
import { appRoutingModule } from './app.routing';
|
||||
import { JwtInterceptor, ErrorInterceptor } from './_helpers';
|
||||
import { AppComponent } from './app.component';
|
||||
import { HomeComponent } from './home';
|
||||
import { LoginComponent } from './login';
|
||||
import { GroupComponent } from './group';
|
||||
import { GroupsComponent } from './groups';
|
||||
import { RegisterComponent } from './register';
|
||||
import { AlertComponent } from './_components';
|
||||
import { ChallangeComponent } from './challange/challange.component';
|
||||
import { AddChallangeComponent } from './addChallange';
|
||||
import { FinishChallangeComponent } from './finishChallange';
|
||||
import { RankChallangesComponent } from './rank_challanges';
|
||||
import { RankChallangeComponent } from './rank_challange';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
ReactiveFormsModule,
|
||||
HttpClientModule,
|
||||
appRoutingModule,
|
||||
FormsModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HomeComponent,
|
||||
LoginComponent,
|
||||
RegisterComponent,
|
||||
GroupComponent,
|
||||
GroupsComponent,
|
||||
AlertComponent,
|
||||
ChallangeComponent,
|
||||
AddChallangeComponent,
|
||||
FinishChallangeComponent,
|
||||
RankChallangesComponent,
|
||||
RankChallangeComponent
|
||||
],
|
||||
providers: [
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
|
||||
|
||||
// provider used to create fake backend
|
||||
fakeBackendProvider
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { };
|
@ -1,31 +0,0 @@
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { HomeComponent } from './home';
|
||||
import { LoginComponent } from './login';
|
||||
import { RegisterComponent } from './register';
|
||||
import { GroupsComponent } from './groups';
|
||||
import { GroupComponent } from './group';
|
||||
import { AuthGuard } from './_helpers';
|
||||
import { ChallangeComponent } from './challange';
|
||||
import { AddChallangeComponent } from './addChallange';
|
||||
import { FinishChallangeComponent } from './finishChallange';
|
||||
import { RankChallangesComponent } from './rank_challanges';
|
||||
import { RankChallangeComponent } from './rank_challange';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: HomeComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: 'register', component: RegisterComponent },
|
||||
{ path: 'groups', component: GroupsComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'group/:id', component: GroupComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'challange/:id', component: ChallangeComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'add_challange', component: AddChallangeComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'finish_challange/:id', component: FinishChallangeComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'rank_challanges', component: RankChallangesComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'rank_challange/:id', component: RankChallangeComponent, canActivate: [AuthGuard]},
|
||||
|
||||
// otherwise redirect to home
|
||||
{ path: '**', redirectTo: '' }
|
||||
];
|
||||
|
||||
export const appRoutingModule = RouterModule.forRoot(routes);
|
@ -1,54 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="jumbotron">
|
||||
<div class="row justify-content-md-center">
|
||||
<h2>{{challange.name}}</h2>
|
||||
</div>
|
||||
<div class="row" style="padding-top: 50px;">
|
||||
<div class="col-md-8">
|
||||
<h4>Opis</h4>
|
||||
{{challange.description}}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h4>Dodatkowe informacje:</h4>
|
||||
<p>Obecna kwota: <b>{{challange.currentAmount}}zł</b></p>
|
||||
<p>Liczba obserwujących: <b>{{challange.numberOfObservators}}</b></p>
|
||||
<p *ngIf="challange.sponsoredBy">Oficjalny sponsor: <b>{{challange.sponsoredBy}}</b></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="padding-top: 50px;">
|
||||
<div class="col-md-4">
|
||||
<h6>Dodaj pieniądze</h6>
|
||||
<button type="button" class="btn btn-primary" (click)="addMoney(5)">5zł</button>
|
||||
<button type="button" class="btn btn-primary" (click)="addMoney(10)">10zł</button>
|
||||
<button type="button" class="btn btn-primary" (click)="addMoney(20)">20zł</button>
|
||||
</div>
|
||||
<div class="col-md-4"><button type="button" class="btn btn-info" (click)="observe()">Obserwuj</button></div>
|
||||
<div class="col-md-4" *ngIf="!taken"><button type="button" class="btn btn-success" (click)="take()">Podejmij się!</button></div>
|
||||
<div class="col-md-4" *ngIf="taken"><button type="button" class="btn btn-success" (click)="finish()">Zakończ wyzwanie!</button></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h2>Komentarze</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
Autor
|
||||
<input type="text" [(ngModel)]="author">
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<textarea type="text" [(ngModel)]="body" style="width: 100%;"></textarea>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button (click)="addComment()">Dodaj komentarz</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-2"><b>Autor</b></div>
|
||||
<div class="col-md-10"><b>Komentarz</b></div>
|
||||
</div>
|
||||
<div *ngFor="let comment of comments" class="row" style="padding-top: 20px;">
|
||||
<div class="col-md-2">{{comment.author}}</div>
|
||||
<div class="col-md-10">{{comment.body}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,54 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Challange } from '@/_models';
|
||||
import { ChallangesService } from '@/_services';
|
||||
|
||||
@Component({ templateUrl: 'challange.component.html' })
|
||||
export class ChallangeComponent implements OnInit {
|
||||
comments = [
|
||||
{author: "szalony", body: "Wow, ale opcja!!!!!"},
|
||||
{author: "krejzol", body: "Nie wierzę!!!!!"},
|
||||
]
|
||||
challange: Challange = null
|
||||
observing = false
|
||||
taken = false
|
||||
|
||||
author: string = '';
|
||||
body: string = '';
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private service: ChallangesService
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const challangeId = this.route.snapshot.paramMap.get('id')
|
||||
this.challange = this.service.getChallange(challangeId)
|
||||
}
|
||||
|
||||
addMoney(amount) {
|
||||
this.service.addMoneyToChallange(this.challange.id, amount)
|
||||
this.challange.currentAmount += amount
|
||||
}
|
||||
|
||||
observe() {
|
||||
if (this.observing) return
|
||||
this.observing = true
|
||||
this.challange.numberOfObservators += 1
|
||||
}
|
||||
|
||||
addComment() {
|
||||
this.comments.push({author: this.author, body: this.body})
|
||||
}
|
||||
|
||||
take() {
|
||||
this.taken = true
|
||||
}
|
||||
|
||||
finish() {
|
||||
this.router.navigate(['/finish_challange/' + this.challange.id])
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './challange.component';
|
@ -1,20 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="jumbotron" *ngIf="!finished">
|
||||
<h1>Konczenie wyzwania</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<input #fileInput type='file'/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<button class="btn btn-success" (click)="finish()">Wyślij</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jumbotron" *ngIf="finished">
|
||||
<h2>Super!</h2>
|
||||
<div class="row">
|
||||
|
||||
<p>Wysłaliśmy plik do wyzywającego! Zawiadomimy Cię o akceptacji!</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,24 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Challange } from '@/_models';
|
||||
import { ChallangesService } from '@/_services';
|
||||
|
||||
@Component({ templateUrl: 'finishChallange.component.html' })
|
||||
export class FinishChallangeComponent implements OnInit {
|
||||
finished = false
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private service: ChallangesService
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
finish() {
|
||||
this.finished = true
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './finishChallange.component';
|
@ -1,30 +0,0 @@
|
||||
<div class='jumbotron'>
|
||||
<div class="container">
|
||||
<div class="row justify-content-md-center">
|
||||
<h1>Grupa <b>{{group.name}}</b></h1>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-8 offset-sm-2">
|
||||
<h2>Lista członków</h2>
|
||||
<div class="list-group">
|
||||
<a class="list-group-item list-group-item-action">Janek</a>
|
||||
<a class="list-group-item list-group-item-action">Krzychu</a>
|
||||
<a class="list-group-item list-group-item-action">Kuba</a>
|
||||
<a class="list-group-item list-group-item-action">Adam</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row justify-content-md-center" style="padding: 40px;">
|
||||
<div class="col-sm-6 offset-sm-3" *ngIf="doIBelong()">
|
||||
<button type="button" class="btn btn-danger" (click)="leaveGroup()">Opuść grupę</button>
|
||||
<button type="button" class="btn btn-success">Nalezysz do grupy</button>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 offset-sm-3" *ngIf="!doIBelong()">
|
||||
<button type="button" class="btn btn-primary" (click)="joinGroup()">Dołącz do grupy</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,30 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { GroupsService } from '@/_services';
|
||||
import { Group } from '@/_models';
|
||||
|
||||
@Component({ templateUrl: 'group.component.html' })
|
||||
export class GroupComponent implements OnInit {
|
||||
group: Group = null
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private service: GroupsService
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const groupId = this.route.snapshot.paramMap.get('id')
|
||||
this.group = this.service.getGroup(groupId)
|
||||
}
|
||||
|
||||
doIBelong() {
|
||||
return this.service.doIBelong(this.group.id)
|
||||
}
|
||||
|
||||
joinGroup() {
|
||||
this.service.joinGroup(this.group.id)
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './group.component';
|
@ -1,28 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<h1 class="display-4">Twoje Grupy</h1>
|
||||
<div class="list-group">
|
||||
<a class="list-group-item list-group-item-action" *ngFor="let group of myGroups" (click)="goToGroup(group.id)">
|
||||
{{group.name}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
|
||||
<h1 class="display-4">Wszystkie Grupy</h1>
|
||||
<div class="list-group">
|
||||
<a class="list-group-item list-group-item-action" *ngFor="let group of allGroups" (click)="goToGroup(group.id)">
|
||||
{{group.name}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row justify-content-md-center" style="padding: 40px;">
|
||||
<div class="col-sm-6 offset-sm-3">
|
||||
<button type="button" class="btn btn-primary" (click)="addGroup()">Stwórz nową grupę</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,29 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { GroupsService } from '@/_services';
|
||||
|
||||
@Component({ templateUrl: 'groups.component.html' })
|
||||
export class GroupsComponent implements OnInit {
|
||||
myGroups = []
|
||||
allGroups = []
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private groupsService: GroupsService
|
||||
) {
|
||||
this.myGroups = groupsService.myGroups
|
||||
this.allGroups = groupsService.allGroups
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
}
|
||||
|
||||
goToGroup(groupId) {
|
||||
this.router.navigate(['/group/' + groupId])
|
||||
}
|
||||
|
||||
addGroup() {
|
||||
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './groups.component';
|
@ -1,24 +0,0 @@
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 offset-sm-2">
|
||||
<h2>Hi {{currentUser.firstName}}, Challenge Accepted!</h2>
|
||||
<h3>Obecne wyzwania:</h3>
|
||||
<div class="list-group">
|
||||
<a class="list-group-item list-group-item-action" *ngFor="let challange of challanges"
|
||||
(click)="goToChallange(challange.id)">
|
||||
{{challange.name}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="padding-top: 50px;">
|
||||
<div class="col-md-4 offset-md-8">
|
||||
<button type="button" class="btn btn-primary" (click)="addChallange()">Dodaj nowe wyzwanie!</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
@ -1,32 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { User, Challange } from '@/_models';
|
||||
import { AuthenticationService, ChallangesService } from '@/_services';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({ templateUrl: 'home.component.html' })
|
||||
export class HomeComponent implements OnInit {
|
||||
currentUser: User;
|
||||
users = [];
|
||||
challanges: Challange[] = []
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService,
|
||||
private challangeService: ChallangesService
|
||||
) {
|
||||
this.currentUser = this.authenticationService.currentUserValue;
|
||||
}
|
||||
|
||||
goToChallange(challangeId) {
|
||||
this.router.navigate(['/challange/' + challangeId])
|
||||
}
|
||||
|
||||
addChallange() {
|
||||
this.router.navigate(['/add_challange'])
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.challanges = this.challangeService.challanges
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './home.component';
|
@ -1 +0,0 @@
|
||||
export * from './login.component';
|
@ -1,36 +0,0 @@
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 offset-sm-3">
|
||||
<h1 style="padding: 70px;">Challenge Accepted</h1>
|
||||
<h2>Login</h2>
|
||||
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" formControlName="username" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.username.errors }" />
|
||||
<div *ngIf="submitted && f.username.errors" class="invalid-feedback">
|
||||
<div *ngIf="f.username.errors.required">Username is required</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" formControlName="password" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
|
||||
<div *ngIf="submitted && f.password.errors" class="invalid-feedback">
|
||||
<div *ngIf="f.password.errors.required">Password is required</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button [disabled]="loading" class="btn btn-primary">
|
||||
<span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
|
||||
Login
|
||||
</button>
|
||||
<a routerLink="/register" class="btn btn-link">Register</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,64 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
import { AlertService, AuthenticationService } from '@/_services';
|
||||
|
||||
@Component({ templateUrl: 'login.component.html' })
|
||||
export class LoginComponent implements OnInit {
|
||||
loginForm: FormGroup;
|
||||
loading = false;
|
||||
submitted = false;
|
||||
returnUrl: string;
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService,
|
||||
private alertService: AlertService
|
||||
) {
|
||||
// redirect to home if already logged in
|
||||
if (this.authenticationService.currentUserValue) {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.loginForm = this.formBuilder.group({
|
||||
username: ['', Validators.required],
|
||||
password: ['', Validators.required]
|
||||
});
|
||||
|
||||
// get return url from route parameters or default to '/'
|
||||
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
|
||||
}
|
||||
|
||||
// convenience getter for easy access to form fields
|
||||
get f() { return this.loginForm.controls; }
|
||||
|
||||
onSubmit() {
|
||||
this.submitted = true;
|
||||
|
||||
// reset alerts on submit
|
||||
this.alertService.clear();
|
||||
|
||||
// stop here if form is invalid
|
||||
if (this.loginForm.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
this.authenticationService.login(this.f.username.value, this.f.password.value)
|
||||
.pipe(first())
|
||||
.subscribe(
|
||||
data => {
|
||||
this.router.navigate([this.returnUrl]);
|
||||
},
|
||||
error => {
|
||||
this.alertService.error(error);
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './rank_challange.component';
|
@ -1,35 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="jumbotron">
|
||||
<div class="row" style="text-align: center;">
|
||||
<h1 style="margin-left: 20%; padding: 50px;">{{challange.name}}</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<p> Nadesłane przez: <b>Świr1.9TDI</b></p>
|
||||
<p>Data nadesłania: <b>20.01.2020</b></p>
|
||||
<button *ngIf="!voted" (click)="vote()" class="btn btn-success">Zagłosuj!</button>
|
||||
<button *ngIf="voted" disabled class="btn btn-success">Zagłosowane!!</button>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<!-- <iframe width="420" height="315" -->
|
||||
<iframe width="640" height="480"
|
||||
src="https://www.youtube.com/embed/tgbNymZ7vqY">
|
||||
</iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="padding-top: 50px;">
|
||||
<div class="col-sm-4">
|
||||
<p> Nadesłane przez: <b>JestemSuper</b></p>
|
||||
<p>Data nadesłania: <b>19.01.2020</b></p>
|
||||
<button *ngIf="!voted" (click)="vote()" class="btn btn-success">Zagłosuj!</button>
|
||||
<button *ngIf="voted" disabled class="btn btn-success">Zagłosowane!!</button>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<iframe width="640" height="480"
|
||||
src="https://www.youtube.com/embed/17vTLSkXTOo">
|
||||
</iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,28 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { User, Challange } from '@/_models';
|
||||
import { AuthenticationService, ChallangesService } from '@/_services';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Component({ templateUrl: 'rank_challange.component.html' })
|
||||
export class RankChallangeComponent implements OnInit {
|
||||
challange = {}
|
||||
voted = false
|
||||
|
||||
constructor(
|
||||
private service: ChallangesService,
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const challangeId = this.route.snapshot.paramMap.get('id')
|
||||
this.challange = this.service.getChallange(challangeId)
|
||||
}
|
||||
|
||||
vote() {
|
||||
this.voted = true
|
||||
}
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './rank_challanges.component';
|
@ -1,15 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="jumbotron">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 offset-sm-2">
|
||||
<h2>Wyzwania, które sponsorujesz</h2>
|
||||
<div class="list-group">
|
||||
<a class="list-group-item list-group-item-action" *ngFor="let challange of challanges"
|
||||
(click)="goToChallange(challange.id)">
|
||||
{{challange.name}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,23 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ChallangesService } from '@/_services';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({ templateUrl: 'rank_challanges.component.html'})
|
||||
export class RankChallangesComponent implements OnInit {
|
||||
challanges = []
|
||||
|
||||
constructor(
|
||||
private challangeService: ChallangesService,
|
||||
private router: Router
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.challanges = this.challangeService.challanges
|
||||
}
|
||||
|
||||
goToChallange(challangeId) {
|
||||
this.router.navigate(['/rank_challange/' + challangeId])
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './register.component';
|
@ -1,51 +0,0 @@
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 offset-sm-3">
|
||||
<h2>Register</h2>
|
||||
<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
|
||||
<div class="form-group">
|
||||
<label for="firstName">First Name</label>
|
||||
<input type="text" formControlName="firstName" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.firstName.errors }" />
|
||||
<div *ngIf="submitted && f.firstName.errors" class="invalid-feedback">
|
||||
<div *ngIf="f.firstName.errors.required">First Name is required</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastName">Last Name</label>
|
||||
<input type="text" formControlName="lastName" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.lastName.errors }" />
|
||||
<div *ngIf="submitted && f.lastName.errors" class="invalid-feedback">
|
||||
<div *ngIf="f.lastName.errors.required">Last Name is required</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" formControlName="username" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.username.errors }" />
|
||||
<div *ngIf="submitted && f.username.errors" class="invalid-feedback">
|
||||
<div *ngIf="f.username.errors.required">Username is required</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" formControlName="password" class="form-control"
|
||||
[ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
|
||||
<div *ngIf="submitted && f.password.errors" class="invalid-feedback">
|
||||
<div *ngIf="f.password.errors.required">Password is required</div>
|
||||
<div *ngIf="f.password.errors.minlength">Password must be at least 6 characters</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button [disabled]="loading" class="btn btn-primary">
|
||||
<span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
|
||||
Register
|
||||
</button>
|
||||
<a routerLink="/login" class="btn btn-link">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,63 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
import { AlertService, UserService, AuthenticationService } from '@/_services';
|
||||
|
||||
@Component({ templateUrl: 'register.component.html' })
|
||||
export class RegisterComponent implements OnInit {
|
||||
registerForm: FormGroup;
|
||||
loading = false;
|
||||
submitted = false;
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private authenticationService: AuthenticationService,
|
||||
private userService: UserService,
|
||||
private alertService: AlertService
|
||||
) {
|
||||
// redirect to home if already logged in
|
||||
if (this.authenticationService.currentUserValue) {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.registerForm = this.formBuilder.group({
|
||||
firstName: ['', Validators.required],
|
||||
lastName: ['', Validators.required],
|
||||
username: ['', Validators.required],
|
||||
password: ['', [Validators.required, Validators.minLength(6)]]
|
||||
});
|
||||
}
|
||||
|
||||
// convenience getter for easy access to form fields
|
||||
get f() { return this.registerForm.controls; }
|
||||
|
||||
onSubmit() {
|
||||
this.submitted = true;
|
||||
|
||||
// reset alerts on submit
|
||||
this.alertService.clear();
|
||||
|
||||
// stop here if form is invalid
|
||||
if (this.registerForm.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
this.userService.register(this.registerForm.value)
|
||||
.pipe(first())
|
||||
.subscribe(
|
||||
data => {
|
||||
this.alertService.success('Registration successful', true);
|
||||
this.router.navigate(['/login']);
|
||||
},
|
||||
error => {
|
||||
this.alertService.error(error);
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<base href="/" />
|
||||
<title>Challenge Accepted</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- bootstrap css -->
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<app>Loading...</app>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +0,0 @@
|
||||
import './polyfills';
|
||||
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { AppModule } from './app/app.module';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
@ -1,2 +0,0 @@
|
||||
import 'core-js/features/reflect';
|
||||
import 'zone.js/dist/zone';
|
2
front/src/typings.d.ts
vendored
2
front/src/typings.d.ts
vendored
@ -1,2 +0,0 @@
|
||||
// so the typescript compiler doesn't complain about the global config object
|
||||
declare var config: any;
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES5",
|
||||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"app/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/main.ts',
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src/app/'),
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: ['ts-loader', 'angular2-template-loader']
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
use: 'html-loader'
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: ['style-loader', 'css-loader', 'less-loader']
|
||||
},
|
||||
|
||||
// workaround for warning: System.import() is deprecated and will be removed soon. Use import() instead.
|
||||
{
|
||||
test: /[\/\\]@angular[\/\\].+\.js$/,
|
||||
parser: { system: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({ template: './src/index.html' }),
|
||||
new webpack.DefinePlugin({
|
||||
// global app config object
|
||||
config: JSON.stringify({
|
||||
apiUrl: 'http://localhost:4000'
|
||||
})
|
||||
}),
|
||||
|
||||
// workaround for warning: Critical dependency: the request of a dependency is an expression
|
||||
new webpack.ContextReplacementPlugin(
|
||||
/\@angular(\\|\/)core(\\|\/)fesm5/,
|
||||
path.resolve(__dirname, 'src')
|
||||
)
|
||||
],
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
},
|
||||
runtimeChunk: true
|
||||
},
|
||||
devServer: {
|
||||
historyApiFallback: true
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>pl.chal</groupId>
|
||||
<artifactId>chal</artifactId>
|
||||
<version>1.0</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.seleniumhq.selenium</groupId>
|
||||
<artifactId>selenium-java</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.seleniumhq.selenium</groupId>
|
||||
<artifactId>selenium-chrome-driver</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -1,69 +0,0 @@
|
||||
//Aby uruchomić należy pobrać kod z repozytorium, uruchomić mvn clean install, umieścić chromedriver w podanym katalogu i podać dane do logowania do usosa oraz swoje imie i nazwisko ponizej
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.chrome.ChromeDriver;
|
||||
import org.openqa.selenium.support.ui.ExpectedCondition;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class UsosTest {
|
||||
private String testUrl;
|
||||
private WebDriver driver;
|
||||
|
||||
@Test
|
||||
public void testLogin() throws IOException, InterruptedException {
|
||||
System.setProperty("webdriver.chrome.driver", "C:\\projects\\CHAL\\ui-test\\webdriver\\chromedriver.exe");
|
||||
|
||||
testUrl = "https://usosweb.amu.edu.pl";
|
||||
|
||||
driver = new ChromeDriver();
|
||||
|
||||
driver.manage().window().maximize();
|
||||
|
||||
driver.get(testUrl);
|
||||
|
||||
WebDriverWait wait = new WebDriverWait(driver, 5);
|
||||
|
||||
// Find login by attribute lang="READ_MORE_BTN"
|
||||
List<WebElement> login = driver.findElements(By.xpath("//*[@id=\"casmenu\"]/table/tbody/tr/td[2]/a"));
|
||||
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"casmenu\"]/table/tbody/tr/td[2]/a")));
|
||||
//Click the selected button
|
||||
login.get(0).click();
|
||||
|
||||
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"username\"]")));
|
||||
List<WebElement> loginFirst = driver.findElements(By.xpath("//*[@id=\"username\"]"));
|
||||
loginFirst.get(0).click();
|
||||
loginFirst.get(0).sendKeys("96072910592");
|
||||
|
||||
List<WebElement> loginPassword = driver.findElements(By.xpath("//*[@id=\"password\"]"));
|
||||
loginPassword.get(0).click();
|
||||
loginPassword.get(0).sendKeys("haslotu");
|
||||
|
||||
List<WebElement> loginButton = driver.findElements(By.xpath("//*[@id=\"fm1\"]/div[1]/button[1]"));
|
||||
loginButton.get(0).click();
|
||||
|
||||
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"casmenu\"]/table/tbody/tr/td[2]/b")));
|
||||
List<WebElement> loggedUser = driver.findElements(By.xpath("//*[@id=\"casmenu\"]/table/tbody/tr/td[2]/b"));
|
||||
assertEquals("Jakub Kowalczyk", loggedUser.get(0).getText());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() throws IOException {
|
||||
driver.quit();
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user