Compare commits

...

17 Commits

Author SHA1 Message Date
57c9be1c0b fix: various templates
convert to assets
2025-04-27 23:50:07 -04:00
a34c0deee5 fix: reference-editor template
fix bug
2025-04-27 23:48:36 -04:00
57cbb44b91 rem: sidebar template
remove delete note link
2025-04-27 23:45:16 -04:00
238b3a89d7 ref: profile template
convert to asset code
2025-04-27 23:44:48 -04:00
3fc5ab0ba2 ref: home template
Add js module code
fix label
2025-04-27 23:40:53 -04:00
34435f885c fix: defaultcontroller
comment out onload for home
2025-04-27 23:11:51 -04:00
6369f5c7b9 fix: ajax
Bug fix, add flush for reference data
2025-04-27 23:07:03 -04:00
9aa49c9c2c fix: index.php 2025-04-27 23:04:10 -04:00
3f6d32b995 upd: *.js
Refactor methods to other scripts
2025-04-27 22:58:03 -04:00
eb2366ebd8 upd: register.js
Fix error in csrfToken element
2025-04-27 22:54:12 -04:00
13bcafcebf upd: app.js
add jquery
2025-04-27 22:53:32 -04:00
9e85edbb25 upd: main.css
reduce font-size for h1 tag items
2025-04-27 22:49:20 -04:00
879eeb10bf upd: README
Update for v1.1 to add warning about breaking change
2025-04-27 22:48:29 -04:00
b1f207b9be upd: install.sh
Do a check for .env before install and remove
2025-04-27 22:45:59 -04:00
0e1160d292 upd: importmap
add jquery, jquery-ui, datatables
2025-04-27 21:08:30 -04:00
d409c83f13 upd: Dockerfile
Update to php 8.4
add symfony asset compile
Set permissions and ownership of /data directory
2025-04-27 21:01:46 -04:00
95f17a2f3b upd: docker-compose
remove version tag
change data volume
add .env file
add restart
2025-04-27 20:55:34 -04:00
23 changed files with 341 additions and 291 deletions

View File

@ -1,4 +1,4 @@
FROM php:8.3-apache
FROM php:8.4-apache
RUN apt update && \
apt upgrade -y && \
@ -19,7 +19,6 @@ RUN docker-php-ext-configure gd --with-jpeg
RUN docker-php-ext-configure zip
RUN docker-php-ext-install \
#pdo_sqlite \
zip \
mbstring \
exif \
@ -46,12 +45,13 @@ RUN rm -rf /var/www/html/translations
RUN COMPOSER_ALLOW_SUPERUSER=1 composer install --no-scripts --no-dev --optimize-autoloader
RUN mkdir /data
RUN chown -R 33:33 /data
RUN chmod -R 755 /data
COPY data/data.db /data/data.db
RUN mkdir /var/www/html/var/cache
RUN mkdir /var/www/html/var/log
RUN symfony console asset-map:compile
RUN chown -R 33:33 /var/www/html
RUN chmod -R 755 /var/www/html
RUN chown -R 33:33 /var/www/html /data
RUN chmod -R 755 /var/www/html /data
EXPOSE 80

View File

