Переглянути джерело

htmx, tailwind, new css

joel
Joel Galvez 1 рік тому
джерело
коміт
dbdff0617f
22 змінених файлів з 2934 додано та 613 видалено
  1. +2
    -1
      .gitignore
  2. +2
    -2
      docker-compose.yml
  3. +9
    -38
      web/app/static/js/main.js
  4. +1304
    -0
      web/app/static/package-lock.json
  5. +22
    -0
      web/app/static/package.json
  6. +6
    -0
      web/app/static/postcss.config.js
  7. +134
    -0
      web/app/static/src/main.css
  8. BIN
      web/app/static/styles/ApfelGrotezk-Brukt.woff
  9. BIN
      web/app/static/styles/ApfelGrotezk-Brukt.woff2
  10. BIN
      web/app/static/styles/ApfelGrotezk-Fett.woff
  11. BIN
      web/app/static/styles/ApfelGrotezk-Fett.woff2
  12. BIN
      web/app/static/styles/ApfelGrotezk-Regular.woff
  13. BIN
      web/app/static/styles/ApfelGrotezk-Regular.woff2
  14. +922
    -0
      web/app/static/styles/main.css
  15. +36
    -0
      web/app/static/tailwind.config.js
  16. +3
    -1
      web/app/templates/about.html
  17. +183
    -70
      web/app/templates/base.html
  18. +18
    -61
      web/app/templates/book.html
  19. +25
    -25
      web/app/templates/index.html
  20. +179
    -204
      web/app/templates/resource.html
  21. +87
    -199
      web/app/templates/resources.html
  22. +2
    -12
      web/content/home.md

+ 2
- 1
.gitignore Переглянути файл

@@ -5,4 +5,5 @@ web/app/__pycache__/
database_functions_live.sh
old_database_schema
db_exports
db_imports
db_imports
node_modules

+ 2
- 2
docker-compose.yml Переглянути файл

@@ -1,4 +1,4 @@
version: "3.9"
version: "3.0"
services:
web:
build: ./web
@@ -23,4 +23,4 @@ services:
command: '--default-authentication-plugin=mysql_native_password'

volumes:
dbdata:
dbdata:

+ 9
- 38
web/app/static/js/main.js Переглянути файл

@@ -1,38 +1,9 @@
/*
# @name: main.js
# @version: 0.1
# @creation_date: 2022-04-07
# @license: The MIT License <https://opensource.org/licenses/MIT>
# @author: Simon Bowie <ad7588@coventry.ac.uk>
# @purpose: JavaScript functions for various functions
# @acknowledgements:
*/

// dynamic HTML forms based on dropdown menu
$("#resource_type").change(function() {
var $ = jQuery.noConflict();
var resource_type = $(this).val();
$(".resource_type_input").hide("fast", function() {
$("#resource_type_" + resource_type).show("slow");
});
});

// filtering resources by search
$(document).ready(function(){
$("#searchResources").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#resource-boxes #resource").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});

// testing a couple of ways to expand text
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl)
})
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl)
})
// document.addEventListener('DOMContentLoaded', e => {
// htmx.logAll();
// let as = document.querySelectorAll('a');
// as.forEach(a => {
// a.addEventListener('click', ee => {
// ee.preventDefault();
// })
// })
// })

+ 1304
- 0
web/app/static/package-lock.json
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 22
- 0
web/app/static/package.json Переглянути файл

@@ -0,0 +1,22 @@
{
"name": "expub",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"postcss:watch": "postcss ./src/main.css --dir ./styles --watch --verbose"
},
"devDependencies": {
"autoprefixer": "^10.4.2",
"postcss": "^8.4.6",
"postcss-cli": "^9.1.0",
"tailwindcss": "^3.0.18"
},
"author": "",
"license": "ISC",
"dependencies": {

},
"keywords": [],
"description": ""
}

+ 6
- 0
web/app/static/postcss.config.js Переглянути файл

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}

+ 134
- 0
web/app/static/src/main.css Переглянути файл

@@ -0,0 +1,134 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@font-face {
font-family: 'ag';
src: url(ApfelGrotezk-Regular.woff) format("woff");
}

@font-face {
font-family: 'ag-brukt';
src: url(ApfelGrotezk-Brukt.woff) format("woff");
}

@font-face {
font-family: 'ag-fett';
src: url(ApfelGrotezk-Fett.woff) format("woff");
}

body {
font-family: 'ag';
}

strong {
font-family: 'ag-fett';
}

.std-margin {
@apply p-2;
}

.cell-margin {
@apply p-4 pt-4 pb-8 pr-8
}

.block-margin {
@apply mb-8;
}

.std-padding {
@apply p-2;
}

.std-grid {
@apply grid md:grid-cols-2 lg:grid-cols-3;
}

.cell {
@apply cell-margin relative;
/* background: linear-gradient(to right, white 0%, rgb(252, 206, 255) 15px, white 10%, white 100%); */
}

.cell::before {
content: '';
position: absolute;
top: 10px;
right: 0px;
width: 3px;
height: calc(100% - 20px);
background-color: black;
}

.cell::after {
content: '';
position: absolute;
bottom: 0px;
left: 8px;
width: calc(100% - 20px);
height: 3px;
background-color: black;
}

.meta {
transform: rotate(-3.5deg);
}

h2,h3 {
@apply overflow-hidden max-w-full overflow-ellipsis;
}

h2 {
@apply text-4xl;
}

h3 {
font-family: 'ag-fett';
@apply uppercase;
}

.text > h3 {
@apply ml-6 mt-8 ;
}

h2 + *,
h3 + * {
@apply ml-6 mt-1;
}

p {
max-width: 55ch;
}

p + p {
@apply ml-6 mt-[1em];
}

.loading {
opacity: 0;
transition: opacity 200ms ease-in;
}

.htmx-request .loading {
opacity: 1;
display: block;
}

.htmx-request.loading {
opacity: 1;
}

