commit
16af6f5c6c
|
@ -58,4 +58,3 @@ typings/
|
||||||
.env
|
.env
|
||||||
|
|
||||||
#dist
|
#dist
|
||||||
dist
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,60 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="">
|
||||||
|
|
||||||
|
<title>Project manager</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="https://getbootstrap.com/docs/4.1/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="https://getbootstrap.com/docs/4.1/examples/offcanvas/offcanvas.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="bg-light">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
||||||
|
<a class="navbar-brand mr-auto mr-lg-0" href="#/">Project manager</a>
|
||||||
|
<button class="navbar-toggler p-0 border-0" type="button" data-toggle="offcanvas">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="navbar-collapse offcanvas-collapse" id="navbarsExampleDefault">
|
||||||
|
<ul class="navbar-nav mr-auto menu">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#/login">Sign in</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#/register">Register</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!--<div class="nav-scroller bg-white box-shadow">
|
||||||
|
<nav class="nav nav-underline">
|
||||||
|
<a class="nav-link" href="#">Tasks</a>
|
||||||
|
<a class="nav-link" href="#">Users</a>
|
||||||
|
</nav>
|
||||||
|
</div>-->
|
||||||
|
|
||||||
|
<div id="advert"></div>
|
||||||
|
|
||||||
|
<div id="body">
|
||||||
|
<main role="main" class="container">
|
||||||
|
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-info rounded box-shadow">
|
||||||
|
<img class="mr-3" src="https://image.flaticon.com/icons/svg/138/138839.svg" alt="" width="48" height="48">
|
||||||
|
<div class="lh-100">
|
||||||
|
<h6 class="mb-0 text-white lh-100">Task manager</h6>
|
||||||
|
<small>https://github.com/Sundowndev/interview-v1</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -5,23 +5,18 @@
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"build:dev": "webpack --config webpack.config.js",
|
"build:dev": "webpack --config webpack.config.js --mode=development"
|
||||||
"dev": "tsc-watch src/index.ts --outDir ./dist --onSuccess 'node ./dist/index.js' --onFailure 'echo Beep! Compilation Failed'"
|
|
||||||
},
|
},
|
||||||
"author": "Dr. Patrick Bartsch",
|
"author": "Dr. Patrick Bartsch",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tsc-watch": "^1.0.26",
|
|
||||||
"uglifyjs-webpack-plugin": "^1.1.6",
|
"uglifyjs-webpack-plugin": "^1.1.6",
|
||||||
"webpack": "^4.16.4"
|
"webpack": "^4.16.4",
|
||||||
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/express": "^4.11.0",
|
"@sundowndev/router.js": "^1.5.6",
|
||||||
"bootstrap": "^4.0.0-alpha.6",
|
"bootstrap": "^4.0.0-alpha.6",
|
||||||
"express": "^4.16.2",
|
"jquery": "^3.3.1"
|
||||||
"jquery": "^3.3.1",
|
|
||||||
"ts-loader": "^3.2.0",
|
|
||||||
"twig": "^1.12.0",
|
|
||||||
"typescript": "^2.6.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
let $ = require("jquery");
|
||||||
|
let Router = require('@sundowndev/router.js');
|
||||||
|
|
||||||
|
let router = new Router();
|
||||||
|
|
||||||
|
const api_url = 'http://localhost:8000';
|
||||||
|
let connected = false;
|
||||||
|
|
||||||
|
function sendRequest(method, url, data, callback) {
|
||||||
|
let request = new XMLHttpRequest();
|
||||||
|
request.open(method, api_url + url);
|
||||||
|
request.setRequestHeader("Content-Type", "application/json");
|
||||||
|
request.setRequestHeader('Accept', 'application/json');
|
||||||
|
if (localStorage.getItem('sessionToken') !== undefined) {
|
||||||
|
request.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('sessionToken'));
|
||||||
|
}
|
||||||
|
request.responseType = 'json';
|
||||||
|
request.onload = function () {
|
||||||
|
if (callback) callback(request.response);
|
||||||
|
};
|
||||||
|
request.send(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAdvert(message) {
|
||||||
|
$('#advert').html('<div class="alert alert-primary alert-dismissible fade show" role="alert">\n' +
|
||||||
|
' ' + message +
|
||||||
|
' <button type="button" class="close" data-dismiss="alert" aria-label="Close">\n' +
|
||||||
|
' <span aria-hidden="true">×</span>\n' +
|
||||||
|
' </button>\n' +
|
||||||
|
' </div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshTaskList() {
|
||||||
|
sendRequest('GET', '/tasks', null, function (response) {
|
||||||
|
$('.task-list').html('');
|
||||||
|
|
||||||
|
response.data.forEach(function (task) {
|
||||||
|
let status = (task.status === "0") ? 'Closed' : 'Open';
|
||||||
|
|
||||||
|
$('.task-list').append('<div class="media text-muted pt-3">\n' +
|
||||||
|
' <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">\n' +
|
||||||
|
' <div class="d-flex justify-content-between align-items-center w-100">\n' +
|
||||||
|
' <a href="/task/' + task.id + '"><strong class="text-gray-dark">' + task.title + '</strong></a>\n' +
|
||||||
|
' <span class="badge badge-pill badge-primary">' + status + '</span>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' <spadatan class="d-block">' + task.description + '</spadatan>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' </div>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
router.before('*', function () {
|
||||||
|
$(".close").on('click', () => {
|
||||||
|
$(".close").alert('close');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (localStorage.getItem('sessionToken') !== null) {
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
$('.menu').html('<li class="nav-item">\n' +
|
||||||
|
' <a class="nav-link" id="logout-link" href="/logout">Log out</a>\n' +
|
||||||
|
' </li>');
|
||||||
|
|
||||||
|
$('#logout-link').click((e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
sendRequest('POST', '/logout', null, function (res) {
|
||||||
|
localStorage.removeItem('sessionToken');
|
||||||
|
router.fetchRoute('home');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.add('home', '/', function () {
|
||||||
|
$('#body').html('<main role="main" class="container">\n' +
|
||||||
|
' <div class="d-flex align-items-center p-3 my-3 text-white-50 bg-info rounded box-shadow">\n' +
|
||||||
|
' <img class="mr-3" src="https://image.flaticon.com/icons/svg/138/138839.svg" alt="" width="48" height="48">\n' +
|
||||||
|
' <div class="lh-100">\n' +
|
||||||
|
' <h6 class="mb-0 text-white lh-100">Task manager</h6>\n' +
|
||||||
|
' <small>https://github.com/Sundowndev/interview-v1</small>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
'\n' +
|
||||||
|
' <div id="createTaskForm"></div>\n' +
|
||||||
|
'\n' +
|
||||||
|
' <div class="my-3 p-3 bg-white rounded box-shadow">\n' +
|
||||||
|
' <h6 class="border-bottom border-gray pb-2 mb-0">All tasks</h6>\n' +
|
||||||
|
' <div class="task-list"></div>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' </main>');
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
$('#createTaskForm').html('<div class="my-3 p-3 bg-white rounded box-shadow">\n' +
|
||||||
|
' <form>\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="title">Title</label>\n' +
|
||||||
|
' <input type="text" name="title" id="title" class="form-control">\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="description">Description</label>\n' +
|
||||||
|
' <textarea name="description" id="description" class="form-control"></textarea>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
'\n' +
|
||||||
|
' <button type="submit" id="createTask" class="btn btn-success">Create task</button>\n' +
|
||||||
|
' </form>\n' +
|
||||||
|
' </div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#createTask').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
sendRequest('POST', '/tasks', {
|
||||||
|
title: $("#title")[0].value,
|
||||||
|
description: $("#description")[0].value
|
||||||
|
}, function (data) {
|
||||||
|
setAdvert(data.message);
|
||||||
|
refreshTaskList();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshTaskList();
|
||||||
|
});
|
||||||
|
|
||||||
|
router.add('login', '/login', function () {
|
||||||
|
$('#body').html('<main role="main" class="container">\n' +
|
||||||
|
' <div class="my-3 p-3 bg-white rounded box-shadow">\n' +
|
||||||
|
' <form action="#">\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="username">Username</label>\n' +
|
||||||
|
' <input type="text" name="username" id="username" class="form-control">\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="password">Password</label>\n' +
|
||||||
|
' <input type="password" name="password" id="password" class="form-control">\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
'\n' +
|
||||||
|
' <button type="submit" id="signin" class="btn btn-success">Sign in</button>\n' +
|
||||||
|
' </form>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' </main>');
|
||||||
|
|
||||||
|
$('#signin').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
sendRequest('POST', '/auth', {
|
||||||
|
username: $('#username')[0].value,
|
||||||
|
password: $('#password')[0].value
|
||||||
|
}, function (res) {
|
||||||
|
if (res.data.token !== undefined) {
|
||||||
|
localStorage.setItem('sessionToken', res.data.token);
|
||||||
|
router.fetchRoute('home');
|
||||||
|
} else {
|
||||||
|
setAdvert(res.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.add('register', '/register', function () {
|
||||||
|
$('#body').html('<main role="main" class="container">\n' +
|
||||||
|
' <div class="my-3 p-3 bg-white rounded box-shadow">\n' +
|
||||||
|
' <form action="#">\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="username">Username</label>\n' +
|
||||||
|
' <input type="text" name="username" id="username" class="form-control">\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
'\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="email">Email</label>\n' +
|
||||||
|
' <input type="text" name="email" id="email" class="form-control">\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
'\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="password">Password</label>\n' +
|
||||||
|
' <input type="password" name="password" id="password" class="form-control">\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
'\n' +
|
||||||
|
' <button type="submit" id="register" class="btn btn-success">Register</button>\n' +
|
||||||
|
' </form>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
'</main>');
|
||||||
|
|
||||||
|
$('#register').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
sendRequest('POST', '/signup', {
|
||||||
|
username: $('#username')[0].value,
|
||||||
|
password: $('#password')[0].value,
|
||||||
|
email: $('#email')[0].value
|
||||||
|
}, function (res) {
|
||||||
|
setAdvert(res.message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.run();
|
|
@ -1,135 +0,0 @@
|
||||||
let $ = require("jquery");
|
|
||||||
//let bs = require("bootstrap");
|
|
||||||
|
|
||||||
let connected = false;
|
|
||||||
const api_url = 'http://localhost:8000';
|
|
||||||
|
|
||||||
$(".close").on('click', () => {
|
|
||||||
$(".close").alert('close');
|
|
||||||
});
|
|
||||||
|
|
||||||
if (localStorage.getItem('sessionToken') !== null) {
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connected) {
|
|
||||||
$('.menu').html('<li class="nav-item">\n' +
|
|
||||||
' <a class="nav-link" id="logout-link" href="/logout">Log out</a>\n' +
|
|
||||||
' </li>');
|
|
||||||
|
|
||||||
$('#logout-link').click((e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
sendRequest('POST', '/logout', null, function (res) {
|
|
||||||
localStorage.removeItem('sessionToken');
|
|
||||||
window.location.pathname = '/';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendRequest(method, url, data, callback) {
|
|
||||||
let request = new XMLHttpRequest();
|
|
||||||
request.open(method, api_url + url);
|
|
||||||
request.setRequestHeader("Content-Type", "application/json");
|
|
||||||
request.setRequestHeader('Accept', 'application/json');
|
|
||||||
if (localStorage.getItem('sessionToken') !== undefined) {
|
|
||||||
request.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('sessionToken'));
|
|
||||||
}
|
|
||||||
request.responseType = 'json';
|
|
||||||
request.onload = function () {
|
|
||||||
if (callback) callback(request.response);
|
|
||||||
};
|
|
||||||
request.send(JSON.stringify(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAdvert(message) {
|
|
||||||
$('#advert').html('<div class="alert alert-primary alert-dismissible fade show" role="alert">\n' +
|
|
||||||
' ' + message +
|
|
||||||
' <button type="button" class="close" data-dismiss="alert" aria-label="Close">\n' +
|
|
||||||
' <span aria-hidden="true">×</span>\n' +
|
|
||||||
' </button>\n' +
|
|
||||||
' </div>');
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshTaskList() {
|
|
||||||
sendRequest('GET', '/tasks', null, function (response) {
|
|
||||||
$('.task-list').html('');
|
|
||||||
|
|
||||||
response.data.forEach(function (task) {
|
|
||||||
let status = 'Open';
|
|
||||||
|
|
||||||
if (task.status === "0") {
|
|
||||||
status = 'Closed';
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.task-list').append('<div class="media text-muted pt-3">\n' +
|
|
||||||
' <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">\n' +
|
|
||||||
' <div class="d-flex justify-content-between align-items-center w-100">\n' +
|
|
||||||
' <a href="/task/' + task.id + '"><strong class="text-gray-dark">' + task.title + '</strong></a>\n' +
|
|
||||||
' <span class="badge badge-pill badge-primary">' + status + '</span>\n' +
|
|
||||||
' </div>\n' +
|
|
||||||
' <spadatan class="d-block">' + task.description + '</spadatan>\n' +
|
|
||||||
' </div>\n' +
|
|
||||||
' </div>');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connected) {
|
|
||||||
$('#createTaskForm').html('<div class="my-3 p-3 bg-white rounded box-shadow">\n' +
|
|
||||||
' <form>\n' +
|
|
||||||
' <div class="form-group">\n' +
|
|
||||||
' <label for="title">Title</label>\n' +
|
|
||||||
' <input type="text" name="title" id="title" class="form-control">\n' +
|
|
||||||
' </div>\n' +
|
|
||||||
' <div class="form-group">\n' +
|
|
||||||
' <label for="description">Description</label>\n' +
|
|
||||||
' <textarea name="description" id="description" class="form-control"></textarea>\n' +
|
|
||||||
' </div>\n' +
|
|
||||||
'\n' +
|
|
||||||
' <button type="submit" id="createTask" class="btn btn-success">Create task</button>\n' +
|
|
||||||
' </form>\n' +
|
|
||||||
' </div>');
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#createTask').click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
sendRequest('POST', '/tasks', {
|
|
||||||
title: $("#title")[0].value,
|
|
||||||
description: $("#description")[0].value
|
|
||||||
}, function (data) {
|
|
||||||
setAdvert(data.message);
|
|
||||||
refreshTaskList();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
refreshTaskList();
|
|
||||||
|
|
||||||
$('#signin').click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
sendRequest('POST', '/auth', {
|
|
||||||
username: $('#username')[0].value,
|
|
||||||
password: $('#password')[0].value
|
|
||||||
}, function (res) {
|
|
||||||
if (res.data.token !== undefined) {
|
|
||||||
localStorage.setItem('sessionToken', res.data.token);
|
|
||||||
window.location.pathname = '/';
|
|
||||||
} else {
|
|
||||||
setAdvert(res.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#register').click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
sendRequest('POST', '/signup', {
|
|
||||||
username: $('#username')[0].value,
|
|
||||||
password: $('#password')[0].value,
|
|
||||||
email: $('#email')[0].value
|
|
||||||
}, function (res) {
|
|
||||||
setAdvert(res.message);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,32 +0,0 @@
|
||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
//import * as bodyParser from "body-parser";
|
|
||||||
const express = require("express");
|
|
||||||
const http = require("http");
|
|
||||||
let path = require("path");
|
|
||||||
let app = express();
|
|
||||||
app.set('view engine', 'twig');
|
|
||||||
app.set('views', __dirname + '/views');
|
|
||||||
app.use(express.static(path.resolve(__dirname) + '/../dist/public/'));
|
|
||||||
app.get('/', (req, res) => {
|
|
||||||
res.render('index');
|
|
||||||
});
|
|
||||||
app.get('/login', (req, res) => {
|
|
||||||
res.render('login');
|
|
||||||
});
|
|
||||||
app.get('/register', (req, res) => {
|
|
||||||
res.render('register');
|
|
||||||
});
|
|
||||||
app.get('/task/{id}', (req, res) => {
|
|
||||||
//res.render('index', {title: 'Hey', message: 'Hello there!'});
|
|
||||||
});
|
|
||||||
app.get('/task/{id}/edit', (req, res) => {
|
|
||||||
//res.render('index', {title: 'Hey', message: 'Hello there!'});
|
|
||||||
});
|
|
||||||
let httpPort = 3000;
|
|
||||||
app.set("port", httpPort);
|
|
||||||
let httpServer = http.createServer(app);
|
|
||||||
// listen on provided ports
|
|
||||||
httpServer.listen(httpPort, (data) => {
|
|
||||||
console.log(`Listening on port ${httpPort}`);
|
|
||||||
});
|
|
|
@ -1,41 +0,0 @@
|
||||||
//import * as bodyParser from "body-parser";
|
|
||||||
import * as express from "express";
|
|
||||||
import {Request, Response} from "express";
|
|
||||||
import * as http from 'http';
|
|
||||||
|
|
||||||
let path = require("path");
|
|
||||||
|
|
||||||
let app: express.Application = express();
|
|
||||||
|
|
||||||
app.set('view engine', 'twig');
|
|
||||||
app.set('views', __dirname + '/views');
|
|
||||||
app.use(express.static(path.resolve(__dirname)+'/../dist/public/'));
|
|
||||||
|
|
||||||
app.get('/', (req: Request, res: Response) => {
|
|
||||||
res.render('index');
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/login', (req: Request, res: Response) => {
|
|
||||||
res.render('login');
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/register', (req: Request, res: Response) => {
|
|
||||||
res.render('register');
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/task/{id}', (req: Request, res: Response) => {
|
|
||||||
//res.render('index', {title: 'Hey', message: 'Hello there!'});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/task/{id}/edit', (req: Request, res: Response) => {
|
|
||||||
//res.render('index', {title: 'Hey', message: 'Hello there!'});
|
|
||||||
});
|
|
||||||
|
|
||||||
let httpPort = 3000;
|
|
||||||
app.set("port", httpPort);
|
|
||||||
let httpServer = http.createServer(app);
|
|
||||||
|
|
||||||
// listen on provided ports
|
|
||||||
httpServer.listen(httpPort, (data) => {
|
|
||||||
console.log(`Listening on port ${httpPort}`)
|
|
||||||
});
|
|
|
@ -1,20 +0,0 @@
|
||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<main role="main" class="container">
|
|
||||||
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-info rounded box-shadow">
|
|
||||||
<img class="mr-3" src="https://image.flaticon.com/icons/svg/138/138839.svg" alt="" width="48" height="48">
|
|
||||||
<div class="lh-100">
|
|
||||||
<h6 class="mb-0 text-white lh-100">Task manager</h6>
|
|
||||||
<small>https://github.com/Sundowndev/interview-v1</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="createTaskForm"></div>
|
|
||||||
|
|
||||||
<div class="my-3 p-3 bg-white rounded box-shadow">
|
|
||||||
<h6 class="border-bottom border-gray pb-2 mb-0">All tasks</h6>
|
|
||||||
<div class="task-list"></div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
{% endblock %}
|
|
|
@ -1,64 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<link rel="icon" href="/favicon.ico">
|
|
||||||
|
|
||||||
<title>{% block title %}Project manager{% endblock %}</title>
|
|
||||||
|
|
||||||
<!-- Bootstrap core CSS -->
|
|
||||||
<link href="https://getbootstrap.com/docs/4.1/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template -->
|
|
||||||
<link href="https://getbootstrap.com/docs/4.1/examples/offcanvas/offcanvas.css" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body class="bg-light">
|
|
||||||
{% block header %}
|
|
||||||
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
|
||||||
<a class="navbar-brand mr-auto mr-lg-0" href="/">Project manager</a>
|
|
||||||
<button class="navbar-toggler p-0 border-0" type="button" data-toggle="offcanvas">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="navbar-collapse offcanvas-collapse" id="navbarsExampleDefault">
|
|
||||||
<ul class="navbar-nav mr-auto menu">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/login">Sign in</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/register">Register</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!--<div class="nav-scroller bg-white box-shadow">
|
|
||||||
<nav class="nav nav-underline">
|
|
||||||
<a class="nav-link" href="#">Tasks</a>
|
|
||||||
<a class="nav-link" href="#">Users</a>
|
|
||||||
</nav>
|
|
||||||
</div>-->
|
|
||||||
|
|
||||||
<div id="advert"></div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<main role="main" class="container">
|
|
||||||
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-info rounded box-shadow">
|
|
||||||
<img class="mr-3" src="https://image.flaticon.com/icons/svg/138/138839.svg" alt="" width="48" height="48">
|
|
||||||
<div class="lh-100">
|
|
||||||
<h6 class="mb-0 text-white lh-100">Task manager</h6>
|
|
||||||
<small>https://github.com/Sundowndev/interview-v1</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block scripts %}
|
|
||||||
<script src="/app.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,20 +0,0 @@
|
||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<main role="main" class="container">
|
|
||||||
<div class="my-3 p-3 bg-white rounded box-shadow">
|
|
||||||
<form action="#">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<input type="text" name="username" id="username" class="form-control">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password">Password</label>
|
|
||||||
<input type="password" name="password" id="password" class="form-control">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" id="signin" class="btn btn-success">Sign in</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
{% endblock %}
|
|
|
@ -1,26 +0,0 @@
|
||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<main role="main" class="container">
|
|
||||||
<div class="my-3 p-3 bg-white rounded box-shadow">
|
|
||||||
<form action="#">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<input type="text" name="username" id="username" class="form-control">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="email">Email</label>
|
|
||||||
<input type="text" name="email" id="email" class="form-control">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password">Password</label>
|
|
||||||
<input type="password" name="password" id="password" class="form-control">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" id="register" class="btn btn-success">Register</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
{% endblock %}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es6",
|
|
||||||
"module": "commonjs",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"declaration": true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,7 +14,7 @@ fs.readdirSync('node_modules')
|
||||||
const scriptConfig = {
|
const scriptConfig = {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
entry: {
|
entry: {
|
||||||
app: './src/assets/app.js'
|
app: './src/app.js'
|
||||||
},
|
},
|
||||||
target: 'web',
|
target: 'web',
|
||||||
output: {
|
output: {
|
||||||
|
@ -23,32 +23,4 @@ const scriptConfig = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const appConfig = {
|
module.exports = [scriptConfig];
|
||||||
name: 'index',
|
|
||||||
entry: {
|
|
||||||
index: './src/index.ts',
|
|
||||||
},
|
|
||||||
target: 'node',
|
|
||||||
output: {
|
|
||||||
filename: '[name].js',
|
|
||||||
path: path.resolve(__dirname, 'dist')
|
|
||||||
},
|
|
||||||
devtool: 'source-map',
|
|
||||||
resolve: {
|
|
||||||
// Add `.ts` and `.tsx` as a resolvable extension.
|
|
||||||
extensions: ['.ts', '.tsx', '.js']
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
|
|
||||||
{test: /\.tsx?$/, loader: 'ts-loader'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
externals: nodeModules,
|
|
||||||
node: {
|
|
||||||
__filename: true,
|
|
||||||
__dirname: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = [scriptConfig, appConfig];
|
|
|
@ -43,16 +43,6 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- '443:443'
|
- '443:443'
|
||||||
|
|
||||||
client:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: ./Dockerfile.client
|
|
||||||
volumes:
|
|
||||||
# Comment out the next line in production
|
|
||||||
- ./client:/usr/src/app:rw
|
|
||||||
ports:
|
|
||||||
- 3000:3000
|
|
||||||
|
|
||||||
# For development purposes
|
# For development purposes
|
||||||
adminer:
|
adminer:
|
||||||
image: adminer
|
image: adminer
|
||||||
|
|
|
@ -17,7 +17,7 @@ class JsonResponse
|
||||||
];
|
];
|
||||||
|
|
||||||
//header('Access-Control-Allow-Origin: ' . getenv('ALLOW_ORIGIN'));
|
//header('Access-Control-Allow-Origin: ' . getenv('ALLOW_ORIGIN'));
|
||||||
header("Access-Control-Allow-Origin: http://localhost:3000");
|
header("Access-Control-Allow-Origin: *");
|
||||||
header("Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization");
|
header("Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization");
|
||||||
header("Access-Control-Allow-Credentials: true");
|
header("Access-Control-Allow-Credentials: true");
|
||||||
header('Access-Control-Max-Age: 1');
|
header('Access-Control-Max-Age: 1');
|
||||||
|
|
Loading…
Reference in New Issue