| @ -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') | |||||