.active {
@apply bg-[#ffff00]
}

details[open]::details-content {
display: contents;
}

.text a {
font-family: 'ag-fett';
}


BIN
web/app/static/styles/ApfelGrotezk-Brukt.woff Переглянути файл


BIN
web/app/static/styles/ApfelGrotezk-Brukt.woff2 Переглянути файл


BIN
web/app/static/styles/ApfelGrotezk-Fett.woff Переглянути файл


BIN
web/app/static/styles/ApfelGrotezk-Fett.woff2 Переглянути файл


BIN
web/app/static/styles/ApfelGrotezk-Regular.woff Переглянути файл


BIN
web/app/static/styles/ApfelGrotezk-Regular.woff2 Переглянути файл


+ 922
- 0
web/app/static/styles/main.css Переглянути файл

@@ -0,0 +1,922 @@
/*
! tailwindcss v3.2.7 | MIT License | https://tailwindcss.com
*//*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/

*,
::before,
::after {
box-sizing: border-box; /* 1 */
border-width: 0; /* 2 */
border-style: solid; /* 2 */
border-color: #e5e7eb; /* 2 */
}

::before,
::after {
--tw-content: '';
}

/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
*/

html {
line-height: 1.5; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-moz-tab-size: 4; /* 3 */
-o-tab-size: 4;
tab-size: 4; /* 3 */
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */
font-feature-settings: normal; /* 5 */
}

/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/

body {
margin: 0; /* 1 */
line-height: inherit; /* 2 */
}

/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/

hr {
height: 0; /* 1 */
color: inherit; /* 2 */
border-top-width: 1px; /* 3 */
}

/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/

abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}

/*
Remove the default font size and weight for headings.
*/

h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}

/*
Reset links to optimize for opt-in styling instead of opt-out.
*/

a {
color: inherit;
text-decoration: inherit;
}

/*
Add the correct font weight in Edge and Safari.
*/

b,
strong {
font-weight: bolder;
}

/*
1. Use the user's configured `mono` font family by default.
2. Correct the odd `em` font sizing in all browsers.
*/

code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */
font-size: 1em; /* 2 */
}

/*
Add the correct font size in all browsers.
*/

small {
font-size: 80%;
}

/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/

sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}

sub {
bottom: -0.25em;
}

sup {
top: -0.5em;
}

/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/

table {
text-indent: 0; /* 1 */
border-color: inherit; /* 2 */
border-collapse: collapse; /* 3 */
}

/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/

button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
font-weight: inherit; /* 1 */
line-height: inherit; /* 1 */
color: inherit; /* 1 */
margin: 0; /* 2 */
padding: 0; /* 3 */
}

/*
Remove the inheritance of text transform in Edge and Firefox.
*/

button,
select {
text-transform: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/

button,
[type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button; /* 1 */
background-color: transparent; /* 2 */
background-image: none; /* 2 */
}

/*
Use the modern Firefox focus style for all focusable elements.
*/

:-moz-focusring {
outline: auto;
}

/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/

:-moz-ui-invalid {
box-shadow: none;
}

/*
Add the correct vertical alignment in Chrome and Firefox.
*/

progress {
vertical-align: baseline;
}

/*
Correct the cursor style of increment and decrement buttons in Safari.
*/

::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}

/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/

[type='search'] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}

/*
Remove the inner padding in Chrome and Safari on macOS.
*/

::-webkit-search-decoration {
-webkit-appearance: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/

::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}

/*
Add the correct display in Chrome and Safari.
*/

summary {
display: list-item;
}

/*
Removes the default spacing and border for appropriate elements.
*/

blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}

fieldset {
margin: 0;
padding: 0;
}

legend {
padding: 0;
}

ol,
ul,
menu {
list-style: none;
margin: 0;
padding: 0;
}

/*
Prevent resizing textareas horizontally by default.
*/

textarea {
resize: vertical;
}

/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/

input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1; /* 1 */
color: #9ca3af; /* 2 */
}

input::placeholder,
textarea::placeholder {
opacity: 1; /* 1 */
color: #9ca3af; /* 2 */
}

/*
Set the default cursor for buttons.
*/

button,
[role="button"] {
cursor: pointer;
}

/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}

/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/

img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block; /* 1 */
vertical-align: middle; /* 2 */
}

/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/

img,
video {
max-width: 100%;
height: auto;
}

/* Make elements with the HTML hidden attribute stay hidden by default */
[hidden] {
display: none;
}

*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}

