From 22dff8705dcf517207d012218c4c800c55f7997c Mon Sep 17 00:00:00 2001 From: P-A Date: Thu, 5 Feb 2026 20:24:22 +0100 Subject: [PATCH] First commit of homework assistant. Only contains vocabulary base functionality --- css/styles.css | 140 +++++++ images/de_DE.svg | 5 + images/en_GB.svg | 7 + images/es_ES.svg | 544 +++++++++++++++++++++++++++ images/favicon.png | Bin 0 -> 1010 bytes images/fr_FR.svg | 7 + images/sv_SE.svg | 4 + index.html | 19 + javascript/homeworkElement.js | 31 ++ javascript/homeworkLayout.js | 22 ++ javascript/homeworkPage.js | 96 +++++ javascript/homeworkSession.js | 78 ++++ javascript/homeworkVocabularyTask.js | 16 + resources/en_GB.json | 4 + resources/sv_SE.json | 39 ++ 15 files changed, 1012 insertions(+) create mode 100644 css/styles.css create mode 100644 images/de_DE.svg create mode 100644 images/en_GB.svg create mode 100644 images/es_ES.svg create mode 100644 images/favicon.png create mode 100644 images/fr_FR.svg create mode 100644 images/sv_SE.svg create mode 100644 index.html create mode 100644 javascript/homeworkElement.js create mode 100644 javascript/homeworkLayout.js create mode 100644 javascript/homeworkPage.js create mode 100644 javascript/homeworkSession.js create mode 100644 javascript/homeworkVocabularyTask.js create mode 100644 resources/en_GB.json create mode 100644 resources/sv_SE.json diff --git a/css/styles.css b/css/styles.css new file mode 100644 index 0000000..c54a619 --- /dev/null +++ b/css/styles.css @@ -0,0 +1,140 @@ +@charset "UTF-8"; + +:host { + display: block; +} + +html { + min-height: 100vh; + min-width: 100vw; +} + +body { + min-height: 100vh; + min-width: 100vw; + margin: 0px; + scrollbar-width: thin; +} + +.text { + color: black; +} + +homework-session { + display: block; + min-height: 100vh; + min-width: 100vw; + font-family: Georgia, Times, serif; + font-size: 18pt; + text-shadow: none; + user-select: none; + margin: 0px; + background-color: white; + overflow: hidden; + padding: 0 0 0 0; +} + +homework-layout > #headings { + padding: .1em .5em 1em .4em; + margin: .1em; + border-radius: .3em; + background-color:white; + box-shadow: -4px 2px 5px 2px rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); + z-index: 5000; +} + +homework-layout > #headings > h1 { + margin-bottom: .1em; +} + +homework-layout > #headings > h3 { + margin-top: .1em; + font-size: .8em; +} + +homework-page { + margin: 0; + padding: 0; +} + +homework-page > #sub-headers { + display: flex; + flex-flow: row nowrap; + justify-content: flex-start; + column-gap: .5em; + margin-left: .7em; +} + +p.source-language, p.target-language { + width: 40%; + margin-bottom: 0; +} + +p.target-language { + margin-left: .3em; +} + +homework-page > #content { + margin-left: .7em; +} + +homework-vocabulary-task { + display: flex; + flex-flow: row nowrap; + column-gap: .5em; + margin-top: .4em; +} + +homework-vocabulary-task > input { + font-size: .8em; + width: 40%; +} + +#page-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-left: .4em; +} + +#page-header > #buttons { + display: flex; + flex-flow: row nowrap; + justify-content: flex-end; +} + +.button { + display: flex; + flex-flow: column; + background: linear-gradient(#F2F2F2, #CFCFCF); + height: .7em; + min-width: 3em; + width: auto; + padding: .4em 1em .4em 1em; + border-style: solid; + border-color: #707070; + border-width: .1em; + border-radius: .3em; + vertical-align: middle; + text-align: center; + margin-right: .6em; + align-items: center; + cursor: pointer; + user-select: none; +} + +.button-text { + font-family: Georgia, Times, serif; + font-size: .6em; + margin: 0; + white-space: nowrap; + overflow: hidden; +} + +.button:hover { + box-shadow: 0 0 2px 1px #707070; +} + +.button:active { + box-shadow: 0 0 3px 2px #707070; +} \ No newline at end of file diff --git a/images/de_DE.svg b/images/de_DE.svg new file mode 100644 index 0000000..b08334b --- /dev/null +++ b/images/de_DE.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/images/en_GB.svg b/images/en_GB.svg new file mode 100644 index 0000000..dbac25e --- /dev/null +++ b/images/en_GB.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/images/es_ES.svg b/images/es_ES.svg new file mode 100644 index 0000000..815e0f8 --- /dev/null +++ b/images/es_ES.svg @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/favicon.png b/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..e3a31db3b7a4ab26ac0a325245685c05bcd12bf2 GIT binary patch literal 1010 zcmVPyt5;Bo*LPK&XIF0qKCF0!Rgz3Ua9ccR)IT`A+-Lu(#`7|De-J z9%*Esy*u;X{CV&E?8N2##POf41dg4-H3Mq~W=3Ewp_u`kz5Rb?;EADYOu2Tmk!B1m zNdTZPOgE-)!o7Fsb{XGAPKbWC40&fXv`?RAj6&A z`}s|YUDvP(Yak=1lqmK~pk@BnZa%vGS+|}5-~j2x&+qvCHbfF&b3{Gmg9G@R8l#>- zYa1A;5)8jI?Zbn3+=|>L5GhR!k7s8;bcW&{`Rx{vz00u#SWo=}2%*bKrNn=+A@?-l zfD&m<<6}U!37rl9L7hy%gNzB#AJj5J)W}Xr8e0JPWCKQz4+)8X z*V)4{2ecAV-uodji2%{{U*z6?Q|Ab!@ynrz$<+WXt+}xUAKW5Jw3xY}CdQWkQhRc7 zd6mG`yl-uhA0lL!Ob?1DkUG>+=hXX!Dg7a#$^416qrDxo1@scFD^{gouLa|EEBDJRWp;BqJefFJ`+gapH- zPdap^a+> g77FBKGbf*cKdEfnj%0 + + + + + + diff --git a/images/sv_SE.svg b/images/sv_SE.svg new file mode 100644 index 0000000..0e41780 --- /dev/null +++ b/images/sv_SE.svg @@ -0,0 +1,4 @@ + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..5bc2d69 --- /dev/null +++ b/index.html @@ -0,0 +1,19 @@ + + + + + + + Homework vocabulary + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/homeworkElement.js b/javascript/homeworkElement.js new file mode 100644 index 0000000..148bbc9 --- /dev/null +++ b/javascript/homeworkElement.js @@ -0,0 +1,31 @@ +class HomeworkElement extends HTMLElement { + + static updateTexts(container) { + let textElements = container.querySelectorAll(".text") + console.log(textElements) + textElements.forEach((item, index) => { + let itemId = item.getAttribute("id") + let itemText = HomeworkSession.texts[itemId] + HomeworkElement.applyText(itemText, item, null) + }) + } + + static applyText(sourceText, targetElement, fallback = '') { + if(sourceText.length > 0) { + targetElement.innerHTML = sourceText + targetElement.innerHTML = targetElement.textContent.trim() + } else if(fallback == '') { + console.warn('Missing text in: ', sourceText) + } else { + targetElement.innerHTML = fallback + } + } +} + +const HomeworkTypes = Object.freeze({ + VOCABULARY_ENGLISH: "'English vocabulary'", + VOCABULARY_FRENCH: "'French vocabulary'", + VOCABULARY_GERMAN: "'German vocabulary'", + VOCABULARY_SPANISH: "'Spanish vocabulary'", + MATH: "'Math'" +}) diff --git a/javascript/homeworkLayout.js b/javascript/homeworkLayout.js new file mode 100644 index 0000000..61700f7 --- /dev/null +++ b/javascript/homeworkLayout.js @@ -0,0 +1,22 @@ +class HomeworkLayout extends HomeworkElement { + constructor () { + super() + this.innerHTML = + ` +
+