@ -2,11 +2,26 @@
A program to take notes during a sermon. The web app was built with PHP and Symfony.
## ATTN: !!!!BREAKING CHANGE!!!! v1.0 -> v1.1
This was my first publicly available docker container so I did not realize what some decisions would do. If you are upgrading from v1 you first need to save your database OR you will lose all your current notes!! Follow the steps below to do that
1. You need to make sure that you have a running SSH server on your host computer
2. On your host computer, `docker exec -it sermon-notes bash`
3. `cd var/`
4. `scp data.db {user}@{host computer IP}:{path}`
5. Authenticate with the password
6. This will copy the file over SFTP to the host computer
7. After this then you run the `docker run...` command in Step 1 of the `Installation` instructions below, once the container is running you need to copy the `data.db` file into the working directory of the docker container.
- For example, if you have `~/docker/sermon-notes` as the path for the container on the host computer, you'll copy the `data.db` to `~/docker/sermon-notes/data`
## Installation
1. Run `docker run -d --name sermon-notes -p 80:80 ryanprather/sermon-notes:latest`, this will download and start the container and keep it running in the background. If you already have something on port 80 change the first `80` to whatever open port you'd like.
2. Run `docker exec -it sermon-notes bash install.sh` This will run an install script to create an .env file specific to your install, populate with the beginning factors, and then run a `composer` command to download the necessary package dependancies.
3. Once complete you have a running system that you can navigate to in your browser with `http://{ip}:{port}|{hostname}:{port}`. Then you just need to register for an account. The first account that is created is made an admin so that you can access the `Reference Editor` and update any reference material if necessary.
1. Make a directory in your desired docker storage folder (e.g. `~/docker/sermon-notes`), then `cd` into it.
2. Create a file called `.env` in that folder, no need to add anything to it right now.
3. Run `docker run -d --name sermon-notes -p 80:80 -v $PWD/data:/data -v $PWD/.env:/var/www/html/.env ryanprather/sermon-notes:latest`, this will download and start the container and keep it running in the background. If you already have something on port 80 change the first `80` to whatever open port you'd like.
4. Run `docker exec -it sermon-notes bash install.sh` This will run an install script to create an .env file specific to your install, populate with the beginning factors, and then run a `composer` command to download the necessary package dependancies.
5. Once complete you have a running system that you can navigate to in your browser with `http://{ip}:{port}`|`http://{hostname}:{port}`. Then you just need to register for an account. The first account that is created is made an admin so that you can access the `Reference Editor` and update any reference material if necessary.
## Operation

View File

@ -6,5 +6,6 @@ import './bootstrap.js';
* which should already be in your base.html.twig.
*/
import './styles/app.css';
const $ = require('jquery');
console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');
// console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');

View File

@ -307,7 +307,7 @@ h6 a {
}
h1 {
font-size: 4em;
font-size: 2em;
margin: 0 0 0.5em 0;
line-height: 1.3;
}

85
assets/js/reference.js Normal file
View File

@ -0,0 +1,85 @@
/**
* Retrieves the reference type from the server and populates the reference series dropdown.
*
* @param {HTMLElement} el - The element that triggered the function.
* @return {Promise} A promise that resolves with the response from the server.
*/
export function retrieveReferenceType(el) {
fetch('/reference/' + el.value, {
method: 'GET',
header: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(results => {
document.querySelector('#referenceSeries').innerHTML = '';
var none = document.createElement('option');
none.value = '';
none.text = '-- Select --';
document.querySelector('#referenceSeries').appendChild(none);
for (var x in results) {
var newSeries = document.createElement('option');
newSeries.value = results[x].id;
newSeries.text = results[x].label;
document.querySelector('#referenceSeries').appendChild(newSeries);
}
});
}
/**
* Retrieves a reference based on the provided element value.
*
* @param {Element} el - The element triggering the reference retrieval
* @return {void} No return value
*/
export function retrieveReference(el) {
if (el.value == 'new') {
document.querySelector('#refName').style.display = 'inline-block';
return;
}
fetch('/get-reference', {
method: "POST",
header: {
"Content-Type": "application/json"
},
body: JSON.stringify({
id: el.value
})
})
.then(response => response.json())
.then(results => {
document.querySelector('#reference').value = results.text;
});
}
/**
* Saves a reference by sending a POST request to the server with the selected type,
* file, and text values. Displays an alert with the response message, and clears
* the reference and file input fields.
*
* @return {Promise} A Promise that resolves with the response message from the server.
*/
export function saveReference() {
let ref = document.querySelector('#referenceSeries');
let cont = document.querySelector('#reference');
fetch('/save-reference', {
method: 'POST',
header: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
refId: ref.value,
text: cont.value
})
})
.then(response => response.json())
.then(results => {
//alert(results.msg);
document.querySelector('#reference').value = '';
document.querySelector('#referenceType').value = '';
document.querySelector('#referenceSeries').value = '';
});
}

