@ -1,13 +1,8 @@ | |||||
composer.phar | |||||
/vendor/ | |||||
node_modules | node_modules | ||||
.env | .env | ||||
*.log | |||||
rysnc_exclude | |||||
/storage/database | |||||
/storage/files | |||||
storage/database/* | |||||
!storage/database/.gitkeep | |||||
storage/cache/* | |||||
!storage/cache/.gitkeep | |||||
!/storage/database/.gitkeep | |||||
!/storage/files/.gitkeep |
@ -1,28 +0,0 @@ | |||||
<?php | |||||
namespace App\Flight; | |||||
use Flight; | |||||
/** | |||||
* abstract FlightAbstract get instance of flight engine | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @license http://opensource.org/licenses/MIT The MIT License | |||||
* | |||||
*/ | |||||
abstract class FlightAbstract | |||||
{ | |||||
/** object of flight */ | |||||
protected $app; | |||||
/** | |||||
* getting object of flight | |||||
* | |||||
*/ | |||||
public function __construct() | |||||
{ | |||||
$this->app = Flight::app(); | |||||
} | |||||
} |
@ -1,42 +0,0 @@ | |||||
<?php | |||||
/** | |||||
* fake function for blade @inject | |||||
* | |||||
* @param string $class | |||||
* @return object | |||||
*/ | |||||
function app($class) | |||||
{ | |||||
return new $class(); | |||||
} | |||||
/** | |||||
* function similar to blade asset | |||||
* | |||||
* @param $path | |||||
* @return string | |||||
* | |||||
*/ | |||||
function asset($path, $prefix = '/public') | |||||
{ | |||||
// get flight | |||||
$app = Flight::app(); | |||||
// getting basePath | |||||
$basePath = $app->get('basePath'); | |||||
// path to mix-manifest | |||||
$file = $app->get('basePath').'mix-manifest.json'; | |||||
if (file_exists($file)) { | |||||
$manifest = file_get_contents($file); | |||||
$files = json_decode($manifest, true); | |||||
if (isset($files[$prefix.$path])) { | |||||
$path = str_replace($prefix, '', $files[$prefix.$path]); | |||||
} | |||||
} | |||||
return $path; | |||||
} |
@ -1,39 +0,0 @@ | |||||
<?php | |||||
namespace App\Http; | |||||
use Rakit\Validation\Validator; | |||||
use App\Flight\FlightAbstract; | |||||
use App\Models\Bucket; | |||||
use Carbon\Carbon; | |||||
/** | |||||
* | |||||
* | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @link https://gitea.tentakelfabrik.de/mITSM/feedback GitHub Repository | |||||
* | |||||
* | |||||
*/ | |||||
class Bucket extends FlightAbstract | |||||
{ | |||||
public function viewAction($id) | |||||
{ | |||||
$this->app->render('bucket', [ | |||||
'id' => $id | |||||
]); | |||||
} | |||||
public function indexAction($id, $visibilty, $page) | |||||
{ | |||||
$bucketStore = new Bucket(); | |||||
$publicBuckets = $bucketStore->findBy(); | |||||
$this->app->json([ | |||||
'publicBuckets' => $publicBuckets | |||||
]); | |||||
} | |||||
} |
@ -1,29 +0,0 @@ | |||||
<?php | |||||
namespace App\Http; | |||||
use Rakit\Validation\Validator; | |||||
use App\Flight\FlightAbstract; | |||||
use App\Models\Bucket; | |||||
use Carbon\Carbon; | |||||
/** | |||||
* | |||||
* | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @link https://gitea.tentakelfabrik.de/mITSM/feedback GitHub Repository | |||||
* | |||||
* | |||||
*/ | |||||
class Home extends FlightAbstract | |||||
{ | |||||
public function indexAction() | |||||
{ | |||||
$this->app->render('home', [ | |||||
]); | |||||
} | |||||
} |
@ -1,58 +0,0 @@ | |||||
<?php | |||||
namespace App\Http; | |||||
use Rakit\Validation\Validator; | |||||
use App\Flight\FlightAbstract; | |||||
use App\Models\Bucket; | |||||
use Carbon\Carbon; | |||||
/** | |||||
* | |||||
* | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @link https://gitea.tentakelfabrik.de/mITSM/feedback GitHub Repository | |||||
* | |||||
* | |||||
*/ | |||||
class Note extends FlightAbstract | |||||
{ | |||||
/** | |||||
* | |||||
* @param integer $id | |||||
* | |||||
*/ | |||||
public function viewAction($id) | |||||
{ | |||||
$this->app->render('bucket', [ | |||||
'id' => $id | |||||
]); | |||||
} | |||||
public function indexAction($bucketId) | |||||
{ | |||||
$noteStore = new Note(); | |||||
$notes = $noteStore->findBy(); | |||||
$this->app->json([ | |||||
'data' => $notes, | |||||
'page' => $page | |||||
]); | |||||
} | |||||
public function createAction($bucketId) | |||||
{ | |||||
$result = [ | |||||
'success' => false | |||||
]; | |||||
$noteStore = new Note(); | |||||
$this->app->json([ | |||||
'data' => $notes, | |||||
]); | |||||
} | |||||
} |
@ -1,26 +0,0 @@ | |||||
<?php | |||||
namespace App\Models; | |||||
/** | |||||
* Store for Courses | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @link https://gitea.tentakelfabrik.de/mITSM/feedback GitHub Repository | |||||
* | |||||
*/ | |||||
class Bucket extends ModelAbstract | |||||
{ | |||||
// name of store | |||||
protected $name = 'buckets'; | |||||
public function findByVisiblity($visiblity) | |||||
{ | |||||
return $this->store->findBy( | |||||
[ 'visiblity' => $visiblity ], | |||||
[ 'created_at' => 'ASC' ], | |||||
100 | |||||
); | |||||
} | |||||
} |
@ -1,46 +0,0 @@ | |||||
<?php | |||||
namespace App\Models; | |||||
use SleekDB\Store; | |||||
use SleekDB\Query; | |||||
/** | |||||
* Abstract Class for Stores | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @link https://gitea.tentakelfabrik.de/mITSM/feedback GitHub Repository | |||||
* | |||||
*/ | |||||
class ModelAbstract | |||||
{ | |||||
// store of model | |||||
public $store; | |||||
// name of store | |||||
protected $name; | |||||
// configuration of store | |||||
protected $configuration = [ | |||||
'auto_cache' => true, | |||||
'cache_lifetime' => null, | |||||
'timeout' => 120, | |||||
'primary_key' => '_id', | |||||
'search' => [ | |||||
'min_length' => 2, | |||||
'mode' => 'or', | |||||
'score_key' => 'scoreKey', | |||||
'algorithm' => Query::SEARCH_ALGORITHM['hits'] | |||||
] | |||||
]; | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
public function __construct() | |||||
{ | |||||
$this->store = new Store($this->name, __DIR__.'/../../storage/database', $this->configuration); | |||||
} | |||||
} |
@ -1,17 +0,0 @@ | |||||
<?php | |||||
namespace App\Models; | |||||
/** | |||||
* Store for Tags | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @link https://gitea.tentakelfabrik.de/mITSM/feedback GitHub Repository | |||||
* | |||||
*/ | |||||
class Tag extends ModelAbstract | |||||
{ | |||||
// name of store | |||||
protected $name = 'tags'; | |||||
} |
@ -1,17 +0,0 @@ | |||||
<?php | |||||
namespace App\Models; | |||||
/** | |||||
* Store for Users | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* @link https://gitea.tentakelfabrik.de/mITSM/feedback GitHub Repository | |||||
* | |||||
*/ | |||||
class User extends ModelAbstract | |||||
{ | |||||
// name of store | |||||
protected $name = 'users'; | |||||
} |
@ -1,31 +0,0 @@ | |||||
<?php | |||||
// adding functions | |||||
require_once(__DIR__.'/Flight/Functions.php'); | |||||
// adding env | |||||
$env = Dotenv\Dotenv::createImmutable(__DIR__.'/..'); | |||||
$env->load(); | |||||
// display all errors if debug is true | |||||
if (getenv('DEBUG') === true) { | |||||
error_reporting(E_ALL); | |||||
ini_set('display_errors', 1); | |||||
} | |||||
// create app | |||||
$app = Flight::app(); | |||||
// setting view path | |||||
$app->set('flight.views.path', __DIR__.'/../resources/views'); | |||||
// adding blade for templates | |||||
Flight::register('view', 'Jenssegers\Blade\Blade', [ $app->get('flight.views.path'), __DIR__.'/../storage/cache']); | |||||
Flight::map('render', function($view, $data) { | |||||
echo Flight::view()->make($view, $data); | |||||
}); | |||||
// setting path | |||||
$app->set('basePath', __DIR__.'/../'); | |||||
$app->set('publicPath', __DIR__.'/../public'); | |||||
$app->set('storagePath', __DIR__.'/../storage'); |
@ -1,16 +0,0 @@ | |||||
{ | |||||
"require": { | |||||
"mikecao/flight": "^1.3", | |||||
"rakibtg/sleekdb": "^2.11", | |||||
"vlucas/phpdotenv": "^5.3", | |||||
"jenssegers/blade": "^1.4", | |||||
"rakit/validation": "^1.4", | |||||
"nesbot/carbon": "^2.49", | |||||
"microweber/screen": "^1.0" | |||||
}, | |||||
"autoload": { | |||||
"psr-4": { | |||||
"App\\": "app/" | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,5 @@ | |||||
{ | |||||
"/public/js/index.js": "/public/js/index.js", | |||||
"/public/js/critical.js": "/public/js/critical.js", | |||||
"/public/css/index.css": "/public/css/index.css" | |||||
} |
@ -0,0 +1,19 @@ | |||||
{ | |||||
"private": true, | |||||
"scripts": { | |||||
"test": "echo \"Error: no test specified\" && exit 1" | |||||
}, | |||||
"author": "me@herr-hase.wtf", | |||||
"license": "GPL", | |||||
"dependencies": { | |||||
"turbolinks": "^5.2.0" | |||||
}, | |||||
"devDependencies": { | |||||
"@riotjs/webpack-loader": "^5.0.0", | |||||
"cross-env": "^7.0.3", | |||||
"laravel-mix": "^6.0.25", | |||||
"resolve-url-loader": "^4.0.0", | |||||
"sass": "^1.35.1", | |||||
"sass-loader": "^12.1.0" | |||||
} | |||||
} |
@ -0,0 +1,5 @@ | |||||
.turbolinks-progress-bar { | |||||
width: 5px; | |||||
height: 100%; | |||||
background-color: blue; | |||||
} |
@ -1,18 +0,0 @@ | |||||
<?php | |||||
require __DIR__.'/../vendor/autoload.php'; | |||||
require __DIR__.'/../app/bootstrap.php'; | |||||
$app->route('GET /', array(new App\Http\Home, 'homeAction')); | |||||
$app->route('GET /bucket/@id:[0-9]', array(new App\Http\Bucket, 'viewAction')); | |||||
$app->route('GET /bucket/@id:[0-9]', array(new App\Http\Bucket, 'indexAction')); | |||||
$app->route('POST /bucket', array(new App\Http\Bucket, 'createAction')); | |||||
$app->route('PUT /bucket/@id:[0-9]', array(new App\Http\Bucket, 'updateAction')); | |||||
$app->route('DELETE /bucket/@id:[0-9]', array(new App\Http\Bucket, 'destroyAction')); | |||||
$app->route('POST /note', array(new App\Http\Note, 'createAction')); | |||||
$app->route('PUT /note/@id:[0-9]', array(new App\Http\Note, 'updateAction')); | |||||
$app->route('DELETE /note/@id:[0-9]', array(new App\Http\Note, 'destroyAction')); | |||||
$app->start(); |
@ -0,0 +1,166 @@ | |||||
/******/ (() => { // webpackBootstrap | |||||
/******/ var __webpack_modules__ = ({ | |||||
/***/ "./resources/js/index.js": | |||||
/*!*******************************!*\ | |||||
!*** ./resources/js/index.js ***! | |||||
\*******************************/ | |||||
/***/ (() => { | |||||
/***/ }), | |||||
/***/ "./resources/scss/index.scss": | |||||
/*!***********************************!*\ | |||||
!*** ./resources/scss/index.scss ***! | |||||
\***********************************/ | |||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { | |||||
"use strict"; | |||||
__webpack_require__.r(__webpack_exports__); | |||||
// extracted by mini-css-extract-plugin | |||||
/***/ }) | |||||
/******/ }); | |||||
/************************************************************************/ | |||||
/******/ // The module cache | |||||
/******/ var __webpack_module_cache__ = {}; | |||||
/******/ | |||||
/******/ // The require function | |||||
/******/ function __webpack_require__(moduleId) { | |||||
/******/ // Check if module is in cache | |||||
/******/ var cachedModule = __webpack_module_cache__[moduleId]; | |||||
/******/ if (cachedModule !== undefined) { | |||||
/******/ return cachedModule.exports; | |||||
/******/ } | |||||
/******/ // Create a new module (and put it into the cache) | |||||
/******/ var module = __webpack_module_cache__[moduleId] = { | |||||
/******/ // no module.id needed | |||||
/******/ // no module.loaded needed | |||||
/******/ exports: {} | |||||
/******/ }; | |||||
/******/ | |||||
/******/ // Execute the module function | |||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); | |||||
/******/ | |||||
/******/ // Return the exports of the module | |||||
/******/ return module.exports; | |||||
/******/ } | |||||
/******/ | |||||
/******/ // expose the modules object (__webpack_modules__) | |||||
/******/ __webpack_require__.m = __webpack_modules__; | |||||
/******/ | |||||
/************************************************************************/ | |||||
/******/ /* webpack/runtime/chunk loaded */ | |||||
/******/ (() => { | |||||
/******/ var deferred = []; | |||||
/******/ __webpack_require__.O = (result, chunkIds, fn, priority) => { | |||||
/******/ if(chunkIds) { | |||||
/******/ priority = priority || 0; | |||||
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1]; | |||||
/******/ deferred[i] = [chunkIds, fn, priority]; | |||||
/******/ return; | |||||
/******/ } | |||||
/******/ var notFulfilled = Infinity; | |||||
/******/ for (var i = 0; i < deferred.length; i++) { | |||||
/******/ var [chunkIds, fn, priority] = deferred[i]; | |||||
/******/ var fulfilled = true; | |||||
/******/ for (var j = 0; j < chunkIds.length; j++) { | |||||
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) { | |||||
/******/ chunkIds.splice(j--, 1); | |||||
/******/ } else { | |||||
/******/ fulfilled = false; | |||||
/******/ if(priority < notFulfilled) notFulfilled = priority; | |||||
/******/ } | |||||
/******/ } | |||||
/******/ if(fulfilled) { | |||||
/******/ deferred.splice(i--, 1) | |||||
/******/ result = fn(); | |||||
/******/ } | |||||
/******/ } | |||||
/******/ return result; | |||||
/******/ }; | |||||
/******/ })(); | |||||
/******/ | |||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */ | |||||
/******/ (() => { | |||||
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) | |||||
/******/ })(); | |||||
/******/ | |||||
/******/ /* webpack/runtime/make namespace object */ | |||||
/******/ (() => { | |||||
/******/ // define __esModule on exports | |||||
/******/ __webpack_require__.r = (exports) => { | |||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { | |||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | |||||
/******/ } | |||||
/******/ Object.defineProperty(exports, '__esModule', { value: true }); | |||||
/******/ }; | |||||
/******/ })(); | |||||
/******/ | |||||
/******/ /* webpack/runtime/jsonp chunk loading */ | |||||
/******/ (() => { | |||||
/******/ // no baseURI | |||||
/******/ | |||||
/******/ // object to store loaded and loading chunks | |||||
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched | |||||
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded | |||||
/******/ var installedChunks = { | |||||
/******/ "/public/js/index": 0, | |||||
/******/ "public/css/index": 0 | |||||
/******/ }; | |||||
/******/ | |||||
/******/ // no chunk on demand loading | |||||
/******/ | |||||
/******/ // no prefetching | |||||
/******/ | |||||
/******/ // no preloaded | |||||
/******/ | |||||
/******/ // no HMR | |||||
/******/ | |||||
/******/ // no HMR manifest | |||||
/******/ | |||||
/******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0); | |||||
/******/ | |||||
/******/ // install a JSONP callback for chunk loading | |||||
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { | |||||
/******/ var [chunkIds, moreModules, runtime] = data; | |||||
/******/ // add "moreModules" to the modules object, | |||||
/******/ // then flag all "chunkIds" as loaded and fire callback | |||||
/******/ var moduleId, chunkId, i = 0; | |||||
/******/ for(moduleId in moreModules) { | |||||
/******/ if(__webpack_require__.o(moreModules, moduleId)) { | |||||
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; | |||||
/******/ } | |||||
/******/ } | |||||
/******/ if(runtime) var result = runtime(__webpack_require__); | |||||
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); | |||||
/******/ for(;i < chunkIds.length; i++) { | |||||
/******/ chunkId = chunkIds[i]; | |||||
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { | |||||
/******/ installedChunks[chunkId][0](); | |||||
/******/ } | |||||
/******/ installedChunks[chunkIds[i]] = 0; | |||||
/******/ } | |||||
/******/ return __webpack_require__.O(result); | |||||
/******/ } | |||||
/******/ | |||||
/******/ var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || []; | |||||
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); | |||||
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); | |||||
/******/ })(); | |||||
/******/ | |||||
/************************************************************************/ | |||||
/******/ | |||||
/******/ // startup | |||||
/******/ // Load entry module and return exports | |||||
/******/ // This entry module depends on other loaded chunks and execution need to be delayed | |||||
/******/ __webpack_require__.O(undefined, ["public/css/index"], () => (__webpack_require__("./resources/js/index.js"))) | |||||
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["public/css/index"], () => (__webpack_require__("./resources/scss/index.scss"))) | |||||
/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__); | |||||
/******/ | |||||
/******/ })() | |||||
; |
@ -0,0 +1,4 @@ | |||||
const Turbolinks = require('turbolinks') | |||||
Turbolinks.start() | |||||
Turbolinks.setProgressBarDelay(500) |
@ -0,0 +1,5 @@ | |||||
.turbolinks-progress-bar { | |||||
width: 5px; | |||||
height: 100%; | |||||
background-color: blue; | |||||
} |
@ -0,0 +1,55 @@ | |||||
<% layout('./../layout.html') %> | |||||
<div class="container"> | |||||
<div class="grid"> | |||||
<div class="col-12"> | |||||
<h2> | |||||
Create Bucket | |||||
</h2> | |||||
</div> | |||||
<div class="col-12"> | |||||
<form action="/bucket/store" method="POST" novalidate> | |||||
<div class="field"> | |||||
<label class="field__label"> | |||||
title* | |||||
<input class="field__text" name="title" type="text" /> | |||||
</label> | |||||
</div> | |||||
<div class="field"> | |||||
<label class="field__label"> | |||||
description* | |||||
<input class="field__text" name="description" type="text" /> | |||||
</label> | |||||
</div> | |||||
<div class="field"> | |||||
<label class="field__label"> | |||||
type* | |||||
<% it.types.forEach(function(type) { %> | |||||
<input class="field__choice" name="type" type="radio" value="<%= type.value %>" /> | |||||
<span class="field__help"> | |||||
<%= type %> | |||||
</span> | |||||
<% }) %> | |||||
</label> | |||||
</div> | |||||
<div class="field"> | |||||
<label class="field__label"> | |||||
visiblity* | |||||
<% it.visiblities.forEach(function(visiblity) { %> | |||||
<input class="field__choice" name="visiblity" type="radio" value="<%= visiblity.value %>" /> | |||||
<span> | |||||
<%= visiblity %> | |||||
</span> | |||||
<% }) %> | |||||
</label> | |||||
</div> | |||||
<div class=""> | |||||
<button class="button"> | |||||
Create | |||||
</button> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</div> | |||||
</div> |
@ -0,0 +1,12 @@ | |||||
<% layout('./../layout.html') %> | |||||
<div class="container"> | |||||
<div class="grid"> | |||||
<div class="col-12"> | |||||
<h1><%= it.bucket.title %></h1> | |||||
<span> | |||||
<%= it.bucket.description %> | |||||
</span> | |||||
</div> | |||||
</div> | |||||
</div> |
@ -0,0 +1 @@ | |||||
404 |
@ -0,0 +1 @@ | |||||
ldjlsjfl |
@ -1,24 +0,0 @@ | |||||
@extends('layout') | |||||
@section('main') | |||||
<div class="container"> | |||||
<h2> | |||||
Buckets | |||||
<button class="button"> | |||||
Create | |||||
</button> | |||||
</h2> | |||||
<h3> | |||||
</h3> | |||||
<app-buckets></app-buckets> | |||||
</div> | |||||
@push('scripts') | |||||
<script type="text/javascript" src="js/buckets.js"></script> | |||||
<script type="text/javascript" defer> | |||||
riot.mount('buckets', {!! json_encode([ 'buckets' => $buckets ]) !!}); | |||||
</script> | |||||
@endpush | |||||
@endsection |
@ -0,0 +1,22 @@ | |||||
<% layout('./layout.html') %> | |||||
<div class="container"> | |||||
<div class="grid"> | |||||
<div class="col-12"> | |||||
<h2> | |||||
Buckets | |||||
<a class="button" href="/bucket/create"> | |||||
Create | |||||
</a> | |||||
</h2> | |||||
</div> | |||||
<h3> | |||||
Your Buckets | |||||
</h3> | |||||
<app-buckets visiblity="private"></app-buckets> | |||||
<h3> | |||||
Other Buckets | |||||
</h3> | |||||
<app-buckets visiblity="public,community"></app-buckets> | |||||
</div> | |||||
</div> |
@ -1,55 +0,0 @@ | |||||
<!DOCTYPE html> | |||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> | |||||
<head> | |||||
<meta charset="utf-8"> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||||
<title>Nano Buckets</title> | |||||
@yield('head') | |||||
<link rel="stylesheet" href="css/app.css" /> | |||||
</head> | |||||
<body> | |||||
<header class="app-header"> | |||||
<div class="container is-fluid pt-2 pb-2"> | |||||
<nav class="navbar" role="navigation" aria-label="main navigation"> | |||||
<div class="navbar-brand"> | |||||
<a class="navbar-item" href="/"> | |||||
<img class="app-header__logo" src="/logo.svg" alt="Urban Filehub" /> | |||||
<span class="app-header__title ml-2"> | |||||
Filehub<strong>.Freifunk Minden</strong> | |||||
</span> | |||||
</a> | |||||
</div> | |||||
<div class="navbar-menu"> | |||||
<div class="navbar-start"> | |||||
<a class="navbar-item"> | |||||
Dashboard | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</nav> | |||||
</div> | |||||
</header> | |||||
<section class="section"> | |||||
<div class="container is-fluid mt-3 mb-4"> | |||||
<urban-accordion> | |||||
<div title="Send me a Link"> | |||||
<urban-login-email></urban-login-email> | |||||
</div> | |||||
<div title="Login with Password"> | |||||
<urban-login-password></urban-login-password> | |||||
</div> | |||||
</urban-accordion> | |||||
</div> | |||||
</section> | |||||
<main> | |||||
@yield('main') | |||||
</main> | |||||
<script type="text/javascript" src="js/app.js"></script> | |||||
@stack('scripts') | |||||
</body> | |||||
</html> |
@ -0,0 +1,31 @@ | |||||
<!DOCTYPE html> | |||||
<html lang="en"> | |||||
<head> | |||||
<meta charset="utf-8"> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||||
<title>Nano Buckets</title> | |||||
<link rel="stylesheet" href="/css/index.css" /> | |||||
<script type="text/javascript" src="/js/critical.js" defer></script> | |||||
</head> | |||||
<body> | |||||
<header class="app-header"> | |||||
<div class="container"> | |||||
<nav class="navbar" role="navigation" aria-label="main navigation"> | |||||
</nav> | |||||
</div> | |||||
</header> | |||||
<section class="app-section"> | |||||
<div class=""> | |||||
</div> | |||||
</section> | |||||
<main> | |||||
<%~ it.body %> | |||||
</main> | |||||
</body> | |||||
</html> |
@ -0,0 +1,43 @@ | |||||
import 'https://deno.land/x/dotenv@v2.0.0/load.ts' | |||||
import { | |||||
opine, | |||||
serveStatic, | |||||
json, | |||||
urlencoded | |||||
} from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
import { dirname, join, createError } from "https://deno.land/x/opine@1.5.3/deps.ts"; | |||||
import { renderFile } from 'https://deno.land/x/eta@v1.12.2/mod.ts' | |||||
// getting routes | |||||
import index from './src/http/index.ts' | |||||
import bucket from './src/http/bucket.ts' | |||||
import bucketApi from './src/http/api/bucket.ts' | |||||
const app = opine() | |||||
const __dirname = dirname(import.meta.url) | |||||
// | |||||
app.use(json()); // for parsing application/json | |||||
app.use(urlencoded()); // for parsing application/x-www-form-urlencoded | |||||
// adding static files | |||||
app.use(serveStatic(join(__dirname, 'public'))) | |||||
// adding eta as view engine | |||||
app.engine('.html', renderFile) | |||||
app.set('views', join(__dirname, 'resources/views')) | |||||
app.set('view engine', 'html') | |||||
// adding http classes for routes | |||||
app.use('/', index) | |||||
app.use('/bucket', bucket) | |||||
app.use('/api/bucket', bucketApi) | |||||
app.use((request, response, next) => { | |||||
response.setStatus(404) | |||||
response.render('errors/404') | |||||
}) | |||||
// let it rain | |||||
app.listen(Number(Deno.env.get('SERVER_PORT'))) | |||||
console.log('running on ' + Deno.env.get('SERVER_PORT')) | |||||
@ -0,0 +1,18 @@ | |||||
import Enum from 'https://deno.land/x/enum@v3.0.4/index.js' | |||||
// visibilties are a template for the roles | |||||
export const visibilties = new Enum([ | |||||
'PUBLIC', | |||||
'COMMUNITY', | |||||
'PRIVATE' | |||||
], { freeze: true, name: 'visibilties' }) | |||||
// types define the structure of a bucket | |||||
// kanban: columns with title | |||||
// masonry: wall with columns and each note can have different hight | |||||
// blog: all notes will be organized in one column | |||||
export const types = new Enum([ | |||||
'KANBAN', | |||||
'MASONRY', | |||||
'BLOG' | |||||
], { freeze: true, name: 'types' }) |
@ -0,0 +1,49 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
const router = Router() | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.get('/:uuid', function(request, response) { | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.post('/', function(request, response, next) { | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.put('/:uuid', function(request, response, next) { | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.delete('/:uuid', function(request, response, next) { | |||||
}) | |||||
export default router |
@ -0,0 +1,46 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
const router = Router() | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.post('/:bucket_id', function(request, response) | |||||
{ | |||||
const [ valid, errors ] = await validate(body, { | |||||
title: [ maxLength(255) ], | |||||
content: [ maxLength(10922) ], | |||||
tags: [ ], | |||||
url: isUrl | |||||
}) | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.put('/:bucket_id/:id', function(request, response, next) | |||||
{ | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.delete('/:bucket_id/:id', function(request, response, next) | |||||
{ | |||||
}) | |||||
export default router |
@ -0,0 +1,102 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
import { v4 } from "https://deno.land/std@0.99.0/uuid/mod.ts"; | |||||
import { validate, required, isIn, maxLength } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts' | |||||
import { Database } from 'https://deno.land/x/aloedb@0.9.0/mod.ts' | |||||
import { escapeHtml } from "https://deno.land/x/escape@1.3.0/mod.ts" | |||||
import { BucketSchema } from './../stores/bucket.ts' | |||||
import { visibilties, types } from './../enums/bucket.ts' | |||||
const router = Router() | |||||
/** | |||||
* render template for form | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.get('/create', function(request, response, next) | |||||
{ | |||||
response.render('bucket/form', { | |||||
visiblities: visibilties.enums, | |||||
types: types.enums | |||||
}) | |||||
}) | |||||
/** | |||||
* render template for form | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.post('/store', async function(request, response, next) | |||||
{ | |||||
const body = request.body | |||||
let typeValues = <any>[] | |||||
let visiblityValues = <any>[] | |||||
types.enums.forEach(function(type) { | |||||
typeValues.push(String(type.value)) | |||||
}) | |||||
visibilties.enums.forEach(function(visiblity) { | |||||
visiblityValues.push(String(visiblity.value)) | |||||
}) | |||||
// escape before validate | |||||
if (body.title) { | |||||
body.title = escapeHtml(body.title) | |||||
} | |||||
if (body.description) { | |||||
body.description = escapeHtml(body.description) | |||||
} | |||||
const [ valid, errors ] = await validate(body, { | |||||
title: [ required, maxLength(255) ], | |||||
description: [ required, maxLength(255) ], | |||||
type: [ required, isIn(typeValues) ], | |||||
visiblity: [ required, isIn(visiblityValues)] | |||||
}); | |||||
if (valid) { | |||||
const db = new Database<BucketSchema>('./storage/database/buckets.json') | |||||
body._id = v4.generate() | |||||
const bucket = await db.insertOne(body) | |||||
response.redirect('/bucket/' + bucket._id) | |||||
} else { | |||||
response.redirect('/bucket/create') | |||||
} | |||||
}) | |||||
/** | |||||
* render template for form | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.get('/:id', async function(request, response, next) | |||||
{ | |||||
if (!v4.validate(request.params.id)) { | |||||
response.setStatus(404) | |||||
} | |||||
const db = new Database<BucketSchema>('./storage/database/buckets.json') | |||||
const bucket = await db.findOne({ '_id': request.params.id }) | |||||
if (!bucket) { | |||||
response.setStatus(404) | |||||
} | |||||
response.render('bucket/single', { | |||||
bucket: bucket | |||||
}) | |||||
}) | |||||
export default router |
@ -0,0 +1,16 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
const router = Router() | |||||
/** | |||||
* render template for form | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.get('/', function(request, response, next) { | |||||
response.render('index') | |||||
}) | |||||
export default router |
@ -0,0 +1,43 @@ | |||||
import { Drash } from 'https://deno.land/x/drash@v1.4.4/mod.ts' | |||||
import { v4 } from 'https://deno.land/std@0.99.0/uuid/mod.ts' | |||||
import { Bucket as BucketSchema } from './src/schemas/bucket.ts' | |||||
import Schema, { Type, string, number, array } from 'https://denoporter.sirjosh.workers.dev/v1/deno.land/x/computed_types/src/index.ts' | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
export class BucketResource extends Drash.Http.Resource | |||||
{ | |||||
// route | |||||
static paths = ['/bucket/[:id?]'] | |||||
/** | |||||
* [GET description] | |||||
* @param id [description] | |||||
* @return [description] | |||||
*/ | |||||
public GET(id) | |||||
{ | |||||
const db = new Database<BucketSchema>() | |||||
const buckets = await db.findOne({ | |||||
'_id': id | |||||
}) | |||||
this.response.body = bucket | |||||
return this.response | |||||
} | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
public POST() | |||||
{ | |||||
const db = new Database<BucketSchema>() | |||||
this.response.body = bucket | |||||
return this.response | |||||
} | |||||
} |
@ -0,0 +1,24 @@ | |||||
import { Drash } from 'https://deno.land/x/drash@v1.4.4/mod.ts' | |||||
import { v4 } from 'https://deno.land/std@0.99.0/uuid/mod.ts' | |||||
import { Bucket as BucketSchema } from './src/schemas/bucket.ts' | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
export class BucketResource extends Drash.Http.Resource | |||||
{ | |||||
// route | |||||
static paths = ['/buckets'] | |||||
// | |||||
public GET() | |||||
{ | |||||
const db = new Database<BucketSchema>() | |||||
const buckets = await db.findMany() | |||||
this.response.body = buckets | |||||
return this.response | |||||
} | |||||
} |
@ -0,0 +1,18 @@ | |||||
import { Drash } from 'https://deno.land/x/drash@v1.4.4/mod.ts' | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
export class IndexResource extends Drash.Http.Resource | |||||
{ | |||||
// route | |||||
static paths = ['/'] | |||||
// | |||||
public GET() | |||||
{ | |||||
this.response.body = 'Hallo' | |||||
return this.response | |||||
} | |||||
} |
@ -0,0 +1,14 @@ | |||||
import { Database } from 'https://deno.land/x/aloedb/mod.ts'; | |||||
class BaseStore | |||||
{ | |||||
construct() | |||||
{ | |||||
this.db = new Database<('./storage/database/' + this.name + '.json') | |||||
} | |||||
uuid() | |||||
{ | |||||
} | |||||
} |
@ -0,0 +1,10 @@ | |||||
export interface BucketSchema { | |||||
_id: string; | |||||
title: string; | |||||
description: string; | |||||
owner: string; | |||||
configuration: string[]; | |||||
visiblity: string; | |||||
created_at: string; | |||||
updated_at: string; | |||||
} |
@ -0,0 +1,8 @@ | |||||
export interface Note { | |||||
_id: string; | |||||
title: string; | |||||
type: string; | |||||
content: string; | |||||
attachment: array; | |||||
tags: string[]; | |||||
} |
@ -0,0 +1,4 @@ | |||||
interface Tag { | |||||
_bucket_id: string; | |||||
name: string; | |||||
} |
@ -0,0 +1,6 @@ | |||||
interface Bucket { | |||||
_id: string; | |||||
username: string; | |||||
password: string; | |||||
displayname: string; | |||||
} |
@ -0,0 +1,13 @@ | |||||
import { validate, required, isNumber } from 'https://deno.land/x/validasaur@0.15.0/mod.ts' | |||||
// create shema for validation | |||||
const BucketSchema = Schema({ | |||||
title: string.trim().normalize(), | |||||
description: string.trim().normalize().optional(), | |||||
type: Schema.either('a', 'b', 'c'), | |||||
visiblity: Schema.either('a', 'b', 'c') | |||||
}) | |||||
// create type and get validator from schema | |||||
export type bucketType = Type<typeof BucketSchema> | |||||
export const bucketValidator = BucketSchema.destruct() |
@ -0,0 +1,15 @@ | |||||
import Schema, { Type, string, number, array } from 'https://denoporter.sirjosh.workers.dev/v1/deno.land/x/computed_types/src/index.ts' | |||||
// create shema for validation | |||||
const NoteSchema = Schema({ | |||||
title: string.trim().normalize(), | |||||
description: string.trim().normalize().optional(), | |||||
type: Schema.either('a', 'b', 'c'), | |||||
visiblity: Schema.either('a', 'b', 'c') | |||||
}) | |||||
// create type and get validator from schema | |||||
type Note = Type<typeof NoteSchema> | |||||
const validator = NoteSchema.destruct() | |||||
export default validator |
@ -0,0 +1,14 @@ | |||||
import Schema, { Type, string, number, array } from 'https://denoporter.sirjosh.workers.dev/v1/deno.land/x/computed_types/src/index.ts' | |||||
// create shema for validation | |||||
const UserSchema = Schema({ | |||||
username: string.trim().normalize(), | |||||
password: string.normalize(), | |||||
email: Schema.email() | |||||
}) | |||||
// create type and get validator from schema | |||||
type User = Type<typeof UserSchema> | |||||
const validator = UserSchema.destruct() | |||||
export default validator |
@ -0,0 +1,23 @@ | |||||
const mix = require('laravel-mix') | |||||
/* | |||||
|-------------------------------------------------------------------------- | |||||
| Mix Asset Management | |||||
|-------------------------------------------------------------------------- | |||||
| | |||||
| Mix provides a clean, fluent API for defining some Webpack build steps | |||||
| for your Laravel application. By default, we are compiling the Sass | |||||
| file for the application as well as bundling up all the JS files. | |||||
| | |||||
*/ | |||||
mix.options({ | |||||
terser: { | |||||
extractComments: false | |||||
} | |||||
}) | |||||
mix | |||||
.js('resources/js/index.js', 'public/js') | |||||
.js('resources/js/critical.js', 'public/js') | |||||
.sass('resources/scss/index.scss', 'public/css') |