212 Commits

Author SHA1 Message Date
ryan 235e80449f upd: docker compose
update docker compose files to us new 2.0 version
2026-06-21 19:42:30 -04:00
ryan f1e8bb2880 fix: defaultcontroller
fix typo
2026-06-21 19:40:36 -04:00
ryan f222fe0002 del: new-home
delete twig file since we used it to update home.twig
2026-06-21 19:38:50 -04:00
ryan 62fc8871ae upd: twig
update home format and reference editor styles and scripts
2026-06-21 19:37:44 -04:00
ryan 9d37f0b802 upd: asset.js 2026-06-21 19:36:54 -04:00
ryan 3bf4e03ba6 upd: styles
update styles to fix a couple bugs
2026-06-21 19:36:03 -04:00
ryan 49cbc2de59 upd: composer 2026-06-17 22:17:34 -04:00
ryan 02b843a2b7 upd: Dockerfile
change default brange for building image
2026-06-17 19:12:26 -04:00
ryan e7c64a5a13 upd: install script
fix import-bible
fix import-heidelberg
2026-06-13 13:41:48 -04:00
ryan 743885608d upd: composer
update composer lock file
2026-06-13 13:40:50 -04:00
ryan 60712b81ea upd: sidebar twig
update format for new home format
2026-06-13 13:39:25 -04:00
ryan d3508943a2 fix: dbts
fix typos
2026-06-13 13:39:01 -04:00
ryan 161e73f354 upd: note entity
fix js calls
add recording URL to json output
2026-06-13 13:38:38 -04:00
ryan e14abe23fd upd: ajaxcontroller
fix couple typos
2026-06-13 13:37:24 -04:00
ryan 70f01a171d upd: import-bible
rename ingest-bible to import-bible
2026-06-13 13:34:57 -04:00
ryan 1fd6fdc4b6 upd: app-import-heidelberg 2026-06-13 13:33:43 -04:00
ryan e2eaa400a4 add: local webfonts for font awesome 2026-06-13 12:57:32 -04:00
ryan 354fa538e6 upd: framework.yaml
add trusted_proxies var for use
2026-06-13 12:20:57 -04:00
ryan 77b900acc3 upd: main
Updates , this css will be remove din future versions
2026-06-13 12:20:02 -04:00
ryan a1a9a57048 upd: styles
split functionality to 3 different stylesheets
2026-06-13 12:15:55 -04:00
ryan c34ccfc3e8 del: site.js 2026-06-13 12:14:53 -04:00
ryan f295906300 upd: state.js
migrate from old to new
2026-06-13 12:14:46 -04:00
ryan 537940e394 upd: note.js
migrate from old to new
2026-06-13 12:14:36 -04:00
ryan 2b2b2aaec5 upd: home.js
migrate from old to new
2026-06-13 12:14:23 -04:00
ryan 4a13760def add: sidebar-style 2026-06-13 12:10:58 -04:00
ryan 5e81358f47 add: mid-screen-style 2026-06-13 12:10:40 -04:00
ryan 48e5c77ef2 add: lg-screen-style 2026-06-13 12:10:25 -04:00
ryan c7a1d6b3b7 upd: setup script
disable postgres ssl
add null default mailer dsn
2026-06-07 17:59:57 -04:00
ryan 623eebc9b2 fix: data.json
fix numbering for hc
2026-05-29 11:52:03 -04:00
ryan 05874c025f upd: importmap
add new js files
2026-05-13 17:25:24 -04:00
ryan 10267a261d upd: compose.lock 2026-05-13 17:25:06 -04:00
ryan ccab4ba655 upd: sidebar
add id
2026-05-13 17:24:54 -04:00
ryan dec1b801d8 add: new home
add new home page will change for final version
2026-05-13 17:24:21 -04:00
ryan 723d046ce3 upd: twig config
remove caching in dev env for twig files
2026-05-13 17:22:47 -04:00
ryan 52bdf2f16e upd: login
remove sidebar from login screen
2026-05-13 17:22:21 -04:00
ryan 788190328b add: new js files for simplicity 2026-05-13 17:21:03 -04:00
ryan 0a55500892 add: default stylesheet 2026-05-13 17:19:53 -04:00
ryan 29f8b7461f add: dark and light mode style default colors 2026-05-13 17:17:46 -04:00
ryan eb28e41930 updates 2026-03-27 16:31:09 -04:00
ryan 559ab4e2a8 upd: entrypoint
Make sure the change the permissions to the var folder everytime we restart
2026-03-27 16:29:52 -04:00
ryan 4d1cfeadcd del: migrations
remove migrations folder as it is unnecessary since we have mutliple database types available
2026-03-27 15:53:59 -04:00
ryan 819f8b35b9 upd: gitignore
add migrations folder to gitignore
2026-03-27 15:49:08 -04:00
ryan 0e97468f7d upd: install
update migration commands to use entities instead of migration scripts
2026-03-27 15:48:07 -04:00
ryan 9f9ee82c6b upd: setup
remove backticks
2026-03-27 15:46:46 -04:00
ryan e03dd0aaf7 upd: remove backtick 2026-03-27 14:50:31 -04:00
ryan 525c6a47a6 fix: dockerfile
several changes including cloning repo instead of file copy
fixed cron
copy temporary production .env file add importmap and asset-map
custom entrypoint
2026-03-27 14:45:55 -04:00
ryan 5af898a702 fix: readme
fixed install and setup commands
2026-03-27 14:43:51 -04:00
ryan 7ee5437f8a fix: ingestreferencecommand
fix label generation for canons of dort content
2026-03-27 14:43:29 -04:00
ryan fa7af9d5c7 fix: install
adopted shell_exec instead of backtick for running a shell.
2026-03-27 14:42:38 -04:00
ryan 77ae65c2bd fix typo 2026-03-27 14:09:14 -04:00
ryan 9a496c07b0 upd: fontawesome
remove empty lines
2026-03-27 13:51:36 -04:00
ryan 95911a210a fix: main.css
fix path for fontawesome library
2026-03-27 13:49:15 -04:00
ryan 9482ea3708 upd: scripts
update permissions to install and setup.php along with adding #! to first line of files
2026-03-27 13:48:54 -04:00
ryan 82d03aeb6a upd: entrypoint permissions 2026-03-27 13:46:32 -04:00
ryan 3f1c9841a2 upd: lock files 2026-03-27 12:58:02 -04:00
ryan 9fdda7e2ba add: entrypoint 2026-03-27 12:55:06 -04:00
ryan 2e4028d623 upd: docker-compose
Add logging notation
2026-03-26 19:58:21 -04:00
ryan 5e6d63ef26 upd: Dockerfile
remove logrotate functionality in favor of docker native logging
2026-03-26 19:57:59 -04:00
ryan 39ef5a4c49 upd: Dockerfile
convert to do a git clone instead of copying the files into the folder and with it dev code
2026-03-26 18:46:06 -04:00
ryan db9e1cd469 upd: Database transfer (#25)
stylize transfer_summary.html.twig by adding stylesheet and javascript blocks
2026-03-26 18:35:21 -04:00
ryan b1726bba34 upd: PWA (#15)
add service worker script block, manifest file, and fix error for share button email
2026-03-26 18:34:11 -04:00
ryan 4ed6c18825 upd: DefaultController
Clean up
2026-03-26 18:32:37 -04:00
ryan 5ac8736004 feat: PWA (#15)
add for PWA capability
2026-03-26 18:32:07 -04:00
ryan 36f3ab3bd1 upd: install.php
comment out building asset map
2026-03-26 18:31:06 -04:00
ryan 4a1777d160 upd: Dockerfile
add pdo_sqlite and move asset-map compiling to this instead of install.php
2026-03-26 18:30:36 -04:00
ryan 2a22a3e027 upd: DefaultController (#25)
add database transfer capability
2026-03-26 15:14:15 -04:00
ryan c948b1e39d upd: csrf
add csrf protection for forms
2026-03-26 15:12:56 -04:00
ryan 840058873a upd: update permissions on files after copy 2026-03-26 15:12:12 -04:00
ryan d12b94b4b1 upd: symfony/config 2026-03-26 08:26:06 -04:00
ryan 26b9e6fe97 upd: .gitignore
ignore .continue folder
2026-03-26 08:22:32 -04:00
ryan 3aab29cd03 add: migration 2026-03-26 08:22:01 -04:00
ryan d06f24b1fa upd: utils
Add method to get file permissions
2026-02-16 14:16:37 -05:00
ryan ed774a5a37 upd: profile twig
add saveProfile method and required support
2026-02-16 14:15:51 -05:00
ryan 6664a7c71e upd: user
add home church rss field
2026-02-16 14:15:10 -05:00
ryan 4be33834d4 upd: ajaxcontroller
add method to save profile and include home church rss feed url
2026-02-16 14:14:42 -05:00
ryan b445295959 upd: database
add home church rss url for users
2026-02-16 14:13:56 -05:00
ryan 20ba17c684 git: ignore
ignore composer.lock file
2026-02-16 14:12:44 -05:00
ryan 323e668ac9 upd: dockerfile
install logrotate and cron to accomplish scripting to retrieve audio recording links for sermon
2026-02-16 14:12:09 -05:00
ryan 0d384a8fa3 fix: install
fix typo
2026-02-16 14:10:51 -05:00
ryan b14a0c23f6 add: app:get-audio
Script command to crawl RSS feed and find uploaded recordings to update the notes
2026-01-16 13:54:45 -05:00
ryan 50cf4800fd upd: update for 1.2 processes 2025-12-05 13:39:01 -05:00
ryan 289bfc1a3f upd: split install functions 2025-12-05 13:38:10 -05:00
ryan b8125dcbf9 rem: remove old docker-compose files 2025-12-05 13:00:29 -05:00
ryan 71ffd82dab add: default docker-compose files for each database type 2025-12-05 13:00:15 -05:00
ryan 05b5491665 upd: added blanket exclusion for all .env* files 2025-12-05 10:56:01 -05:00
ryan b95c018b36 upd: removed copy for database file since it's going to be created and populated with install.php 2025-12-05 10:54:53 -05:00
ryan b30bf8eda6 upd: several
- Added print statements
- Added questions so user could import only what they want
2025-12-05 10:53:53 -05:00
ryan 1dd8d3dbb2 upd: added ESV citation to end of return 2025-12-05 10:51:38 -05:00
ryan fcb466d9a7 upd: changed command to import instead of ingest 2025-12-05 10:51:17 -05:00
ryan 46b11bdaa4 upd: converted for json file 2025-12-05 10:50:29 -05:00
ryan d58721ca5b upd: prepared for cli execution 2025-12-05 10:50:09 -05:00
ryan 8b44329e09 fix: added missing labels 2025-12-05 10:48:31 -05:00
ryan 7d6dfeef42 add: Westminster Shorter Catechism 2025-12-05 09:24:18 -05:00
ryan 43e78baf1e add: Westminster Larger Catechism 2025-12-05 09:24:05 -05:00
ryan 067a040982 add: Westminster Confession of Faith 2025-12-05 09:23:53 -05:00
ryan 599dc04474 add: Second Helvetic Confession 2025-12-05 09:23:41 -05:00
ryan ad67a38bca add: Savoy Declaration 2025-12-05 09:23:28 -05:00
ryan 7a76b411c3 add: Luther's Small Catechism 2025-12-05 09:23:20 -05:00
ryan 0ed2982627 add: Luther's Large Catechism 2025-12-05 09:23:08 -05:00
ryan a6c31e2d90 add: London Baptists Confession 2025-12-05 09:22:59 -05:00
ryan b5c7ad8be4 add: Heidelberg Catechism 2025-12-05 09:22:48 -05:00
ryan e1d4ce9766 add: First Helvetic Confession 2025-12-05 09:22:36 -05:00
ryan d1189bb803 add: Bible 2025-12-05 09:22:27 -05:00
ryan d99446aff3 add: Nicene Creed 2025-12-05 09:22:20 -05:00
ryan bc25a17ba6 add: French Confession 2025-12-05 09:22:13 -05:00
ryan 13a63cddf4 add: Definition of Chalcedon 2025-12-05 09:22:05 -05:00
ryan cb11505e9c add: Athanasian Creed 2025-12-05 09:21:57 -05:00
ryan e1ab7ffa7b add: Apostles Creed 2025-12-05 09:21:45 -05:00
ryan 98495e53d4 add: Canons of Dort 2025-12-05 09:21:33 -05:00
ryan 1598dcd8cc add: Belgic Confession 2025-12-05 09:21:18 -05:00
ryan 3981e08966 add: Augsberg Confession 2025-12-05 09:21:06 -05:00
ryan edc8046fed add: 39 Articles 2025-12-05 09:20:39 -05:00
ryan f63735659c Upgrade symfony to 7.4 2025-12-05 08:49:11 -05:00
ryan 4da5f8f30b upd: update Dockerfile
Add libraries for mysql and pgsql
2025-11-24 20:41:07 -05:00
ryan 07f5503165 fix: install script migration
migrate install.sh script to install.php to make it a little easier to manage
2025-11-24 20:40:25 -05:00
ryan 33ff77590f upg: importmap 2025-11-02 15:36:15 -05:00
ryan 1c783d8ed3 fix: Rounded reference box corners
Increased border radius for reference box to be consistent with note box
2025-11-02 15:23:18 -05:00
ryan d9c88b40b1 Merge pull request 'Release 1.1' (#18) from 1.1 into main
Reviewed-on: #18
2025-10-10 23:32:42 -04:00
ryan dd83e0de95 upd: docker
update docker-compose and readme with updated docker image
2025-10-10 17:15:00 -04:00
ryan f3b91ac1d7 docker: install
Update docker info
2025-10-08 21:13:17 -04:00
ryan 205fa5f3a1 {type}: {component}
{summary}
2025-10-08 21:11:48 -04:00
ryan 5b284cc107 {type}: {component}
{summary}
2025-10-08 21:11:10 -04:00
ryan 9c682ea58d upd: registration
- added dd return if fail to register
2025-08-11 13:02:34 -04:00
ryan 24a0892160 fix: index
- fixed problem with files not pulling from server correct with MIME types
2025-08-11 13:00:55 -04:00
ryan 50f62535e6 fix: registration
- fixed account registration problem
2025-08-11 12:59:57 -04:00
ryan abd2d93c90 upd: index
- simplified link to return home if logged in
2025-08-11 12:59:21 -04:00
ryan 3fdb7d4e09 upd: home
- update to pull sorted speaker and series
2025-08-11 12:58:11 -04:00
ryan c822de468c upd: DefaultController
- add get for speakers and series sorted by name
2025-08-11 12:57:34 -04:00
ryan f1fceff25a fix: dirty text
- add check for backspace key
2025-08-11 12:53:42 -04:00
ryan f6b4aeea83 upd: scripts
- add check for escape key and input validation for new speaker and series
2025-08-11 12:53:03 -04:00
ryan 44a8a72219 upd: home
Add input-error style for validation feedback
2025-06-03 13:01:47 -04:00
ryan c933e6b91b upd: registration
Add CSRF protection to registration form
2025-06-03 13:00:34 -04:00
ryan 573b8b1d26 upd: notes
add validation feedback if user doesn't fill out all required fields.
2025-06-03 12:58:42 -04:00
ryan 1aed314ae3 fix: registration
Fix a couple typos in registration JS
2025-06-03 12:44:03 -04:00
ryan 135a03f8d1 upd: data.db
Updates to starting database
2025-04-28 00:09:22 -04:00
ryan 57c9be1c0b fix: various templates
convert to assets
2025-04-27 23:50:07 -04:00
ryan a34c0deee5 fix: reference-editor template
fix bug
2025-04-27 23:48:36 -04:00
ryan 57cbb44b91 rem: sidebar template
remove delete note link
2025-04-27 23:45:16 -04:00
ryan 238b3a89d7 ref: profile template
convert to asset code
2025-04-27 23:44:48 -04:00
ryan 3fc5ab0ba2 ref: home template
Add js module code
fix label
2025-04-27 23:40:53 -04:00
ryan 34435f885c fix: defaultcontroller
comment out onload for home
2025-04-27 23:11:51 -04:00
ryan 6369f5c7b9 fix: ajax
Bug fix, add flush for reference data
2025-04-27 23:07:03 -04:00
ryan 9aa49c9c2c fix: index.php 2025-04-27 23:04:10 -04:00
ryan 3f6d32b995 upd: *.js
Refactor methods to other scripts
2025-04-27 22:58:03 -04:00
ryan eb2366ebd8 upd: register.js
Fix error in csrfToken element
2025-04-27 22:54:12 -04:00
ryan 13bcafcebf upd: app.js
add jquery
2025-04-27 22:53:32 -04:00
ryan 9e85edbb25 upd: main.css
reduce font-size for h1 tag items
2025-04-27 22:49:20 -04:00
ryan 879eeb10bf upd: README
Update for v1.1 to add warning about breaking change
2025-04-27 22:48:29 -04:00
ryan b1f207b9be upd: install.sh
Do a check for .env before install and remove
2025-04-27 22:45:59 -04:00
ryan 0e1160d292 upd: importmap
add jquery, jquery-ui, datatables
2025-04-27 21:08:30 -04:00
ryan 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
ryan 95f17a2f3b upd: docker-compose
remove version tag
change data volume
add .env file
add restart
2025-04-27 20:55:34 -04:00
ryan f114843e4c Other various changes 2025-04-04 15:27:16 -04:00
ryan 6af5f2a3f8 Upgrade to Symfony 7.2 2025-04-04 15:26:34 -04:00
ryan f68f5b5aa1 Change document root 2025-04-04 15:26:12 -04:00
ryan 042f88f649 delete old files 2025-04-04 15:25:55 -04:00
ryan 432d6ca246 Move files 2025-04-04 15:25:13 -04:00
ryan 979443da36 JS updates and expand HC 2024-11-18 00:24:05 -05:00
ryan cb849308cc Style updates 2024-11-18 00:22:40 -05:00
ryan f61a5ff81b Delete previous classes 2024-07-21 21:33:43 -04:00
ryan 514ca624e5 Update styles 2024-07-12 20:33:57 -04:00
ryan 35042278ac Update base database 2024-07-12 20:13:13 -04:00
ryan 82700e2dc5 Add NoteShares 2024-07-02 19:24:48 -04:00
ryan 8aa1652283 Add email for registration notification 2024-07-02 19:24:21 -04:00
ryan 16d5df4095 Convert profile view to rows
Add additional sections for shared notes
2024-07-02 19:24:08 -04:00
ryan 885298437b Add parsedown library and symfony mailer 2024-07-02 01:57:29 -04:00
ryan 8cf8d82443 Add shareNote, openShareNote, closeShareNote and docblock comments for each function 2024-07-02 01:56:20 -04:00
ryan 37f3ade420 Add modal dialog to share note 2024-07-02 01:54:43 -04:00
ryan 258ff9eda7 Add template for note sharing 2024-07-02 01:53:45 -04:00
ryan 2c9511ecf4 migrate email to use Util class and method 2024-07-02 01:41:47 -04:00
ryan 97d656912c migrate email to use Util class and method 2024-07-02 01:41:33 -04:00
ryan 717b9398bc Added credential login check for visiting the profile page 2024-07-02 01:39:11 -04:00
ryan 6a070ca4e0 Added shareNote method to share an individual note with an email 2024-07-02 01:38:36 -04:00
ryan fa8ef2ab78 Update styles 2024-07-02 01:33:24 -04:00
ryan 20dc1622f2 Fix error with not sending emails 2024-07-02 01:33:14 -04:00
ryan fbf5ac564a To support note deletion 2024-06-24 15:43:03 -04:00
ryan d24c304c97 Updates 2024-06-23 22:41:33 -04:00
ryan 752b2a291e Add profile data 2024-06-23 22:40:50 -04:00
ryan 87fb461c26 Update database and add new migration 2024-06-23 20:13:25 -04:00
ryan 70e9ef508c Style updates 2024-06-23 20:13:02 -04:00
ryan fba8454743 Added formatted cheat sheet html content for help 2024-06-11 21:23:43 -04:00
ryan da5e3b538d Updates to docker build 2024-06-09 20:42:39 -04:00
ryan c2c08db342 Add saveFailCounter
Fix bug with not clearing noteId
Refactor a class removal and additions
Add script.min.js
2024-06-09 20:26:54 -04:00
ryan 4d55711190 Adding new reference type retrieval 2024-06-09 20:24:44 -04:00
ryan 164ed62a48 add method for retrieving 39 articles 2024-06-09 20:18:54 -04:00
ryan bdc67942ea Add validation for email registration 2024-06-09 20:18:27 -04:00
ryan 4a6191e287 Add link to markdown cheat sheet 2024-06-09 20:17:40 -04:00
ryan d809e7eb38 Add new reference types 2024-06-09 20:17:20 -04:00
ryan 83709509f2 Move markdown cheat sheet 2024-06-09 20:16:42 -04:00
ryan 7bb909dfe4 Add link for recording 2024-05-29 00:37:56 -04:00
ryan 1d98940341 removed onload method call since it's now in script.js 2024-05-29 00:37:27 -04:00
ryan 14b4ca0545 add moment.js and datatables.js 2024-05-29 00:37:12 -04:00
ryan ea60cf2622 add methods to retrieve new references 2024-05-29 00:35:42 -04:00
ryan 53e5c48aa9 Changed reference editor to not pass through data 2024-05-29 00:34:50 -04:00
ryan a1e921063a add getNotes method for open notes table 2024-05-29 00:32:07 -04:00
ryan 2552335513 Migrate openNotes table to use DataTables
Added couple helper methods
Fixed not clearing recording link on "New Note"
add retrieveReferenceType method for reference editor
2024-05-29 00:30:42 -04:00
ryan 74b24afc75 Style updates 2024-05-29 00:24:05 -04:00
ryan 451a61722e New starter dataset 2024-05-29 00:23:48 -04:00
ryan a46253ec7d Add retrieveLBC and retrieveNote for references 2024-05-26 22:46:54 -04:00
ryan 45a3398ac7 Fix error with retrieving HC and CD references and add LBC 2024-05-26 22:46:25 -04:00
ryan a20caf1fc8 Added LBC and note reference retrieval
Convert get-reference to retrieve data from database instead of files
Fixed error with saving new note
2024-05-26 22:43:56 -04:00
ryan 435402ee41 Add LBC and new reference field 2024-05-26 22:40:45 -04:00
ryan 8315970571 Reorg the note fields and add recording link field
Add LBC
2024-05-26 22:33:41 -04:00
ryan d26874d88b Add recording link field 2024-05-26 22:30:53 -04:00
ryan d1ac0578f3 Add recording link field to note 2024-05-26 22:30:39 -04:00
ryan 3d10944b6d Style updates 2024-05-26 22:30:20 -04:00
ryan 72bf4273f3 increase saveTimeout
add check for note text to see if something has changed
add recording link text field
fix error for check
covert reference buttons to match style of other buttons
2024-05-26 22:30:03 -04:00
ryan 77e2777c7a Add LBC 2024-05-26 22:24:51 -04:00
ryan a1f5ce416c Style updates 2024-05-26 22:24:40 -04:00
ryan 6af0095470 Merge pull request 'Remerge' (#3) from main into 1.1
Reviewed-on: #3
2024-05-25 08:11:00 -04:00
ryan 11f566897f Fix install instructions 2024-05-25 08:01:46 -04:00
ryan 7044d16ee0 Update docker-compose 2024-05-24 11:48:08 -04:00
1032 changed files with 59596 additions and 3666 deletions
+5 -5
View File
@@ -1,13 +1,11 @@
###> symfony/framework-bundle ###
/.env
/.env.local
/.env.local.php
/.env.*.local
/.env*
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
/migrations/
###< symfony/framework-bundle ###
###> phpunit/phpunit ###
@@ -25,4 +23,6 @@
/assets/vendor/
###< symfony/asset-mapper ###
/references/
/references/
composer.lock
.continue
+3
View File
@@ -0,0 +1,3 @@
{type}: {component}
{summary}
+1 -1
View File
@@ -9,7 +9,7 @@
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/public
DocumentRoot /var/www/html/public/index.php
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
+38 -14
View File
@@ -1,4 +1,4 @@
FROM php:8.2-apache
FROM php:8.5-apache
RUN apt update && \
apt upgrade -y && \
@@ -10,23 +10,29 @@ RUN apt update && \
libpng-dev \
libjpeg-dev \
libicu-dev \
libpq-dev \
libsqlite3-dev \
sqlite3 \
curl \
git \
cron \
nano
RUN docker-php-ext-configure gd --with-jpeg
RUN docker-php-ext-configure zip
RUN docker-php-ext-install \
#pdo_sqlite \
zip \
mbstring \
exif \
pcntl \
bcmath \
xml \
intl
intl \
pdo_mysql \
pdo_pgsql \
pdo_sqlite
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
php composer-setup.php --install-dir=/usr/local/bin --filename=composer && \
@@ -35,20 +41,38 @@ RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" &&
RUN curl -sS https://get.symfony.com/cli/installer | bash && \
mv /root/.symfony5/bin/symfony /usr/local/bin/symfony
COPY . /var/www/html/
ARG CACHEBURST=1
ARG BRANCH=main
WORKDIR /var/www/html
RUN git clone -b ${BRANCH} --single-branch https://gitea.rkprather.com/ryan/sermon-notes.git ./
RUN git config --global --add safe.directory /var/www/html
RUN mv 000-default.conf /etc/apache2/sites-available/
RUN rm /var/www/html/.env*
RUN rm -rf /var/www/html/var/*
RUN rm -rf /var/www/html/vendor
RUN rm -rf /var/www/html/tests
RUN rm -rf /var/www/html/translations
RUN echo "20 1 * * 6 root cd /var/www/html && /usr/local/bin/php bin/console app:get-audio > /proc/1/fd/1 2>&1" > /etc/cron.d/get-audio
RUN chmod 644 /etc/cron.d/get-audio
RUN crontab /etc/cron.d/get-audio
RUN COMPOSER_ALLOW_SUPERUSER=1 composer install --no-scripts --no-dev --optimize-autoloader
RUN mv /var/www/html/data/data.db /var/www/html/var/
RUN mkdir /data
RUN mkdir /var/www/html/var/cache
RUN mkdir /var/www/html/var/log
RUN mkdir -p /var/www/html/var/cache/prod
RUN mkdir -p /var/www/html/var/log
RUN chown -R www-data:www-data /var/www/html
RUN chmod -R 755 /var/www/html
RUN chown -R 33:33 /var/www/html /data
RUN find /var/www/html -type d -exec chmod 755 '{}' \;
RUN find /var/www/html -type f -exec chmod 644 '{}' \;
RUN chmod 755 /data
RUN a2enmod rewrite setenvif headers
COPY prod.env /var/www/html/.env
RUN /usr/local/bin/php bin/console importmap:install
RUN /usr/local/bin/php bin/console asset-map:compile
RUN rm /var/www/html/.env
RUN chmod +x /var/www/html/bin/entrypoint.sh
EXPOSE 80
ENTRYPOINT ["/var/www/html/bin/entrypoint.sh"]
CMD ["apache2-foreground"]
+33 -3
View File
@@ -2,9 +2,39 @@
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. Make a directory in your `sermon-notes` folder for your database (e.g. `data`)
3. On your host computer, `docker exec -it sermon-notes bash`
4. `scp .env {user}@{IP}:{path}`
5. Authenticate with the password
6. `cd var/`
7. `scp data.db {user}@{IP}:{path}/data`
8. This will copy the file to the host computer
9. After this then you run the `docker run...` command in Step 3 of the `Installation` instructions below
## Installation
The best option for installing is using the Docker container. Download the `docker-compose.yml` file from this repository and run `docker-compose up -d` from the command line.
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. Download your preferred compose file (`wget -O compose.yml {link}`)
1. [`compose.sqlite.yml`](https://gitea.rkprather.com/ryan/sermon-notes/raw/branch/main/docker/compose.sqlite.yml) - compose file for if you are planning to use SQLite
2. [`compose.mysql.yml`](https://gitea.rkprather.com/ryan/sermon-notes/raw/branch/main/docker/compose.mysql.yml) - compose file with an integrated MYSQL database image
3. [`compose.mariadb.yml`](https://gitea.rkprather.com/ryan/sermon-notes/raw/branch/main/docker/compose.mariadb.yml) - compose file with an integrate MariaDB database image
4. [`compose.pgsql.yml`](https://gitea.rkprather.com/ryan/sermon-notes/raw/branch/main/docker/compose.pgsql.yml) - compose file with an integrate Postgres database image
5. [`compose.shared-db.yml`](https://gitea.rkprather.com/ryan/sermon-notes/raw/branch/main/docker/compose.shared-db.yml) - compose file with no database image because you are planning on using an existing database container or bare metal server
4. Pull the image `docker pull gitea.rkprather.com/ryan/sermon-notes:latest`
5. **NOTE: IF UPGRADING SKIP THIS STEP!!!** - Run the setup script, this will setup your .env file so that when you start the container everything will be where it is supposed to be.
- `docker run --rm -it -v ${PWD}/.env:/var/www/html/.env gitea.rkprather.com/ryan/sermon-notes:latest php /var/www/html/setup.php --{database-type} {--shared}`
- `{database-type}` = `sqlite`, `mysql`, `mariadb`, or `pgsql`
- If you intend on this being connected to a shared database make sure that you specify `--shared`.
6. Start the container with compose `docker compose up -d`
7. **NOTE: IF UPGRADING SKIP THIS STEP!!!** Run `docker exec -it sermon-notes php /var/www/html/install.php`. This will run the `php composer` to populate the database with all the desired reference material.
- NOTE: You will see deprecation warnings, you can ignore these
8. 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
@@ -24,7 +54,7 @@ Once you get logged in you'll be presented with the main home page
![HomePage](/assets/images/HomePage.png)
If you are accessing on a regular iPad the menu should be collapsed, if not, you may need to do that. I built this with a iPad 9th Gen in mind so your mileage may vary.
If you are accessing on a regular iPad the menu should be collapsed, if not, you may need to do that. I built this with a iPad 9th Gen in mind so visibility on another device may vary.
![Header](/assets/images/Header.png)
@@ -62,5 +92,5 @@ or if the note was recently made you will see the most recent 4 notes listed und
![RecentNotes](/assets/images/RecentNotes.png)
By click either of the title links it will open the note and display it for you to edit or read. I can add "Notes" as future reference content.
By clicking either of the title links it will open the note and display it for you to edit or read. I can add "Notes" as future reference content.
+2 -2
View File
@@ -5,6 +5,6 @@ import './bootstrap.js';
* This file will be included onto the page via the importmap() Twig function,
* which should already be in your base.html.twig.
*/
import './styles/app.css';
//import './styles/app.css';
console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');
// console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');
+18
View File
@@ -0,0 +1,18 @@
:root {
--dark: #3d4449;
--primary: #00760e;
--light: #f5f6f7;
--medium: #d1d1d1;
--text: var(--light);
--background: var(--dark);
--recording: #00f;
--success: #080;
--warning: orange;
--error: #f00;
--border: var(--primary);
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}/*# sourceMappingURL=dark-mode.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["dark-mode.scss","dark-mode.css"],"names":[],"mappings":"AACA;EACC,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,oBAAA;EACA,yBAAA;EACA,iBAAA;EACA,eAAA;EACA,iBAAA;EACA,aAAA;EACA,wBAAA;EAEA,SAAA;EACA,UAAA;EACA,SAAA;EACA,aAAA;EACA,wBAAA;ACDD","file":"dark-mode.css"}
+20
View File
@@ -0,0 +1,20 @@
// dark mode color scheme
:root {
--dark: #3d4449;
--primary: #00760e;
--light: #f5f6f7;
--medium: #d1d1d1;
--text: var(--light);
--background: var(--dark);
--recording: #00f;
--success: #080;
--warning: orange;
--error: #f00;
--border: var(--primary);
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 448 B

After

Width:  |  Height:  |  Size: 448 B

Before

Width:  |  Height:  |  Size: 429 B

After

Width:  |  Height:  |  Size: 429 B

Before

Width:  |  Height:  |  Size: 448 B

After

Width:  |  Height:  |  Size: 448 B

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 421 B

Before

Width:  |  Height:  |  Size: 408 B

After

Width:  |  Height:  |  Size: 408 B

Before

Width:  |  Height:  |  Size: 417 B

After

Width:  |  Height:  |  Size: 417 B

Before

Width:  |  Height:  |  Size: 497 B

After

Width:  |  Height:  |  Size: 497 B

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

+121
View File
@@ -0,0 +1,121 @@
@media screen and (min-width: 1501px) {
.mobile-note-header {
display: none;
}
#note-list {
display: none;
overflow-y: scroll;
}
#note-table_wrapper {
width: 97%;
}
.container #sidebar-link.toggle {
left: 25em;
}
.container {
display: grid;
height: 100vh;
grid-template-columns: 25em 60px 35% 0.98fr;
grid-template-rows: 60px 100vh;
gap: 5px 5px;
grid-auto-flow: row;
grid-template-areas: "sidebar-header ref-btn-header ref-header note-header" "sidebar ref-btn ref-text notes";
transition: grid-template-columns 0.5s ease-in-out;
}
.container p {
margin: 0 0 1em 0;
}
.container .fields-container {
display: none;
}
.container.sidebar-collapsed {
grid-template-columns: 0px 60px 35% 0.98fr;
}
.container.sidebar-collapsed #sidebar-link.toggle {
left: 0;
}
.bottom-row {
height: calc(100vh - 75px);
}
.notes {
display: flex;
flex-direction: column;
grid-template-columns: 100vh;
grid-template-rows: 75px 100vh;
gap: 2px 0px;
grid-template-areas: "fields-container" "note-text";
grid-area: notes;
}
.notes .fields-container {
justify-content: space-evenly;
flex-wrap: wrap;
width: 99.5%;
}
.notes .fields-container input[type=text], .notes .fields-container select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--dark);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 2;
min-width: 50px;
max-width: 200px;
}
.notes .note-text {
height: 100%;
width: 100%;
}
.notes .note-text textarea {
height: -webkit-fill-available;
height: -moz-available;
height: stretch;
width: -webkit-fill-available;
width: -moz-available;
width: stretch;
border-radius: 10px;
background-color: transparent;
color: var(--text);
font-family: "Roboto Sans";
}
.note-header, .ref-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.note-header h2, .ref-header h2 {
margin: 0;
}
.note-header select, .ref-header select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--dark);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 2;
min-width: 50px;
max-width: 200px;
margin-right: 3px;
}
}/*# sourceMappingURL=lg-screen-style.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["lg-screen-style.scss","lg-screen-style.css"],"names":[],"mappings":"AAAA;EACA;IACC,aAAA;ECCC;EDEF;IACC,aAAA;IACA,kBAAA;ECAC;EDGF;IACC,UAAA;ECDC;EDIF;IACI,UAAA;ECFF;EDKF;IACC,aAAA;IACA,aAAA;IACA,2CAAA;IACA,8BAAA;IACA,YAAA;IACA,mBAAA;IACA,4GACC;IAGD,kDAAA;ECNC;EDQD;IACC,iBAAA;ECNA;EDSD;IACC,aAAA;ECPA;EDUD;IACC,0CAAA;ECRA;EDUA;IACC,OAAA;ECRD;EDaF;IACC,0BAAA;ECXC;EDcF;IACC,aAAA;IACA,sBAAA;IACA,4BAAA;IACA,8BAAA;IACA,YAAA;IACA,mDAAA;IAEA,gBAAA;ECbC;EDeD;IACC,6BAAA;IACA,eAAA;IACA,YAAA;ECbA;EDgBA;IACC,mCAAA;IACA,kBAAA;IACA,aAAA;IACA,qBAAA;IACA,wBAAA;IAEA,gBAAA;IACA,sBAAA;IACA,6BAAA;IACA,UAAA;IACA,cAAA;IACA,qBAAA;IACA,eAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,YAAA;IACA,cAAA;IACA,eAAA;IACA,gBAAA;ECdD;EDkBD;IACC,YAAA;IACA,WAAA;EChBA;EDkBA;IACC,8BAAA;IAAA,sBAAA;IAAA,eAAA;IACA,6BAAA;IAAA,qBAAA;IAAA,cAAA;IACA,mBAAA;IACA,6BAAA;IACA,kBAAA;IACA,0BAAA;EChBD;EDqBF;IACC,aAAA;IACA,8BAAA;IACA,mBAAA;ECnBC;EDqBD;IACC,SAAA;ECnBA;EDsBD;IACC,mCAAA;IACA,kBAAA;IACA,aAAA;IACA,qBAAA;IACA,wBAAA;IAEA,gBAAA;IACA,sBAAA;IACA,6BAAA;IACA,UAAA;IACA,cAAA;IACA,qBAAA;IACA,eAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,YAAA;IACA,cAAA;IACA,eAAA;IACA,gBAAA;IACA,iBAAA;ECpBA;AACF","file":"lg-screen-style.css"}
+141
View File
@@ -0,0 +1,141 @@
@media screen and (min-width: 1501px) {
.mobile-note-header {
display: none;
}
#note-list {
display: none;
overflow-y: scroll
}
#note-table_wrapper {
width: 97%;
}
.container #sidebar-link.toggle {
left: 25em;
}
.container {
display: grid;
height: 100vh;
grid-template-columns: 25em 60px 35% 0.98fr;
grid-template-rows: 60px 100vh;
gap: 5px 5px;
grid-auto-flow: row;
grid-template-areas:
"sidebar-header ref-btn-header ref-header note-header"
"sidebar ref-btn ref-text notes";
transition: grid-template-columns 0.5s ease-in-out;
p {
margin: 0 0 1em 0;
}
.fields-container {
display: none;
}
&.sidebar-collapsed {
grid-template-columns: 0px 60px 35% 0.98fr;
#sidebar-link.toggle {
left: 0;
}
}
}
.bottom-row {
height: calc(100vh - 75px);
}
.notes {
display: flex;
flex-direction: column;
grid-template-columns: 100vh;
grid-template-rows: 75px 100vh;
gap: 2px 0px;
grid-template-areas: "fields-container" "note-text";
grid-area: notes;
.fields-container {
justify-content: space-evenly;
flex-wrap: wrap;
width: 99.5%;
// height: 75px;
input[type="text"], select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--dark);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 2;
min-width: 50px;
max-width: 200px;
}
}
.note-text {
height: 100%;
width: 100%;
textarea {
height: stretch;
width: stretch;
border-radius: 10px;
background-color: transparent;
color: var(--text);
font-family: 'Roboto Sans';
}
}
}
.note-header, .ref-header {
display: flex;
justify-content: space-between;
align-items: center;
h2 {
margin: 0;
}
select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--dark);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 2;
min-width: 50px;
max-width: 200px;
margin-right: 3px;
}
}
}
+18
View File
@@ -0,0 +1,18 @@
:root {
--dark: #3d4449;
--primary: #f56a6a;
--light: #f5f6f7;
--medium: #d1d1d1;
--text: var(--dark);
--background: var(--light);
--recording: #00f;
--success: #080;
--warning: orange;
--error: #f00;
--border: var(--primary);
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}/*# sourceMappingURL=light-mode.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["light-mode.scss","light-mode.css"],"names":[],"mappings":"AACA;EACC,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;EACA,0BAAA;EACA,iBAAA;EACA,eAAA;EACA,iBAAA;EACA,aAAA;EACA,wBAAA;EAEA,SAAA;EACA,UAAA;EACA,SAAA;EACA,aAAA;EACA,wBAAA;ACDD","file":"light-mode.css"}
+20
View File
@@ -0,0 +1,20 @@
// light mode color scheme
:root {
--dark: #3d4449;
--primary: #f56a6a;
--light: #f5f6f7;
--medium: #d1d1d1;
--text: var(--dark);
--background: var(--light);
--recording: #00f;
--success: #080;
--warning: orange;
--error: #f00;
--border: var(--primary);
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}
@@ -6,7 +6,8 @@
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/
html,
/*html,
body,
div,
span,
@@ -106,6 +107,7 @@ menu,
nav {
display: block;
width: 250px;
margin-bottom: 1em;
}
body {
@@ -306,7 +308,7 @@ h6 a {
}
h1 {
font-size: 4em;
font-size: 2em;
margin: 0 0 0.5em 0;
line-height: 1.3;
}
@@ -419,8 +421,111 @@ hr.major {
text-align: right;
}
/* =========================================
Base & Mobile First (Phones)
========================================= */
body {
margin: 0;
height: 100vh;
overflow: hidden;
}
.inner {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
padding-left: 0; /* from your original CSS */
}
.ref-tab {
display: none;
}
.ref {
flex: 1;
display: flex;
flex-direction: column;
padding: 10px;
overflow-y: auto;
}
.notes {
flex: 1;
display: flex;
flex-direction: column;
padding: 10px;
}
#note-header-left,
#note-header-right {
/* display: none !important; */
}
/* =========================================
Mobile "Typing Mode" (Keyboard Active)
========================================= */
body.typing-mode .ref {
display: none;
}
body.typing-mode .notes {
flex: 1 1 100%;
}
/* =========================================
Tablet & Desktop (Pixel Tablet Layout)
========================================= */
@media (min-width: 768px) {
.inner {
flex-direction: row;
max-width: 1060px; /* Kept your original width preference */
margin: 0 auto;
}
.ref-tab {
display: block;
flex: 0 0 60px;
padding-top: 60px !important;
}
.ref {
flex: 0 0 36%;
padding: 20px;
}
.notes {
flex: 1;
padding: 20px;
}
#note-header-left {
display: inline-flex;
flex-direction: row;
width: 25%;
}
#note-header-right {
display: inline-flex;
flex-direction: row-reverse;
width: 74%;
}
}
/* =========================================
App Specific Styles (DO NOT DELETE BELOW THIS LINE)
========================================= */
textarea#notes {
width: 100%;
height: 100%;
font-size: 14pt;
flex-grow: 1;
resize: none;
}
/* ... the rest of your original style.css continues here (#notePreview, #save-check, modals, etc.) ... */
/* Row */
.row {
/* .row {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
@@ -1875,7 +1980,7 @@ hr.major {
padding-top: 3em;
}
}
*/
/* Section/Article */
section.special,
article.special {
@@ -1891,10 +1996,11 @@ header p {
text-transform: uppercase;
}
header.major> :last-child {
header.major {
/*> :last-child {*/
border-bottom: solid 3px #f56a6a;
display: inline-block;
margin: 0 0 2em 0;
margin: 0 0 10px 0;
padding: 0 0.75em 0.5em 0;
}
@@ -1921,6 +2027,7 @@ input[type="email"],
input[type="tel"],
input[type="search"],
input[type="url"],
input[type="number"],
select,
textarea {
-moz-appearance: none;
@@ -1967,7 +2074,7 @@ select {
background-size: 1.25em;
background-repeat: no-repeat;
background-position: calc(100% - 1em) center;
height: 2.75em;
height: 2em;
padding-right: 2.75em;
text-overflow: ellipsis;
}
@@ -1992,8 +2099,9 @@ input[type="tel"],
input[type="search"],
input[type="url"],
input[type="date"],
input[type="number"],
select {
height: 2.75em;
height: 1.5em;
}
textarea {
@@ -2233,7 +2341,6 @@ a.image:hover img {
ol {
list-style: decimal;
margin: 0 0 2em 0;
padding-left: 1.5em;
}
ol li {
@@ -2243,7 +2350,6 @@ ol li {
ul {
list-style: disc;
margin: 0 0 2em 0;
padding-left: 1em;
}
ul.alt {
@@ -2679,8 +2785,7 @@ button:disabled,
/* Mini Posts */
.mini-posts article {
border-top: solid 1px rgba(210, 215, 217, 0.75);
margin-top: 2em;
padding-top: 2em;
padding-top: 1em;
}
.mini-posts article .image {
@@ -2695,7 +2800,7 @@ button:disabled,
.mini-posts article:first-child {
border-top: 0;
margin-top: 0;
margin-top: 1em;
padding-top: 0;
}
@@ -3088,13 +3193,13 @@ button:disabled,
}
#main>.inner {
padding: 0 0.5em 0.1em 0.5em;
padding: 0 0.25em 0.1em 0.25em;
margin: 0 auto;
max-width: 110em;
}
#main>.inner>section {
padding: 0.5em 0 0.5em 0;
padding: 0.25em 0 0.25em 0;
border-top: solid 2px rgba(210, 215, 217, 0.75);
}
@@ -3104,13 +3209,13 @@ button:disabled,
@media screen and (max-width: 1680px) {
#main>.inner {
padding: 0 0 0 2em;
padding: 0 0 0 0;
}
}
@media screen and (max-width: 1280px) {
#main>.inner {
padding: 0 0 0 2em;
padding: 0 0 0 0;
}
}
@@ -3199,7 +3304,7 @@ button:disabled,
#sidebar>.inner>* {
border-bottom: solid 2px rgba(210, 215, 217, 0.75);
margin: 0 0 3.5em 0;
padding: 0 0 3.5em 0;
/*padding: 0 0 3.5em 0;*/
}
#sidebar>.inner>*> :last-child {
@@ -3229,9 +3334,9 @@ button:disabled,
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
border: 0;
display: block;
height: 7.5em;
height: 4.5em;
left: 26em;
line-height: 7.5em;
line-height: 4.5em;
outline: 0;
overflow: hidden;
position: absolute;
@@ -3283,17 +3388,19 @@ button:disabled,
}
#sidebar>.inner>.alt {
margin: -1.66667em 0 3.33333em -1.66667em;
margin: 0;
padding: 1.66667em;
width: calc(100% + 3.33333em);
}
#sidebar .toggle {
height: 6.25em;
left: 24em;
line-height: 6.25em;
height: 4.5em;
left: 23em;
line-height: 4.5em;
text-indent: 5em;
width: 5em;
background-color: #fff;
margin-left: 1em;
}
#sidebar .toggle:before {
@@ -3338,7 +3445,7 @@ button:disabled,
#sidebar .toggle {
text-indent: 6em;
width: 6em;
width: 4.5em;
}
#sidebar .toggle:before {
@@ -3408,7 +3515,18 @@ button:disabled,
}
@media screen and (max-width: 1680px) {
#header {}
#header .logo {
font-size: 1.25em;
margin: 0;
}
#header .icons {
height: 5em;
line-height: 5em;
position: absolute;
right: -0.5em;
top: 0;
}
}
@media screen and (max-width: 736px) {
+162
View File
@@ -0,0 +1,162 @@
@media screen and (min-width: 1051px) and (max-width: 1500px) {
:root {
--sidebar-width: 20em;
--sidebar-header-width: 15em;
--hidden-sidebar-width: -20em;
--hidden-sidebar-header-width: -15em;
}
.mobile-note-header, #note-list {
display: none;
}
.container #sidebar-link.toggle {
left: 20em;
}
.container {
position: relative;
height: 100vh;
overflow-x: hidden;
display: grid;
grid-template-columns: 60px 35% 0.95fr;
grid-template-rows: 60px 1fr;
gap: 5px 5px;
grid-auto-flow: row;
grid-template-areas: "ref-btn-header ref-header note-header" "ref-btn ref-text notes";
}
.container #sidebar-header, .container #sidebar {
position: absolute;
left: 0;
z-index: 10000;
transition: left 0.5s ease-in-out;
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.5);
box-sizing: border-box;
}
.container #sidebar-header {
top: 0;
width: calc(var(--sidebar-header-width) + 40px);
height: 60px;
padding: 0 !important;
overflow: visible !important;
}
.container #sidebar {
top: 61px;
width: var(--sidebar-width);
height: calc(100vh - 61px);
padding: 15px;
}
.container #sidebar .inner {
width: 100%;
}
.container #sidebar-header #search {
padding: 19px;
width: 15em !important;
}
.container #sidebar-link.toggle {
left: calc(var(--sidebar-header-width) + 40px);
}
.container.sidebar-collapsed #sidebar {
left: var(--hidden-sidebar-width);
box-shadow: none;
}
.container.sidebar-collapsed #sidebar-header {
left: calc(var(--hidden-sidebar-header-width) - 40px);
box-shadow: none;
}
.container .fields-container {
display: none;
}
.bottom-row {
height: calc(100vh - 75px);
}
.notes {
display: flex;
flex-direction: column;
grid-template-columns: 1fr;
grid-template-rows: 75px 1fr;
gap: 2px 0px;
grid-template-areas: "fields-container" "note-text";
grid-area: notes;
}
.notes .fields-container {
justify-content: space-evenly;
flex-wrap: wrap;
width: 99.5%;
}
.notes .fields-container input[type=text], .notes .fields-container select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--dark);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 1;
min-width: 50px;
max-width: 200px;
}
.notes .note-text {
height: 100%;
width: 98.5%;
}
.notes .note-text textarea {
height: -webkit-fill-available;
height: -moz-available;
height: stretch;
width: 95.5%;
border-radius: 10px;
background-color: transparent;
color: var(--text);
font-family: "Roboto Sans";
}
.note-header, .ref-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.note-header h2, .ref-header h2 {
margin: 0;
}
.note-header select, .ref-header select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--dark);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 2;
min-width: 50px;
max-width: 200px;
margin-right: 3px;
}
input#query {
font-size: 10pt !important;
padding: 0 !important;
}
#old-notes {
padding: 15px !important;
}
#menu {
padding: 15px !important;
}
#sidebar header.major {
margin: 0 15px !important;
}
}/*# sourceMappingURL=mid-screen-style.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["mid-screen-style.scss","mid-screen-style.css"],"names":[],"mappings":"AAAA;EACA;IACC,qBAAA;IACA,4BAAA;IACA,6BAAA;IACA,oCAAA;ECCC;EDEF;IACC,aAAA;ECAC;EDGF;IACI,UAAA;ECDF;EDIF;IACC,kBAAA;IACA,aAAA;IACA,kBAAA;IAEA,aAAA;IACA,sCAAA;IACA,4BAAA;IACA,YAAA;IACA,mBAAA;IACA,qFACC;ECJA;EDOD;IACC,kBAAA;IACA,OAAA;IACA,cAAA;IACA,iCAAA;IACA,yCAAA;IAEA,sBAAA;ECNA;EDSD;IACC,MAAA;IACA,+CAAA;IACA,YAAA;IACA,qBAAA;IACA,4BAAA;ECPA;EDUD;IACC,SAAA;IACA,2BAAA;IACA,0BAAA;IACA,aAAA;ECRA;EDUA;IACC,WAAA;ECRD;EDYD;IACC,aAAA;IACA,sBAAA;ECVA;EDaD;IACC,8CAAA;ECXA;EDeA;IACC,iCAAA;IACA,gBAAA;ECbD;EDgBA;IACC,qDAAA;IACA,gBAAA;ECdD;EDkBD;IACC,aAAA;EChBA;EDoBF;IACC,0BAAA;EClBC;EDqBF;IACC,aAAA;IACA,sBAAA;IACA,0BAAA;IACA,4BAAA;IACA,YAAA;IACA,mDAAA;IAEA,gBAAA;ECpBC;EDsBD;IACC,6BAAA;IACA,eAAA;IACA,YAAA;ECpBA;EDuBA;IACC,mCAAA;IACA,kBAAA;IACA,aAAA;IACA,qBAAA;IACA,wBAAA;IAEA,gBAAA;IACA,sBAAA;IACA,6BAAA;IACA,UAAA;IACA,cAAA;IACA,qBAAA;IACA,eAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,YAAA;IACA,cAAA;IACA,eAAA;IACA,gBAAA;ECrBD;EDyBD;IACC,YAAA;IACA,YAAA;ECvBA;EDyBA;IACC,8BAAA;IAAA,sBAAA;IAAA,eAAA;IACA,YAAA;IACA,mBAAA;IACA,6BAAA;IACA,kBAAA;IACA,0BAAA;ECvBD;ED4BF;IACC,aAAA;IACA,8BAAA;IACA,mBAAA;EC1BC;ED4BD;IACC,SAAA;EC1BA;ED6BD;IACC,mCAAA;IACA,kBAAA;IACA,aAAA;IACA,qBAAA;IACA,wBAAA;IAEA,gBAAA;IACA,sBAAA;IACA,6BAAA;IACA,UAAA;IACA,cAAA;IACA,qBAAA;IACA,eAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,YAAA;IACA,cAAA;IACA,eAAA;IACA,gBAAA;IACA,iBAAA;EC3BA;ED+BF;IACC,0BAAA;IACA,qBAAA;EC7BC;EDgCF;IACC,wBAAA;EC9BC;EDiCF;IACC,wBAAA;EC/BC;EDkCF;IACC,yBAAA;EChCC;AACF","file":"mid-screen-style.css"}
+195
View File
@@ -0,0 +1,195 @@
@media screen and (min-width: 1051px) and (max-width: 1500px) {
:root {
--sidebar-width: 20em;
--sidebar-header-width: 15em;
--hidden-sidebar-width: -20em;
--hidden-sidebar-header-width: -15em;
}
.mobile-note-header, #note-list {
display: none;
}
.container #sidebar-link.toggle {
left: 20em;
}
.container {
position: relative;
height: 100vh;
overflow-x: hidden;
display: grid;
grid-template-columns: 60px 35% 0.95fr;
grid-template-rows: 60px 1fr;
gap: 5px 5px;
grid-auto-flow: row;
grid-template-areas:
"ref-btn-header ref-header note-header"
"ref-btn ref-text notes";
#sidebar-header, #sidebar {
position: absolute;
left: 0;
z-index: 10000;
transition: left 0.5s ease-in-out;
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.5);
//display: block;
box-sizing: border-box;
}
#sidebar-header {
top: 0;
width: calc(var(--sidebar-header-width) + 40px);
height: 60px;
padding: 0 !important;
overflow: visible !important;
}
#sidebar {
top: 61px;
width: var(--sidebar-width);
height: calc(100vh - 61px);
padding: 15px;
.inner {
width: 100%;
}
}
#sidebar-header #search {
padding: 19px;
width: 15em !important;
}
#sidebar-link.toggle {
left: calc(var(--sidebar-header-width) + 40px);
}
&.sidebar-collapsed {
#sidebar {
left: var(--hidden-sidebar-width);
box-shadow: none;
}
#sidebar-header {
left: calc(var(--hidden-sidebar-header-width) - 40px);
box-shadow: none;
}
}
.fields-container {
display: none;
}
}
.bottom-row {
height: calc(100vh - 75px);
}
.notes {
display: flex;
flex-direction: column;
grid-template-columns: 1fr;
grid-template-rows: 75px 1fr;
gap: 2px 0px;
grid-template-areas: "fields-container" "note-text";
grid-area: notes;
.fields-container {
justify-content: space-evenly;
flex-wrap: wrap;
width: 99.5%;
// height: 75px;
input[type="text"], select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--dark);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 1;
min-width: 50px;
max-width: 200px;
}
}
.note-text {
height: 100%;
width: 98.5%;
textarea {
height: stretch;
width: 95.5%;
border-radius: 10px;
background-color: transparent;
color: var(--text);
font-family: 'Roboto Sans';
}
}
}
.note-header, .ref-header {
display: flex;
justify-content: space-between;
align-items: center;
h2 {
margin: 0;
}
select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--dark);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 2;
min-width: 50px;
max-width: 200px;
margin-right: 3px;
}
}
input#query {
font-size: 10pt !important;
padding: 0 !important;
}
#old-notes {
padding: 15px !important;
}
#menu {
padding: 15px !important;
}
#sidebar header.major {
margin: 0 15px !important;
}
}
+97
View File
@@ -0,0 +1,97 @@
@media screen and (max-width: 1050px) {
#sidebar {
display: none;
}
.note-header, #note-list, .ref-header, .ref-btn-header, .ref-btn, .fields-container {
display: none;
}
.container {
display: grid;
height: 100vh;
width: 100vw;
grid-template-columns: 1fr;
grid-template-rows: 50px 50% 1fr;
gap: 5px 0;
grid-auto-flow: column;
grid-template-areas: "mobile-note-header" "notes" "ref-text";
}
.container .ref-text {
height: 100%;
width: 98vw;
margin-left: 1vw;
}
.container .ref-text a {
color: var(--primary);
}
.ref-header, .ref-btn-header, .ref-btn, .note-header, .fields-container {
display: none;
}
.mobile-note-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.mobile-note-header h2 {
margin: 0 10px;
}
.mobile-note-header button {
margin: 0 10px;
}
.notes {
width: 98vw;
margin-left: 1vw;
display: flex;
flex-direction: column;
grid-template-columns: 1fr;
grid-template-rows: 1fr 50px;
gap: 2px 0;
grid-template-areas: "note-text" "fields-container";
grid-area: notes;
}
.notes .fields-container {
justify-content: space-between;
flex-wrap: wrap;
width: 99.5%;
}
.notes .fields-container input[type=text], .notes .fields-container select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--border);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 1;
min-width: 50px;
max-width: 200px;
}
.notes .note-text {
height: 100%;
width: 100%;
}
.notes .note-text textarea {
height: 100%;
width: 98%;
border-radius: 10px;
background-color: transparent;
color: var(--text);
font-family: "Roboto Sans";
padding: 0 5px;
}
#sidebar {
position: fixed !important;
}
#refQuery {
height: 150px !important;
}
}/*# sourceMappingURL=mobile-style.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["mobile-style.scss","mobile-style.css"],"names":[],"mappings":"AAAA;EACA;IACC,aAAA;ECCC;EDEF;IACC,aAAA;ECAC;EDGF;IACC,aAAA;IACA,aAAA;IACA,YAAA;IACA,0BAAA;IACA,gCAAA;IACA,UAAA;IACA,sBAAA;IACA,4DACC;ECFA;EDMD;IACC,YAAA;IACA,WAAA;IACA,gBAAA;ECJA;EDMA;IACC,qBAAA;ECJD;EDSF;IACC,aAAA;ECPC;EDUF;IACC,aAAA;IACA,mBAAA;IACA,8BAAA;IACA,mBAAA;ECRC;EDUD;IACC,cAAA;ECRA;EDWD;IACC,cAAA;ECTA;EDaF;IACC,WAAA;IACA,gBAAA;IAEA,aAAA;IACA,sBAAA;IACA,0BAAA;IACA,4BAAA;IACA,UAAA;IACA,mDAAA;IAEA,gBAAA;ECbC;EDeD;IACC,8BAAA;IACA,eAAA;IACA,YAAA;ECbA;EDeA;IACC,mCAAA;IACA,kBAAA;IACA,aAAA;IACA,qBAAA;IACA,wBAAA;IAEA,gBAAA;IACA,sBAAA;IACA,+BAAA;IACA,UAAA;IACA,cAAA;IACA,qBAAA;IACA,eAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,YAAA;IACA,cAAA;IACA,eAAA;IACA,gBAAA;ECbD;EDiBD;IACC,YAAA;IACA,WAAA;ECfA;EDiBA;IACC,YAAA;IACA,UAAA;IACA,mBAAA;IACA,6BAAA;IACA,kBAAA;IACA,0BAAA;IACA,cAAA;ECfD;EDoBF;IACC,0BAAA;EClBC;EDqBF;IACC,wBAAA;ECnBC;AACF","file":"mobile-style.css"}
+118
View File
@@ -0,0 +1,118 @@
@media screen and (max-width: 1050px) {
#sidebar {
display: none;
}
.note-header, #note-list, .ref-header, .ref-btn-header, .ref-btn, .fields-container {
display: none;
}
.container {
display: grid;
height: 100vh;
width: 100vw;
grid-template-columns: 1fr;
grid-template-rows: 50px 50% 1fr;
gap: 5px 0;
grid-auto-flow: column;
grid-template-areas:
"mobile-note-header"
"notes"
"ref-text";
.ref-text {
height: 100%;
width: 98vw;
margin-left: 1vw;
& a {
color: var(--primary);
}
}
}
.ref-header, .ref-btn-header, .ref-btn, .note-header, .fields-container {
display: none;
}
.mobile-note-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
h2 {
margin: 0 10px;
}
button {
margin: 0 10px;
}
}
.notes {
width: 98vw;
margin-left: 1vw;
display: flex;
flex-direction: column;
grid-template-columns: 1fr;
grid-template-rows: 1fr 50px;
gap: 2px 0;
grid-template-areas: "note-text" "fields-container";
grid-area: notes;
.fields-container {
justify-content: space-between;
flex-wrap: wrap;
width: 99.5%;
input[type="text"], select {
background-color: var(--background);
color: var(--text);
height: 1.5em;
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
border-radius: 0.375em;
border: solid 1px var(--border);
outline: 0;
padding: 0 1em;
text-decoration: none;
font-size: 14pt;
font-weight: 400;
line-height: 1.65;
flex-basis: auto;
flex-grow: 1;
flex-shrink: 1;
min-width: 50px;
max-width: 200px;
}
}
.note-text {
height: 100%;
width: 100%;
textarea {
height: 100%;
width: 98%;
border-radius: 10px;
background-color: transparent;
color: var(--text);
font-family: 'Roboto Sans';
padding: 0 5px;
}
}
}
#sidebar {
position: fixed !important;
}
#refQuery {
height: 150px !important;
}
}
+198
View File
@@ -0,0 +1,198 @@
/**
* Sidebar
*/
#sidebar-header {
grid-area: sidebar-header;
background-color: var(--background);
overflow: hidden;
min-width: 0;
padding: 10px;
}
#sidebar-header #search {
width: 90%;
}
#sidebar {
grid-area: sidebar;
top: 0;
z-index: 10000;
overflow-y: auto;
min-width: 0;
border-right: solid 2px var(--border);
height: calc(100vh - 60px);
background-color: var(--background);
color: var(--text);
font-size: 0.9em;
position: relative;
overflow-x: hidden;
}
#sidebar .inner {
width: 25em;
}
#sidebar h2 {
font-size: 1.38889em;
text-align: center;
display: block;
}
.container #sidebar-link.toggle {
position: absolute;
top: 0;
width: 60px;
height: 60px;
line-height: 60px;
z-index: 10001;
transition: left 0.5s ease-in-out;
background-color: var(--background);
text-decoration: none;
border: 0;
overflow: hidden;
text-indent: -9999px;
}
.container #sidebar-link.toggle:before {
content: "\f0c9";
font-family: "Font Awesome 5 Free";
font-weight: 900;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
text-align: center;
text-indent: 0;
font-size: 2rem;
color: var(--text);
}
#menu {
padding: 25px;
}
#menu a {
color: var(--text);
}
#menu ul {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
font-family: "Roboto Slab", serif;
font-weight: 400;
letter-spacing: 0.075em;
list-style: none;
padding: 0;
text-transform: uppercase;
}
#menu ul li {
border-top: solid 1px var(--medium);
margin: 0.5em 0 0 0;
padding: 0.5em 0 0 0;
}
#menu ul li:first-child {
border-top: 0;
margin-top: 0;
padding-top: 0;
}
#menu ul a {
border-bottom: 0;
color: inherit;
cursor: pointer;
display: block;
font-size: 0.9em;
padding: 0.625em 0;
text-decoration: none;
}
input#query {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: var(--background);
border-radius: 0.375em;
border: solid 1px var(--medium);
color: inherit;
display: block;
outline: 0;
padding: 0 1em;
text-decoration: none;
width: 90%;
font-weight: 400;
line-height: 1.65;
font-size: 14pt;
height: 1.5em;
}
#sidebar header.major {
border-bottom: solid 3px var(--border);
border-top: solid 3px var(--border);
display: block;
padding: 10px 0;
text-align: center;
margin: 0 25px;
}
#old-notes {
padding: 25px;
}
.mini-posts article {
display: block;
width: 100%;
margin-bottom: 1em;
border-top: solid 1px var(--medium);
padding-top: 1em;
}
.mini-posts article a {
font-size: 12pt;
border-bottom: dotted 1px;
color: var(--primary);
text-decoration: none;
cursor: pointer;
}
.mini-posts article p:last-child {
font-size: 12pt;
text-indent: 0;
margin-top: 0;
}
.mini-posts article:first-child {
border-top: 0;
margin-top: 1em;
padding-top: 0;
}
.mini-posts article:last-child {
border-bottom: 0;
margin-bottom: 1em;
padding-bottom: 0;
}
#old-notes article p:first-child {
margin-bottom: 0;
font-size: 10pt;
text-indent: 0;
}
ul.contact {
list-style: none;
padding: 0;
}
ul.contact li:before {
font-family: "Font Awesome 5 Free";
color: var(--text);
font-weight: 900;
display: inline-block;
font-size: 1.5em;
height: 1.125em;
position: absolute;
text-align: center;
width: 1.5em;
}
ul.contact a {
color: var(--primary);
margin-left: 35px;
}/*# sourceMappingURL=sidebar-style.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["sidebar-style.scss","sidebar-style.css"],"names":[],"mappings":"AAAA;;EAAA;AAIA;EACI,yBAAA;EACA,mCAAA;EACA,gBAAA;EACA,YAAA;EACA,aAAA;ACAJ;ADEI;EACI,UAAA;ACAR;;ADIA;EACI,kBAAA;EACA,MAAA;EACA,cAAA;EACA,gBAAA;EACA,YAAA;EACA,qCAAA;EACA,0BAAA;EAEA,mCAAA;EACA,kBAAA;EACA,gBAAA;EACA,kBAAA;EACA,kBAAA;ACFJ;ADII;EACI,WAAA;ACFR;;ADMA;EACI,oBAAA;EACA,kBAAA;EACA,cAAA;ACHJ;;ADMA;EACI,kBAAA;EACA,MAAA;EACA,WAAA;EACA,YAAA;EACA,iBAAA;EACA,cAAA;EACA,iCAAA;EACA,mCAAA;EACA,qBAAA;EACA,SAAA;EACA,gBAAA;EACA,oBAAA;ACHJ;ADKI;EACI,gBAAA;EACA,kCAAA;EACA,gBAAA;EACA,kBAAA;EACA,OAAA;EACA,MAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;EACA,cAAA;EACA,eAAA;EACA,kBAAA;ACHR;;ADOA;EACI,aAAA;ACJJ;;ADOA;EACI,kBAAA;ACJJ;;ADOA;EACC,yBAAA;KAAA,sBAAA;UAAA,iBAAA;EACA,iCAAA;EACA,gBAAA;EACA,uBAAA;EACA,gBAAA;EACA,UAAA;EACA,yBAAA;ACJD;;ADOA;EACC,mCAAA;EACA,mBAAA;EACA,oBAAA;ACJD;;ADOA;EACC,aAAA;EACA,aAAA;EACA,cAAA;ACJD;;ADOA;EACC,gBAAA;EACA,cAAA;EACA,eAAA;EACA,cAAA;EACA,gBAAA;EACA,kBAAA;EACG,qBAAA;ACJJ;;ADOA;EACI,wBAAA;KAAA,qBAAA;UAAA,gBAAA;EACA,6BAAA;EACA,sBAAA;EACA,+BAAA;EACA,cAAA;EACA,cAAA;EACA,UAAA;EACA,cAAA;EACA,qBAAA;EACA,UAAA;EACA,gBAAA;EACA,iBAAA;EACA,eAAA;EACA,aAAA;ACJJ;;ADOA;EACI,sCAAA;EACA,mCAAA;EACA,cAAA;EACA,eAAA;EACA,kBAAA;EACA,cAAA;ACJJ;;ADOA;EACI,aAAA;ACJJ;;ADOA;EACI,cAAA;EACA,WAAA;EACA,kBAAA;EAEA,mCAAA;EACA,gBAAA;ACLJ;ADOI;EACI,eAAA;EACA,yBAAA;EACA,qBAAA;EACA,qBAAA;EACA,eAAA;ACLR;ADQI;EACI,eAAA;EACA,cAAA;EACA,aAAA;ACNR;;ADUA;EACI,aAAA;EACA,eAAA;EACA,cAAA;ACPJ;;ADUA;EACI,gBAAA;EACA,kBAAA;EACA,iBAAA;ACPJ;;ADUA;EACI,gBAAA;EACA,eAAA;EACA,cAAA;ACPJ;;ADUA;EACI,gBAAA;EACA,UAAA;ACPJ;ADSI;EACI,kCAAA;EACA,kBAAA;EACA,gBAAA;EACA,qBAAA;EACA,gBAAA;EACA,eAAA;EACA,kBAAA;EACA,kBAAA;EACA,YAAA;ACPR;ADUI;EACI,qBAAA;EACA,iBAAA;ACRR","file":"sidebar-style.css"}
+204
View File
@@ -0,0 +1,204 @@
/**
* Sidebar
*/
#sidebar-header {
grid-area: sidebar-header;
background-color: var(--background);
overflow: hidden;
min-width: 0;
padding: 10px;
#search {
width: 90%;
}
}
#sidebar {
grid-area: sidebar;
top: 0;
z-index: 10000;
overflow-y: auto;
min-width: 0;
border-right: solid 2px var(--border);
height: calc(100vh - 60px);
background-color: var(--background);
color: var(--text);
font-size: 0.9em;
position: relative;
overflow-x: hidden;
.inner {
width: 25em;
}
}
#sidebar h2 {
font-size: 1.38889em;
text-align: center;
display: block;
}
.container #sidebar-link.toggle {
position: absolute;
top: 0;
width: 60px;
height: 60px;
line-height: 60px;
z-index: 10001;
transition: left 0.5s ease-in-out;
background-color: var(--background);
text-decoration: none;
border: 0;
overflow: hidden;
text-indent: -9999px;
&:before {
content: '\f0c9';
font-family: 'Font Awesome 5 Free';
font-weight: 900;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
text-align: center;
text-indent: 0;
font-size: 2rem;
color: var(--text);
}
}
#menu {
padding: 25px;
}
#menu a {
color: var(--text);
}
#menu ul {
user-select: none;
font-family: "Roboto Slab", serif;
font-weight: 400;
letter-spacing: 0.075em;
list-style: none;
padding: 0;
text-transform: uppercase;
}
#menu ul li {
border-top: solid 1px var(--medium);
margin: 0.5em 0 0 0;
padding: 0.5em 0 0 0;
}
#menu ul li:first-child {
border-top: 0;
margin-top: 0;
padding-top: 0;
}
#menu ul a {
border-bottom: 0;
color: inherit;
cursor: pointer;
display: block;
font-size: 0.9em;
padding: 0.625em 0;
text-decoration: none;
}
input#query {
appearance: none;
background: var(--background);
border-radius: 0.375em;
border: solid 1px var(--medium);
color: inherit;
display: block;
outline: 0;
padding: 0 1em;
text-decoration: none;
width: 90%;
font-weight: 400;
line-height: 1.65;
font-size: 14pt;
height: 1.5em;
}
#sidebar header.major {
border-bottom: solid 3px var(--border);
border-top: solid 3px var(--border);
display: block;
padding: 10px 0;
text-align: center;
margin: 0 25px;
}
#old-notes {
padding: 25px;
}
.mini-posts article {
display: block;
width: 100%;
margin-bottom: 1em;
border-top: solid 1px var(--medium);
padding-top: 1em;
a {
font-size: 12pt;
border-bottom: dotted 1px;
color: var(--primary);
text-decoration: none;
cursor: pointer;
}
p:last-child {
font-size: 12pt;
text-indent: 0;
margin-top: 0;
}
}
.mini-posts article:first-child {
border-top: 0;
margin-top: 1em;
padding-top: 0;
}
.mini-posts article:last-child {
border-bottom: 0;
margin-bottom: 1em;
padding-bottom: 0;
}
#old-notes article p:first-child {
margin-bottom: 0;
font-size: 10pt;
text-indent: 0;
}
ul.contact {
list-style: none;
padding: 0;
li:before {
font-family: 'Font Awesome 5 Free';
color: var(--text);
font-weight: 900;
display: inline-block;
font-size: 1.5em;
height: 1.125em;
position: absolute;
text-align: center;
width: 1.5em;
}
a {
color: var(--primary);
margin-left: 35px;
}
}
+263
View File
@@ -0,0 +1,263 @@
@import url(mobile-style.css);
@import url(mid-screen-style.css);
@import url(lg-screen-style.css);
@import url(sidebar-style.css);
@import url(fontawesome-all.min.css);
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,600,400italic,600italic|Roboto+Slab:400,700");
/* Global style settings */
#previewBtn.active,
#show-hide-btn.active,
.ref-list button.active,
#open-ref.active,
#mobile-open-ref.active {
background-color: var(--primary) !important;
color: var(--light) !important;
}
input:focus {
border-color: var(--primary);
}
#save-check {
color: var(--success);
opacity: 0;
font-size: 20pt;
margin-left: 15px;
}
#save-check.saving {
color: var(--warning);
opacity: 1;
}
#save-check.error {
color: var(--error);
opacity: 1;
}
#ui-datepicker-div {
z-index: 11 !important;
}
body {
font-family: "Roboto Slab", "Open Sans", sans-serif !important;
background-color: var(--background);
color: var(--text);
margin: 0;
padding: 0;
}
h1, h2, h3, h4, h5, h6 {
color: var(--text);
font-family: "Roboto Slab", serif;
font-weight: 700;
line-height: 1.5;
margin: 0 0 1.5em 0;
}
h2 {
font-size: 1.5em;
display: inline-block;
}
.tab button {
display: flex;
justify-content: center;
align-items: center;
height: 80px;
width: 60px;
text-align: center;
font-size: 14px;
margin-bottom: 3px;
}
button,
.button {
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
background-color: transparent;
border-radius: 0.5em;
border: 0;
box-shadow: inset 0 0 0 2px var(--primary);
color: var(--primary) !important;
cursor: pointer;
display: inline-block;
font-family: "Roboto Slab", serif;
font-size: 0.8em;
font-weight: 700;
height: 3em;
letter-spacing: 0.075em;
line-height: 3em;
padding: 0 2em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
white-space: nowrap;
}
button.button i {
font-size: 1.5em;
}
.input-warning {
border: solid 2px var(--warning) !important;
}
.input-error {
border: solid 2px var(--error) !important;
}
.ref-btn-header {
grid-area: ref-btn-header;
}
.ref-btn {
grid-area: ref-btn;
}
.ref-btn .ref-list {
display: flex;
flex-direction: column;
align-items: start;
height: calc(100vh - 80px);
padding: 1px;
margin: 1px;
list-style: none;
}
.ref-text {
grid-area: ref-text;
display: block;
overflow-y: scroll;
border: var(--border) solid 1px;
border-radius: 10px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
z-index: 1;
}
.ref-text h2 {
display: block;
}
#refQuery {
position: fixed;
background-color: var(--background);
z-index: 999;
width: 400px;
height: 200px;
border: solid 2px var(--border);
border-radius: 10px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
margin: 10px 50px;
padding: 5px;
}
#chapter-range, #verse-range {
color: var(--text);
}
.note-header {
grid-area: note-header;
}
.notes {
z-index: 10;
}
#notePreview {
display: none;
z-index: 9;
}
.ref-header {
grid-area: ref-header;
}
/** drowndown button */
.dropdown {
position: relative;
}
.dropdown select {
background-color: var(--background);
color: var(--text);
}
.dropdown select option:hover {
background-color: var(--primary);
color: var(--text);
}
/* slider switch */
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 42px;
height: 24px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: 0.5s;
}
.slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background-color: white;
transition: 0.5s;
}
input:checked + .slider {
background-color: var(--primary);
}
input:focus + .slider {
box-shadow: 0 0 1px var(--primary);
}
input:checked + .slider:before {
transform: translateX(18px);
}
/* Rounded sliders */
.slider.round {
border-radius: 24px;
}
.slider.round:before {
border-radius: 50%;
}
#refQuery, #passage-popup, #modal-backdrop, #modal-container {
display: none;
}
h2.dirty {
color: darkorange;
}
textarea {
padding: 0.75em 1em;
}
#note-table a, #note-table a:active {
color: var(--text);
cursor: pointer;
}/*# sourceMappingURL=styles.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["styles.scss","styles.css"],"names":[],"mappings":"AAAQ,6BAAA;AACA,iCAAA;AACA,gCAAA;AACA,8BAAA;AAEA,oCAAA;AACA,gHAAA;AACR,0BAAA;AAEA;;;;;EAKE,2CAAA;EACA,8BAAA;ACDF;;ADIA;EACC,4BAAA;ACDD;;ADIA;EACC,qBAAA;EACA,UAAA;EACA,eAAA;EACA,iBAAA;ACDD;ADGC;EACC,qBAAA;EACA,UAAA;ACDF;ADIC;EACC,mBAAA;EACA,UAAA;ACFF;;ADMA;EACC,sBAAA;ACHD;;ADMA;EACE,8DAAA;EACA,mCAAA;EACA,kBAAA;EACA,SAAA;EACA,UAAA;ACHF;;ADMA;EACC,kBAAA;EACA,iCAAA;EACA,gBAAA;EACA,gBAAA;EACA,mBAAA;ACHD;;ADKA;EACC,gBAAA;EACA,qBAAA;ACFD;;ADKA;EACE,aAAA;EACA,uBAAA;EACA,mBAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,eAAA;EACA,kBAAA;ACFF;;ADKA;;EAEC,qBAAA;EACA,wBAAA;EAEA,gBAAA;EAIA,qEAAA;EACA,6BAAA;EACA,oBAAA;EACA,SAAA;EACA,0CAAA;EACA,gCAAA;EACA,eAAA;EACA,qBAAA;EACA,iCAAA;EACA,gBAAA;EACA,gBAAA;EACA,WAAA;EACA,uBAAA;EACA,gBAAA;EACA,cAAA;EAGA,kBAAA;EACA,qBAAA;EACA,yBAAA;EACA,mBAAA;ACJD;;ADOA;EACC,gBAAA;ACJD;;ADOA;EACC,2CAAA;ACJD;;ADOA;EACC,yCAAA;ACJD;;ADOA;EAAkB,yBAAA;ACHlB;;ADKA;EACC,kBAAA;ACFD;ADIC;EACC,aAAA;EACA,sBAAA;EACA,kBAAA;EACA,0BAAA;EACA,YAAA;EACA,WAAA;EACA,gBAAA;ACFF;;ADMA;EACC,mBAAA;EAEA,cAAA;EACA,kBAAA;EAEA,+BAAA;EACA,mBAAA;EACA,0CAAA;EACA,UAAA;ACLD;ADQC;EACC,cAAA;ACNF;;ADUA;EACC,eAAA;EACA,mCAAA;EACA,YAAA;EACA,YAAA;EACA,aAAA;EACA,+BAAA;EACA,mBAAA;EACA,0CAAA;EACA,iBAAA;EACA,YAAA;ACPD;;ADUA;EACC,kBAAA;ACPD;;ADUA;EACC,sBAAA;ACPD;;ADUA;EACC,WAAA;ACPD;;ADUA;EACC,aAAA;EACA,UAAA;ACPD;;ADUA;EACC,qBAAA;ACPD;;ADUA,sBAAA;AACA;EACC,kBAAA;ACPD;;ADWA;EACC,mCAAA;EACA,kBAAA;ACRD;ADUC;EACC,gCAAA;EACA,kBAAA;ACRF;;ADYA,kBAAA;AACA,2CAAA;AACA;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,YAAA;ACTF;;ADYA,+BAAA;AACA;EACE,UAAA;EACA,QAAA;EACA,SAAA;ACTF;;ADYA,eAAA;AACA;EACE,kBAAA;EACA,eAAA;EACA,MAAA;EACA,OAAA;EACA,QAAA;EACA,SAAA;EACA,sBAAA;EAEA,gBAAA;ACTF;;ADYA;EACE,kBAAA;EACA,WAAA;EACA,YAAA;EACA,WAAA;EACA,SAAA;EACA,WAAA;EACA,uBAAA;EAEA,gBAAA;ACTF;;ADYA;EACE,gCAAA;ACTF;;ADYA;EACE,kCAAA;ACTF;;ADYA;EAGE,2BAAA;ACTF;;ADYA,oBAAA;AACA;EACE,mBAAA;ACTF;;ADYA;EACE,kBAAA;ACTF;;ADYA;EACC,aAAA;ACTD;;ADYA;EACE,iBAAA;ACTF;;ADYA;EACC,mBAAA;ACTD;;ADYA;EACC,kBAAA;EACA,eAAA;ACTD","file":"styles.css"}
+281
View File
@@ -0,0 +1,281 @@
@import url(mobile-style.css);
@import url(mid-screen-style.css);
@import url(lg-screen-style.css);
@import url(sidebar-style.css);
// Set up the global font styles
@import url(fontawesome-all.min.css);
@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,600,400italic,600italic|Roboto+Slab:400,700");
/* Global style settings */
#previewBtn.active,
#show-hide-btn.active,
.ref-list button.active,
#open-ref.active,
#mobile-open-ref.active {
background-color: var(--primary) !important;
color: var(--light) !important;
}
input:focus {
border-color: var(--primary);
}
#save-check {
color: var(--success);
opacity: 0;
font-size: 20pt;
margin-left: 15px;
&.saving {
color: var(--warning);
opacity: 1;
}
&.error {
color: var(--error);
opacity: 1;
}
}
#ui-datepicker-div {
z-index: 11 !important;
}
body {
font-family: 'Roboto Slab', 'Open Sans', sans-serif !important;
background-color: var(--background);
color: var(--text);
margin: 0;
padding: 0;
}
h1, h2, h3, h4, h5, h6 {
color: var(--text);
font-family: 'Roboto Slab', serif;
font-weight: 700;
line-height: 1.5;
margin: 0 0 1.5em 0;
}
h2 {
font-size: 1.5em;
display: inline-block;
}
.tab button {
display: flex;
justify-content: center;
align-items: center;
height: 80px;
width: 60px;
text-align: center;
font-size: 14px;
margin-bottom: 3px;
}
button,
.button {
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
-moz-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
-webkit-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
-ms-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
background-color: transparent;
border-radius: 0.5em;
border: 0;
box-shadow: inset 0 0 0 2px var(--primary);
color: var(--primary) !important;
cursor: pointer;
display: inline-block;
font-family: "Roboto Slab", serif;
font-size: 0.8em;
font-weight: 700;
height: 3em;
letter-spacing: 0.075em;
line-height: 3em;
padding: 0 2em;
// min-width: 30px;
// max-width: 60px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
white-space: nowrap;
}
button.button i {
font-size: 1.5em;
}
.input-warning {
border: solid 2px var(--warning) !important;
}
.input-error {
border: solid 2px var(--error) !important;
}
.ref-btn-header { grid-area: ref-btn-header; }
.ref-btn {
grid-area: ref-btn;
.ref-list {
display: flex;
flex-direction: column;
align-items: start;
height: calc(100vh - 80px);
padding: 1px;
margin: 1px;
list-style: none;
}
}
.ref-text {
grid-area: ref-text;
display: block;
overflow-y: scroll;
// width: 100%;
border: var(--border) solid 1px;
border-radius: 10px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
z-index: 1;
// position: relative;
h2 {
display: block;
}
}
#refQuery {
position: fixed;
background-color: var(--background);
z-index: 999;
width: 400px;
height: 200px;
border: solid 2px var(--border);
border-radius: 10px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
margin: 10px 50px;
padding: 5px;
}
#chapter-range, #verse-range {
color: var(--text);
}
.note-header {
grid-area: note-header;
}
.notes {
z-index: 10;
}
#notePreview {
display: none;
z-index: 9;
}
.ref-header {
grid-area: ref-header;
}
/** drowndown button */
.dropdown {
position: relative;
// height: 20px;
}
.dropdown select {
background-color: var(--background);
color: var(--text);
option:hover {
background-color: var(--primary);
color: var(--text);
}
}
/* slider switch */
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 42px;
height: 24px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .5s;
transition: .5s;
}
.slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background-color: white;
-webkit-transition: 0.5s;
transition: 0.5s;
}
input:checked + .slider {
background-color: var(--primary);
}
input:focus + .slider {
box-shadow: 0 0 1px var(--primary);
}
input:checked + .slider:before {
-webkit-transform: translateX(18px);
-ms-transform: translateX(18px);
transform: translateX(18px);
}
/* Rounded sliders */
.slider.round {
border-radius: 24px;
}
.slider.round:before {
border-radius: 50%;
}
#refQuery, #passage-popup, #modal-backdrop, #modal-container {
display: none;
}
h2.dirty {
color: darkorange;
}
textarea {
padding: 0.75em 1em;
}
#note-table a, #note-table a:active {
color: var(--text);
cursor: pointer;
}

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