View File

@ -3,7 +3,7 @@ const nameInput = document.getElementById("name");
const emailInput = document.getElementById("emailAddress");
const passwordInput = document.getElementById("password");
const confirmPasswordInput = document.getElementById("confirmPassword");
const csrfToken = document.getElementById("csrfToken").value;
const csrfToken = document.getElementById("registration_form__token").value;
// Add event listeners to the form
const registerBtn = document.querySelector("#register-btn");

View File

@ -8,122 +8,6 @@ var to = null;
let controller;
var BOOKS = {};
$(function () {
setHeight();
setBooks();
setEventListeners();
$('#note-table').DataTable({
paging: false,
ajax: {
url: '/get-notes',
type: 'POST'
},
columns: [
{ data: 'link' },
{ data: 'speaker.name' },
{ data: 'passage' },
{
data: 'date.date',
render: DataTable.render.date("L")
},
]
});
$('#shareBtn').on('click', openShareNote);
$('#modal-backdrop').on('click', closeShareNote);
});
/**
* Fetches data from '/js/data.json', assigns it to BOOKS, and handles errors.
*
* @return {void}
*/
function setBooks() {
fetch('js/data.json')
.then((res) => {
if (!res.ok) {
throw new Error('HTTP Error: Status: ${res.status}');
}
return res.json();
})
.then((data) => {
BOOKS = data;
})
.catch((error) => {
console.log(error);
})
}
/**
* Sets event listeners for keyup events on the document and the '#notes' element.
*
* @return {void}
*/
function setEventListeners() {
document.addEventListener('keyup', function (event) {
if (event.key == "F3") {
openRef(false);
}
});
document.querySelector('#notes').addEventListener('keyup', function (event) {
let key = event.keyCode;
if (key >= 48 && key <= 90 || key >= 96 && key <= 111 || key >= 186 && key <= 222) {
textDirty = true;
document.querySelector('#note-header-left h2').classList.add('dirty');
}
});
}
/**
* Sets the height of various elements on the page based on the window's inner height.
* Also initializes a datepicker and event listener for the search input field.
*
* @return {void}
*/
function setHeight() {
md = new markdownit({
html: true,
linkify: true,
breaks: true
});
body = document.querySelector('body');
body.style.height = window.innerHeight + 'px';
cont = document.querySelector('#main');
cont.style.height = (window.innerHeight) + 'px';
tabs = document.querySelector('.ref-tab');
tabs.style.height = (window.innerHeight - 13) + 'px';
ref = document.querySelector('.ref');
ref.style.height = (window.innerHeight - 60) + 'px';
noteList = document.querySelector('#note-list');
noteList.style.height = (window.innerHeight - 60) + 'px';
notes = document.querySelector('.notes');
notes.style.height = (window.innerHeight - 60) + 'px';
notePreview = document.querySelector('#notePreview');
notePreview.style.height = (window.innerHeight - 50) + 'px';
if ($('#noteDate')) {
$('#noteDate').datepicker();
}
if ($('#query')) {
document.querySelector('#query').addEventListener('keyup', function (event) {
if (event.key == "Enter") {
search();
}
});
}
if (!to) {
to = setTimeout(saveNote, saveInterval);
}
}
/**
* Searches for notes based on the query entered in the search field.
@ -619,56 +503,6 @@ function removeActiveRef() {
}
}
/**
* Retrieves a template from the server and sets it as the value of a specified destination element.
*
* @param {string} orig - The ID of the element containing the original template value.
* @param {string} dest - The ID of the destination element where the retrieved template will be set.
* @return {Promise} A Promise that resolves when the template is successfully retrieved and set as the value of the destination element.
*/
function retrieveTemplate(orig, dest) {
const temp = document.querySelector('#' + orig);
if (temp.value == '0') {
document.querySelector('#' + dest).value = '';
return;
}
fetch('/retrieve-template', {
method: 'POST',
headers: {
'Content-Type': 'plain/text'
},
body: JSON.stringify({
'template': temp.value
})
})
.then(response => response.text())
.then(results => {
const div = document.querySelector('#' + dest);
div.value = results;
});
}
/**
* Saves the template by sending a POST request to the server with template data.
*/
function saveTemplate() {
fetch('/save-template', {
method: 'POST',
headers: {
'Content-Type': 'plain/text'
},
body: JSON.stringify({
'template_id': document.querySelector('#template_id').value,
'template_name': document.querySelector('#template_name').value,
'template_value': document.querySelector('#template_value').value,
})
})
.then(response => response.text())
.then(results => {
alert(results);
});
}
/**
* Toggles the visibility of the fields container and updates the active state of the show/hide button.
*
@ -843,93 +677,6 @@ function filterVerse() {
verseRange.innerText = 'Verse: ' + verse;
}
/**
* Retrieves the reference type from the server and populates the reference series dropdown.
*
* @param {HTMLElement} el - The element that triggered the function.
* @return {Promise} A promise that resolves with the response from the server.
*/
function retrieveReferenceType(el) {
fetch('/reference/' + el.value, {
method: 'GET',
header: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(results => {
document.querySelector('#referenceSeries').innerHTML = '';
var none = document.createElement('option');
none.value = '';
none.text = '-- Select --';
document.querySelector('#referenceSeries').appendChild(none);
for (var x in results) {
var newSeries = document.createElement('option');
newSeries.value = results[x].id;
newSeries.text = results[x].label;
document.querySelector('#referenceSeries').appendChild(newSeries);
}
})
}
/**
* Retrieves a reference based on the provided element value.
*
* @param {Element} el - The element triggering the reference retrieval
* @return {void} No return value
*/
function retrieveReference(el) {
if (el.value == 'new') {
document.querySelector('#refName').style.display = 'inline-block';
return;
}
fetch('/get-reference', {
method: "POST",
header: {
"Content-Type": "application/json"
},
body: JSON.stringify({
id: el.value
})
})
.then(response => response.json())
.then(results => {
document.querySelector('#reference').value = results.text;
});
}
/**
* Saves a reference by sending a POST request to the server with the selected type,
* file, and text values. Displays an alert with the response message, and clears
* the reference and file input fields.
*
* @return {Promise} A Promise that resolves with the response message from the server.
*/
function saveReference() {
let ref = document.querySelector('#referenceSeries');
let cont = document.querySelector('#reference');
fetch('/save-reference', {
method: 'POST',
header: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
refId: ref.value,
text: cont.value
})
})
.then(response => response.json())
.then(results => {
alert(results.msg);
document.querySelector('#reference').value = '';
document.querySelector('#references').value = '';
document.querySelector('#referenceType').value = '';
document.querySelector('#referenceSeries').value = '';
});
}
/**
* Previews a note by rendering the markdown content of the note in a preview section.
* Toggles between the note text and preview sections.
@ -1236,6 +983,8 @@ function shareNote(event) {
function increaseFont() {
var currentSize = document.querySelector('#ref').style.fontSize;
document.querySelector('#ref').style.fontSize = (parseInt(currentSize) + 1) + 'pt';
document.querySelector('#notes').style.fontSize = (parseInt(currentSize) + 1) + 'pt';
document.querySelector('#notePreview').style.fontSize = (parseInt(currentSize) + 1) + 'pt';
}
/**
@ -1246,6 +995,8 @@ function increaseFont() {
function decreaseFont() {
var currentSize = document.querySelector('#ref').style.fontSize;
document.querySelector('#ref').style.fontSize = (parseInt(currentSize) - 1) + 'pt';
document.querySelector('#notes').style.fontSize = (parseInt(currentSize) - 1) + 'pt';
document.querySelector('#notePreview').style.fontSize = (parseInt(currentSize) - 1) + 'pt';
}
/**

116
assets/js/site.js Normal file
View File

@ -0,0 +1,116 @@
export function initHome() {
setHeight();
setBooks();
setEventListeners();
$('#note-table').DataTable({
paging: false,
ajax: {
url: '/get-notes',
type: 'POST'
},
columns: [
{ data: 'link' },
{ data: 'speaker.name' },
{ data: 'passage' },
{
data: 'date.date',
render: DataTable.render.date("L")
},
]
});
$('#shareBtn').on('click', openShareNote);
$('#modal-backdrop').on('click', closeShareNote);
}
/**
* Fetches data from '/js/data.json', assigns it to BOOKS, and handles errors.
*
* @return {void}
*/
export function setBooks() {
fetch('js/data.json')
.then((res) => {
if (!res.ok) {
throw new Error('HTTP Error: Status: ${res.status}');
}
return res.json();
})
.then((data) => {
BOOKS = data;
})
.catch((error) => {
console.log(error);
})
}
/**
* Sets event listeners for keyup events on the document and the '#notes' element.
*
* @return {void}
*/
export function setEventListeners() {
document.addEventListener('keyup', function (event) {
if (event.key == "F3") {
openRef(false);
}
});
document.querySelector('#notes').addEventListener('keyup', function (event) {
let key = event.keyCode;
if (key >= 48 && key <= 90 || key >= 96 && key <= 111 || key >= 186 && key <= 222) {
textDirty = true;
document.querySelector('#note-header-left h2').classList.add('dirty');
}
});
}
/**
* Sets the height of various elements on the page based on the window's inner height.
* Also initializes a datepicker and event listener for the search input field.
*
* @return {void}
*/
export function setHeight() {
md = new markdownit({
html: true,
linkify: true,
breaks: true
});
var body = document.querySelector('body');
body.style.height = window.innerHeight + 'px';
var cont = document.querySelector('#main');
cont.style.height = (window.innerHeight) + 'px';
var tabs = document.querySelector('.ref-tab');
tabs.style.height = (window.innerHeight - 13) + 'px';
var ref = document.querySelector('.ref');
ref.style.height = (window.innerHeight - 60) + 'px';
var noteList = document.querySelector('#note-list');
noteList.style.height = (window.innerHeight - 60) + 'px';
var notes = document.querySelector('.notes');
notes.style.height = (window.innerHeight - 60) + 'px';
var notePreview = document.querySelector('#notePreview');
notePreview.style.height = (window.innerHeight - 50) + 'px';
if ($('#noteDate')) {
$('#noteDate').datepicker();
}
if ($('#query')) {
document.querySelector('#query').addEventListener('keyup', function (event) {
if (event.key == "Enter") {
search();
}
});
}
if (!to) {
to = setTimeout(saveNote, saveInterval);
}
}

