Browse Source
I tried it and I find it easier to work with Caveman2. I didn't realise this templating program is built around Hunchentoot -- whereas Caveman2 builds on top of. So, I'm moving the code to back to Caveman2 -- where I originally started. It looks like a waste of time but the knowledge of having a look at the other stuff has been helpful.stable
Craig Oates
2 years ago
18 changed files with 0 additions and 839 deletions
@ -1,16 +0,0 @@ |
|||||||
LISP ?= sbcl
|
|
||||||
|
|
||||||
all: test |
|
||||||
|
|
||||||
run: |
|
||||||
rlwrap $(LISP) --load run.lisp
|
|
||||||
|
|
||||||
build: |
|
||||||
$(LISP) --non-interactive \
|
|
||||||
--load ritherdon-archive.asd \
|
|
||||||
--eval '(ql:quickload :ritherdon-archive)' \
|
|
||||||
--eval '(asdf:make :ritherdon-archive)'
|
|
||||||
|
|
||||||
test: |
|
||||||
$(LISP) --non-interactive \
|
|
||||||
--load run-tests.lisp
|
|
@ -1,101 +0,0 @@ |
|||||||
# ritherdon-archive |
|
||||||
|
|
||||||
Archive of Ritherdon and Nicola Ellis. |
|
||||||
|
|
||||||
# Usage |
|
||||||
|
|
||||||
Run from sources: |
|
||||||
|
|
||||||
make run |
|
||||||
# aka sbcl --load run.lisp |
|
||||||
|
|
||||||
choose your lisp: |
|
||||||
|
|
||||||
LISP=ccl make run |
|
||||||
|
|
||||||
or build and run the binary: |
|
||||||
|
|
||||||
``` |
|
||||||
$ make build |
|
||||||
$ ./ritherdon-archive [name] |
|
||||||
Hello [name] from ritherdon-archive |
|
||||||
``` |
|
||||||
|
|
||||||
## Init config file |
|
||||||
|
|
||||||
Create a config file: |
|
||||||
|
|
||||||
cp config-example.lisp config.lisp |
|
||||||
|
|
||||||
You can override global variables (for example, the port, which can be |
|
||||||
handy if you run the app from sources, without building a binary and |
|
||||||
using the `--port` flag. |
|
||||||
|
|
||||||
The config file is `load`ed before the web server starts (see the `(main)`). |
|
||||||
|
|
||||||
|
|
||||||
## Roswell integration |
|
||||||
|
|
||||||
Roswell is an implementation manager and [script launcher](https://github.com/roswell/roswell/wiki/Roswell-as-a-Scripting-Environment). |
|
||||||
|
|
||||||
A POC script is in the roswell/ directory. |
|
||||||
|
|
||||||
Your users can install the script with `craig/ritherdon-archive`. |
|
||||||
|
|
||||||
# Dev |
|
||||||
|
|
||||||
Load the .asd, quickload it then |
|
||||||
|
|
||||||
``` |
|
||||||
CL-USER> (ritherdon-archive/web:start-app) |
|
||||||
``` |
|
||||||
|
|
||||||
See also: |
|
||||||
|
|
||||||
- `web::load-config &key port load-init-p` |
|
||||||
|
|
||||||
|
|
||||||
## Tests |
|
||||||
|
|
||||||
Tests are defined with [Fiveam](https://common-lisp.net/project/fiveam/docs/). |
|
||||||
|
|
||||||
Run them from the terminal with `make test`. You should see a failing test. |
|
||||||
|
|
||||||
```bash |
|
||||||
$ make test |
|
||||||
Running test suite TESTMAIN |
|
||||||
Running test TEST1 f |
|
||||||
Did 1 check. |
|
||||||
Pass: 0 ( 0%) |
|
||||||
Skip: 0 ( 0%) |
|
||||||
Fail: 1 (100%) |
|
||||||
|
|
||||||
Failure Details: |
|
||||||
-------------------------------- |
|
||||||
TEST1 in TESTMAIN []: |
|
||||||
|
|
||||||
3 |
|
||||||
|
|
||||||
evaluated to |
|
||||||
|
|
||||||
3 |
|
||||||
|
|
||||||
which is not |
|
||||||
|
|
||||||
= |
|
||||||
|
|
||||||
to |
|
||||||
|
|
||||||
2 |
|
||||||
|
|
||||||
Makefile:15: recipe for target 'test' failed |
|
||||||
|
|
||||||
$ echo $? |
|
||||||
2 |
|
||||||
``` |
|
||||||
|
|
||||||
On Slime, load the test package and run `run!`. |
|
||||||
|
|
||||||
--- |
|
||||||
|
|
||||||
Licence: BSD |
|
@ -1,9 +0,0 @@ |
|||||||
* Ritherdon Archive |
|
||||||
|
|
||||||
An archive of Ritherdon. I need to speak to Nic more about what this |
|
||||||
means. |
|
||||||
|
|
||||||
* Project Summary |
|
||||||
|
|
||||||
This is a website written in Common Lisp and the Caveman2 framework. The |
|
||||||
databased it uses in SQLite3 and Steel Bank Common Lisp (SBCL). |
|
@ -1,12 +0,0 @@ |
|||||||
|
|
||||||
(in-package :ritherdon-archive) |
|
||||||
|
|
||||||
(in-package :ritherdon-archive/web) |
|
||||||
|
|
||||||
;; |
|
||||||
;; To use an init configuration file: |
|
||||||
;; cp config-example.lisp config.lisp |
|
||||||
;; |
|
||||||
|
|
||||||
;; Override the port: |
|
||||||
;; (setf *port* 4545) |
|
@ -1,18 +0,0 @@ |
|||||||
(in-package :asdf-user) |
|
||||||
(defsystem "ritherdon-archive-tests" |
|
||||||
:description "Test suite for the ritherdon-archive system" |
|
||||||
:author "Craig Oates <craig@craigoates.net>" |
|
||||||
:version "0.0.0" |
|
||||||
:depends-on (:ritherdon-archive |
|
||||||
:parachute) |
|
||||||
:license "MIT" |
|
||||||
:serial t |
|
||||||
:components ((:module "tests" |
|
||||||
:serial t |
|
||||||
:components ((:file "packages") |
|
||||||
(:file "test-ritherdon-archive")))) |
|
||||||
:perform (test-op (op s) (symbol-call :parachute :test :tests)) |
|
||||||
|
|
||||||
;; The following would not return the right exit code on error, but still 0. |
|
||||||
;; :perform (test-op (op _) (symbol-call :fiveam :run-all-tests)) |
|
||||||
) |
|
@ -1,37 +0,0 @@ |
|||||||
|
|
||||||
## How to use Roswell to build and share binaries |
|
||||||
|
|
||||||
From the project root: |
|
||||||
|
|
||||||
Run as a script: |
|
||||||
|
|
||||||
chmod +x roswell/ritherdon-archive.ros |
|
||||||
./roswell/ritherdon-archive.ros |
|
||||||
|
|
||||||
Build a binary: |
|
||||||
|
|
||||||
ros build roswell/ritherdon-archive.ros |
|
||||||
|
|
||||||
and run it: |
|
||||||
|
|
||||||
./roswell/ritherdon-archive |
|
||||||
|
|
||||||
Or install it in ~/.roswell/bin: |
|
||||||
|
|
||||||
ros install roswell/ritherdon-archive.ros |
|
||||||
|
|
||||||
It creates the binary in ~/.roswell/bin/ |
|
||||||
Run it: |
|
||||||
|
|
||||||
~/.roswell/bin/ritherdon-archive [name]~& |
|
||||||
|
|
||||||
Your users can install the script with ros install craig/ritherdon-archive |
|
||||||
|
|
||||||
Use `+Q` if you don't have Quicklisp dependencies to save startup time. |
|
||||||
Use `ros build --disable-compression` to save on startup time and loose on application size. |
|
||||||
|
|
||||||
|
|
||||||
## See |
|
||||||
|
|
||||||
- https://github.com/roswell/roswell/wiki/ |
|
||||||
- https://github.com/roswell/roswell/wiki/Reducing-Startup-Time |
|
@ -1,28 +0,0 @@ |
|||||||
#!/bin/sh |
|
||||||
#|-*- mode:lisp -*-|# |
|
||||||
#| |
|
||||||
exec ros -Q -- $0 "$@" |
|
||||||
|# |
|
||||||
|
|
||||||
;; use +Q if you don't have Quicklisp dependencies to save startup time. |
|
||||||
|
|
||||||
(defun help () |
|
||||||
(format t "~&Usage: |
|
||||||
|
|
||||||
ritherdon-archive [name] |
|
||||||
|
|
||||||
")) |
|
||||||
|
|
||||||
;; XXX: this load does not load from everywhere |
|
||||||
;; it doesn't work for to run as a script. |
|
||||||
(load (truename "ritherdon-archive.asd")) |
|
||||||
(ql:quickload "ritherdon-archive") |
|
||||||
|
|
||||||
(defun main (&rest argv) |
|
||||||
"Optional name parameter." |
|
||||||
(when (member "-h" argv :test #'equal) |
|
||||||
;; To parse command line arguments, use a third-party library such as |
|
||||||
;; unix-opts, defmain, adopt… |
|
||||||
(help) |
|
||||||
(uiop:quit)) |
|
||||||
(ritherdon-archive::greet (first argv))) |
|
@ -1,9 +0,0 @@ |
|||||||
|
|
||||||
(load "ritherdon-archive.asd") |
|
||||||
(load "ritherdon-archive-tests.asd") |
|
||||||
|
|
||||||
(ql:quickload "ritherdon-archive-tests") |
|
||||||
|
|
||||||
(in-package :ritherdon-archive-tests) |
|
||||||
|
|
||||||
(uiop:quit (if (run-all-tests) 0 1)) |
|
@ -1,25 +0,0 @@ |
|||||||
" |
|
||||||
Usage: |
|
||||||
|
|
||||||
rlwrap sbcl --load run.lisp |
|
||||||
|
|
||||||
This loads the project's asd, loads the quicklisp dependencies, and |
|
||||||
calls the main function. |
|
||||||
|
|
||||||
Then, we are given the lisp prompt. |
|
||||||
|
|
||||||
If you don't want to land in the REPL, you can (quit) below or call lisp with the --non-interactive flag. |
|
||||||
|
|
||||||
Another solution to run the app is to build and run a binary (see README). |
|
||||||
" |
|
||||||
|
|
||||||
(load "ritherdon-archive.asd") |
|
||||||
|
|
||||||
(ql:quickload "ritherdon-archive") |
|
||||||
|
|
||||||
(in-package :ritherdon-archive) |
|
||||||
(handler-case |
|
||||||
(main) |
|
||||||
(error (c) |
|
||||||
(format *error-output* "~&An error occured: ~a~&" c) |
|
||||||
(uiop:quit 1))) |
|
@ -1,30 +0,0 @@ |
|||||||
(in-package :ritherdon-archive/models) |
|
||||||
;;; |
|
||||||
;;; DB connection, migrations. |
|
||||||
;;; |
|
||||||
|
|
||||||
(defparameter *tables* '(product user) |
|
||||||
"List of the DB tables that need to be checked for migrations.") |
|
||||||
|
|
||||||
(defun connect (&optional (db-name *db-name*)) |
|
||||||
"Connect to the DB." |
|
||||||
;; *db* could be mito:*connection* |
|
||||||
(log:debug "connecting to ~a~&" *db-name*) |
|
||||||
(setf *db* (mito:connect-toplevel :sqlite3 :database-name db-name))) |
|
||||||
|
|
||||||
(defun ensure-tables-exist () |
|
||||||
"Run SQL to create the missing tables." |
|
||||||
(unless mito::*connection* |
|
||||||
(connect)) |
|
||||||
(mapcar #'mito:ensure-table-exists *tables*)) |
|
||||||
|
|
||||||
(defun migrate-all () |
|
||||||
"Migrate the tables after we changed the class definition." |
|
||||||
(mapcar #'mito:migrate-table *tables*)) |
|
||||||
|
|
||||||
;; |
|
||||||
;; Entry points |
|
||||||
;; |
|
||||||
(defun init-db () |
|
||||||
"Connect to the DB, run the required migrations and define a couple base user roles." |
|
||||||
(ensure-tables-exist)) |
|
@ -1,61 +0,0 @@ |
|||||||
(in-package :ritherdon-archive/models) |
|
||||||
|
|
||||||
(defparameter *db-name* (asdf:system-relative-pathname :ritherdon-archive "ritherdon-archive.db")) |
|
||||||
|
|
||||||
(defparameter *db* nil |
|
||||||
"DB connection object, returned by (connect).") |
|
||||||
|
|
||||||
;; After modification, run (migrate-all) |
|
||||||
;; |
|
||||||
;; - to create a date: (local-time:now) |
|
||||||
;; " |
|
||||||
(defclass product () |
|
||||||
((title |
|
||||||
:accessor title |
|
||||||
:initarg :title |
|
||||||
:initform nil |
|
||||||
:type string |
|
||||||
:col-type (:varchar 128)) |
|
||||||
|
|
||||||
(reference |
|
||||||
:accessor reference |
|
||||||
:initarg :reference |
|
||||||
:initform nil |
|
||||||
:type (or string null) |
|
||||||
:col-type (or (:varchar 128) :null)) |
|
||||||
|
|
||||||
(price |
|
||||||
:accessor price |
|
||||||
:initarg :price |
|
||||||
;; we don't the price to 0 (nil denotes a missing field) |
|
||||||
:initform nil |
|
||||||
:type (or integer null) |
|
||||||
:col-type (or :float :null) |
|
||||||
:documentation "Store prices as integers. $9.80 => 980") |
|
||||||
|
|
||||||
(quantity |
|
||||||
:accessor quantity |
|
||||||
:initform 1 |
|
||||||
:type (or integer null) |
|
||||||
:col-type (or (:integer) :null) |
|
||||||
:documentation "Quantity in stock.")) |
|
||||||
|
|
||||||
(:metaclass mito:dao-table-class) |
|
||||||
(:documentation "A product.")) |
|
||||||
|
|
||||||
(defun make-product (&key title reference price) |
|
||||||
"Create a product instance. |
|
||||||
It is not saved in the DB yet." |
|
||||||
(make-instance 'product |
|
||||||
:title title |
|
||||||
:reference reference |
|
||||||
:price price)) |
|
||||||
|
|
||||||
(defun select-products (&key (order :asc)) |
|
||||||
(mito:select-dao 'product |
|
||||||
(sxql:order-by `(,order :created-at)))) |
|
||||||
|
|
||||||
(defun find-by (key val) |
|
||||||
"Find a product by slot. Example: (find-by :id xxx). Return only the first matching result." |
|
||||||
(when val |
|
||||||
(mito:find-dao 'product key val))) |
|
@ -1,41 +0,0 @@ |
|||||||
;;; |
|
||||||
;;; define helper packages, |
|
||||||
;;; the models, |
|
||||||
;;; the web, |
|
||||||
;;; and the base package that relies on all of them. |
|
||||||
;;; |
|
||||||
|
|
||||||
(defpackage ritherdon-archive/utils |
|
||||||
(:use :cl |
|
||||||
:log4cl) |
|
||||||
(:export #:format-date |
|
||||||
#:i18n-load |
|
||||||
#:_ |
|
||||||
#:parse-iso-date) |
|
||||||
(:documentation "Utilities that do not depend on models.")) |
|
||||||
|
|
||||||
(defpackage ritherdon-archive/models |
|
||||||
(:use :cl) |
|
||||||
(:export :connect |
|
||||||
:make-product |
|
||||||
:select-products |
|
||||||
:find-by)) |
|
||||||
|
|
||||||
(defpackage ritherdon-archive/web |
|
||||||
(:use :cl) |
|
||||||
(:import-from :easy-routes |
|
||||||
:defroute) |
|
||||||
(:export :start-app |
|
||||||
:stop-app) |
|
||||||
(:local-nicknames (#:a #:alexandria) |
|
||||||
(#:models #:ritherdon-archive/models) |
|
||||||
(#:utils #:ritherdon-archive/utils))) |
|
||||||
|
|
||||||
(defpackage ritherdon-archive |
|
||||||
(:use :cl |
|
||||||
:log4cl) |
|
||||||
(:export :main :run) |
|
||||||
(:local-nicknames (#:a #:alexandria) |
|
||||||
(#:models #:ritherdon-archive/models) |
|
||||||
(#:web #:ritherdon-archive/web) |
|
||||||
(#:utils #:ritherdon-archive/utils))) |
|
@ -1,105 +0,0 @@ |
|||||||
(in-package :ritherdon-archive) |
|
||||||
|
|
||||||
;; Define your project functionality here... |
|
||||||
|
|
||||||
(defparameter +version+ "0.0.1") ;; xxx: read from .asd |
|
||||||
|
|
||||||
(defun print-system-info (&optional (stream t)) |
|
||||||
;; see also https://github.com/40ants/cl-info |
|
||||||
(format stream "~&OS: ~a ~a~&" (software-type) (software-version)) |
|
||||||
(format stream "~&Lisp: ~a ~a~&" (lisp-implementation-type) (lisp-implementation-version)) |
|
||||||
#+asdf |
|
||||||
(format stream "~&ASDF: ~a~&" (asdf:asdf-version)) |
|
||||||
#-asdf |
|
||||||
(format stream "NO ASDF!") |
|
||||||
#+quicklisp |
|
||||||
(format stream "~&Quicklisp: ~a~&" (ql-dist:all-dists)) |
|
||||||
#-quicklisp |
|
||||||
(format stream "!! Quicklisp is not installed !!")) |
|
||||||
|
|
||||||
(defun handle-parser-error (c) |
|
||||||
"unix-opts error handler." |
|
||||||
(format t "Argument error: ~a~&" (opts:option c))) |
|
||||||
|
|
||||||
(defun main () |
|
||||||
"Parse basic CLI args, start our web app." |
|
||||||
|
|
||||||
(unless (uiop:file-exists-p models::*db-name*) |
|
||||||
(uiop:format! t "Creating the database into ~a...~&" models::*db-name*) |
|
||||||
(models::init-db)) |
|
||||||
|
|
||||||
(opts:define-opts |
|
||||||
(:name :help |
|
||||||
:description "print this help and exit." |
|
||||||
:short #\h |
|
||||||
:long "help") |
|
||||||
|
|
||||||
(:name :version |
|
||||||
:description "print the version number and exit." |
|
||||||
:short #\v |
|
||||||
:long "version") |
|
||||||
|
|
||||||
(:name :verbose |
|
||||||
:description "print debug info." |
|
||||||
:short #\V |
|
||||||
:long "verbose") |
|
||||||
|
|
||||||
(:name :port |
|
||||||
:arg-parser #'parse-integer |
|
||||||
:description "set the port for the web server. You can also use the XYZ_PORT environment variable." |
|
||||||
:short #\p |
|
||||||
:long "port")) |
|
||||||
|
|
||||||
(multiple-value-bind (options free-args) |
|
||||||
(handler-bind ((error #'handle-parser-error)) |
|
||||||
(opts:get-opts)) |
|
||||||
|
|
||||||
(format t "ritherdon-archive version ~a~&" +version+) |
|
||||||
|
|
||||||
(when (getf options :version) |
|
||||||
(print-system-info) |
|
||||||
(uiop:quit)) |
|
||||||
|
|
||||||
(when (getf options :help) |
|
||||||
(opts:describe) |
|
||||||
(uiop:quit)) |
|
||||||
|
|
||||||
(when (getf options :verbose) |
|
||||||
(print-system-info)) |
|
||||||
|
|
||||||
(web::load-config) |
|
||||||
|
|
||||||
(web:start-app :port (or (getf options :port) |
|
||||||
(ignore-errors (parse-integer (uiop:getenv "XYZ_PORT"))) |
|
||||||
web::*port*)))) |
|
||||||
|
|
||||||
(defun run () |
|
||||||
"Start our web app calling the MAIN function, and: |
|
||||||
|
|
||||||
- put the server thread on the foreground, so that Lisp doesn't quit |
|
||||||
instantly, and our binary keeps running |
|
||||||
- catch a couple errors: port in use, a user's C-c." |
|
||||||
(handler-case |
|
||||||
(progn |
|
||||||
|
|
||||||
(main) |
|
||||||
|
|
||||||
;; That's only needed for the binary, not when running from sources |
|
||||||
;; (except if you run for Systemd…). |
|
||||||
;; Put the server thread on the foreground. |
|
||||||
;; Without this, the binary exits immediately. |
|
||||||
(bt:join-thread |
|
||||||
(find-if (lambda (th) |
|
||||||
(search "hunchentoot" (bt:thread-name th))) |
|
||||||
(bt:all-threads)))) |
|
||||||
|
|
||||||
;; Catch some errors. |
|
||||||
(usocket:address-in-use-error () |
|
||||||
(format *error-output* "This port is already taken.~&")) |
|
||||||
#+sbcl |
|
||||||
(sb-sys:interactive-interrupt () |
|
||||||
(format *error-output* "~&Bye!~&") |
|
||||||
(uiop:quit)) |
|
||||||
(error (c) |
|
||||||
(format *error-output* "~&An error occured: ~a~&" c) |
|
||||||
(uiop:quit 1)))) |
|
@ -1,2 +0,0 @@ |
|||||||
|
|
||||||
console.log("Hello ritherdon-archive!"); |
|
@ -1,144 +0,0 @@ |
|||||||
<!DOCTYPE html> |
|
||||||
<html lang="en"> |
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css"> |
|
||||||
<link rel="stylesheet" type="text/css" href="../css/admin.css"> |
|
||||||
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script> |
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/notiflix@2.1.3/dist/AIO/notiflix-aio-2.1.3.min.js"></script> |
|
||||||
|
|
||||||
<!-- Vue.js --> |
|
||||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6/dist/vue.js"></script> |
|
||||||
<!-- Icons --> |
|
||||||
<link rel="stylesheet" href="https://cdn.materialdesignicons.com/5.3.45/css/materialdesignicons.min.css"> |
|
||||||
<!-- lodash --> |
|
||||||
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script> |
|
||||||
<!-- Buefy (Vue UI components) --> |
|
||||||
<link rel="stylesheet" href="https://unpkg.com/buefy/dist/buefy.min.css"> |
|
||||||
<script src="https://unpkg.com/buefy/dist/buefy.min.js"></script> |
|
||||||
<script src="https://cdn.jsdelivr.net/npm/vue-resource@1.5.1"></script> |
|
||||||
|
|
||||||
<!-- HTMX (yet another tool is the toolbet) --> |
|
||||||
<script src="https://unpkg.com/htmx.org@1.3.3"></script> |
|
||||||
|
|
||||||
<!-- The app --> |
|
||||||
<script defer src="/static/ritherdon-archive.js"></script> |
|
||||||
|
|
||||||
<title>{% block title %} ritherdon-archive {% endblock %}</title> |
|
||||||
</head> |
|
||||||
|
|
||||||
<body> |
|
||||||
<!-- START NAV --> |
|
||||||
<nav class="navbar is-white"> |
|
||||||
<div class="container"> |
|
||||||
<div class="navbar-brand"> |
|
||||||
<a class="navbar-item brand-text" href="/"> ritherdon-archive </a> |
|
||||||
<div class="navbar-burger burger" data-target="navMenu"> |
|
||||||
<span></span> |
|
||||||
<span></span> |
|
||||||
<span></span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div id="navMenu" class="navbar-menu"> |
|
||||||
<div class="navbar-start"> |
|
||||||
<a class="navbar-item" href="/"> |
|
||||||
<div class="navbar-item has-dropdown is-hoverable"> |
|
||||||
<a class="navbar-link"> |
|
||||||
Database |
|
||||||
</a> |
|
||||||
</div> |
|
||||||
</a> |
|
||||||
|
|
||||||
<div id ="quick-search" class="navbar-item field"> |
|
||||||
<p class="control has-icons-right"> |
|
||||||
<b-autocomplete placeholder="ISBN or Keywords..." |
|
||||||
v-model="name" |
|
||||||
field="title" |
|
||||||
:data ="data" |
|
||||||
:loading="isFetching" |
|
||||||
@typing="getAsyncData" |
|
||||||
@select="option => itemSelected(option)" |
|
||||||
><template slot-scope="props">{$ {{ props.option.title }} $}</template> |
|
||||||
</b-autocomplete> |
|
||||||
<span class="icon is-small is-right"> |
|
||||||
</span> |
|
||||||
</p> |
|
||||||
</div> |
|
||||||
|
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
|
|
||||||
<div class="navbar-end" > |
|
||||||
<div class="navbar-item" > |
|
||||||
{% if current-user %} |
|
||||||
<div class="dropdown is-hoverable"> |
|
||||||
<div class="dropdown-trigger" > |
|
||||||
<button class="button" aria-haspopup="true" aria-controls="profile-dropdown" > |
|
||||||
<span class="icon is-small" > |
|
||||||
<i class="fas fa-user" aria-hidden="true"></i> |
|
||||||
</span> |
|
||||||
<span>{{ current-user | user-name }}</span> |
|
||||||
</button> |
|
||||||
</div> |
|
||||||
<div class="dropdown-menu" role="menu" id="profile-dropdown"> |
|
||||||
<div class="dropdown-content" > |
|
||||||
<div class="dropdown-item" > |
|
||||||
<form action="/logout" method="POST" > |
|
||||||
<button class="button is-light">Logout</button> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
{% else %} |
|
||||||
<form action="/login" > |
|
||||||
<input name="referer-route" type="hidden" value="{{ request-uri }}"/> |
|
||||||
<button class="button is-light" >Login</button> |
|
||||||
</form> |
|
||||||
{% endif %} |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</nav> |
|
||||||
<!-- END NAV --> |
|
||||||
|
|
||||||
<!-- START MENU --> |
|
||||||
<div class="container"> |
|
||||||
<div class="columns"> |
|
||||||
<div class="column is-3 "> |
|
||||||
<aside class="menu is-hidden-mobile"> |
|
||||||
<p class="menu-label"> |
|
||||||
General |
|
||||||
</p> |
|
||||||
<ul class="menu-list"> |
|
||||||
<li><a {% if route == "/stock" %} class="is-active" {% endif %} href="/home"> Home </a></li> |
|
||||||
</ul> |
|
||||||
</aside> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="column is-9"> |
|
||||||
{% block content %} {% endblock %} |
|
||||||
</div> |
|
||||||
|
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
</body> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script> |
|
||||||
// bulma.js: hamburger toggle for mobile. |
|
||||||
(function() { |
|
||||||
var burger = document.querySelector('.burger'); |
|
||||||
var menu = document.querySelector('#'+burger.dataset.target); |
|
||||||
burger.addEventListener('click', function() { |
|
||||||
burger.classList.toggle('is-active'); |
|
||||||
menu.classList.toggle('is-active'); |
|
||||||
}); |
|
||||||
})(); |
|
||||||
</script> |
|
||||||
</html> |
|
@ -1,177 +0,0 @@ |
|||||||
|
|
||||||
|
|
||||||
{% extends "base.html" %} |
|
||||||
|
|
||||||
{% block content %} |
|
||||||
|
|
||||||
<!-- this comes straight from a Bulma demo. --> |
|
||||||
|
|
||||||
|
|
||||||
<section class="hero is-info welcome is-small"> |
|
||||||
<div class="hero-body"> |
|
||||||
<div class="container"> |
|
||||||
<h1 class="title"> |
|
||||||
Hello, Admin. |
|
||||||
</h1> |
|
||||||
<h2 class="subtitle"> |
|
||||||
I hope you are having a great day! |
|
||||||
</h2> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</section> |
|
||||||
<section class="info-tiles"> |
|
||||||
<div class="tile is-ancestor has-text-centered"> |
|
||||||
<div class="tile is-parent"> |
|
||||||
<article class="tile is-child box"> |
|
||||||
<p class="title"> {{ data.nb-titles }} </p> |
|
||||||
<p class="subtitle"> Nombre de titres </p> |
|
||||||
</article> |
|
||||||
</div> |
|
||||||
<div class="tile is-parent"> |
|
||||||
<article class="tile is-child box"> |
|
||||||
<p class="title"> {{ data.nb-books }} </p> |
|
||||||
<p class="subtitle"> Nombre de livres </p> |
|
||||||
</article> |
|
||||||
</div> |
|
||||||
<div class="tile is-parent"> |
|
||||||
<article class="tile is-child box"> |
|
||||||
<p class="title"> {{ data.nb-titles-negative }} </p> |
|
||||||
<p class="subtitle"> Titres en stock négatif </p> |
|
||||||
</article> |
|
||||||
</div> |
|
||||||
<div class="tile is-parent"> |
|
||||||
<article class="tile is-child box"> |
|
||||||
<p class="title">19</p> |
|
||||||
<p class="subtitle">Exceptions</p> |
|
||||||
</article> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</section> |
|
||||||
<div class="columns"> |
|
||||||
<div class="column is-6"> |
|
||||||
<div class="card events-card"> |
|
||||||
<header class="card-header"> |
|
||||||
<p class="card-header-title"> |
|
||||||
Events |
|
||||||
</p> |
|
||||||
<a href="#" class="card-header-icon" aria-label="more options"> |
|
||||||
<span class="icon"> |
|
||||||
<i class="fa fa-angle-down" aria-hidden="true"></i> |
|
||||||
</span> |
|
||||||
</a> |
|
||||||
</header> |
|
||||||
<div class="card-table"> |
|
||||||
<div class="content"> |
|
||||||
<table class="table is-fullwidth is-striped"> |
|
||||||
<tbody> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td width="5%"><i class="fa fa-bell-o"></i></td> |
|
||||||
<td>Lorum ipsum dolem aire</td> |
|
||||||
<td class="level-right"><a class="button is-small is-primary" href="#">Action</a></td> |
|
||||||
</tr> |
|
||||||
</tbody> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<footer class="card-footer"> |
|
||||||
<a href="#" class="card-footer-item">View All</a> |
|
||||||
</footer> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div class="column is-6"> |
|
||||||
<div class="card"> |
|
||||||
<header class="card-header"> |
|
||||||
<p class="card-header-title"> |
|
||||||
Inventory Search |
|
||||||
</p> |
|
||||||
<a href="#" class="card-header-icon" aria-label="more options"> |
|
||||||
<span class="icon"> |
|
||||||
<i class="fa fa-angle-down" aria-hidden="true"></i> |
|
||||||
</span> |
|
||||||
</a> |
|
||||||
</header> |
|
||||||
<div class="card-content"> |
|
||||||
<div class="content"> |
|
||||||
<div class="control has-icons-left has-icons-right"> |
|
||||||
<input class="input is-large" type="text" placeholder=""> |
|
||||||
<span class="icon is-medium is-left"> |
|
||||||
<i class="fa fa-search"></i> |
|
||||||
</span> |
|
||||||
<span class="icon is-medium is-right"> |
|
||||||
<i class="fa fa-check"></i> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div class="card"> |
|
||||||
<header class="card-header"> |
|
||||||
<p class="card-header-title"> |
|
||||||
User Search |
|
||||||
</p> |
|
||||||
<a href="#" class="card-header-icon" aria-label="more options"> |
|
||||||
<span class="icon"> |
|
||||||
<i class="fa fa-angle-down" aria-hidden="true"></i> |
|
||||||
</span> |
|
||||||
</a> |
|
||||||
</header> |
|
||||||
<div class="card-content"> |
|
||||||
<div class="content"> |
|
||||||
<div class="control has-icons-left has-icons-right"> |
|
||||||
<input class="input is-large" type="text" placeholder=""> |
|
||||||
<span class="icon is-medium is-left"> |
|
||||||
<i class="fa fa-search"></i> |
|
||||||
</span> |
|
||||||
<span class="icon is-medium is-right"> |
|
||||||
<i class="fa fa-check"></i> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
{% endblock %} |
|
||||||
|
|
||||||
|
|
@ -1,8 +0,0 @@ |
|||||||
(in-package :asdf-user) |
|
||||||
(defpackage :ritherdon-archive-tests |
|
||||||
(:use :common-lisp |
|
||||||
:parachute |
|
||||||
:ritherdon-archive)) |
|
||||||
|
|
||||||
|
|
||||||
(in-package :ritherdon-archive-tests) |
|
@ -1,16 +0,0 @@ |
|||||||
(in-package :ritherdon-archive-tests) |
|
||||||
|
|
||||||
#| parachute: https://shinmera.github.io/parachute/ |
|
||||||
================================================================================ |
|
||||||
Use the URL to access the documentation for parachute. |
|
||||||
|# |
|
||||||
|
|
||||||
;; This was an example taken from the doc's for parachute. I'm going to keep it |
|
||||||
;; here as a reference until I get comfortable with parachute. |
|
||||||
(define-test reference-tests |
|
||||||
(of-type integer 5) |
|
||||||
(true (numberp 2/3)) |
|
||||||
(false (numberp :keyword)) |
|
||||||
(is-values (values 0 "1") |
|
||||||
(= 0) |
|
||||||
(equal "1"))) |
|
Loading…
Reference in new issue