+383
View File
@@ -0,0 +1,383 @@
import * as note from './note.js';
import { state } from './state.js';
import * as ref from './reference.js';
// Get the link element
var tabs = [];
let controller;
// Function to change the CSS file based on checkbox state
/**
* Method to toggle dark/light mode
*
* @param {*} event
*/
export function toggleDarkMode(event) {
let mainCssLink = $('link[data-css="mode"');
if(mainCssLink.length > 0) {
mainCssLink[0].href = (event.target.checked ? mainCssLink.data('dark') : mainCssLink.data('light'));
}
}
/**
* Toggles the visibility of the fields container and updates the active state of the show/hide button.
*
* @param Event e
* @param boolean forceShow
* @return {void}
*/
export function toggleFields(e, forceShow = false) {
const fieldsContainer = document.querySelector('.fields-container');
let showHideBtn = document.getElementById('show-hide-btn');
let mobileShowHideBtn = document.getElementById('mobile-show-hide-btn');
if (forceShow || !fieldsContainer.classList.contains('show')) {
fieldsContainer.classList.add('show');
fieldsContainer.style.display = 'flex';
showHideBtn.classList.add('active');
mobileShowHideBtn.classList.add('active');
} else {
fieldsContainer.classList.remove('show');
fieldsContainer.style.display = 'none';
showHideBtn.classList.remove('active');
mobileShowHideBtn.classList.remove('active');
}
}
/**
* Increases the font size of the element with the id 'ref' by 1 point.
*
* @return {void} This function does not return a value.
*/
export function increaseFont() {
var currentSize = document.querySelector('#ref-text').style.fontSize;
const newSize = parseInt(currentSize) + 1;
document.querySelector('#ref-text').style.fontSize = newSize + 'pt';
document.querySelector('#notes').style.fontSize = newSize + 'pt';
document.querySelector('#notePreview').style.fontSize = newSize + 'pt';
}
/**
* Decreases the font size of the element with the id 'ref' by 1 point.
*
* @return {void} This function does not return a value.
*/
export function decreaseFont() {
var currentSize = document.querySelector('#ref-text').style.fontSize;
const newSize = parseInt(currentSize) - 1;
document.querySelector('#ref-text').style.fontSize = newSize + 'pt';
document.querySelector('#notes').style.fontSize = newSize + 'pt';
document.querySelector('#notePreview').style.fontSize = newSize + 'pt';
}
/**
* Previews a note by rendering the markdown content of the note in a preview section.
* Toggles between the note text and preview sections.
*
* @return {void} This function does not return anything.
*/
export function previewNote() {
var noteText = document.querySelector('#notes');
var notePreview = document.querySelector('#notePreview');
var previewButton = document.querySelector('#previewBtn');
const title = document.querySelector('#noteTitle');
const speaker = document.querySelector('#speaker');
const passage = document.querySelector('#passage');
const markdownPreview = "# " + title.value + " - " +
speaker.options[speaker.selectedIndex].text + " - " + passage.value + "\n\n" + noteText.value;
notePreview.innerHTML = state.md.render(markdownPreview);
if (previewButton.classList.contains('active')) {
document.querySelector('.note-text').style.display = 'block';
notePreview.style.display = 'none';
previewButton.classList.remove('active');
} else {
document.querySelector('.note-text').style.display = 'none';
notePreview.style.display = 'block';
previewButton.classList.add('active');
}
note.findLinks();
}
/**
* 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();
}
});
document.querySelector('#notes').addEventListener('keyup', function (event) {
let key = event.keyCode;
if (key == 8 || key >= 48 && key <= 90 || key >= 96 && key <= 111 || key >= 186 && key <= 222) {
state.saved = false
state.textDirty = true;
document.querySelector('.mobile-note-header h2').classList.add('dirty');
document.querySelector('.note-header h2').classList.add('dirty');
if(state.failureCount > 0 && !state.to) {
state.to = setTimeout(note.saveNote, state.saveTimeout);
}
}
});
document.getElementById('dark-mode-checkbox').addEventListener('click', toggleDarkMode);
document.getElementById('mobile-dark-mode-checkbox').addEventListener('click', toggleDarkMode);
document.getElementById('show-hide-btn').addEventListener('click', toggleFields);
document.getElementById('mobile-show-hide-btn').addEventListener('click', toggleFields);
document.getElementById('increaseFont').addEventListener('click', increaseFont);
document.getElementById('decreaseFont').addEventListener('click', decreaseFont);
const openRefBtn = document.getElementById('open-ref');
openRefBtn.addEventListener('click', openRef);
openRefBtn.closeSidebar = true;
const mobileOpenRefBtn = document.getElementById('mobile-open-ref');
mobileOpenRefBtn.addEventListener('click', openRef);
mobileOpenRefBtn.closeSidebar = true;
document.getElementById('previewBtn').addEventListener('click', previewNote);
//document.getElementById('shareBtn').addEventListener('click', note.openShareNote);
document.getElementById('searchBtn').addEventListener('click', ref.queryRef);
document.getElementById('closeSearch').addEventListener('click', closeRef);
}
export function initHome() {
setBooks();
setEventListeners();
// expand the sidebar by default if we are on a large screen
if(document.body.clientWidth >= 1501) {
document.querySelector('.container').classList.remove('sidebar-collapsed');
}
$('#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")
},
]
});
$('#note-table').css('width', '100%');
$('#shareBtn').on('click', note.openShareNote);
$('#modal-backdrop').on('click', note.closeShareNote);
state.md = new markdownit({
html: true,
linkify: true,
breaks: true
});
if ($('#noteDate')) {
$('#noteDate').datepicker();
}
if ($('#query')) {
document.querySelector('#query').addEventListener('keyup', function (event) {
if (event.key == "Enter") {
search();
}
});
}
// Assuming 'to' and 'saveInterval' are declared globally elsewhere in your script
if (typeof state.to === 'undefined' || !state.to) {
state.to = setTimeout(note.saveNote, state.saveInterval);
}
}
/**
* 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) => {
state.BOOKS = data;
})
.catch((error) => {
console.log(error);
})
}
/**
* Opens the reference with the option to close the sidebar.
*/
export function openRef(e) {
document.querySelector('#open-ref').classList.add('active');
document.querySelector('#mobile-open-ref').classList.add('active');
let refQuery = document.querySelector('#refQuery');
refQuery.style.display = 'block';
let closeSidebar = false;
if(typeof e.currentTarget.closeSidebar !== 'undefined') {
closeSidebar = e.currentTarget.closeSidebar;
}
if (closeSidebar && !document.querySelector('.container').classList.contains('sidebar-collapsed')) {
document.querySelector('.toggle').click();
}
let ref = document.querySelector('#ref-text');
refQuery.style.left = ref.offsetLeft + 'px';
refQuery.style.top = ref.offsetTop + 'px';
}
/**
* Closes the reference query and resets the reference search form.
*
* @return {void} This function does not return anything.
*/
export function closeRef() {
document.querySelector('#referenceSearch').value = '';
document.querySelector('#referenceSearch').style.display = '';
document.querySelector('#referenceType').value = '';
document.querySelector('#referenceBook').value = '';
document.querySelector('#referenceBook').style.display = 'none';
document.querySelector('#chapter-range').innerText = '';
document.querySelector('#verse-range').innerText = '';
document.querySelector('#refQuery').style.display = 'none';
document.querySelector('#open-ref').classList.remove('active');
document.querySelector('#mobile-open-ref').classList.remove('active');
}
/**
* A function to create a button element with the specified title and event listeners for click and double click actions.
*
* @param {string} title - The title to be displayed on the button.
* @return {Element} The created button element.
*/
export function makeButton(title) {
var btn = document.createElement('button');
btn.innerText = title;
btn.class = 'button';
btn.style = 'line-height:normal;'
btn.addEventListener('click', function () {
removeActiveRef();
document.querySelector('#ref-text').innerHTML = state.md.render(state.references[title]);
this.classList.add('active');
note.findRefLinks();
});
btn.addEventListener('dblclick', function () {
document.querySelector('#ref-text').innerHTML = '';
delete state.references[title];
var list = this.parentElement;
list.remove();
state.saved = false;
state.textDirty = true;
note.saveNote();
});
removeActiveRef();
btn.classList.add('active');
return btn;
}
/**
* Removes the 'active' class from all elements with the class 'active'.
*
* @return {void} This function does not return a value.
*/
export function removeActiveRef() {
tabs = document.querySelectorAll('#ref-list .active');
for (var t in tabs) {
if (isFinite(parseInt(t))) {
tabs[t].classList.remove('active');
}
}
}
/**
* Generates a random UUIDv4 string.
*
* @return {string} The generated UUIDv4 string.
*/
export function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
/**
* Searches for notes based on the query entered in the search field.
* Sends a POST request to the '/search' endpoint with the query as a JSON payload.
* Updates the '#old-notes' element with the search results.
*
* @return {Promise} A Promise that resolves with the search results.
*/
export function search() {
query = document.querySelector('#query').value;
fetch('/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'query': query
})
})
.then(response => response.json())
.then(results => {
var oldNotes = document.querySelector('#old-notes');
oldNotes.innerHTML = '';
for (var n in results) {
var link = document.createElement('a');
link.href = '#';
link.setAttribute('onclick', "note.retrieveNote('" + results[n].id + "');note.openNote();");
link.innerHTML = results[n].title;
var p = document.createElement('p');
p.innerHTML = results[n].passage;
var article = document.createElement('article');
article.appendChild(link);
article.appendChild(p);
oldNotes.append(article);
}
});
}
/**
* Closes the passage popup by clearing its content and hiding it.
*
* @return {void} This function does not return anything.
*/
export function closePopup() {
const popup = document.querySelector('#passage-popup');
popup.innerHTML = '';
popup.style.display = 'none';
}
+506
View File
@@ -0,0 +1,506 @@
import { state } from './state.js';
import { toggleFields, makeButton } from './home.js';
var failureCount = state.saveFailureCount;
/**
* Retrieves a note from the server based on the provided ID.
*
* @param {string} id - The ID of the note to retrieve.
* @param {boolean} [runOpen=true] - Whether to open the note sidebar after retrieving the note.
* @return {Promise<void>} A promise that resolves when the note is successfully retrieved and the UI is updated.
*/
export function retrieveNote(id, runOpen = true) {
fetch('/get-note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'id': id
})
})
.then(response => response.json())
.then(result => {
var dt = new Date(result.date.date);
document.querySelector('#notes').value = result.text;
document.querySelector('#passage').value = result.passage;
document.querySelector('#series').value = result.series.id;
document.querySelector('#speaker').value = result.speaker.id;
document.querySelector('#noteTitle').value = result.title;
document.querySelector('#noteDate').value = '';
document.querySelector('#noteDate').value =
(dt.getMonth() < 9 ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '/' +
(dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate()) + '/' +
dt.getFullYear();
document.querySelector('#noteId').value = result.id;
if (result.recording) {
document.querySelector('#recording').value = result.recording;
}
if (result.refs) {
state.references = result.refs;
}
const list = document.querySelector('#ref-list');
list.innerHTML = '';
var newList = null;
for (var x in state.references) {
var newList = document.createElement('li');
newList.className = 'tab';
var button = makeButton(x);
newList.appendChild(button);
list.appendChild(newList);
}
if (runOpen) {
note.openNote(false);
}
});
}
/**
* Toggles the visibility of the note list and reference elements.
*
* @param {boolean} [openSidebar=true] - Whether to open the sidebar after toggling the visibility.
* @return {void}
*/
export function openNote(openSidebar = true) {
const noteList = document.querySelector('#note-list');
const refs = document.querySelector('#ref-text');
if (noteList.style.display == 'block') {
noteList.style.display = 'none';
refs.style.display = 'block';
} else {
noteList.style.display = 'block';
refs.style.display = 'none';
}
if (openSidebar && !document.querySelector('.container').classList.contains('sidebar-collapsed')) {
document.querySelector('.container').classList.add('sidebar-collapsed');
}
}
/**
* Starts the save process by updating the save-check element's classList, removing error, fa-times-circle, and fa-save classes,
* adding the 'saving' and 'fa-save' classes, and setting the opacity to 1.
*
* @return {void} This function does not return anything.
*/
export function startSave() {
document.querySelector('#save-check').classList.remove('error', 'fa-times-circle', 'fa-save');
document.querySelector('#save-check').classList.add('saving', 'fa-save');
document.querySelector('#save-check').style.opacity = 1;
}
/**
* Displays a checkmark animation on the screen.
*
* @param {none} - This function does not take any parameters.
* @return {none} - This function does not return any value.
*/
export function showSave() {
if (state.saved) { return; }
var checkmark = document.getElementById("save-check");
checkmark.classList.add('fa-save');
// Schedule the animation to run every 1 second (which is equivalent to a 1-second delay between each iteration)
var si = setInterval(function () {
// Increment the opacity of the checkmark by 0.01 each time
let op = parseFloat(checkmark.style.opacity);
checkmark.style.opacity = op - 0.1;
// If the opacity is greater than or equal to 1, reset it back to 0 and stop the animation
if (checkmark.style.opacity == 0.1) {
checkmark.style.opacity = 0;
clearInterval(si);
state.saved = false;
}
}, 100);
}
/**
* function to discard the note by clearing all input fields and closing the menu.
*/
export function deleteNote(noteId, link) {
document.querySelector('#noteTitle').value = '';
document.querySelector('#speaker').value = 0;
document.querySelector('#series').value = 0;
document.querySelector('#template').value = 0;
document.querySelector('#passage').value = '';
document.querySelector('#notes').value = '';
document.querySelector('#recording').value = '';
document.querySelector('#noteDate').value = '';
document.querySelector('#noteId').value = '';
var row = link.parentElement.parentElement;
fetch('/delete-note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'id': noteId
})
})
.then(response => response.json())
.then(data => {
if (data.msg != 'deleted') {
return;
}
alert('Note deleted.');
row.remove();
});
}
/**
* Validates a note by checking if all required fields are filled.
*
* @return {boolean} Returns true if all required fields are filled, false otherwise.
*/
export function validateNote() {
const note = document.querySelector('#notes');
const date = document.querySelector('#noteDate');
const speaker = document.querySelector('#speaker');
const series = document.querySelector('#series');
const title = document.querySelector('#noteTitle');
const psg = document.querySelector('#passage');
let ret = true;
if (!title.value.length) { title.classList.add('input-error'); ret = false; }
if (!date.value) { date.classList.add('input-error'); ret = false; }
if (!parseInt(speaker.value)) { speaker.classList.add('input-error'); ret = false; }
if (!parseInt(series.value)) { series.classList.add('input-error'); ret = false; }
if (!psg.value) { psg.classList.add('input-error'); ret = false; }
if (!note.value.length) { note.classList.add('input-error'); ret = false; }
if (!ret) {
toggleFields(null, true);
}
return ret;
}
/**
* Resets the state of the note editor by clearing the text and form fields,
* resetting the references, and removing any dirty classes. It also sets the
* date to the current date, clears the speaker, series, template, passage,
* recording, and note ID fields. Finally, it clears the reference list and
* reference display.
*
* @return {void} This function does not return anything.
*/
export function newNote() {
notes = document.querySelector('#notes');
notes.text = '';
notes.value = '';
state.references = {};
state.saved = true;
state.textDirty = false;
document.querySelector('.note-header-column h2').classList.remove('dirty');
var dt = new Date();
document.querySelector('#noteDate').value = dt.getFullYear() + '-' +
(dt.getMonth() < 9 ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '-' +
(dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate());
document.querySelector('#noteTitle').value = '';
document.querySelector('#speaker').value = 0;
document.querySelector('#series').value = 0;
document.querySelector('#template').value = 0;
document.querySelector('#passage').value = '';
document.querySelector('#recording').value = '';
document.querySelector('#noteId').value = '';
document.querySelector('#ref-list').innerHTML = '';
document.querySelector('#ref-text').innerHTML = '';
document.querySelector('.container').classList.add('sidebar-collapsed');
}
/**
* Save a note by sending it to the server for storage.
*
* @param {Event} event - The event object triggering the save action.
* @return {void} No explicit return value.
*/
export function saveNote(event) {
console.debug('called saveNote '+new Date());
if (event) {
event.preventDefault();
}
if (!state.textDirty) {
clearTimeout(state.to);
state.to = setTimeout(saveNote, state.saveInterval);
return;
}
document.querySelector('#noteTitle').classList.remove('input-error');
document.querySelector('#noteDate').classList.remove('input-error');
document.querySelector('#speaker').classList.remove('input-error');
document.querySelector('#series').classList.remove('input-error');
document.querySelector('#passage').classList.remove('input-error');
document.querySelector('#notes').classList.remove('input-error');
if (!validateNote()) {
clearTimeout(state.to);
state.to = setTimeout(saveNote, state.saveInterval);
return;
}
let saveCheck = document.querySelector('#save-check');
var noteText = document.querySelector('#notes').value;
startSave();
var note = {
id: document.querySelector("#noteId").value,
date: document.querySelector('#noteDate').value,
title: document.querySelector('#noteTitle').value,
speaker: document.querySelector('#speaker').value,
series: document.querySelector('#series').value,
passage: document.querySelector('#passage').value,
note: document.querySelector('#notes').value,
recording: document.querySelector('#recording').value,
refs: state.references
};
$.ajax({
url: '/save-note',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(note),
dataType: 'json',
timeout: state.saveTimeout
})
.done(function (data) {
if (data.msg == 'saved' && !state.saved) {
saveCheck.classList.remove('saving', 'error', 'fa-times-circle', 'fa-save');
showSave();
if (noteText == document.querySelector('#notes').value) {
state.saved = true;
state.textDirty = false;
document.querySelector('.note-header h2').classList.remove('dirty');
document.querySelector('.mobile-note-header h2').classList.remove('dirty');
}
if (data.new) {
document.querySelector('#noteId').value = data.id;
}
}
})
.fail(function (xhr, status, error) {
state.failureCount--;
saveCheck.classList.remove('saving', 'fa-save');
saveCheck.classList.add('fa-times-circle', 'error');
console.error(error);
})
.always(function (xhr, status) {
if (status == 'timeout') {
saveCheck.classList.remove('saving', 'fa-save');
saveCheck.classList.add('error', 'fa-times-circle');
}
clearTimeout(state.to);
if (state.failureCount > 0) {
state.to = setTimeout(saveNote, state.saveInterval);
} else {
state.failureCount = state.saveFailureCount;
}
});
}
/**
* Function that finds reference links and fetches passage data when clicked.
*/
export function findRefLinks() {
var links = document.querySelector('#ref-text').querySelectorAll('a');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function (e) {
e.preventDefault();
if (!this.href.includes('get-passage')) {
return;
}
var passage = this.href.split('/');
passage = passage[passage.length - 1];
fetch(this.href, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'passage': passage
})
})
.then(response => response.text())
.then(result => {
let psg, book, cv;
passage = passage.replace(/\+/g, ' ');
psg = passage.split(' ');
if (psg.length > 2) {
book = psg[0] + ' ' + psg[1];
cv = psg[2];
} else {
book = psg[0];
cv = psg[1];
}
showPassage(
e,
"<button onclick='note.closePopup()'>Close</button>&nbsp;&nbsp;" +
"<button onclick=\"ref.queryRef('bible', '" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
result);
});
});
}
}
/**
* Finds all links in the note preview and adds event listeners to them.
*
* @return {void}
*/
export function findLinks() {
var links = document.querySelector('#notePreview').querySelectorAll('a');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function (e) {
e.preventDefault();
if (!this.href.includes('get-passage')) {
return;
}
var passage = this.href.split('/');
passage = passage[passage.length - 1];
fetch(this.href, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'passage': passage
})
})
.then(response => response.text())
.then(result => {
passage = passage.replace(/\+/g, ' ');
psg = passage.split(' ');
if (psg.length > 2) {
book = psg[0] + ' ' + psg[1];
cv = psg[2];
} else {
book = psg[0];
cv = psg[1];
}
showPassage(
e,
"<button onclick='note.closePopup()'>Close</button>&nbsp;&nbsp;" +
"<button onclick=\"ref.queryRef('bible', '" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
result);
});
});
}
}
/**
* Shows a passage in a popup element relative to the cursor position.
*
* @param {Event} event - The event that triggered the function.
* @param {string} text - The text to be displayed in the popup.
* @return {void} This function does not return a value.
*/
export function showPassage(event, text) {
// Create a new div element for the popup
const popup = document.querySelector('#passage-popup');
popup.innerHTML = state.md.render(text);
// Position the popup relative to the cursor
let x = event.clientX + window.scrollX;
let y = event.clientY + window.scrollY;
// Set the position of the popup element
popup.style.top = `${y}px`;
popup.style.left = `${x}px`;
popup.style.display = 'block';
}
/**
* Closes the passage popup by clearing its content and hiding it.
*
* @return {void} This function does not return anything.
*/
export function closePopup() {
const popup = document.querySelector('#passage-popup');
popup.innerHTML = '';
popup.style.display = 'none';
}
/**
* Opens the share note functionality.
*/
export function openShareNote() {
let id = document.querySelector('#noteId').value;
if (!id) {
alert('No Open Note Found');
return;
}
let bd = document.querySelector('#modal-backdrop');
bd.style.display = 'block';
let cont = document.querySelector('#modal-container');
cont.style.display = bd.style.display;
let emailCont = document.querySelector('#modal-container');
emailCont.style.left = ((window.innerWidth / 2) - (emailCont.clientWidth / 2)) + 'px';
emailCont.style.top = ((window.innerHeight / 2) - (emailCont.clientHeight / 2)) + 'px';
}
/**
* Closes the share note modal by hiding the backdrop and container,
* and clears the email input value.
*/
export function closeShareNote() {
var bd = document.querySelector('#modal-backdrop');
var cont = document.querySelector('#modal-container');
bd.style.display = 'none';
cont.style.display = 'none';
document.querySelector('#shareEmail').value = '';
}
/**
* Function to share a note by sending the note ID and email to the server.
*/
export function shareNote(event) {
var id = document.querySelector('#noteId').value;
var email = document.querySelector('#shareEmail').value;
if (!id || !email) {
alert('Invalid Input');
return;
}
fetch('/share-note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'id': id,
'email': email
})
})
.then(response => response.json())
.then(result => {
if (result) {
alert(result.msg);
}
});
closeShareNote();
}
+292
View File
@@ -0,0 +1,292 @@
import { state } from './state.js';
import { closeRef, makeButton } from './home.js';
import { saveNote, findRefLinks } from './note.js';
/**
* 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',
headers: {
'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",
headers: {
"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',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
refId: ref.value,
text: cont.value
})
})
.then(response => response.json())
.then(results => {
document.querySelector('#reference').value = '';
document.querySelector('#referenceType').value = '';
document.querySelector('#referenceSeries').value = '';
});
}
/**
* Retrieves the list of books based on the selected reference type.
*
* @return {void}
*/
export function retrieveBooks() {
document.querySelector('#chapter-range').innerText = '';
document.querySelector('#verse-range').innerText = '';
document.querySelector('#referenceSearch').value = '';
document.querySelector('#referenceSearch').style.display = 'none';
const selectedType = document.querySelector('#referenceType').value;
if (!selectedType) { return; }
var bookList = document.querySelector('#referenceBook');
bookList.style.display = "block";
bookList.innerHTML = '';
if (selectedType == 'bible') {
document.querySelector('#referenceSearch').style.display = 'block';
var none = document.createElement("option");
none.value = '';
none.text = '-- Select --';
bookList.appendChild(none);
for (var x in state.BOOKS.bible) {
var newBook = document.createElement("option");
newBook.text = x;
bookList.appendChild(newBook);
}
} else if (selectedType == 'creed') {
var none = document.createElement('option');
none.value = '';
none.text = '-- Select --';
bookList.appendChild(none);
for (var x in state.BOOKS.creed) {
var newBook = document.createElement('option');
newBook.value = x;
newBook.text = state.BOOKS.creed[x];
bookList.appendChild(newBook);
}
} else if (selectedType == 'cd') {
var none = document.createElement("option");
none.value = '';
none.text = '-- Select --';
bookList.appendChild(none);
for (var x in state.BOOKS.cd) {
var newBook = document.createElement("option");
newBook.text = state.BOOKS.cd[x];
bookList.appendChild(newBook);
}
} else if (selectedType == 'hc') {
var none = document.createElement("option");
none.value = '';
none.text = '-- Select --';
bookList.appendChild(none);
for (var x in state.BOOKS[selectedType]) {
var newBook = document.createElement("optgroup");
newBook.label = "Lord's Day " + (parseInt(x) + 1)
var ld = document.createElement("option");
ld.value = 'ld' + (parseInt(x) + 1);
ld.text = "LD " + (parseInt(x) + 1) + " All";
newBook.appendChild(ld);
for (var y in state.BOOKS[selectedType][x]) {
var question = document.createElement("option");
question.value = 'hc' + state.BOOKS[selectedType][x][y];
question.text = "HC" + state.BOOKS[selectedType][x][y];
newBook.appendChild(question);
}
bookList.appendChild(newBook);
}
} else if (selectedType == 'note') {
var none = document.createElement("option");
none.value = '';
none.text = '-- Select --';
bookList.appendChild(none);
fetch('/retrieve-reference', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'type': 'note'
})
})
.then(response => response.json())
.then(results => {
for (var x in results) {
var newBook = document.createElement("option");
newBook.value = results[x].id;
newBook.text = results[x].title;
bookList.appendChild(newBook);
}
});
} else {
var min = state.BOOKS[selectedType][0];
var max = state.BOOKS[selectedType][1];
var none = document.createElement("option");
none.value = '';
none.text = '-- Select --';
bookList.appendChild(none);
for (var x = min; x <= max; x++) {
var newBook = document.createElement("option");
newBook.value = x;
newBook.text = x;
bookList.appendChild(newBook);
}
}
}
/**
* Filters the books based on the selected reference type and updates the chapter range.
*
* @return {void} This function does not return anything.
*/
export function filterBooks() {
document.querySelector('#chapter-range').innerText = '';
document.querySelector('#verse-range').innerText = '';
if (document.querySelector('#referenceType').value != 'bible') {
return;
}
var bookList = document.querySelector('#referenceBook');
var book = state.BOOKS.bible[bookList.value];
var max = Object.keys(book).length;
var chapterRange = document.querySelector('#chapter-range');
chapterRange.innerText = 'Chapters: ' + max;
}
/**
* Filters the verse based on the selected book and chapter.
*
* @return {void} This function does not return anything.
*/
export function filterVerse() {
if (document.querySelector('#referenceType').value != 'bible') {
return;
}
var bookList = document.querySelector('#referenceBook').value;
var search = document.querySelector('#referenceSearch').value;
var chapter = search.split(':')[0];
var verseRange = document.querySelector('#verse-range');
if (!state.BOOKS.bible[bookList] || !state.BOOKS.bible[bookList][chapter]) {
verseRange.innerText = 'Unknown Chapter';
return;
}
var verse = state.BOOKS.bible[bookList][chapter];
verseRange.innerText = 'Verse: ' + verse;
}
/**
* Fetches a reference based on the provided type, book, and input.
*
* @param {string} type - The type of reference.
* @param {string} book - The book of the reference.
* @param {string} input - The input for the reference.
* @return {void} This function does not return anything directly, but processes the fetched reference data.
*/
export function queryRef(e, type = null, book = null, input = null) {
if (!input) {
var input = document.querySelector('#refQuery #referenceSearch').value;
}
if (!type) {
var type = document.querySelector('#referenceType').value;
}
if (!book) {
var book = document.querySelector('#referenceBook').value;
}
fetch('/retrieve-reference', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'type': type,
'book': book,
'reference': input,
})
})
.then(response => response.json())
.then(results => {
const list = document.querySelector('#ref-list');
var newList = document.createElement('li');
newList.className = 'tab';
let button = makeButton(results.title);
newList.appendChild(button);
list.appendChild(newList);
const ref = document.querySelector('#ref-text');
ref.innerHTML = state.md.render(results.text);
state.references[results.title] = results.text;
closeRef();
state.saved = false;
state.textDirty = true;
saveNote();
findRefLinks();
});
}
@@ -1,9 +1,8 @@
// Get references to the form elements
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 nameInput = document.getElementById("registration_form_name");
const emailInput = document.getElementById("registration_form_email");
const passwordInput = document.getElementById("registration_form_plainPassword");
const csrfToken = document.getElementById("registration_form__token").value;
// Add event listeners to the form
const registerBtn = document.querySelector("#register-btn");
@@ -11,35 +10,26 @@ registerBtn.addEventListener("click", handleSubmit);
// Function to handle form submission
function handleSubmit(event) {
// Prevent default form submission behavior
event.preventDefault();
// Validate input
const name = nameInput.value;
const email = emailInput.value;
const password = passwordInput.value;
const confirmPassword = confirmPasswordInput.value;
if (name === "" || email === "" || password === "") {
event.preventDefault();
alert("Please fill in all fields.");
return;
}
if (password !== confirmPassword) {
alert("Passwords do not match.");
return;
}
// Send data to server for processing
const data = {
"name": name,
"email": email,
"password": password,
"plainPassword": password,
"csrf_token": csrfToken
"_token": csrfToken
};
fetch("/index.php/register", {
fetch("/register", {
method: "POST",
headers: {
"Content-Type": "application/json",
+360 -204
View File
@@ -4,87 +4,21 @@ var references = {};
var tabs = [];
let saved = false;
let textDirty = false;
let saveTimeout = 10000;
var to = null;
let controller;
var BOOKS = {};
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);
})
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');
}
});
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 - 50) + 'px';
noteList = document.querySelector('#note-list');
noteList.style.height = (window.innerHeight - 50) + 'px';
notes = document.querySelector('.notes');
notes.style.height = (window.innerHeight - 50) + '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, saveTimeout);
}
}
/**
* Searches for notes based on the query entered in the search field.
* Sends a POST request to the '/search' endpoint with the query as a JSON payload.
* Updates the '#old-notes' element with the search results.
*
* @return {Promise} A Promise that resolves with the search results.
*/
function search() {
query = document.querySelector('#query').value;
fetch('/index.php/search', {
fetch('/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -115,6 +49,15 @@ function search() {
});
}
/**
* Resets the state of the note editor by clearing the text and form fields,
* resetting the references, and removing any dirty classes. It also sets the
* date to the current date, clears the speaker, series, template, passage,
* recording, and note ID fields. Finally, it clears the reference list and
* reference display.
*
* @return {void} This function does not return anything.
*/
function newNote() {
notes = document.querySelector('#notes');
notes.text = '';
@@ -133,7 +76,8 @@ function newNote() {
document.querySelector('#series').value = 0;
document.querySelector('#template').value = 0;
document.querySelector('#passage').value = '';
document.querySelector('#noteId').value = uuidv4();
document.querySelector('#recording').value = '';
document.querySelector('#noteId').value = '';
document.querySelector('#ref-list').innerHTML = '';
document.querySelector('#ref').innerHTML = '';
@@ -151,13 +95,21 @@ function saveNote(event) {
event.preventDefault();
}
document.querySelector('#noteTitle').classList.remove('input-error');
document.querySelector('#noteDate').classList.remove('input-error');
document.querySelector('#speaker').classList.remove('input-error');
document.querySelector('#series').classList.remove('input-error');
document.querySelector('#passage').classList.remove('input-error');
document.querySelector('#notes').classList.remove('input-error');
if (!textDirty || !validateNote()) {
clearTimeout(to);
to = setTimeout(saveNote, saveTimeout);
to = setTimeout(saveNote, saveInterval);
return;
}
let saveCheck = document.querySelector('#save-check');
var noteText = document.querySelector('#notes').value;
startSave();
@@ -169,44 +121,58 @@ function saveNote(event) {
series: document.querySelector('#series').value,
passage: document.querySelector('#passage').value,
note: document.querySelector('#notes').value,
recording: document.querySelector('#recording').value,
refs: references
};
$.ajax({
url: '/index.php/save-note',
url: '/save-note',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(note),
dataType: 'json',
timeout: 5000
timeout: saveTimeout
})
.done(function (data) {
if (data.msg == 'saved' && !saved) {
saveCheck.classList.remove('saving');
saveFailureCount = SAVE_FAILURE_LIMIT;
saveCheck.classList.remove('saving', 'error', 'fa-times-circle', 'fa-save');
showSave();
saved = true;
textDirty = false;
document.querySelector('#note-header-left h2').classList.remove('dirty');
if (noteText == document.querySelector('#notes').value) {
saved = true;
textDirty = false;
document.querySelector('#note-header-left h2').classList.remove('dirty');
}
if (data.new) {
document.querySelector('#noteId').value = data.id;
}
}
})
.fail(function (data) {
saveCheck.classList.remove('saving');
saveCheck.classList.add('error');
console.error(data);
.fail(function (xhr, status, error) {
saveFailureCount--;
saveCheck.classList.remove('saving', 'fa-save');
saveCheck.classList.add('fa-times-circle', 'error');
console.error(error);
})
.always(function (xhr, status) {
if (status == 'timeout') {
saveCheck.classList.remove('saving');
saveCheck.classList.add('error');
saveCheck.classList.remove('saving', 'fa-save');
saveCheck.classList.add('error', 'fa-times-circle');
}
clearTimeout(to);
to = setTimeout(saveNote, saveTimeout);
if (saveFailureCount > 0) {
to = setTimeout(saveNote, saveInterval);
} else {
saveFailureCount = SAVE_FAILURE_LIMIT;
}
});
}
/**
* Validates a note by checking if all required fields are filled.
*
* @return {boolean} Returns true if all required fields are filled, false otherwise.
*/
function validateNote() {
const note = document.querySelector('#notes');
const date = document.querySelector('#noteDate');
@@ -215,23 +181,42 @@ function validateNote() {
const title = document.querySelector('#noteTitle');
const psg = document.querySelector('#passage');
if (!title.value.length) { return false; }
if (!date.value) { return false; }
if (!parseInt(speaker.value)) { return false; }
if (!parseInt(series.value)) { return false; }
if (!psg.value) { return false; }
if (!note.value.length) { return false; }
let ret = true;
return true;
if (!title.value.length) { title.classList.add('input-error'); ret = false; }
if (!date.value) { date.classList.add('input-error'); ret = false; }
if (!parseInt(speaker.value)) { speaker.classList.add('input-error'); ret = false; }
if (!parseInt(series.value)) { series.classList.add('input-error'); ret = false; }
if (!psg.value) { psg.classList.add('input-error'); ret = false; }
if (!note.value.length) { note.classList.add('input-error'); ret = false; }
if (!ret) {
toggleFields(true);
}
return ret;
}
/**
* Checks if a given UUID is valid.
*
* @param {string} uuid - The UUID to be validated.
* @return {boolean} Returns true if the UUID is valid, false otherwise.
*/
function isUuidValid(uuid) {
const regex = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[8|9|a|b][a-f0-9]{3}-[a-f0-9]{12}$/i;
return regex.test(uuid);
}
/**
* Starts the save process by updating the save-check element's classList, removing error, fa-times-circle, and fa-save classes,
* adding the 'saving' and 'fa-save' classes, and setting the opacity to 1.
*
* @return {void} This function does not return anything.
*/
function startSave() {
document.querySelector('#save-check').classList.add('saving');
document.querySelector('#save-check').classList.remove('error', 'fa-times-circle', 'fa-save');
document.querySelector('#save-check').classList.add('saving', 'fa-save');
document.querySelector('#save-check').style.opacity = 1;
}
@@ -245,6 +230,7 @@ function showSave() {
if (saved) { return; }
var checkmark = document.getElementById("save-check");
checkmark.classList.add('fa-save');
// Schedule the animation to run every 1 second (which is equivalent to a 1-second delay between each iteration)
var si = setInterval(function () {
@@ -264,33 +250,44 @@ function showSave() {
/**
* Function to discard the note by clearing all input fields and closing the menu.
*/
function discardNote() {
function deleteNote(noteId, link) {
document.querySelector('#noteTitle').value = '';
document.querySelector('#speaker').value = 0;
document.querySelector('#series').value = 0;
document.querySelector('#template').value = 0;
document.querySelector('#passage').value = '';
document.querySelector('#notes').value = '';
document.querySelector('#recording').value = '';
document.querySelector('#noteDate').value = '';
document.querySelector('#noteId').value = '';
fetch('/index.php/discard-note', {
var row = link.parentElement.parentElement;
fetch('/delete-note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'id': document.querySelector('#noteId').value
'id': noteId
})
.then(response => response.json())
.then(data => {
if (data.msg == 'deleted') {
alert('Note deleted.');
}
})
});
})
.then(response => response.json())
.then(data => {
if (data.msg != 'deleted') {
return;
}
openRef();
alert('Note deleted.');
row.remove();
});
}
/**
* Toggles the display of the new speaker input field and hides the speaker select field.
*
* @return {void} This function does not return anything.
*/
function newSpeaker() {
if (document.querySelector('#speaker').value == 'new') {
document.querySelector('#newSpeaker').style.display = 'inline-block';
@@ -301,9 +298,20 @@ function newSpeaker() {
textDirty = true;
}
/**
* Saves a new speaker to the database and updates the UI with the new speaker option.
*
* @param {Event} event - The keydown event triggered by the user.
* @return {Promise} A Promise that resolves with the results of the fetch request.
*/
function saveSpeaker(event) {
if (event.keyCode == 13) {
fetch('/index.php/save-speaker', {
if (event.keyCode == 27) {
document.querySelector('#newSpeaker').style.display = 'none';
document.querySelector('#speaker').style.display = 'inline-block';
document.querySelector('#speaker').value = 0;
}
if (event.keyCode == 13 && document.querySelector('#newSpeaker').value != '') {
fetch('/save-speaker', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -329,6 +337,9 @@ function saveSpeaker(event) {
}
}
/**
* A description of the entire function.
*/
function newSeries() {
if (document.querySelector('#series').value == 'new') {
document.querySelector('#newSeries').style.display = 'inline-block';
@@ -339,9 +350,20 @@ function newSeries() {
textDirty = true;
}
/**
* Saves a series by making a POST request to '/save-series' with the series name as the request body.
*
* @param {Event} event - The keydown event.
* @return {Promise} A Promise that resolves with the response from the server.
*/
function saveSeries(event) {
if (event.keyCode == 13) {
fetch('/index.php/save-series', {
if (event.keyCode == 27) {
document.querySelector('#newSeries').style.display = 'none';
document.querySelector('#series').style.display = 'inline-block';
document.querySelector('#series').value = 0;
}
if (event.keyCode == 13 && document.querySelector('#newSeries').value != '') {
fetch('/save-series', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -367,7 +389,14 @@ function saveSeries(event) {
}
}
/**
* Opens the reference with the option to close the sidebar.
*
* @param {boolean} closeSidebar - Indicates whether to close the sidebar when opening the reference.
*/
function openRef(closeSidebar = true) {
document.querySelector('#openRefBtn').classList.add('active');
refQuery = document.querySelector('#refQuery');
refQuery.style.display = 'block';
@@ -379,6 +408,11 @@ function openRef(closeSidebar = true) {
}
}
/**
* Closes the reference query and resets the reference search form.
*
* @return {void} This function does not return anything.
*/
function closeRef() {
document.querySelector('#referenceSearch').value = '';
document.querySelector('#referenceSearch').style.display = '';
@@ -389,8 +423,17 @@ function closeRef() {
document.querySelector('#verse-range').innerText = '';
document.querySelector('#refQuery').style.display = 'none';
document.querySelector('#openRefBtn').classList.remove('active');
}
/**
* Fetches a reference based on the provided type, book, and input.
*
* @param {string} type - The type of reference.
* @param {string} book - The book of the reference.
* @param {string} input - The input for the reference.
* @return {void} This function does not return anything directly, but processes the fetched reference data.
*/
function queryRef(type = null, book = null, input = null) {
if (!input) {
var input = document.querySelector('#refQuery #referenceSearch').value;
@@ -401,7 +444,7 @@ function queryRef(type = null, book = null, input = null) {
if (!book) {
var book = document.querySelector('#referenceBook').value;
}
fetch('/index.php/retrieve-reference', {
fetch('/retrieve-reference', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -435,13 +478,21 @@ function queryRef(type = null, book = null, input = null) {
});
}
/**
* A function to create a button element with the specified title and event listeners for click and double click actions.
*
* @param {string} title - The title to be displayed on the button.
* @return {Element} The created button element.
*/
function makeButton(title) {
var btn = document.createElement('button');
btn.innerText = title;
btn.class = 'button';
btn.style = 'line-height:normal;'
btn.addEventListener('click', function () {
removeActiveRef();
document.querySelector('#ref').innerHTML = md.render(references[title]);
this.classList.add('activeRef');
this.classList.add('active');
findRefLinks();
});
@@ -456,80 +507,53 @@ function makeButton(title) {
});
removeActiveRef();
btn.classList.add('activeRef');
btn.classList.add('active');
return btn;
}
/**
* Removes the 'active' class from all elements with the class 'active'.
*
* @return {void} This function does not return a value.
*/
function removeActiveRef() {
tabs = document.querySelectorAll('.activeRef');
tabs = document.querySelectorAll('.active');
for (var t in tabs) {
if (isFinite(parseInt(t))) {
tabs[t].classList.remove('activeRef');
tabs[t].classList.remove('active');
}
}
}
function retrieveTemplate(orig, dest) {
const temp = document.querySelector('#' + orig);
if (temp.value == '0') {
document.querySelector('#' + dest).value = '';
return;
}
fetch('/index.php/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.
* Toggles the visibility of the fields container and updates the active state of the show/hide button.
*
* @param boolean show
* @return {void}
*/
function saveTemplate() {
fetch('/index.php/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);
});
}
function toggleFields() {
function toggleFields(show = false) {
const fieldsContainer = document.getElementById('fields-container');
const showHideBtn = document.getElementById('show-hide-btn');
if (fieldsContainer.classList.contains('show')) {
fieldsContainer.classList.remove('show');
fieldsContainer.style.display = 'none';
showHideBtn.classList.remove('active');
} else {
if (show || !fieldsContainer.classList.contains('show')) {
fieldsContainer.classList.add('show');
fieldsContainer.style.display = 'block';
showHideBtn.classList.add('active');
} else {
fieldsContainer.classList.remove('show');
fieldsContainer.style.display = 'none';
showHideBtn.classList.remove('active');
}
setHeight();
}
/**
* Retrieves the list of books based on the selected reference type.
*
* @return {void}
*/
function retrieveBooks() {
document.querySelector('#chapter-range').innerText = '';
document.querySelector('#verse-range').innerText = '';
@@ -573,6 +597,51 @@ function retrieveBooks() {
newBook.text = BOOKS.cd[x];
bookList.appendChild(newBook);
}
} else if (selectedType == 'hc') {
var none = document.createElement("option");
none.value = '';
none.text = '-- Select --';
bookList.appendChild(none);
for (var x in BOOKS[selectedType]) {
var newBook = document.createElement("optgroup");
newBook.label = "Lord's Day " + (parseInt(x) + 1)
var ld = document.createElement("option");
ld.value = 'ld' + (parseInt(x) + 1);
ld.text = "LD " + (parseInt(x) + 1) + " All";
newBook.appendChild(ld);
for (var y in BOOKS[selectedType][x]) {
var question = document.createElement("option");
question.value = 'hc' + BOOKS[selectedType][x][y];
question.text = "HC" + BOOKS[selectedType][x][y];
newBook.appendChild(question);
}
bookList.appendChild(newBook);
}
} else if (selectedType == 'note') {
var none = document.createElement("option");
none.value = '';
none.text = '-- Select --';
bookList.appendChild(none);
fetch('/retrieve-reference', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'type': 'note'
})
})
.then(response => response.json())
.then(results => {
for (var x in results) {
var newBook = document.createElement("option");
newBook.value = results[x].id;
newBook.text = results[x].title;
bookList.appendChild(newBook);
}
});
} else {
var min = BOOKS[selectedType][0];
var max = BOOKS[selectedType][1];
@@ -589,6 +658,11 @@ function retrieveBooks() {
}
}
/**
* Filters the books based on the selected reference type and updates the chapter range.
*
* @return {void} This function does not return anything.
*/
function filterBooks() {
document.querySelector('#chapter-range').innerText = '';
document.querySelector('#verse-range').innerText = '';
@@ -604,6 +678,11 @@ function filterBooks() {
chapterRange.innerText = 'Chapters: ' + max;
}
/**
* Filters the verse based on the selected book and chapter.
*
* @return {void} This function does not return anything.
*/
function filterVerse() {
if (document.querySelector('#referenceType').value != 'bible') {
return;
@@ -622,45 +701,12 @@ function filterVerse() {
verseRange.innerText = 'Verse: ' + verse;
}
function retrieveReference(el) {
fetch('/index.php/get-reference', {
method: "POST",
header: {
"Content-Type": "application/json"
},
body: JSON.stringify({
file: el.value,
type: el.options[el.selectedIndex].getAttribute('type')
})
})
.then(response => response.json())
.then(results => {
document.querySelector('#reference').value = results.text;
});
}
function saveReference() {
var select = document.querySelector('#references');
fetch('/index.php/save-reference', {
method: 'POST',
header: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: select.options[select.selectedIndex].getAttribute('type'),
file: select.value,
text: document.querySelector('#reference').value
})
})
.then(response => response.json())
.then(results => {
alert(results.msg);
document.querySelector('#reference').value = '';
document.querySelector('#references').value = '';
});
}
/**
* Previews a note by rendering the markdown content of the note in a preview section.
* Toggles between the note text and preview sections.
*
* @return {void} This function does not return anything.
*/
function previewNote() {
var noteText = document.querySelector('#notes');
var notePreview = document.querySelector('#notePreview');
@@ -688,6 +734,11 @@ function previewNote() {
findLinks();
}
/**
* Finds all links in the note preview and adds event listeners to them.
*
* @return {void}
*/
function findLinks() {
var links = document.querySelector('#notePreview').querySelectorAll('a');
@@ -730,6 +781,9 @@ function findLinks() {
}
}
/**
* Function that finds reference links and fetches passage data when clicked.
*/
function findRefLinks() {
var links = document.querySelector('#ref').querySelectorAll('a');
@@ -772,6 +826,13 @@ function findRefLinks() {
}
}
/**
* Shows a passage in a popup element relative to the cursor position.
*
* @param {Event} event - The event that triggered the function.
* @param {string} text - The text to be displayed in the popup.
* @return {void} This function does not return a value.
*/
function showPassage(event, text) {
// Create a new div element for the popup
const popup = document.querySelector('#passage-popup');
@@ -787,12 +848,23 @@ function showPassage(event, text) {
popup.style.display = 'block';
}
/**
* Closes the passage popup by clearing its content and hiding it.
*
* @return {void} This function does not return anything.
*/
function closePopup() {
const popup = document.querySelector('#passage-popup');
popup.innerHTML = '';
popup.style.display = 'none';
}
/**
* Toggles the visibility of the note list and reference elements.
*
* @param {boolean} [openSidebar=true] - Whether to open the sidebar after toggling the visibility.
* @return {void}
*/
function openNote(openSidebar = true) {
const noteList = document.querySelector('#note-list');
const refs = document.querySelector('#ref');
@@ -810,8 +882,15 @@ function openNote(openSidebar = true) {
}
}
/**
* Retrieves a note from the server based on the provided ID.
*
* @param {string} id - The ID of the note to retrieve.
* @param {boolean} [runOpen=true] - Whether to open the note sidebar after retrieving the note.
* @return {Promise<void>} A promise that resolves when the note is successfully retrieved and the UI is updated.
*/
function retrieveNote(id, runOpen = true) {
fetch('/index.php/get-note', {
fetch('/get-note', {
method: 'POST',
header: {
'Content-Type': 'application/json'
@@ -857,14 +936,91 @@ function retrieveNote(id, runOpen = true) {
});
}
/**
* Opens the share note functionality.
*/
function openShareNote() {
var id = document.querySelector('#noteId').value;
if (!id) {
alert('No Open Note Found');
return;
}
bd = document.querySelector('#modal-backdrop');
bd.style.display = 'block';
cont = document.querySelector('#modal-container');
cont.style.display = bd.style.display;
emailCont = document.querySelector('#modal-container');
emailCont.style.left = ((window.innerWidth / 2) - (emailCont.clientWidth / 2)) + 'px';
emailCont.style.top = ((window.innerHeight / 2) - (emailCont.clientHeight / 2)) + 'px';
}
/**
* Closes the share note modal by hiding the backdrop and container,
* and clears the email input value.
*/
function closeShareNote() {
var bd = document.querySelector('#modal-backdrop');
var cont = document.querySelector('#modal-container');
bd.style.display = 'none';
cont.style.display = 'none';
document.querySelector('#shareEmail').value = '';
}
/**
* Function to share a note by sending the note ID and email to the server.
*/
function shareNote(event) {
var id = document.querySelector('#noteId').value;
var email = document.querySelector('#shareEmail').value;
if (!id || !email) {
alert('Invalid Input');
return;
}
fetch('/share-note', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'id': id,
'email': email
})
})
.then(response => response.json())
.then(result => {
if (result) {
alert(result.msg);
}
});
closeShareNote();
}
/**
* Increases the font size of the element with the id 'ref' by 1 point.
*
* @return {void} This function does not return a value.
*/
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';
}
/**
* Decreases the font size of the element with the id 'ref' by 1 point.
*
* @return {void} This function does not return a value.
*/
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';
}
/**
+1
View File
File diff suppressed because one or more lines are too long
+54
View File
@@ -0,0 +1,54 @@
import { state } from './state.js';
/**
* A description of the entire function.
*/
export function newSeries() {
if (document.querySelector('#series').value == 'new') {
document.querySelector('#newSeries').style.display = 'inline-block';
document.querySelector('#series').style.display = 'none';
}
state.saved = false;
state.textDirty = true;
}
/**
* Saves a series by making a POST request to '/save-series' with the series name as the request body.
*
* @param {Event} event - The keydown event.
* @return {Promise} A Promise that resolves with the response from the server.
*/
export function saveSeries(event) {
if (event.keyCode == 27) {
document.querySelector('#newSeries').style.display = 'none';
document.querySelector('#series').style.display = 'inline-block';
document.querySelector('#series').value = 0;
}
if (event.keyCode == 13 && document.querySelector('#newSeries').value != '') {
fetch('/save-series', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'seriesName': document.querySelector('#newSeries').value
})
})
.then(response => response.json())
.then(results => {
var newSeries = document.createElement('option');
newSeries.text = document.querySelector('#newSeries').value;
newSeries.value = results.id;
document.querySelector('#series').add(newSeries);
alert(results.msg);
document.querySelector('#newSeries').style.display = 'none';
document.querySelector('#series').style.display = 'inline-block';
document.querySelector('#newSeries').value = '';
document.querySelector('#series').value = results.id;
});
}
}
+54
View File
@@ -0,0 +1,54 @@
import { state } from './state.js';
/**
* Toggles the display of the new speaker input field and hides the speaker select field.
*
* @return {void} This function does not return anything.
*/
export function newSpeaker() {
if (document.querySelector('#speaker').value == 'new') {
document.querySelector('#newSpeaker').style.display = 'inline-block';
document.querySelector('#speaker').style.display = 'none';
}
state.saved = false;
state.textDirty = true;
}
/**
* Saves a new speaker to the database and updates the UI with the new speaker option.
*
* @param {Event} event - The keydown event triggered by the user.
* @return {Promise} A Promise that resolves with the results of the fetch request.
*/
export function saveSpeaker(event) {
if (event.keyCode == 27) {
document.querySelector('#newSpeaker').style.display = 'none';
document.querySelector('#speaker').style.display = 'inline-block';
document.querySelector('#speaker').value = 0;
}
if (event.keyCode == 13 && document.querySelector('#newSpeaker').value != '') {
fetch('/save-speaker', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'speakerName': document.querySelector('#newSpeaker').value
})
})
.then(response => response.json())
.then(results => {
var newSpeaker = document.createElement('option');
newSpeaker.text = document.querySelector('#newSpeaker').value;
newSpeaker.value = results.id;
document.querySelector('#speaker').add(newSpeaker);
alert(results.msg);
document.querySelector('#newSpeaker').style.display = 'none';
document.querySelector('#speaker').style.display = 'inline-block';
document.querySelector('#newSpeaker').value = '';
document.querySelector('#speaker').value = results.id;
});
}
}
+12
View File
@@ -0,0 +1,12 @@
export let state = {
textDirty: false,
saved: true,
references: {},
saveTimeout: null,
saveInterval: 5000,
saveFailureCount: 0,
to: null,
BOOKS: {},
md: null,
failureCount: 0,
}
+52
View File
@@ -0,0 +1,52 @@
import { state } from "./state.js";
/**
* 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;
state.textDirty = true;
});
}
/**
* 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);
});
}
@@ -1507,14 +1507,6 @@ input[type=radio] {
input[type=checkbox] + label,
input[type=radio] + label {
text-decoration: none;
color: #7f888f;
cursor: pointer;
display: inline-block;
font-size: 1em;
font-weight: 400;
padding-left: 2.4em;
padding-right: 0.75em;
position: relative;
}
input[type=checkbox] + label:before,
input[type=radio] + label:before {
@@ -1529,6 +1521,17 @@ input[type=radio] + label:before {
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
input[type=checkbox] + label,
input[type=radio] + label {
color: #7f888f;
cursor: pointer;
display: inline-block;
font-size: 1em;
font-weight: 400;
padding-left: 2.4em;
padding-right: 0.75em;
position: relative;
}
input[type=checkbox] + label:before,
input[type=radio] + label:before {
background: #ffffff;
@@ -1607,8 +1610,6 @@ input[type=radio] + label:before {
/* Icon */
.icon {
text-decoration: none;
border-bottom: none;
position: relative;
}
.icon:before {
-moz-osx-font-smoothing: grayscale;
@@ -1622,6 +1623,10 @@ input[type=radio] + label:before {
font-family: "Font Awesome 5 Free";
font-weight: 400;
}
.icon {
border-bottom: none;
position: relative;
}
.icon > .label {
display: none;
}
@@ -1812,10 +1817,6 @@ ul.contact {
}
ul.contact li {
text-decoration: none;
border-top: solid 1px rgba(210, 215, 217, 0.75);
margin: 1.5em 0 0 0;
padding: 1.5em 0 0 3em;
position: relative;
}
ul.contact li:before {
-moz-osx-font-smoothing: grayscale;
@@ -1829,6 +1830,12 @@ ul.contact li:before {
font-family: "Font Awesome 5 Free";
font-weight: 400;
}
ul.contact li {
border-top: solid 1px rgba(210, 215, 217, 0.75);
margin: 1.5em 0 0 0;
padding: 1.5em 0 0 3em;
position: relative;
}
ul.contact li:before {
color: #f56a6a;
display: inline-block;
@@ -1883,10 +1890,10 @@ ul.pagination li > .page.active {
color: #ffffff !important;
}
ul.pagination li > .page.active:hover {
background-color: #f67878;
background-color: rgb(245.9622641509, 120.3377358491, 120.3377358491);
}
ul.pagination li > .page.active:active {
background-color: #f45c5c;
background-color: rgb(244.0377358491, 91.6622641509, 91.6622641509);
}
ul.pagination li:first-child {
padding-right: 0.75em;
@@ -2045,14 +2052,14 @@ input[type=reset].primary:hover,
input[type=button].primary:hover,
button.primary:hover,
.button.primary:hover {
background-color: #f67878;
background-color: rgb(245.9622641509, 120.3377358491, 120.3377358491);
}
input[type=submit].primary:active,
input[type=reset].primary:active,
input[type=button].primary:active,
button.primary:active,
.button.primary:active {
background-color: #f45c5c;
background-color: rgb(244.0377358491, 91.6622641509, 91.6622641509);
}
input[type=submit].disabled, input[type=submit]:disabled,
input[type=reset].disabled,
@@ -2418,7 +2425,6 @@ button:disabled,
/* Sidebar */
#search form {
text-decoration: none;
position: relative;
}
#search form:before {
-moz-osx-font-smoothing: grayscale;
@@ -2432,6 +2438,9 @@ button:disabled,
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
#search form {
position: relative;
}
#search form:before {
transform: scaleX(-1);
color: #7f888f;
@@ -2486,7 +2495,7 @@ button:disabled,
padding-bottom: 0;
}
#sidebar > .inner > .alt {
background-color: #eff1f2;
background-color: rgb(239.3333333333, 240.9, 242.4666666667);
border-bottom: 0;
margin: -2.2222222222em 0 4.4444444444em -2.2222222222em;
padding: 2.2222222222em;
@@ -2494,6 +2503,20 @@ button:disabled,
}
#sidebar .toggle {
text-decoration: none;
}
#sidebar .toggle:before {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
text-transform: none !important;
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
#sidebar .toggle {
transition: left 0.5s ease;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
border: 0;
@@ -2511,18 +2534,6 @@ button:disabled,
width: 6em;
z-index: 10000;
}
#sidebar .toggle:before {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
text-transform: none !important;
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
#sidebar .toggle:before {
content: "\f0c9";
font-size: 2rem;
@@ -2616,7 +2627,7 @@ button:disabled,
z-index: 1;
}
#sidebar .toggle:after {
background: rgba(222, 225, 226, 0.75);
background: rgba(222.2, 224.50625, 226.3, 0.75);
border-radius: 0.375em;
content: "";
height: 3.5em;
@@ -2786,8 +2797,6 @@ button:disabled,
#menu ul a.opener, #menu ul span.opener {
transition: color 0.2s ease-in-out;
text-decoration: none;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
position: relative;
}
#menu ul a.opener:before, #menu ul span.opener:before {
-moz-osx-font-smoothing: grayscale;
@@ -2801,6 +2810,10 @@ button:disabled,
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
#menu ul a.opener, #menu ul span.opener {
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
position: relative;
}
#menu ul a.opener:before, #menu ul span.opener:before {
transition: color 0.2s ease-in-out, transform 0.2s ease-in-out;
color: #9fa3a6;
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More