49
assets/js/template.js Normal file
View File

@ -0,0 +1,49 @@
/**
* Retrieves a template from the server and sets it as the value of a specified destination element.
*
* @param {string} orig - The ID of the element containing the original template value.
* @param {string} dest - The ID of the destination element where the retrieved template will be set.
* @return {Promise} A Promise that resolves when the template is successfully retrieved and set as the value of the destination element.
*/
export function retrieveTemplate(orig, dest) {
const temp = document.querySelector('#' + orig);
if (temp.value == '0') {
document.querySelector('#' + dest).value = '';
return;
}
fetch('/retrieve-template', {
method: 'POST',
headers: {
'Content-Type': 'plain/text'
},
body: JSON.stringify({
'template': temp.value
})
})
.then(response => response.text())
.then(results => {
const div = document.querySelector('#' + dest);
div.value = results;
});
}
/**
* Saves the template by sending a POST request to the server with template data.
*/
export function saveTemplate() {
fetch('/save-template', {
method: 'POST',
headers: {
'Content-Type': 'plain/text'
},
body: JSON.stringify({
'template_id': document.querySelector('#template_id').value,
'template_name': document.querySelector('#template_name').value,
'template_value': document.querySelector('#template_value').value,
})
})
.then(response => response.text())
.then(results => {
alert(results);
});
}