::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.container {
width: 100%;
}
@media (min-width: 640px) {

.container {
max-width: 640px;
}
}
@media (min-width: 768px) {

.container {
max-width: 768px;
}
}
@media (min-width: 1024px) {

.container {
max-width: 1024px;
}
}
@media (min-width: 1280px) {

.container {
max-width: 1280px;
}
}
@media (min-width: 1536px) {

.container {
max-width: 1536px;
}
}
.pointer-events-none {
pointer-events: none;
}
.collapse {
visibility: collapse;
}
.static {
position: static;
}
.fixed {
position: fixed;
}
.absolute {
position: absolute;
}
.relative {
position: relative;
}
.sticky {
position: sticky;
}
.left-0 {
left: 0px;
}
.right-10 {
right: 2.5rem;
}
.top-0 {
top: 0px;
}
.top-10 {
top: 2.5rem;
}
.top-20 {
top: 5rem;
}
.top-16 {
top: 4rem;
}
.top-8 {
top: 2rem;
}
.top-12 {
top: 3rem;
}
.top-11 {
top: 2.75rem;
}
.z-10 {
z-index: 10;
}
.z-20 {
z-index: 20;
}
.z-50 {
z-index: 50;
}
.row-span-2 {
grid-row: span 2 / span 2;
}
.float-right {
float: right;
}
.m-16 {
margin: 4rem;
}
.mb-2 {
margin-bottom: 0.5rem;
}
.mb-3 {
margin-bottom: 0.75rem;
}
.mr-auto {
margin-right: auto;
}
.mt-20 {
margin-top: 5rem;
}
.mt-3 {
margin-top: 0.75rem;
}
.mb-8 {
margin-bottom: 2rem;
}
.block {
display: block;
}
.flex {
display: flex;
}
.table {
display: table;
}
.grid {
display: grid;
}
.h-10 {
height: 2.5rem;
}
.h-40 {
height: 10rem;
}
.h-full {
height: 100%;
}
.h-screen {
height: 100vh;
}
.w-10 {
width: 2.5rem;
}
.w-40 {
width: 10rem;
}
.w-full {
width: 100%;
}
.min-w-\[15rem\] {
min-width: 15rem;
}
.min-w-\[20rem\] {
min-width: 20rem;
}
.min-w-\[10rem\] {
min-width: 10rem;
}
.max-w-\[30rem\] {
max-width: 30rem;
}
.max-w-\[20rem\] {
max-width: 20rem;
}
.rotate-\[15deg\] {
--tw-rotate: 15deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.cursor-pointer {
cursor: pointer;
}
.grid-cols-\[1fr\2c 3fr\] {
grid-template-columns: 1fr 3fr;
}
.items-center {
align-items: center;
}
.justify-center {
justify-content: center;
}
.justify-evenly {
justify-content: space-evenly;
}
.gap-8 {
gap: 2rem;
}
.overflow-y-scroll {
overflow-y: scroll;
}
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.rounded-full {
border-radius: 9999px;
}
.border {
border-width: 1px;
}
.border-\[3px\] {
border-width: 3px;
}
.border-2 {
border-width: 2px;
}
.border-b-\[3px\] {
border-bottom-width: 3px;
}
.border-b-2 {
border-bottom-width: 2px;
}
.border-black {
--tw-border-opacity: 1;
border-color: rgb(0 0 0 / var(--tw-border-opacity));
}
.bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
.bg-black\/20 {
background-color: rgb(0 0 0 / 0.2);
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
.object-contain {
-o-object-fit: contain;
object-fit: contain;
}
.p-2 {
padding: 0.5rem;
}
.p-4 {
padding: 1rem;
}
.p-8 {
padding: 2rem;
}
.py-3 {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
.pt-4 {
padding-top: 1rem;
}
.text-center {
text-align: center;
}
.text-base {
font-size: 1.2rem;
line-height: 1.35;
}
.text-sm {
font-size: 0.95rem;
line-height: 1.35;
}
.text-xs {
font-size: 0.75rem;
line-height: 1rem;
}
.text-red-600 {
--tw-text-opacity: 1;
color: rgb(220 38 38 / var(--tw-text-opacity));
}
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.grayscale {
--tw-grayscale: grayscale(100%);
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

@font-face {
font-family: 'ag';
src: url(ApfelGrotezk-Regular.woff) format("woff");
}

@font-face {
font-family: 'ag-brukt';
src: url(ApfelGrotezk-Brukt.woff) format("woff");
}

@font-face {
font-family: 'ag-fett';
src: url(ApfelGrotezk-Fett.woff) format("woff");
}

body {
font-family: 'ag';
}

strong {
font-family: 'ag-fett';
}

.std-margin {
padding: 0.5rem;
}

.cell-margin {
padding: 1rem;
padding-top: 1rem;
padding-bottom: 2rem;
padding-right: 2rem;
}

.block-margin {
margin-bottom: 2rem;
}

.std-padding {
padding: 0.5rem;
}

.std-grid {
display: grid;
}

@media (min-width: 768px) {

.std-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}

@media (min-width: 1024px) {

.std-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}

.cell {
position: relative;
padding: 1rem;
padding-top: 1rem;
padding-bottom: 2rem;
padding-right: 2rem;
/* background: linear-gradient(to right, white 0%, rgb(252, 206, 255) 15px, white 10%, white 100%); */
}

.cell::before {
content: '';
position: absolute;
top: 10px;
right: 0px;
width: 3px;
height: calc(100% - 20px);
background-color: black;
}

.cell::after {
content: '';
position: absolute;
bottom: 0px;
left: 8px;
width: calc(100% - 20px);
height: 3px;
background-color: black;
}

.meta {
transform: rotate(-3.5deg);
}

h2,h3 {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}

h2 {
font-size: 3rem;
line-height: 1;
}

h3 {
font-family: 'ag-fett';
text-transform: uppercase;
}

.text > h3 {
margin-left: 1.5rem;
margin-top: 2rem;
}

h2 + *,
h3 + * {
margin-left: 1.5rem;
margin-top: 0.25rem;
}

p {
max-width: 55ch;
}

p + p {
margin-left: 1.5rem;
margin-top: 1em;
}

.loading {
opacity: 0;
transition: opacity 200ms ease-in;
}

.htmx-request .loading {
opacity: 1;
display: block;
}

.htmx-request.loading {
opacity: 1;
}

.active {
--tw-bg-opacity: 1;
background-color: rgb(255 255 0 / var(--tw-bg-opacity));
}

details[open]::details-content {
display: contents;
}

.text a {
font-family: 'ag-fett';
}

@media (min-width: 1024px) {

.lg\:flex {
display: flex;
}

.lg\:grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.lg\:grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}


+ 36
- 0
web/app/static/tailwind.config.js Переглянути файл

@@ -0,0 +1,36 @@
module.exports = {
mode: 'jit',
content: [
'../templates/*.html'
],
theme: {
extend: {
fontSize: {
// xs: ['0.95rem', { lineHeight: '1.35' }],
sm: ['0.95rem', { lineHeight: '1.35' }],
base: ['1.2rem', { lineHeight: '1.35' }],
// lg: ['1.125rem', { lineHeight: '1.5' }],
// xl: ['1.25rem', { lineHeight: '1.6' }],
// '2xl': ['1.5rem', { lineHeight: '1.88rem' }],
// '3xl': ['1.875rem', { lineHeight: '2.25rem' }],
'4xl': ['3rem', { lineHeight: '1' }],
// '5xl': ['3rem', { lineHeight: '1.1' }],
// '6xl': ['3.75rem', { lineHeight: '1.04' }],
// '7xl': ['4.5rem', { lineHeight: '1.1' }],
// '8xl': ['6rem', { lineHeight: '1' }],
// '9xl': ['8rem', { lineHeight: '1' }],
},
colors: {
// 'ggreen': {
// light: '#67e8f9',
// DEFAULT: 'var(--primary-color)',
// dark: '#0e7490',
// },
},
}
},
variants: {
extend: {},
},
plugins: [],
}

+ 3
- 1
web/app/templates/about.html Переглянути файл

@@ -2,6 +2,8 @@

{% block content %}

{{ text|safe }}
<div class="std-margin text">
{{ text|safe }}
</div>

{% endblock %}

+ 183
- 70
web/app/templates/base.html Переглянути файл

@@ -12,6 +12,99 @@
# Boostrap select: https://stackoverflow.com/questions/67942546/bootstrap-5-select-dropdown-with-the-multiple-attribute-collapsed
-->

{% macro resource_lead(type, title, leadtext, url, year, thumbnail='', large_title=false) %}
<div class="relative cell ">
<a
class="block cursor-pointer"

href="{{ url }}"
hx-target="#modal-content"
hx-select="main"
hx-swap="innerHTML"

@click="openModal()"
>
{% if large_title %}
<h2 class="">{{ title }}</h2>
{% else %}
<h3 class="">{{ title }}</h3>
{% endif %}
{% if year %}
<div class="">{{ year }}</div>
{% endif %}

{% if type == 'book' and thumbnail %}
<img class="w-40 h-40 object-contain float-right m-16 grayscale rotate-[15deg]" src={{ book['thumbnail'] }} alt="cover for {{ title }}">
{% endif %}

<div class="">
{{ leadtext | truncate(100) }}
</div>
</a>
{% if current_user.is_authenticated %}
<div class="">
{% if resource['type'] == 'tool' %}
<a href="{{ url_for('tool.edit_tool', tool_id=resource['id']) }}">
<span class="absolute top-0 left-0 text-xs">Edit</span>
</a>
{% elif resource['type'] == 'practice' %}
<a href="{{ url_for('practice.edit_practice', practice_id=resource['id']) }}">
<span class="absolute top-0 left-0 text-xs">Edit</span>
</a>
{% elif resource['type'] == 'book' %}
<a href="{{ url_for('book.edit_book', book_id=resource['id']) }}">
<span class="absolute top-0 left-0 text-xs">Edit</span>
</a>
{% endif %}
</div>
{% endif %}
</div>

{% endmacro %}

{% macro resource_small(resource) %}
{% if resource['type'] == 'tool' %}
{{
resource_lead(
resource['type'],
resource['name'],
resource['description'],
url_for('tool.show_tool',
tool_id=resource['id']),
null,
'',
true
)
}}
{% elif resource['type'] == 'practice' %}
{{
resource_lead(
resource['type'],
resource['name'],
resource['description'],
url_for('practice.show_practice',
practice_id=resource['id']),
null
)
}}
{% elif resource['type'] == 'book' %}
{{
resource_lead(
resource['type'],
resource['name'],
resource['author'],
url_for('book.show_book',
book_id=resource['id']),
null,
resource['thumbnail'],
true
)
}}
{% endif %}
{% endmacro %}


<!DOCTYPE html>
<html>

@@ -20,111 +113,131 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://unpkg.com/htmx.org@1.8.6"></script>
<script src="//unpkg.com/alpinejs" defer></script>
<title>ExPub Compendium</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<link href="{{ url_for('static',filename='styles/custom.css') }}" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.14.0-beta2/css/bootstrap-select.min.css" integrity="sha512-mR/b5Y7FRsKqrYZou7uysnOdCIJib/7r5QeJMFvLNHNhtye3xJp1TdJVPLtetkukFn227nKpXD9OjUc09lx97Q==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link href="{{ url_for('static',filename='styles/main.css') }}" rel="stylesheet">
</head>

<body class="d-flex flex-column min-vh-100">

<header>
<!-- Fixed navbar -->
<nav class="navbar navbar-expand-md navbar-light sticky-top">
<a class="navbar-brand" href="{{ url_for('main.index')}}">ExPub Compendium</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a href="{{ url_for('main.about') }}" class="nav-link">
About
</a>
</li>
<li class="nav-item">
<script>
htmx.logAll();
function base() {
return {
menuOpen: false,
modalOpen: false,
home: '/',
init() {
window.addEventListener('popstate', e => {
console.log(document.location);
if (document.location == this.home) {
this.modalOpen = false;
}
})
},
hideOverlay() {
this.modalOpen = false;
window.history.pushState({}, '', this.home);
},
openModal() {
this.$refs.modal.innerHTML = '';
this.modalOpen = true;
}
}
}
</script>
<body
class="text-base overflow-y-scroll"
x-data="base()"
hx-boost="true"
hx-select="#all"
hx-target="#all"
hx-indicator="#loading"

>
<div id="loading" class="loading">
<div class="pointer-events-none fixed top-0 left-0 w-full h-screen z-50 flex justify-center items-center p-4">
<div class="rounded-full bg-black text-white p-4 ">
Loading...
</div>
</div>
</div>
<div id="all">
<header class="sticky top-0 z-10 bg-white std-padding border-b-[3px] border-black">
<nav class="lg:flex gap-8">
<a class="mr-auto" href="{{ url_for('main.index')}}">ExPub Compendium</a>
<a href="{{ url_for('main.about') }}" class="nav-link">
About
</a>
<a href="{{ url_for('tool.get_tools') }}" class="nav-link">
Tools
</a>
</li>
<li class="nav-item">
<a href="{{ url_for('practice.get_practices') }}" class="nav-link">
Practices
</a>
</li>
<li class="nav-item">
<a href="{{ url_for('book.get_books') }}" class="nav-link">
Books
</a>
</li>
{% if current_user.is_authenticated %}
<li class="nav-item">
{% if current_user.is_authenticated %}
<a href="{{ url_for('create.create_resource') }}" class="nav-link">
Add resource
</a>
</li>
{% endif %}
{% if current_user.is_authenticated %}
<li class="nav-item">
{% endif %}
{% if current_user.is_authenticated %}
<a href="{{ url_for('main.profile') }}" class="nav-link">
Profile
</a>
</li>
{% endif %}
{% if not current_user.is_authenticated %}
<li class="nav-item">
{% endif %}
{% if not current_user.is_authenticated %}
<a href="{{ url_for('auth.login') }}" class="nav-link">
Login
</a>
</li>
<li class="nav-item">
<a href="{{ url_for('auth.signup') }}" class="nav-link">
Sign Up
</a>
</li>
{% endif %}
{% if current_user.is_authenticated %}
<li class="nav-item">
{% endif %}
{% if current_user.is_authenticated %}
<a href="{{ url_for('auth.logout') }}" class="nav-link">
Logout
</a>
</li>
{% endif %}
</nav>
</header>
<!-- Begin page content -->
<main>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-danger">
{{ messages[0] }}
</div>
{% endif %}
</ul>
</div>
</nav>
</header>

<!-- Begin page content -->
<main class="flex-shrink-0">
<div class="layer-bg w-100">
<img class="img-fluid w-100" src="{{ url_for('static',filename='images/dots-bg.png') }}" alt="bg-shape">
</div>
<div class="container-fluid">
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-danger">
{{ messages[0] }}
</div>
{% endif %}
{% endwith %}
{% block content %}
{% endblock %}
</div>
</main>
{% endwith %}
{% block content %}
{% endblock %}
</main>
</div>

<div id="modal" x-show="modalOpen" class="modal h-screen w-full fixed top-0 z-20 p-8 bg-black/20">
<div class="cross cursor-pointer absolute top-10 right-10 w-10 h-10" @click="hideOverlay()">
<svg width="100%" height="100%" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 2L18 18M18 2L2 18" stroke="black" stroke-width="1"></path>
</svg>
</div>
<div id="modal-content" @click.outside="hideOverlay()" x-ref="modal" class="content w-full overflow-y-scroll h-full bg-white " style="box-shadow:0 0 4rem rgba(0,0,0,0.3)">

</div>
</div>

<!-- Sticky footer-->
<footer class="footer py-3 mt-auto" style="background-color: #dcddde;">
<footer class="std-margin mt-20 text-sm">
<div class="container">
<span class="text-muted">© 2022–{{ moment().format('YYYY') }} <a href="https://copim.ac.uk/">COPIM</a> and licensed under a <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License (CC BY 4.0)</a>.</span>
<span class="">© 2022–{{ moment().format('YYYY') }} <a href="https://copim.ac.uk/">COPIM</a> and licensed under a <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License (CC BY 4.0)</a>.</span>
</div>
</footer>
<!-- JavaScript -->
<!-- jQuery first, then Popper JS, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.14.0-beta2/js/bootstrap-select.min.js" integrity="sha512-FHZVRMUW9FsXobt+ONiix6Z0tIkxvQfxtCSirkKc5Sb4TKHmqq1dZa8DphF0XqKb3ldLu/wgMa8mT6uXiLlRlw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="{{ url_for('static',filename='js/main.js') }}"></script>
</body>


+ 18
- 61
web/app/templates/book.html Переглянути файл

@@ -2,23 +2,20 @@

{% block content %}

{% if book['thumbnail'] %}
<img class="img-fluid mx-auto d-block py-3" src={{ book['thumbnail'] }} alt="cover for {{ book['Title'] }}">
{% else %}
<div class="row">
<div class="col">
<h1 class="text-center">{% block title %} {{ book['Title'] or resource['name'] }} {% endblock %}</h1>
</div>
</div>
{% endif %}
{% if current_user.is_authenticated %}
<div class="row text-center py-3">
<a href="{{ url_for('book.edit_book', book_id=resource['id']) }}">
<span class="badge bg-dark">Edit</span>
</a>
</div>
{% endif %}
<div class="row">
<div class="cell-margin">
{% if book['thumbnail'] %}
<img class="w-40 h-40 object-contain float-right m-16 grayscale rotate-[15deg]" src={{ book['thumbnail'] }} alt="cover for {{ book['Title'] }}">
{% endif %}
<h2 class="max-w-[30rem]">{% block title %} {{ book['Title'] or resource['name'] }} {% endblock %}</h2>
{% if current_user.is_authenticated %}
<div class="row text-center py-3">
<a href="{{ url_for('book.edit_book', book_id=resource['id']) }}">
<span class="badge bg-dark">Edit</span>
</a>
</div>
{% endif %}
</div>
<div class="row block-margin">
<div class="col">
<table class="table table-hover">
<tbody>
@@ -165,50 +162,10 @@
</div>
</div>
{% if relationships %}
<div class="row">
<div class="col">
<h2 class="text-center">Linked resources:</h2>
</div>
</div>
<div class="row">
{% for relationship in relationships %}
<div class="col-md-4 col-sm-6 py-3">
{% if relationship['type'] == 'tool' %}
<div class="card text-dark bg-tool mb-3">
<div class="card-body">
<a href="{{ url_for('tool.show_tool', tool_id=relationship['id']) }}">
<h3 class="card-title text-center text-dark">{{ relationship['name'] }}</h3>
</a>
<p class="card-text">
{{ relationship['description']|truncate(100) }}
</p>
</div>
</div>
{% elif relationship['type'] == 'practice' %}
<div class="card text-dark bg-practice mb-3">
<div class="card-body">
<a href="{{ url_for('practice.show_practice', practice_id=relationship['id']) }}">
<h3 class="card-title text-center text-dark">{{ relationship['name'] }}</h3>
</a>
<p class="card-text">
{{ relationship['description']|truncate(100) }}
</p>
</div>
</div>
{% elif relationship['type'] == 'book' %}
<div class="card text-dark bg-book mb-3">
<div class="card-body">
<a href="{{ url_for('book.show_book', book_id=relationship['id']) }}">
<h3 class="card-title text-center text-dark">{{ relationship['name'] }}</h3>
</a>
<p class="card-text">
{{ relationship['description']|truncate(100) }}
</p>
</div>
</div>
{% endif %}
</div>
{% endfor %}
<div class="grid lg:grid-cols-3">
{% for relationship in relationships %}
{{ resource_small(relationship)}}
{% endfor %}
</div>
{% endif %}
{% endblock %}

+ 25
- 25
web/app/templates/index.html Переглянути файл

@@ -1,33 +1,33 @@
{% extends "base.html" %}

{% block content %}
<div class="std-grid">

{{ text|safe }}

<hr>
<p>
Browse from this selection of random tools, search or explore tools, practices, and experimental books.
</p>

<div class="row">
{% for tool in tools %}
<div class="col-md-4 col-sm-6 py-3">
<div class="card text-dark bg-info mb-3">
<div class="card-body">
<a href="{{ url_for('tool.show_tool', tool_id=tool['id']) }}">
<h3 class="card-title text-center text-dark">{{ tool['name'] }}</h3>
</a>
<p class="card-text">
{{ tool['description']|truncate(100) }}
</p>
{% if current_user.is_authenticated %}
<a href="{{ url_for('tool.edit_tool', tool_id=tool['id']) }}">
<span class="badge bg-dark">Edit</span>
</a>
{% endif %}
</div>
<div class="std-margin text row-span-2 cell meta">
{{ text|safe }}
</div>
{% for tool in tools %}

{{ resource_small(tool) }}

{% endfor %}

<div class="cell text-red-600">
MISSING :<br>

Clusters of things (book + tool). SHow books and what tools they're made with, and "tagged" with practice and typology
</div>
{% endfor %}
<div class="cell text-red-600">
MISSING :<br>

Lead into Typology with some examples and lead text
</div>
<div class="cell text-red-600">
MISSING :<br>

Lead into Practices with some examples and lead text
</div>

</div>
{% endblock %}

+ 179
- 204
web/app/templates/resource.html Переглянути файл

@@ -1,213 +1,188 @@
{% extends 'base.html' %}

{% block content %}
<div class="cell-margin">
<div class="cell-margin">
<h2 class="block-margin">
{% block title %}
{% autoescape false %}
{{ resource['name'] | replace(" ","<br>") }}
{% endautoescape %}
{% endblock %}
</h2>
{% if current_user.is_authenticated %}
{% if resource['type'] == 'tool' %}
<div class="row text-center py-3">
<a href="{{ url_for('tool.edit_tool', tool_id=resource['id']) }}">
<span class="">Edit</span>
</a>
</div>
{% elif resource['type'] == 'practice' %}
<div class="row text-center py-3">
<a href="{{ url_for('practice.edit_practice', practice_id=resource['id']) }}">
<span class="">Edit</span>
</a>
</div>
{% endif %}
{% endif %}
<table class="table table-hover">
<tbody>
<tr>
<th>
Created:
</th>
<td>
{{ resource['created'].strftime("%Y-%m-%d %H:%M") }} UTC
</td>
</tr>
{% if resource['description'] %}
<tr>
<th>
Description:
</th>
<td>
{{ resource['description'] }}
</td>
</tr>
{% endif %}
<!-- fields for tools -->
{% if resource['developer'] %}
<tr>
<th>
Developer
</th>
<td>
{% if resource['developerUrl'] %}
<a href="{{ resource['developerUrl'] }}">{{ resource['developer'] }}</a>
{% else %}
{{ resource['developer'] }}
{% endif %}
</td>
</tr>
{% endif %}
{% if resource['license'] %}
<tr>
<th>
Software license:
</th>
<td>
{{ resource['license'] }}
</td>
</tr>
{% endif %}
{% if resource['scriptingLanguage'] %}
<tr>
<th>
Software language(s):
</th>
<td>
{{ resource['scriptingLanguage'] }}
</td>
</tr>
{% endif %}
{% if resource['projectUrl'] %}
<tr>
<th>
Project page:
</th>
<td>
<a href="{{ resource['projectUrl'] }}">{{ resource['projectUrl'] }}</a>
</td>
</tr>
{% endif %}
{% if resource['repositoryUrl'] %}
<tr>
<th>
Code repository:
</th>
<td>
<a href="{{ resource['repositoryUrl'] }}">{{ resource['repositoryUrl'] }}</a>
</td>
</tr>
{% endif %}
{% if resource['ingestFormats'] %}
<tr>
<th>
Import / ingest formats:
</th>
<td>
{{ resource['ingestFormats'] }}
</td>
</tr>
{% endif %}
{% if resource['outputFormats'] %}
<tr>
<th>
Output formats:
</th>
<td>
{{ resource['outputFormats'] }}
</td>
</tr>
{% endif %}
{% if resource['status'] %}
<tr>
<th>
Platform status:
</th>
<td>
{{ resource['status'] }}
</td>
</tr>
{% endif %}
<!-- fields for practices -->
{% if resource['longDescription'] %}
<tr>
<th>
Full description
</th>
<td>
{{ resource['longDescription']|safe }}
</td>
</tr>
{% endif %}
{% if resource['experimental'] %}
<tr>
<th>
Experimental uses
</th>
<td>
{{ resource['experimental']|safe }}
</td>
</tr>
{% endif %}
{% if resource['considerations'] %}
<tr>
<th>
Considerations
</th>
<td>
<p style="white-space: pre-line">{{ resource['considerations']|safe }}</p>
</td>
</tr>
{% endif %}
{% if resource['references'] %}
<tr>
<th>
References:
</th>
<td>
<p style="white-space: pre-line">{{ resource['references']|safe }}</p>
</td>
</tr>
{% endif %}
</tbody>
</table>

<div class="row">
<div class="col">
<h1 class="text-center">{% block title %} {{ resource['name'] }} {% endblock %}</h1>
</div>
</div>
{% if current_user.is_authenticated %}
{% if resource['type'] == 'tool' %}
<div class="row text-center py-3">
<a href="{{ url_for('tool.edit_tool', tool_id=resource['id']) }}">
<span class="badge bg-dark">Edit</span>
</a>
</div>
{% elif resource['type'] == 'practice' %}
<div class="row text-center py-3">
<a href="{{ url_for('practice.edit_practice', practice_id=resource['id']) }}">
<span class="badge bg-dark">Edit</span>
</a>
</div>
{% endif %}
{% endif %}
<div class="row">
<div class="col">
<table class="table table-hover">
<tbody>
<tr>
<th>
Created:
</th>
<td>
{{ resource['created'].strftime("%Y-%m-%d %H:%M") }} UTC
</td>
</tr>
{% if resource['description'] %}
<tr>
<th>
Description:
</th>
<td>
{{ resource['description'] }}
</td>
</tr>
{% endif %}
<!-- fields for tools -->
{% if resource['developer'] %}
<tr>
<th>
Developer
</th>
<td>
{% if resource['developerUrl'] %}
<a href="{{ resource['developerUrl'] }}">{{ resource['developer'] }}</a>
{% else %}
{{ resource['developer'] }}
{% endif %}
</td>
</tr>
{% endif %}
{% if resource['license'] %}
<tr>
<th>
Software license:
</th>
<td>
{{ resource['license'] }}
</td>
</tr>
{% endif %}
{% if resource['scriptingLanguage'] %}
<tr>
<th>
Software language(s):
</th>
<td>
{{ resource['scriptingLanguage'] }}
</td>
</tr>
{% endif %}
{% if resource['projectUrl'] %}
<tr>
<th>
Project page:
</th>
<td>
<a href="{{ resource['projectUrl'] }}">{{ resource['projectUrl'] }}</a>
</td>
</tr>
{% endif %}
{% if resource['repositoryUrl'] %}
<tr>
<th>
Code repository:
</th>
<td>
<a href="{{ resource['repositoryUrl'] }}">{{ resource['repositoryUrl'] }}</a>
</td>
</tr>
{% endif %}
{% if resource['ingestFormats'] %}
<tr>
<th>
Import / ingest formats:
</th>
<td>
{{ resource['ingestFormats'] }}
</td>
</tr>
{% endif %}
{% if resource['outputFormats'] %}
<tr>
<th>
Output formats:
</th>
<td>
{{ resource['outputFormats'] }}
</td>
</tr>
{% endif %}
{% if resource['status'] %}
<tr>
<th>
Platform status:
</th>
<td>
{{ resource['status'] }}
</td>
</tr>
{% endif %}
<!-- fields for practices -->
{% if resource['longDescription'] %}
<tr>
<th>
Full description
</th>
<td>
{{ resource['longDescription']|safe }}
</td>
</tr>
{% endif %}
{% if resource['experimental'] %}
<tr>
<th>
Experimental uses
</th>
<td>
{{ resource['experimental']|safe }}
</td>
</tr>
{% endif %}
{% if resource['considerations'] %}
<tr>
<th>
Considerations
</th>
<td>
<p style="white-space: pre-line">{{ resource['considerations']|safe }}</p>
</td>
</tr>
{% endif %}
{% if resource['references'] %}
<tr>
<th>
References:
</th>
<td>
<p style="white-space: pre-line">{{ resource['references']|safe }}</p>
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
</div>
</div>
{% if relationships %}
<div class="row">
<div class="col">
<h2 class="text-center">Linked resources:</h2>
</div>
</div>
<div class="row">
{% for relationship in relationships %}
<div class="col-md-4 col-sm-6 py-3">
{% if relationship['type'] == 'tool' %}
<div class="card text-dark bg-tool mb-3">
<div class="card-body">
<a href="{{ url_for('tool.show_tool', tool_id=relationship['id']) }}">
<h3 class="card-title text-center text-dark">{{ relationship['name'] }}</h3>
</a>
<p class="card-text">
{{ relationship['description']|truncate(100) }}
</p>
</div>
</div>
{% elif relationship['type'] == 'practice' %}
<div class="card text-dark bg-practice mb-3">
<div class="card-body">
<a href="{{ url_for('practice.show_practice', practice_id=relationship['id']) }}">
<h3 class="card-title text-center text-dark">{{ relationship['name'] }}</h3>
</a>
<p class="card-text">
{{ relationship['description']|truncate(100) }}
</p>
</div>
</div>
{% endif %}
</div>
{% endfor %}
<div class="grid lg:grid-cols-3">
{% for relationship in relationships %}
{{ resource_small(relationship) }}
{% endfor %}
</div>
{% endif %}
{% endblock %}

+ 87
- 199
web/app/templates/resources.html Переглянути файл

@@ -2,209 +2,97 @@

{% block content %}

<div class="row">
<div class="col-12 text-center">
<h1>{% block title %}
{{ type|capitalize + 's' }}
{% endblock %}
</h1>
<div class="cell-margin">
<div class="mb-8">
<h2>
{% block title %}
{% autoescape false %}
{{ type + 's' | replace(" ","<br>") }}
{% endautoescape %}
{% endblock %}
</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget viverra magna. Nam in ante ultricies
purus feugiat vestibulum et ac erat. Donec in sagittis ante. Maecenas non mauris et eros commodo fringilla.
Integer accumsan ullamcorper diam, non rhoncus tellus molestie ut. Maecenas finibus pretium dolor ac sagittis.
</p>
</div>
</div>
<div class="">
<div class="search sticky top-11 z-10 border-b-2 border-black">
<div class="sticky top-20 flex p-2 pt-4 gap-8 bg-white ">
<input class="border-2 border-black p-2 mb-2" type="text" placeholder="filter by search...">
{% if practices_filter %}
<details class="min-w-[10rem]">
<summary>Practices</summary>
<div class="">
{% for practice in practices_filter %}
<div {% if request.args.get('practice')==practice[0]|string %} class="active" {% endif %}>
<a href="/{{type + 's'}}?practice={{practice[0]}}">{{ practice[1] }}</a>
</div>
{% endfor %}
</div>
</div>
<div class="row">
<div class="col-12 text-center">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget viverra magna. Nam in ante ultricies purus feugiat vestibulum et ac erat. Donec in sagittis ante. Maecenas non mauris et eros commodo fringilla. Integer accumsan ullamcorper diam, non rhoncus tellus molestie ut. Maecenas finibus pretium dolor ac sagittis.
</p>
</details>
{% endif %}
{% if year_filter %}
<details class="min-w-[10rem]">
<summary>Year</summary>
<div id="filter-year" class="collapse filter-items">
{% for year in year_filter %}
<li {% if request.args.get('year')==year %} class="active" {% endif %}>
<a href="/books?year={{year}}">{{ year }}</a>
</li>
{% endfor %}
</div>
</div>
<div class="row">
<div class="col-md-4 col-lg-3 py-3">
<div class="search-filter-sidebar">
<input class="form-control" id="searchResources" type="text" placeholder="filter by search...">
<div class="row">
{% if practices_filter %}
<div class="col-sm-6 d-md-block d-sm-none d-none">
<div class="filter-title">Practices</div>
<ul class="filter-items">
{% for practice in practices_filter %}
<li {% if request.args.get('practice') == practice[0]|string %} class="fw-bold"{% endif %}>
<a href="/{{type + 's'}}?practice={{practice[0]}}">{{ practice[1] }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="d-md-none accordion">
<div class="accordion-item">
<div class="filter-title accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#filter-practice">Practices</div>
<div class="accordion-body">
<ul id="filter-practice" class="collapse filter-items">
{% for practice in practices_filter %}
<li {% if request.args.get('practice') == practice[0]|string %} class="fw-bold"{% endif %}>
<a href="/{{type + 's'}}?practice={{practice[0]}}">{{ practice[1] }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
{% if year_filter %}
<div class="col-sm-6 d-md-block d-sm-none d-none">
<div class="filter-title">Year</div>
<ul class="filter-items">
{% for year in year_filter %}
<li {% if request.args.get('year') == year %} class="fw-bold"{% endif %}>
<a href="/books?year={{year}}">{{ year }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="d-md-none accordion">
<div class="accordion-item">
<div class="filter-title accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#filter-year">Year</div>
<div class="accordion-body">
<ul id="filter-year" class="collapse filter-items">
{% for year in year_filter %}
<li {% if request.args.get('year') == year %} class="fw-bold"{% endif %}>
<a href="/books?year={{year}}">{{ year }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
</details>
{% endif %}
{% if typology_filter %}
<details class="min-w-[10rem]">
<summary class="">Typology category</summary>
<div class="">
{% for typology in typology_filter %}
<div {% if request.args.get('typology')==typology %} class="active" {% endif %}>
<a href="/books?typology={{typology}}">{{ typology }}</a>
</div>
<div class="row">
{% if typology_filter %}
<div class="col-sm-6 d-md-block d-sm-none d-none">
<div class="filter-title">Typology category</div>
<ul class="filter-items">
{% for typology in typology_filter %}
<li {% if request.args.get('typology') == typology %} class="fw-bold"{% endif %}>
<a href="/books?typology={{typology}}">{{ typology }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="d-md-none accordion">
<div class="accordion-item">
<div class="filter-title accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#filter-typology">Typology category</div>
<div class="accordion-body">
<ul id="filter-typology" class="collapse filter-items">
{% for typology in typology_filter %}
<li {% if request.args.get('typology') == typology %} class="fw-bold"{% endif %}>
<a href="/books?typology={{typology}}">{{ typology }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
{% if languages_filter %}
<div class="col-sm-6 d-md-block d-sm-none d-none">
<div class="filter-title">Scripting languages</div>
<ul class="filter-items">
{% for language in languages_filter %}
<li {% if request.args.get('scriptingLanguage') == language %} class="fw-bold"{% endif %}>
<a href="/tools?scriptingLanguage={{language}}">{{ language }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="d-md-none accordion">
<div class="accordion-item">
<div class="filter-title accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#filter-language">Scripting language</div>
<div class="accordion-body">
<ul id="filter-language" class="collapse filter-items">
{% for language in languages_filter %}
<li {% if request.args.get('scriptingLanguage') == language %} class="fw-bold"{% endif %}>
<a href="/tools?scriptingLanguage={{language}}">{{ language }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
{% if licenses_filter %}
<div class="col-sm-6 d-md-block d-sm-none d-none">
<div class="filter-title">License</div>
<ul class="filter-items">
{% for license in licenses_filter %}
<li {% if request.args.get('license') == license %} class="fw-bold"{% endif %}>
<a href="/tools?license={{license}}">{{ license }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="d-md-none accordion">
<div class="accordion-item">
<div class="filter-title accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#filter-license">License</div>
<div class="accordion-body">
<ul id="filter-license" class="collapse filter-items">
{% for license in licenses_filter %}
<li {% if request.args.get('license') == license %} class="fw-bold"{% endif %}>
<a href="/tools?license={{license}}">{{ license }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-8 col-lg-9">
<div id="resource-boxes" class="row">
{% for resource in resources %}
<div id="resource" class="col-md-4 col-sm-6 py-3">
<div class="card text-dark bg-{{type}} mb-3">
<div class="card-body">
{% if resource['type'] == 'tool' %}
<a href="{{ url_for('tool.show_tool', tool_id=resource['id']) }}">
<h3 class="card-title text-center text-dark">{{ resource['name'] }}</h3>
</a>
<p class="card-text">
{{ resource['description']|truncate(100) }}
</p>
{% elif resource['type'] == 'practice' %}
<a href="{{ url_for('practice.show_practice', practice_id=resource['id']) }}">
<h3 class="card-title text-center text-dark">{{ resource['name'] }}</h3>
</a>
<p class="card-text">
{{ resource['description']|truncate(100) }}
</p>
{% elif resource['type'] == 'book' %}
<a href="{{ url_for('book.show_book', book_id=resource['id']) }}">
<h3 class="card-title text-center text-dark">{{ resource['name'] }}</h3>
</a>
<p class="card-text text-center">
{{ resource['author']|truncate(100) }}
</p>
{% endif %}
{% if current_user.is_authenticated %}
{% if resource['type'] == 'tool' %}
<a href="{{ url_for('tool.edit_tool', tool_id=resource['id']) }}">
<span class="badge bg-dark">Edit</span>
</a>
{% elif resource['type'] == 'practice' %}
<a href="{{ url_for('practice.edit_practice', practice_id=resource['id']) }}">
<span class="badge bg-dark">Edit</span>
</a>
{% elif resource['type'] == 'book' %}
<a href="{{ url_for('book.edit_book', book_id=resource['id']) }}">
<span class="badge bg-dark">Edit</span>
</a>
{% endif %}
{% endif %}
</div>
{% endfor %}
</div>
</details>
{% endif %}
{% if languages_filter %}
<details class="min-w-[10rem]">
<summary>Scripting languages</summary>
<div class="">
{% for language in languages_filter %}
<div {% if request.args.get('scriptingLanguage')==language %} class="active" {% endif %}>
<a href="/tools?scriptingLanguage={{language}}">{{ language }}</a>
</div>
{% endfor %}
</div>
{% endfor %}
</details>
{% endif %}
{% if licenses_filter %}
<details class="min-w-[10rem]">
<summary>License</summary>
<div class="">
{% for license in licenses_filter %}
<div {% if request.args.get('license')==license %} class="active" {% endif %}>
<a href="/tools?license={{license}}">{{ license }}</a>
</div>
{% endfor %}
</div>
</div>
</details>
{% endif %}
</div>
{% endblock %}
</div>


<div class="col-md-8 col-lg-9">
<div class="grid lg:grid-cols-3">
{% for resource in resources %}
{{ resource_small(resource) }}
{% endfor %}
</div>
</div>
</div>

{% endblock %}

+ 2
- 12
web/content/home.md Переглянути файл

@@ -1,15 +1,5 @@
# ExPub Compendium
## ExPub Compendium

The Experimental Publishing Compendium is for authors, designers, publishers, institutions and technologist who challenge, push and redefine the shape, form and rationale of scholarly works. The compendium offers a catalogues of tools, practices, and books to inspire experimental scholarly works.

## How to use the compendium

The compendium catalogues potential ingredients for the making of experimental publications.

- Under [Tools](/tools) you’ll find mostly software that supports experimental publication from collective writing to the annotation and remix of published texts.
- [Practices](/practices) provide inspiration for experimental book making.
- [Books](/books) provides examples of experimental books and those who publish them.

Each item is cross linked so that a practice will take you to relevant tools or examples and vice versa.

The selection is tentative, reflecting the knowledge and biases of the contributors of current and previous versions. If you want to submit or edit anything in the catalogue please do so by doing XXthisXXX.
[Read more](/about)

Завантаження…
Відмінити
Зберегти