+

+
+
+
+ ` + this.pages = this.querySelector('#pages') + } + + connectedCallback() { + console.log("Layout added to session") + let page = new HomeworkPage(HomeworkTypes.VOCABULARY_ENGLISH) + this.pages.append(page) + } +} +customElements.define('homework-layout', HomeworkLayout) \ No newline at end of file diff --git a/javascript/homeworkPage.js b/javascript/homeworkPage.js new file mode 100644 index 0000000..ce73523 --- /dev/null +++ b/javascript/homeworkPage.js @@ -0,0 +1,96 @@ +class HomeworkPage extends HomeworkElement { + constructor (type) { + super() + this.innerHTML = + ` + +
+

+

+
+
+
+ ` + let languageTextId = "" + let sourceLanguageTextId = "text030" + let targetLanguageTextId = "" + switch(type) { + case HomeworkTypes.VOCABULARY_ENGLISH: + console.log("English vocabulary") + languageTextId = "text005" + targetLanguageTextId = "text031" + break + case HomeworkTypes.VOCABULARY_FRENCH: + console.log("French vocabulary") + languageTextId = "text025" + targetLanguageTextId = "text032" + break + case HomeworkTypes.VOCABULARY_GERMAN: + console.log("German vocabulary") + languageTextId = "text024" + targetLanguageTextId = "text034" + break + case HomeworkTypes.VOCABULARY_SPANISH: + console.log("Spanish vocabulary") + languageTextId = "text026" + targetLanguageTextId = "text033" + break + default: + console.log("Math") + languageTextId = "text004" + } + this.type = type + this.headingText = this.querySelector('h2') + this.headingText.setAttribute("id", languageTextId) + this.languageHeaders = this.querySelectorAll('#sub-headers > p') + this.sourceLanguage = this.languageHeaders[0] + this.targetLanguage = this.languageHeaders[1] + this.sourceLanguage.setAttribute("id", sourceLanguageTextId) + this.targetLanguage.setAttribute("id", targetLanguageTextId) + this.content = this.querySelector('#content') + this.newButton = this.querySelector('#new') + this.newButton.addEventListener("click", this.newVocabulary.bind(this)) + this.saveButton = this.querySelector('#save') + this.saveButton.addEventListener("click", this.saveVocabularies.bind(this)) + this.trainButton = this.querySelector('#train') + this.trainButton.addEventListener("click", this.trainVocabulary.bind(this)) + } + + connectedCallback() { + console.log("Page of type " + this.type + " added to session") + if(this.type == HomeworkTypes.VOCABULARY_ENGLISH) { + const row = new HomeworkVocabularyTask() + this.content.append(row) + } + } + + newVocabulary() { + if(this.type == HomeworkTypes.VOCABULARY_ENGLISH) { + const row = new HomeworkVocabularyTask() + this.content.append(row) + console.log("New row in page") + } + } + + saveVocabularies() { + console.log("Saving page content") + } + + trainVocabulary() { + console.log("Train!!") + } +} +customElements.define('homework-page', HomeworkPage) \ No newline at end of file diff --git a/javascript/homeworkSession.js b/javascript/homeworkSession.js new file mode 100644 index 0000000..13a9b58 --- /dev/null +++ b/javascript/homeworkSession.js @@ -0,0 +1,78 @@ +class HomeworkSession extends HomeworkElement { + + constructor() { + super() + this.addEventListener('texts-loaded', this.updateTexts.bind(this)) + } + + connectedCallback() { + let top = new HomeworkLayout() + this.append(top) + console.log("Session added to DOM") + } + + static get observedAttributes () { + return [ 'language' ] + } + + attributeChangedCallback(name, oldValue, newValue) { + if(name == 'language') { + if(oldValue === null) { + console.log("Language initiated to " + newValue) + } else { + console.log("Language changed to " + newValue + " from " + oldValue) + } + this.changeLanguage(newValue) + } else { + console.log("Unknown property", name) + } + } + + get language() { + let languageCode = this.getAttribute("language") + return languageCode + } + + set language(languageCode) { + this.setAttribute("language", languageCode) + } + + async changeLanguage(languageCode) { + let languageFile = "/resources/" + languageCode + ".json" + let response = await fetch(languageFile) + HomeworkSession.texts = await response.json() + this.dispatchEvent(new CustomEvent('texts-loaded', { bubbles: true })) + } + + updateTexts() { + HomeworkElement.updateTexts(this) + } + +/* + + homeworkTypeChanged(event) { + let homeworkType = event.target.value + console.log("Changed homework type to " + homeworkType ) + let pages = this.querySelectorAll('.page') + pages.forEach((page) => { + page.classList.remove('active') + }) + let page = null + switch(homeworkType) { + case 'math': + page = this.querySelector('homework-page-math') + page.classList.add('active') + break + case 'englishVocabulary': + page = this.querySelector('homework-page-english-vocabulary') + page.classList.add('active') + break + default: + console.warn("Unknown type " + homeworkType) + break + } + } + */ +} +HomeworkSession.texts = { } +customElements.define('homework-session', HomeworkSession) diff --git a/javascript/homeworkVocabularyTask.js b/javascript/homeworkVocabularyTask.js new file mode 100644 index 0000000..d7dd32c --- /dev/null +++ b/javascript/homeworkVocabularyTask.js @@ -0,0 +1,16 @@ +class HomeworkVocabularyTask extends HomeworkElement { + constructor () { + super() + this.innerHTML = + ` + + +
+ ` + } + + connectedCallback() { + console.log("New task") + } +} +customElements.define('homework-vocabulary-task', HomeworkVocabularyTask) \ No newline at end of file diff --git a/resources/en_GB.json b/resources/en_GB.json new file mode 100644 index 0000000..b6767fa --- /dev/null +++ b/resources/en_GB.json @@ -0,0 +1,4 @@ +{ + "heading1": "Homework assistant", + "heading2": "Your digital assistant that makes the homework more fun" +} \ No newline at end of file diff --git a/resources/sv_SE.json b/resources/sv_SE.json new file mode 100644 index 0000000..94ec085 --- /dev/null +++ b/resources/sv_SE.json @@ -0,0 +1,39 @@ +{ + "text001": "Läxassistent", + "text002": "Din digitala läxassistent i skoldjungeln", + "text003": "Välj typ av läxa", + "text004": "Matematik", + "text005": "Engelska glosor", + "text006": "Välj räknesätt...", + "text007": "Addition", + "text008": "Subtraktion", + "text009": "Multiplikation", + "text010": "Division", + "text011": "Svårighetsgrad", + "text012": "Tiotalsövergång", + "text013": "Negativa tal", + "text014": "Lätt", + "text015": "Medel", + "text016": "Medelsvår", + "text017": "Svår", + "text018": "Omöjlig", + "text019": "Användarnamn", + "text020": "Lösenord", + "text021": "Logga in till läxhjälp", + "text022": "Logga in", + "text023": "Felaktigt användarnamn eller lösenord", + "text024": "Tyska glosor", + "text025": "Franska glosor", + "text026": "Spanska glosor", + "text027": "Användare", + "text028": "Språk", + "text029": "Välj...", + "text030": "Svenska", + "text031": "Engelska", + "text032": "Franska", + "text033": "Spanska", + "text034": "Tyska", + "text035": "Ny...", + "text036": "Träna", + "text037": "Spara" +} \ No newline at end of file