View File

@ -1,5 +1,3 @@
version: "3"
services:
sermon-notes:
container_name: sermon-notes
@ -7,4 +5,6 @@ services:
ports:
- 80:80
volumes:
- ./data:/data
- $PWD/data:/data
- $PWD/.env:/var/www/html/.env
restart: unless-stopped

View File

@ -25,4 +25,13 @@ return [
'@hotwired/turbo' => [
'version' => '7.3.0',
],
'jquery' => [
'version' => '3.3.1',
],
'jquery-ui' => [
'version' => '1.14.1',
],
'datatables' => [
'version' => '1.10.18',
],
];

View File

@ -1,6 +1,9 @@
#!/bin/bash
rm -rf .env*
if [ ! -f /var/www/html/.env ]; then
exit 0
fi
echo "APP_ENV=prod" > .env
echo "APP_DEBUG=0" >> .env

View File

@ -2,8 +2,8 @@
use App\Kernel;
if (preg_match("/js\/data\.json$/", $_SERVER['REQUEST_URI'])) {
print file_get_contents('js/data.json');
if (file_exists(__DIR__.$_SERVER['REQUEST_URI']) && is_readable(__DIR__.$_SERVER['REQUEST_URI']) && is_file(__DIR__.$_SERVER['REQUEST_URI'])) {
print file_get_contents(__DIR__.$_SERVER['REQUEST_URI']);
exit;
}

View File

@ -248,6 +248,7 @@ class AjaxController extends AbstractController
if ($ref) {
$ref->setContent($data->text);
$emi->persist($ref);
$emi->flush();
$res = $this->json(['msg' => 'Reference updated.']);
}

View File

@ -32,7 +32,7 @@ class DefaultController extends AbstractController
$meta = $user->getMetaData();
return $this->render('default/home.html.twig', [
'onLoad' => 'setHeight()',
//'onLoad' => 'initHome()',
'last4Notes' => $last4Notes,
'reverseNoteSort' => $openNotes,
'isAdmin' => $this->isGranted('ROLE_ADMIN'),

View File

@ -35,6 +35,15 @@ let saveTimeout = ({{ meta.saveTimeout }} * 1000);
const SAVE_FAILURE_LIMIT = {{ meta.saveFailureCount }};
let saveFailureCount = {{ meta.saveFailureCount }};
</script>
<script type='module'>
var body;
import {initHome, setBooks, setHeight, setEventListeners} from "{{ asset('js/site.js') }}";
document.onload = initHome();
window.setHeight = setHeight;
import {retrieveTemplate, saveTemplate} from "{{ asset('js/template.js') }}";
window.retrieveTemplate = retrieveTemplate;
window.saveTemplate = saveTemplate;
</script>
<script src='{{ asset('js/script.js') }}'></script>
{% endblock %}
@ -168,7 +177,7 @@ let saveFailureCount = {{ meta.saveFailureCount }};
<!-- The modal body -->
<form id="emailForm" class="modal-body">
<label for="email">Enter Friends Email:</label>
<label for="shareEmail">Enter Friends Email:</label>
<input type="email" id="shareEmail" name="email" required />
<button type='button' id="submit" class="btn btn-primary" onclick='shareNote()'>Submit</button>
</form>

View File

@ -3,10 +3,10 @@
{% block title %}Profile | Sermon Notes{% endblock %}
{% block stylesheets %}
<link href="/theme/assets/css/main.css" rel="stylesheet" />
<link href='/theme/assets/css/jquery-ui.theme.css' rel='stylesheet' />
<link href='/theme/assets/css/jquery-ui.structure.css' rel='stylesheet' />
<link href='/css/style.css' rel='stylesheet' />
<link href="{{ asset('css/main.css') }}" rel="stylesheet" />
<link href="{{ asset('css/jquery-ui.theme.css') }}" rel='stylesheet' />
<link href="{{ asset('css/jquery-ui.structure.css') }}" rel='stylesheet' />
<link href="{{ asset('css/style.css') }}" rel='stylesheet' />
<link href='//cdn.datatables.net/2.0.8/css/dataTables.dataTables.min.css' rel='stylesheet' />
<style>
.flex-container {

View File

@ -23,7 +23,6 @@
<li><a href="#" onclick='newNote()'>New Note</a></li>
<li><a href='#' onclick='openNote()'>Open Note</a></li>
<li><a href="#" onclick="saveNote()">Save Note</a></li>
<li><a href='#' onclick='discardNote()'>Delete Note</a></li>
{% if isAdmin is defined and isAdmin %}
<li><a href='/reference-editor'>Reference Editor</a></li>
{% endif %}

View File

@ -2,6 +2,13 @@
<html>
<head>
<title>Reference Editor</title>
<script type='module'>
import {setHeight, setBooks, setEventListeners} from "{{ asset('js/site.js') }}";
import {retrieveReference, retrieveReferenceType, saveReference} from '{{ asset("js/reference.js") }}';
window.retrieveReference = retrieveReference;
window.retrieveReferenceType = retrieveReferenceType;
window.saveReference = saveReference;
</script>
</head>
<body>
@ -29,6 +36,6 @@
<a href='/home'>Back</a><br />
<textarea id='reference' name='reference' rows=45 cols=100></textarea>
<script src='{{ asset('js/script.js') }}'></script>
{{ encore_entry_script_tags('app') }}
</body>
</html>

View File

@ -15,6 +15,6 @@
<input type='button' name='save' value='Save' onclick='saveSeries()' />&nbsp;&nbsp;
<a href='/'>Back</a>
<script src='/js/script.js'></script>
<script src='{{ asset("/js/script.js") }}'></script>
</body>
</html>

View File

@ -15,6 +15,6 @@
<input type='button' name='save' value='Save' onclick='saveSpeaker()' />&nbsp;&nbsp;
<a href='/'>Back</a>
<script src='/js/script.js'></script>
<script src='{{ asset("js/script.js") }}'></script>
</body>
</html>

View File

@ -20,6 +20,11 @@
<textarea id='template_value' name='template' wrap='hard' cols=100 rows=45></textarea>
</form>
<script src='/js/script.js'></script>
<script src='{{ asset("js/script.js") }}'></script>
<script type='module'>
import {retrieveTemplate, saveTemplate} from "{{ asset('js/template.js') }}";
window.retrieveTemplate = retrieveTemplate;
window.saveTemplate = saveTemplate;
</script>
</body>
</html>

View File

@ -3,17 +3,17 @@
{% block title %}Register{% endblock %}
{% block stylesheets %}
<link href='/theme/assets/css/register.css' rel='stylesheet'/>
<link href="/theme/assets/css/main.css" rel="stylesheet" />
<link href="{{ asset('css/register.css') }}" rel='stylesheet'/>
<link href="{{ asset('css/main.css') }}" rel="stylesheet" />
{% endblock %}
{% block javascripts %}
<script src="/theme/assets/js/register.js"></script>
<script src="/theme/assets/js/jquery.min.js"></script>
<script src="/theme/assets/js/browser.min.js"></script>
<script src="/theme/assets/js/breakpoints.min.js"></script>
<script src="/theme/assets/js/util.js"></script>
<script src="/theme/assets/js/main.js"></script>
<script src="{{ asset('js/register.js') }}"></script>
<script src="{{ asset('js/jquery.min.js') }}"></script>
<script src="{{ asset('js/browser.min.js') }}"></script>
<script src="{{ asset('js/breakpoints.min.js') }}"></script>
<script src="{{ asset('js/util.js') }}"></script>
<script src="{{ asset('js/main.js') }}"></script>
{% endblock %}
{% block body %}
@ -33,7 +33,7 @@
label: 'Password'
}) }}
<button type='submit' class='btn'>Register</button>
<button type='submit' class='btn' id='register-btn'>Register</button>
{{ form_end(registrationForm) }}
<!--
<form action="/register" method="post" id='registration-form'>