This commit is contained in:
commit
067996357a
27 changed files with 13845 additions and 0 deletions
47
.drone.yml
Normal file
47
.drone.yml
Normal file
|
@ -0,0 +1,47 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: install
|
||||
image: node:13.13
|
||||
commands:
|
||||
- npm --prefix ./server install ./server
|
||||
|
||||
- name: test
|
||||
image: node:13.13
|
||||
commands:
|
||||
- npm --prefix ./server run test
|
||||
|
||||
- name: lint
|
||||
image: node:13.13
|
||||
commands:
|
||||
- npm --prefix ./server run lint
|
||||
|
||||
- name: build
|
||||
image: node:13.13
|
||||
commands:
|
||||
- npm --prefix ./server run build
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
- deployment
|
||||
|
||||
- name: deploy
|
||||
image: plugins/docker
|
||||
settings:
|
||||
registry: registry.cliffbreak.de
|
||||
repo: registry.cliffbreak.de/landingpage
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
- deployment
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
113
.gitignore
vendored
Normal file
113
.gitignore
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
# ---> Node
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
## Custom direcotries
|
||||
dist/
|
||||
mongo/
|
||||
webapp/assets/
|
9
.vscode/extensions.json
vendored
Normal file
9
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"sibiraj-s.vscode-scss-formatter",
|
||||
"mikestead.dotenv",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"streetsidesoftware.code-spell-checker-german",
|
||||
]
|
||||
}
|
27
.vscode/settings.json
vendored
Normal file
27
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"editor.formatOnSave": true,
|
||||
"eslint.workingDirectories": [
|
||||
"./server",
|
||||
"./webapp"
|
||||
],
|
||||
"eslint.format.enable": true,
|
||||
"cSpell.language": "de,en,de-DE,en-US",
|
||||
"cSpell.words": [
|
||||
"Cliffbreak",
|
||||
"Fastify",
|
||||
"Giesel",
|
||||
"Roboto",
|
||||
"browserconfig",
|
||||
"camelcase",
|
||||
"cliffbreakmeet",
|
||||
"dbpath",
|
||||
"favicon",
|
||||
"ijmap",
|
||||
"mkdir",
|
||||
"mongod",
|
||||
"msapplication",
|
||||
"nestjs",
|
||||
"playsinline",
|
||||
"uglifycss"
|
||||
],
|
||||
}
|
78
COMMIT_CONVENTION.md
Normal file
78
COMMIT_CONVENTION.md
Normal file
|
@ -0,0 +1,78 @@
|
|||
### Commit Message Format
|
||||
|
||||
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
|
||||
format that includes a **type**, a **scope** and a **subject**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier to read on Gitea as well as in various git tools.
|
||||
|
||||
The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-using-keywords/) if any.
|
||||
|
||||
Samples:
|
||||
|
||||
```
|
||||
docs(readme): update change log to beta.5
|
||||
```
|
||||
```
|
||||
style(server): reorder imports
|
||||
```
|
||||
```
|
||||
fix(webapp): ui animations should now play on the right time
|
||||
|
||||
Closes #123
|
||||
```
|
||||
|
||||
### Revert
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
|
||||
### Type
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, npm)
|
||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: drone)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **perf**: A code change that improves performance
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
* **bump**: Bump a version to X
|
||||
|
||||
### Scope
|
||||
The following is the list of supported scopes (more to come):
|
||||
|
||||
* **core**: used for changes made in server and webapp
|
||||
* **server** used for changes made in the server
|
||||
* **webapp** used for changes made in the webapp
|
||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`)
|
||||
|
||||
|
||||
### Subject
|
||||
The subject contains succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
### Body
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
### Footer
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
|
||||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
||||
|
||||
### More Infos
|
||||
To generate a changelog **[conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)** is used.
|
121
README.md
Normal file
121
README.md
Normal file
|
@ -0,0 +1,121 @@
|
|||
# CliffbreakMeet 💬
|
||||
|
||||
This is the main Repository containing all required resources to run the server and a corresponding website.
|
||||
`/server` contains the complete backend. Offering a REST API for all actions.
|
||||
`/webapp` contains the Web App, communicating with the REST API from `/server`.
|
||||
|
||||
## Getting Started
|
||||
|
||||
The following instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
|
||||
|
||||
After setting up you local environment, you can access the following services with your web browser:
|
||||
* Web frontend via [http://localhost:8080/](http://localhost:8080/)
|
||||
* API documentation via [http://localhost:8080/api-docs/](http://localhost:8080/api-docs/)
|
||||
|
||||
### Prerequisites
|
||||
|
||||
`NodeJS (including NPM)` is required to run this project.
|
||||
Also a working instance of MongoDB `mongod` is required to use all features.
|
||||
You'll also need `git` if you want to contribute to the project.
|
||||
|
||||
|
||||
### Installing
|
||||
|
||||
First clone this repository to your local machine by using
|
||||
|
||||
```
|
||||
git clone https://git.cliffbreak.de/Cliffbreak/CliffbreakMeet.git
|
||||
```
|
||||
|
||||
Change to the cloned repository and inside change your active directory to `server`
|
||||
|
||||
```
|
||||
cd CliffbreakMeet && cd server
|
||||
```
|
||||
|
||||
To install all required packages run
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Copy the .env.example and paste it as .env
|
||||
|
||||
```
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
To test the application run
|
||||
```
|
||||
npm test
|
||||
```
|
||||
|
||||
To get the database running create a directory "mongo"
|
||||
|
||||
```
|
||||
mkdir mongo
|
||||
```
|
||||
|
||||
To start the mongo run
|
||||
|
||||
```
|
||||
cd mongo && mongod --dbpath=.
|
||||
```
|
||||
|
||||
To fill the database with dummy data
|
||||
|
||||
```
|
||||
npm run seed
|
||||
```
|
||||
|
||||
To start the server in development mode run the following npm script
|
||||
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Configure Visual Studio Code
|
||||
If you haven't a instance of Visual Studio Code up and running download the latest version [here](https://code.visualstudio.com/download).
|
||||
Install the recommended extensions by opening the Extensions-Tab (Ctrl+Shift+X).
|
||||
Enter `@recommended` and install all extensions.
|
||||
After that restart Visual Studio Code to apply all changes.
|
||||
|
||||
## Contributing
|
||||
First create an issue and assign it to yourself. Or assign an existing issue.
|
||||
Make sure all issue details (description, labels, milestones) are correct.
|
||||
Check out in a new branch. Notice our convention: use either feature or fix followed by a slash (`/`) and then a **short** description using camel case. (`fix/addMissingImports` or `feature/addBasicAuth`).
|
||||
After that you may create a Pull Request to merge your changes into master (If it's work in progress add `WIP:` to the title!).
|
||||
Also refer to our **[COMMIT_CONVENTION](COMMIT_CONVENTION.md)**
|
||||
|
||||
## Deployment
|
||||
In this section you can read details on the deployment cycle.
|
||||
|
||||
### Changelog
|
||||
After bumping the version in the `package.json` please run:
|
||||
```
|
||||
npm install
|
||||
```
|
||||
to update all packages and bump the application version.
|
||||
|
||||
After that generate a changelog via the `changelog` gulp script.
|
||||
```
|
||||
npm run changelog
|
||||
```
|
||||
Then commit and tag your changes using: (use this format for versioning: `v[major][minor][patch]` i.e. v1.2.3)
|
||||
```
|
||||
git commit -m 'bump: to {version}
|
||||
git tag {version}
|
||||
git push origin
|
||||
git push origin --tags
|
||||
```
|
||||
|
||||
## Built With
|
||||
|
||||
* [Node.js](https://nodejs.org/) - The JavaScript runtime used as the project's base
|
||||
* [NestJS](https://docs.nestjs.com/) - The framework used to create the REST API
|
||||
* [MongoDB](https://docs.mongodb.com/) - The database used to store and retrieve data
|
||||
* [HandlebarsJS](https://handlebarsjs.com/) - Dynamic HTML renderer using templates
|
||||
|
||||
## Authors
|
||||
|
||||
* **Simon Giesel** - *Initial work* - [Simon Giesel](https://git.cliffbreak.de/SimGie)
|
6
server/ .eslintignore
Normal file
6
server/ .eslintignore
Normal file
|
@ -0,0 +1,6 @@
|
|||
# don't ever lint node_modules
|
||||
node_modules
|
||||
# don't lint build output (make sure it's set to your correct build folder name)
|
||||
dist
|
||||
# don't lint nyc coverage output
|
||||
coverage
|
3
server/.env.example
Normal file
3
server/.env.example
Normal file
|
@ -0,0 +1,3 @@
|
|||
PRODUCTION=false
|
||||
|
||||
PORT=8080
|
89
server/.eslintrc.js
Normal file
89
server/.eslintrc.js
Normal file
|
@ -0,0 +1,89 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
],
|
||||
parserOptions: {
|
||||
'ecmaVersion': 2017,
|
||||
},
|
||||
env: {
|
||||
'node': true,
|
||||
'es6': true,
|
||||
},
|
||||
rules: {
|
||||
'camelcase': ['error', {
|
||||
'properties': 'always',
|
||||
'ignoreDestructuring': false,
|
||||
'ignoreImports': false,
|
||||
}],
|
||||
// 'capitalized-comments': ['error', 'always'],
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'comma-spacing': ['error', { 'before': false, 'after': true }],
|
||||
'curly': ['error', 'all'],
|
||||
'eol-last': ['error', 'never'],
|
||||
'indent': ['error', 4],
|
||||
'key-spacing': ['error', {
|
||||
'beforeColon': false,
|
||||
'afterColon': true,
|
||||
'mode': 'strict',
|
||||
}],
|
||||
'keyword-spacing': ['error', {
|
||||
'after': true,
|
||||
'overrides': {
|
||||
'if': { 'after': false },
|
||||
'for': { 'after': false },
|
||||
'while': { 'after': false },
|
||||
},
|
||||
}],
|
||||
'max-classes-per-file': ['error', 1],
|
||||
'max-len': ['error', 150],
|
||||
'no-console': ['warn'],
|
||||
'no-empty': ['error', { 'allowEmptyCatch': false }],
|
||||
'no-multi-spaces': ['error', { 'ignoreEOLComments': false }],
|
||||
'no-trailing-spaces': ['error', { 'ignoreComments': false }],
|
||||
'no-warning-comments': ['warn', { 'location': 'start' }],
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'quotes': ['error', 'single'],
|
||||
'semi': ['error', 'always'],
|
||||
'sort-imports': ['error', {
|
||||
'ignoreCase': false,
|
||||
'ignoreDeclarationSort': false,
|
||||
'ignoreMemberSort': false,
|
||||
'memberSyntaxSortOrder': ['none', 'all', 'multiple', 'single']
|
||||
}],
|
||||
'sort-vars': ['error', { 'ignoreCase': true }],
|
||||
'space-before-blocks': ['error', 'always'],
|
||||
'space-before-function-paren': ['error', {
|
||||
'anonymous': 'always',
|
||||
'named': 'never',
|
||||
'asyncArrow': 'always'
|
||||
}],
|
||||
'space-in-parens': ['error', 'never'],
|
||||
'spaced-comment': ['error', 'always'],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/array-type': ['error', {
|
||||
'default': 'array',
|
||||
'readonly': 'array-simple',
|
||||
}],
|
||||
'@typescript-eslint/interface-name-prefix': ['error', 'always'],
|
||||
'@typescript-eslint/no-empty-interface': ['error', { 'allowSingleExtends': false }],
|
||||
'@typescript-eslint/type-annotation-spacing': ['error', { 'before': false, 'after': true }],
|
||||
}
|
||||
}
|
||||
],
|
||||
};
|
144
server/gulpfile.js
Normal file
144
server/gulpfile.js
Normal file
|
@ -0,0 +1,144 @@
|
|||
const { dest, parallel, series, src, watch } = require('gulp'),
|
||||
changed = require('gulp-changed'),
|
||||
conventionalChangelog = require('gulp-conventional-changelog'),
|
||||
dateFormat = require('dateformat'),
|
||||
del = require('del'),
|
||||
path = require('path'),
|
||||
rename = require('gulp-rename'),
|
||||
sass = require('gulp-sass'),
|
||||
ts = require('gulp-typescript'),
|
||||
uglifycss = require('gulp-uglifycss'),
|
||||
webpack = require('webpack-stream');
|
||||
|
||||
|
||||
require('dotenv').config();
|
||||
|
||||
function clean() {
|
||||
return del(
|
||||
[
|
||||
'./dist/',
|
||||
'./../webapp/assets/css/',
|
||||
'./../webapp/assets/fonts/',
|
||||
'./../webapp/assets/js/',
|
||||
], { force: true }); // Force option needed to delete files outside of project dir
|
||||
}
|
||||
|
||||
function compileJavaScript() {
|
||||
return src('./../webapp/src/js/app.js')
|
||||
.pipe(webpack({
|
||||
entry: {
|
||||
app: './../webapp/src/js/app.js',
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
},
|
||||
},
|
||||
mode: process.env.PRODUCTION ? 'production' : 'development',
|
||||
resolve: {
|
||||
modules: [
|
||||
path.resolve('./../server/node_modules'),
|
||||
],
|
||||
extensions: ['.js', '.json'],
|
||||
// alias: {
|
||||
// handlebars: 'handlebars/dist/handlebars.min.js',
|
||||
// },
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
query: {
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {
|
||||
chrome: 78,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}).on('error', function () { this.emit('end'); }))
|
||||
.pipe(dest('./../webapp/assets/js/'));
|
||||
}
|
||||
|
||||
function compileScss() {
|
||||
return src('./../webapp/src/scss/*.scss')
|
||||
.pipe(sass({ outputStyle: 'compressed', includePaths: ['./../server/node_modules/'] })).on('error', sass.logError)
|
||||
.pipe(dest('./../webapp/assets/css/'));
|
||||
}
|
||||
|
||||
function compileTypeScript() {
|
||||
const tsProject = ts.createProject('tsconfig.json');
|
||||
// do not compile tests in production
|
||||
tsProject.config.exclude = !tsProject.config.exclude ? ['test'] : tsProject.config.exclude.push('test');
|
||||
return tsProject.src()
|
||||
.pipe(tsProject())
|
||||
.js.pipe(dest('./dist/'));
|
||||
}
|
||||
|
||||
function installMaterialIcons() {
|
||||
src(
|
||||
'./node_modules/material-design-icons/iconfont/*.css')
|
||||
.pipe(uglifycss())
|
||||
.pipe(changed('./../webapp/assets/fonts/material-icons/'))
|
||||
.pipe(dest('./../webapp/assets/fonts/material-icons/'));
|
||||
return src(
|
||||
'./node_modules/material-design-icons/iconfont/*',
|
||||
{ ignore: ['**/README.md', '**/codepoints', '**/*.ijmap'] })
|
||||
.pipe(changed('./../webapp/assets/fonts/material-icons/'))
|
||||
.pipe(dest('./../webapp/assets/fonts/material-icons/'));
|
||||
}
|
||||
|
||||
function installRoboto() {
|
||||
src('./node_modules/typeface-roboto/files/*')
|
||||
.pipe(changed('./../webapp/assets/fonts/roboto/files/'))
|
||||
.pipe(dest('./../webapp/assets/fonts/roboto/files/'));
|
||||
return src('./node_modules/typeface-roboto/index.css')
|
||||
.pipe(rename('roboto.css'))
|
||||
.pipe(uglifycss())
|
||||
.pipe(changed('./../webapp/assets/fonts/roboto/'))
|
||||
.pipe(dest('./../webapp/assets/fonts/roboto/'));
|
||||
}
|
||||
|
||||
function watchCompile() {
|
||||
watch('./../webapp/src/scss/*.scss', { ignoreInitial: false }, compileScss);
|
||||
watch('./../webapp/src/js/*.js', { ignoreInitial: false }, compileJavaScript);
|
||||
}
|
||||
|
||||
function changelog() {
|
||||
return src('../CHANGELOG.md')
|
||||
.pipe(conventionalChangelog({
|
||||
// conventional-changelog options go here
|
||||
preset: 'angular',
|
||||
// releaseCount: 0, // Uncomment to regenerate whole changelog
|
||||
}, {
|
||||
// context goes here
|
||||
commit: 'commit',
|
||||
date: dateFormat(new Date(), 'dd.mm.yyyy', true),
|
||||
}, {
|
||||
// git-raw-commits options go here
|
||||
}, {
|
||||
// conventional-commits-parser options go here
|
||||
}, {
|
||||
// conventional-changelog-writer options go here
|
||||
}))
|
||||
.pipe(dest('../'));
|
||||
}
|
||||
|
||||
exports.clean = clean;
|
||||
exports.compileFonts = parallel(installMaterialIcons, installRoboto);
|
||||
exports.compile = parallel(compileScss, compileJavaScript, compileTypeScript, exports.compileFonts);
|
||||
exports.watchCompile = series(clean, exports.compileFonts, watchCompile);
|
||||
exports.build = series(clean, exports.compile);
|
||||
exports.changelog = changelog;
|
||||
exports.default = exports.build;
|
12909
server/package-lock.json
generated
Normal file
12909
server/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
62
server/package.json
Normal file
62
server/package.json
Normal file
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"name": "cliffbreakmeet",
|
||||
"version": "0.0.0",
|
||||
"description": "A self-built video-chat application",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"build": "gulp",
|
||||
"clean": "gulp clean",
|
||||
"dev": "concurrently --kill-others \"gulp watchCompile\" \"npm run dev:node\"",
|
||||
"dev:node": "node -r dotenv/config node_modules/nodemon/bin/nodemon --watch . --ext ts server",
|
||||
"lint": "eslint -c .eslintrc.js --ext .ts ./src ",
|
||||
"test": "echo \"Error: no test specified\" && exit 0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.cliffbreak.de/Cliffbreak/CliffbreakMeet.git"
|
||||
},
|
||||
"author": "Simon Giesel",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^6.11.11",
|
||||
"@nestjs/core": "^6.11.11",
|
||||
"@nestjs/platform-fastify": "^6.11.11",
|
||||
"@nestjs/swagger": "^4.5.2",
|
||||
"class-transformer": "^0.2.3",
|
||||
"class-validator": "^0.11.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"fastify": "^2.13.1",
|
||||
"fastify-swagger": "^2.5.1",
|
||||
"handlebars": "^4.7.6",
|
||||
"mongoose": "^5.9.9",
|
||||
"point-of-view": "^3.8.0",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.5",
|
||||
"@types/mongoose": "^5.7.12",
|
||||
"@types/node": "^13.13.0",
|
||||
"@typescript-eslint/eslint-plugin": "^2.28.0",
|
||||
"@typescript-eslint/parser": "^2.28.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"concurrently": "^5.1.0",
|
||||
"dateformat": "^3.0.3",
|
||||
"del": "^5.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-changed": "^4.0.2",
|
||||
"gulp-conventional-changelog": "^2.0.29",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-sass": "^4.0.2",
|
||||
"gulp-typescript": "^6.0.0-alpha.1",
|
||||
"gulp-uglifycss": "^1.1.0",
|
||||
"material-design-icons": "^3.0.1",
|
||||
"nodemon": "^2.0.3",
|
||||
"normalize-scss": "^7.0.1",
|
||||
"ts-node": "^8.8.2",
|
||||
"typeface-roboto": "0.0.75",
|
||||
"typescript": "^3.8.3",
|
||||
"webpack-stream": "^5.2.1"
|
||||
}
|
||||
}
|
2
server/server.js
Normal file
2
server/server.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
require('ts-node/register');
|
||||
require('./src/server');
|
9
server/src/app/app.module.ts
Normal file
9
server/src/app/app.module.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { AppController } from './controllers/app.controller';
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
@Module({
|
||||
providers: [],
|
||||
controllers: [AppController],
|
||||
exports: [],
|
||||
})
|
||||
export class ApplicationModule { }
|
26
server/src/app/controllers/app.controller.ts
Normal file
26
server/src/app/controllers/app.controller.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { Controller, Get, HttpCode, Logger, Param, Render } from '@nestjs/common';
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
// Constructor(){}
|
||||
|
||||
@Get()
|
||||
@Render('index.hbs')
|
||||
getIndex(): object {
|
||||
return { message: 'Hello world!' };
|
||||
}
|
||||
|
||||
@Get(':room')
|
||||
@Render('room.hbs')
|
||||
getRoom(@Param('room') roomId: string): object {
|
||||
Logger.log('Client joined room: ' + roomId, 'AppController');
|
||||
return { roomId };
|
||||
}
|
||||
|
||||
@Get('favicon.ico')
|
||||
@HttpCode(404)
|
||||
getFavicon(): void {
|
||||
// for now do nothing
|
||||
}
|
||||
|
||||
}
|
5
server/src/app/schemas/interfaces/user.interface.ts
Normal file
5
server/src/app/schemas/interfaces/user.interface.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { Document } from 'mongoose';
|
||||
|
||||
export interface IUser extends Document {
|
||||
email: string;
|
||||
}
|
45
server/src/server.ts
Normal file
45
server/src/server.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
|
||||
import { ApplicationModule } from './app/app.module';
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { join } from 'path';
|
||||
|
||||
const env = process.env;
|
||||
const __webapp = join(__dirname, '..', '..', 'webapp');
|
||||
|
||||
|
||||
async function bootstrap(): Promise<void> {
|
||||
const app = await NestFactory.create<NestFastifyApplication>(
|
||||
ApplicationModule,
|
||||
new FastifyAdapter({ logger: false }), // Set to true to activate the built in logger
|
||||
);
|
||||
|
||||
app.useStaticAssets({
|
||||
root: join(__webapp, 'assets'),
|
||||
prefix: '/assets/',
|
||||
});
|
||||
app.setViewEngine({
|
||||
engine: {
|
||||
handlebars: require('handlebars'),
|
||||
},
|
||||
templates: join(__webapp, 'src', 'views'),
|
||||
layout: join('layouts', 'main.hbs'),
|
||||
options: {
|
||||
partials: {
|
||||
'head': join('partials', 'head.hbs'),
|
||||
'footer': join('partials', 'footer.hbs'),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const swaggerOptions = new DocumentBuilder()
|
||||
.setTitle('CliffbreakMeet API')
|
||||
.setDescription('This is the official CliffbreakMeet API!')
|
||||
.addBearerAuth()
|
||||
.setVersion(require('./../package.json').version)
|
||||
.build();
|
||||
const swaggerDocument = SwaggerModule.createDocument(app, swaggerOptions);
|
||||
SwaggerModule.setup('/api-docs', app, swaggerDocument);
|
||||
await app.listen(parseInt(env.PORT));
|
||||
}
|
||||
bootstrap();
|
23
server/tsconfig.json
Normal file
23
server/tsconfig.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"module": "commonjs",
|
||||
"noImplicitAny": false,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": false,
|
||||
"declaration": false,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"noLib": false,
|
||||
"allowJs": false,
|
||||
"sourceMap": false,
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*",
|
||||
// "./scripts/setup/init.ts",
|
||||
"./migrations/*",
|
||||
],
|
||||
"exclude": [
|
||||
"test",
|
||||
]
|
||||
}
|
64
webapp/src/js/app.js
Normal file
64
webapp/src/js/app.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
(async () => {
|
||||
|
||||
// Send permission dialog to client
|
||||
const openMediaDevices = async (constraints) => {
|
||||
return await navigator.mediaDevices.getUserMedia(constraints);
|
||||
}
|
||||
|
||||
try {
|
||||
const stream = await openMediaDevices({ 'video': true, 'audio': true });
|
||||
console.log('Got MediaStream:', stream);
|
||||
|
||||
function updateList(elements, type) {
|
||||
const listElement = document.querySelector(type == 'video' ? 'select#availableCameras' : 'select#availableMicrophones');
|
||||
listElement.innerHTML = '';
|
||||
elements.forEach(camera => {
|
||||
const cameraOption = document.createElement('option');
|
||||
cameraOption.label = camera.label;
|
||||
cameraOption.value = camera.deviceId;
|
||||
listElement.add(cameraOption);
|
||||
});
|
||||
}
|
||||
|
||||
// Fetch an array of devices of a certain type
|
||||
async function getConnectedDevices(type) {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
return devices.filter(device => device.kind === type)
|
||||
}
|
||||
|
||||
// Listen for changes to media devices and update the list accordingly
|
||||
navigator.mediaDevices.addEventListener('devicechange', async _ => {
|
||||
updateList(await getConnectedDevices('videoinput'), 'video');
|
||||
updateList(await getConnectedDevices('audioinput'), 'audio');
|
||||
});
|
||||
|
||||
updateList(await getConnectedDevices('videoinput'), 'video');
|
||||
updateList(await getConnectedDevices('audioinput'), 'audio');
|
||||
|
||||
|
||||
async function playVideoFromCamera() {
|
||||
try {
|
||||
const videoSelect = document.querySelector('select#availableCameras');
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: {
|
||||
deviceId: videoSelect.options[videoSelect.selectedIndex].value,
|
||||
// width: 1920,
|
||||
// height: 1080,
|
||||
frameRate: 30,
|
||||
}
|
||||
});
|
||||
const videoElement = document.querySelector('video#localVideo');
|
||||
videoElement.srcObject = stream;
|
||||
} catch (error) {
|
||||
console.error('Error opening video camera.', error);
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector('button#startVideo').addEventListener('click', _ => {
|
||||
playVideoFromCamera();
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error accessing media devices.', error);
|
||||
}
|
||||
})();
|
1
webapp/src/scss/_animations.scss
Normal file
1
webapp/src/scss/_animations.scss
Normal file
|
@ -0,0 +1 @@
|
|||
// Add animation here
|
14
webapp/src/scss/index.scss
Normal file
14
webapp/src/scss/index.scss
Normal file
|
@ -0,0 +1,14 @@
|
|||
@import "normalize-scss/sass/normalize/import-now";
|
||||
|
||||
// @import "normalize-scss/sass/_normalize";
|
||||
// @include normalize();
|
||||
|
||||
/** COLORS **/
|
||||
$backgroundColor: #fcfcfc;
|
||||
|
||||
body {
|
||||
font-family: "Roboto";
|
||||
background-color: $backgroundColor;
|
||||
}
|
||||
|
||||
@import "animations";
|
1
webapp/src/scss/noscript.scss
Normal file
1
webapp/src/scss/noscript.scss
Normal file
|
@ -0,0 +1 @@
|
|||
// TODO
|
2
webapp/src/views/index.hbs
Normal file
2
webapp/src/views/index.hbs
Normal file
|
@ -0,0 +1,2 @@
|
|||
<h1>This is the Index!</h1>
|
||||
Message: {{message}}
|
13
webapp/src/views/layouts/main.hbs
Normal file
13
webapp/src/views/layouts/main.hbs
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
{{>head}}
|
||||
|
||||
<body>
|
||||
<content>
|
||||
{{{body}}}
|
||||
</content>
|
||||
{{>footer}}
|
||||
<script src="/assets/js/app.js" async></script>
|
||||
</body>
|
||||
|
||||
</html>
|
10
webapp/src/views/partials/footer.hbs
Normal file
10
webapp/src/views/partials/footer.hbs
Normal file
|
@ -0,0 +1,10 @@
|
|||
<footer>
|
||||
<div class="container">
|
||||
<copyright>© 2020 Cliffbreak.de</copyright>
|
||||
{{!-- <div>
|
||||
<a href="/imprint/">Impressum</a>
|
||||
|
|
||||
<a href="/disclaimer/">Haftungsausschluss</a>
|
||||
</div> --}}
|
||||
</div>
|
||||
</footer>
|
15
webapp/src/views/partials/head.hbs
Normal file
15
webapp/src/views/partials/head.hbs
Normal file
|
@ -0,0 +1,15 @@
|
|||
{{!-- NOTE: Don't import page specific scripts here (They will NOT be recalled on page change - see router.js --}}
|
||||
|
||||
<head>
|
||||
<title>{{title}}</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/assets/fonts/roboto/roboto.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/fonts/material-icons/material-icons.css">
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/index.css">
|
||||
<noscript>
|
||||
<link rel="stylesheet" type="text/css" href="/assets/css/noscript.css">
|
||||
</noscript>
|
||||
</head>
|
7
webapp/src/views/room.hbs
Normal file
7
webapp/src/views/room.hbs
Normal file
|
@ -0,0 +1,7 @@
|
|||
This is a room
|
||||
|
||||
<p>RoomId: {{roomId}}</p>
|
||||
<select name="availableCameras" id="availableCameras"></select>
|
||||
<select name="availableMicrophones" id="availableMicrophones"></select>
|
||||
<button name="startVideo" id="startVideo">Start Video</button>
|
||||
<video id="localVideo" autoplay playsinline />
|
Loading…
Reference in a new issue