mirror of
https://github.com/jorenchik/mdemory.git
synced 2026-03-22 00:26:21 +00:00
Frontend and communication
This commit is contained in:
@@ -2,44 +2,44 @@ package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"log"
|
||||
"github.com/jorenchik/mdemory/src/compiler/lexer"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Question interface {
|
||||
ToString() string;
|
||||
ToString() string
|
||||
}
|
||||
|
||||
type SingleAnswerQuestion struct {
|
||||
id string;
|
||||
question string;
|
||||
answer string;
|
||||
section string;
|
||||
ID string
|
||||
Question string
|
||||
Answer string
|
||||
Section string
|
||||
}
|
||||
|
||||
type Choice struct {
|
||||
answer string;
|
||||
isCorrect bool;
|
||||
answer string
|
||||
isCorrect bool
|
||||
}
|
||||
|
||||
type MultipleChoiceQuestion struct {
|
||||
id string;
|
||||
question string;
|
||||
choices []Choice;
|
||||
section string;
|
||||
id string
|
||||
question string
|
||||
choices []Choice
|
||||
section string
|
||||
}
|
||||
|
||||
func (question SingleAnswerQuestion)ToString() string {
|
||||
func (question SingleAnswerQuestion) ToString() string {
|
||||
return fmt.Sprintf(
|
||||
"<Single choice> (%s) %s: %s\n",
|
||||
question.section,
|
||||
strings.Trim(question.question, "\t\n "),
|
||||
strings.Trim(question.answer, "\t\n "),
|
||||
question.Section,
|
||||
strings.Trim(question.Question, "\t\n "),
|
||||
strings.Trim(question.Answer, "\t\n "),
|
||||
)
|
||||
}
|
||||
|
||||
func (question MultipleChoiceQuestion)ToString() string {
|
||||
func (question MultipleChoiceQuestion) ToString() string {
|
||||
acc := ""
|
||||
acc += fmt.Sprintf(
|
||||
"<Multi choice> (%s) %s\n",
|
||||
@@ -48,7 +48,7 @@ func (question MultipleChoiceQuestion)ToString() string {
|
||||
)
|
||||
for _, el := range question.choices {
|
||||
opener := '-'
|
||||
if (el.isCorrect) {
|
||||
if el.isCorrect {
|
||||
opener = '+'
|
||||
}
|
||||
acc += fmt.Sprintf("\t%c %s\n", opener, strings.Trim(el.answer, "\t\n "))
|
||||
@@ -57,16 +57,16 @@ func (question MultipleChoiceQuestion)ToString() string {
|
||||
}
|
||||
|
||||
type QuestionElement struct {
|
||||
isDash bool;
|
||||
content string;
|
||||
}
|
||||
isDash bool
|
||||
content string
|
||||
}
|
||||
|
||||
var automata map[lexer.TokenType][]lexer.TokenType
|
||||
var automata map[lexer.TokenType][]lexer.TokenType
|
||||
|
||||
type CompilerErr struct {
|
||||
message string;
|
||||
row int32;
|
||||
column int32;
|
||||
message string
|
||||
row int32
|
||||
column int32
|
||||
}
|
||||
|
||||
func (e CompilerErr) Error() string {
|
||||
@@ -74,12 +74,12 @@ func (e CompilerErr) Error() string {
|
||||
}
|
||||
|
||||
func contains(s []lexer.TokenType, e lexer.TokenType) bool {
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parserAutomata() map[lexer.TokenType][]lexer.TokenType {
|
||||
@@ -95,22 +95,22 @@ func parserAutomata() map[lexer.TokenType][]lexer.TokenType {
|
||||
}
|
||||
automata[lexer.QuestionEnd] = []lexer.TokenType{
|
||||
lexer.ElementDashStart, lexer.ElementPlusStart,
|
||||
}
|
||||
}
|
||||
automata[lexer.ElementDashStart] = []lexer.TokenType{
|
||||
lexer.IdentifierStart, lexer.TextFragment,
|
||||
}
|
||||
}
|
||||
automata[lexer.ElementPlusStart] = []lexer.TokenType{
|
||||
lexer.TextFragment,
|
||||
}
|
||||
}
|
||||
automata[lexer.Identifier] = []lexer.TokenType{
|
||||
lexer.IdentifierEnd, lexer.SectionStart,
|
||||
}
|
||||
}
|
||||
automata[lexer.IdentifierStart] = []lexer.TokenType{
|
||||
lexer.Identifier,
|
||||
}
|
||||
}
|
||||
automata[lexer.IdentifierEnd] = []lexer.TokenType{
|
||||
lexer.TextFragment,
|
||||
}
|
||||
}
|
||||
automata[lexer.SectionIdentifierStart] = []lexer.TokenType{
|
||||
lexer.Identifier,
|
||||
}
|
||||
@@ -129,30 +129,30 @@ func parserAutomata() map[lexer.TokenType][]lexer.TokenType {
|
||||
|
||||
func ValidateGrammar(tokens []lexer.Token) error {
|
||||
automata = parserAutomata()
|
||||
for i := 0; i < len(tokens) - 1; i++ {
|
||||
for i := 0; i < len(tokens)-1; i++ {
|
||||
token := tokens[i]
|
||||
nextToken := tokens[i + 1]
|
||||
if (!contains(automata[token.TokenType], nextToken.TokenType)) {
|
||||
nextToken := tokens[i+1]
|
||||
if !contains(automata[token.TokenType], nextToken.TokenType) {
|
||||
return CompilerErr{
|
||||
message: fmt.Sprintf(
|
||||
"Token %s cannot precede %s\n",
|
||||
lexer.ToString(&token.TokenType),
|
||||
lexer.ToString(&nextToken.TokenType),
|
||||
),
|
||||
row: token.Row,
|
||||
row: token.Row,
|
||||
column: token.Column,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseQuestions(fileContents string) ([]Question, error) {
|
||||
tokens, err := lexer.TokenizeMdem([]rune(fileContents))
|
||||
if (err != nil) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if (true) {
|
||||
if true {
|
||||
log.Println("Lexer output:")
|
||||
for _, el := range tokens {
|
||||
fmt.Print(el.ToString())
|
||||
@@ -160,7 +160,7 @@ func ParseQuestions(fileContents string) ([]Question, error) {
|
||||
}
|
||||
|
||||
err = ValidateGrammar(tokens)
|
||||
if (err != nil) {
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
@@ -168,26 +168,26 @@ func ParseQuestions(fileContents string) ([]Question, error) {
|
||||
section := ""
|
||||
i := 0
|
||||
for {
|
||||
if (i >= len(tokens)) {
|
||||
if i >= len(tokens) {
|
||||
break
|
||||
}
|
||||
if (tokens[i].TokenType == lexer.ElementDashStart) {
|
||||
id := tokens[i + 2].Content
|
||||
question := tokens[i + 4].Content
|
||||
if tokens[i].TokenType == lexer.ElementDashStart {
|
||||
id := tokens[i+2].Content
|
||||
question := tokens[i+4].Content
|
||||
quesitonElements := []QuestionElement{}
|
||||
i += 6
|
||||
for {
|
||||
if (i + 1 >= len(tokens) ||
|
||||
if i+1 >= len(tokens) ||
|
||||
!(tokens[i].TokenType == lexer.ElementDashStart ||
|
||||
tokens[i].TokenType == lexer.ElementPlusStart) ||
|
||||
tokens[i+1].TokenType == lexer.IdentifierStart) {
|
||||
tokens[i+1].TokenType == lexer.IdentifierStart {
|
||||
break
|
||||
}
|
||||
questionElement := QuestionElement{}
|
||||
if (tokens[i].TokenType == lexer.ElementDashStart) {
|
||||
questionElement.isDash = true
|
||||
if tokens[i].TokenType == lexer.ElementDashStart {
|
||||
questionElement.isDash = true
|
||||
} else {
|
||||
questionElement.isDash = false
|
||||
questionElement.isDash = false
|
||||
}
|
||||
questionElement.content = tokens[i+1].Content
|
||||
quesitonElements = append(quesitonElements, questionElement)
|
||||
@@ -195,7 +195,7 @@ func ParseQuestions(fileContents string) ([]Question, error) {
|
||||
}
|
||||
if len(quesitonElements) > 1 {
|
||||
question := MultipleChoiceQuestion{
|
||||
id: id,
|
||||
id: id,
|
||||
question: question,
|
||||
}
|
||||
choices := []Choice{}
|
||||
@@ -204,30 +204,30 @@ func ParseQuestions(fileContents string) ([]Question, error) {
|
||||
choice.answer = quesitonElements[k].content
|
||||
choice.isCorrect = !quesitonElements[k].isDash
|
||||
choices = append(choices, choice)
|
||||
}
|
||||
if (section != "") {
|
||||
}
|
||||
if section != "" {
|
||||
question.section = section
|
||||
}
|
||||
question.choices = choices
|
||||
questions = append(questions, question)
|
||||
} else if (len(quesitonElements) == 1) {
|
||||
} else if len(quesitonElements) == 1 {
|
||||
question := SingleAnswerQuestion{
|
||||
id: id,
|
||||
question: question,
|
||||
answer: quesitonElements[0].content,
|
||||
ID: id,
|
||||
Question: question,
|
||||
Answer: quesitonElements[0].content,
|
||||
}
|
||||
if (section != "") {
|
||||
question.section = section
|
||||
if section != "" {
|
||||
question.Section = section
|
||||
}
|
||||
questions = append(questions, question)
|
||||
}
|
||||
} else if (tokens[i].TokenType == lexer.SectionIdentifierStart) {
|
||||
section = tokens[i + 1].Content
|
||||
i += 3;
|
||||
} else if (tokens[i].TokenType == lexer.SectionEnd) {
|
||||
} else if tokens[i].TokenType == lexer.SectionIdentifierStart {
|
||||
section = tokens[i+1].Content
|
||||
i += 3
|
||||
} else if tokens[i].TokenType == lexer.SectionEnd {
|
||||
section = ""
|
||||
i += 1
|
||||
} else if (tokens[i].TokenType == lexer.EOF) {
|
||||
} else if tokens[i].TokenType == lexer.EOF {
|
||||
break
|
||||
} else {
|
||||
log.Fatalf(
|
||||
@@ -236,8 +236,8 @@ func ParseQuestions(fileContents string) ([]Question, error) {
|
||||
)
|
||||
return nil, CompilerErr{
|
||||
message: "",
|
||||
row: tokens[i].Row,
|
||||
column: tokens[i].Column,
|
||||
row: tokens[i].Row,
|
||||
column: tokens[i].Column,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
src/mdemory-app/.vscode/launch.json
vendored
Normal file
16
src/mdemory-app/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Wails: build debug",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "exec",
|
||||
"program": "${workspaceFolder}/myapp",
|
||||
"preLaunchTask": "wails_debug_build",
|
||||
"env": {},
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
||||
11
src/mdemory-app/.vscode/tasks.json
vendored
Normal file
11
src/mdemory-app/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "wails_debug_build",
|
||||
"type": "shell",
|
||||
"command": "wails build -debug"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/jorenchik/mdemory/src/compiler/parser"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
@@ -28,30 +29,76 @@ func (a *App) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello %s, It's show time!", name)
|
||||
}
|
||||
|
||||
type File struct{
|
||||
Name string;
|
||||
IsDir bool;
|
||||
type File struct {
|
||||
Name string
|
||||
IsDir bool
|
||||
}
|
||||
|
||||
// Greet returns a greeting for the given name
|
||||
func (a *App) GetRepoFiles() []File {
|
||||
dirPath := "/home/jorenchik/Code/mdemory/memorybase/"
|
||||
func (a *App) GetRepoFiles(dirPath string) []File {
|
||||
dirEntries, err := os.ReadDir(dirPath)
|
||||
if (err != nil) {
|
||||
if err != nil {
|
||||
return []File{}
|
||||
}
|
||||
files := []File{}
|
||||
exp, err := regexp.Compile(".+\\.mdem")
|
||||
for _, el := range dirEntries {
|
||||
if (err != nil) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if (el.IsDir() || exp.Match([]byte(el.Name()))) {
|
||||
if el.IsDir() || exp.Match([]byte(el.Name())) {
|
||||
file := File{}
|
||||
file.Name = el.Name()
|
||||
file.IsDir = el.IsDir()
|
||||
files = append(files, file)
|
||||
}
|
||||
}
|
||||
return files
|
||||
return files
|
||||
}
|
||||
|
||||
func (a *App) ParseFile(filePath string) (string, error) {
|
||||
fmt.Printf("Parse file requested. Path: %s\n", filePath)
|
||||
dirName := "/home/jorenchik/Code/mdemory/memorybase/"
|
||||
dir, err := os.ReadDir(dirName)
|
||||
|
||||
for _, el := range dir {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
path := dirName + el.Name()
|
||||
fmt.Println(path)
|
||||
bytes, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
fmt.Println(string(bytes))
|
||||
}
|
||||
|
||||
bytes, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
fmt.Printf("File opening error: %s\n", err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
fileContents := string(bytes)
|
||||
questions, err := parser.ParseQuestions(fileContents)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Parsing error: %s\n", err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
for i := 0; i < len(questions); i++ {
|
||||
question := questions[i]
|
||||
switch q := question.(type) {
|
||||
case parser.SingleAnswerQuestion:
|
||||
fmt.Printf(
|
||||
"Single Answer: question: %s; answer: %s",
|
||||
q.Question,
|
||||
q.Answer,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Returning file. Path: %s\n", filePath)
|
||||
return fileContents, nil
|
||||
}
|
||||
|
||||
@@ -1,75 +1,119 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<meta charset="UTF-8" />
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
<title>mdemory-app</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="main-layout">
|
||||
<div>
|
||||
<h3>memorybase</h3>
|
||||
<div class="file-menus">
|
||||
<h4 class="sidebar-heading">mdems</h4>
|
||||
<div>
|
||||
<div id="deck-list" class="deck-list">
|
||||
<div class="mbase-actions">
|
||||
<input class="repo-input" type="text" name="file" value="">
|
||||
<a id="reload-files" href="#">
|
||||
Reload
|
||||
</a>
|
||||
</div>
|
||||
<!--<a class="deck-link" href="#">-->
|
||||
<!-- <div class="deck">-->
|
||||
<!-- <span>></span>-->
|
||||
<!-- <span>math</span>-->
|
||||
<!-- </div>-->
|
||||
<!--</a>-->
|
||||
<!--<a class="deck-link" href="#">-->
|
||||
<!-- <div class="deck">-->
|
||||
<!-- cpp-->
|
||||
<!-- </div>-->
|
||||
<!--</a>-->
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="sidebar-heading">decks</h4>
|
||||
<div class="deck-list">
|
||||
<a class="deck-link" href="#">
|
||||
<div class="deck">
|
||||
cpp
|
||||
</div>
|
||||
</a>
|
||||
<a class="deck-link" href="#">
|
||||
<div class="deck">
|
||||
python
|
||||
</div>
|
||||
</a>
|
||||
<a class="deck-link" href="#">
|
||||
<div class="deck">
|
||||
tikli
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2>flashcards: countries</h2>
|
||||
<div class="deck-listing">
|
||||
<div class="flashcard">
|
||||
<span>></span>
|
||||
<span>What is the capital of Latvia?</span>
|
||||
</div>
|
||||
<div class="flashcard">
|
||||
<span>></span>
|
||||
<span>What is the capital of Lithuania?</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="./src/main.ts" type="module"></script>
|
||||
<div class="master" id="app">
|
||||
<div class="top-menu">
|
||||
<div class="option">
|
||||
<span>Base</span>
|
||||
<div class="list">
|
||||
<div>Save</div>
|
||||
<div>Open</div>
|
||||
<div>Reload</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
Help
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-layout">
|
||||
<div class="file-menus">
|
||||
<div class="mbase-actions">
|
||||
<h3>memorybase</h3>
|
||||
<div class="mbase-search">
|
||||
<input class="repo-input" type="text" name="file" value="">
|
||||
<a id="reload-files" href="#">
|
||||
Reload
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mbase-mdems">
|
||||
<h4 class="sidebar-heading">mdems</h4>
|
||||
<div id="deck-list" class="deck-list">
|
||||
<!-- Mdem example -->
|
||||
<!--<a class="deck-link" href="#">-->
|
||||
<!-- <div class="deck">-->
|
||||
<!-- <span>></span>-->
|
||||
<!-- <span>math</span>-->
|
||||
<!-- </div>-->
|
||||
<!--</a>-->
|
||||
<!--<a class="deck-link" href="#">-->
|
||||
<!-- <div class="deck">-->
|
||||
<!-- cpp-->
|
||||
<!-- </div>-->
|
||||
<!--</a>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="mbase-decks">
|
||||
<!-- Deck example -->
|
||||
<h4 class="sidebar-heading">decks</h4>
|
||||
<div>
|
||||
<a class="deck-link" href="#">
|
||||
<div class="deck">
|
||||
cpp
|
||||
</div>
|
||||
</a>
|
||||
<a class="deck-link" href="#">
|
||||
<div class="deck">
|
||||
python
|
||||
</div>
|
||||
</a>
|
||||
<a class="deck-link" href="#">
|
||||
<div class="deck">
|
||||
tikli
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2>countries.mdem</h2>
|
||||
<div class="deck-listing-box">
|
||||
<div class="deck-listing-top">
|
||||
<div>
|
||||
<span>Flashcards: 12.</span>
|
||||
<span>Page: 1 of 3.</span>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button">Train</button>
|
||||
<button type="button">View stats</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="deck-listing">
|
||||
<div>
|
||||
<div class="flashcard">
|
||||
<span>></span>
|
||||
<span>What is the capital of Latvia?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flashcard">
|
||||
<span>></span>
|
||||
<span>What is the capital of Lithuania?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flashcard">
|
||||
<span>></span>
|
||||
<span>What is the capital of Estonia?</span>
|
||||
</div>
|
||||
<div class="answer">
|
||||
<span>-</span>
|
||||
<span>Tallin</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="./src/main.ts" type="module"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -1,26 +1,60 @@
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: .35fr 1fr; /* Creates 3 equal columns */
|
||||
height: 100%;
|
||||
html {
|
||||
background-color: rgba(27, 38, 54, 1);
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.main-layout > div:nth-child(1) {
|
||||
/*background: white;*/
|
||||
border-right: 1px solid gray;
|
||||
}
|
||||
|
||||
.main-layout .deck-list {
|
||||
padding: .5rem 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/*gap: .5rem;*/
|
||||
body {
|
||||
box-sizing: content-box;
|
||||
margin: 0;
|
||||
color: white;
|
||||
font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
|
||||
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: unset;
|
||||
text-decoration: unset;
|
||||
color: unset;
|
||||
text-decoration: unset;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
#app {
|
||||
text-align: center;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Nunito";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local(""),
|
||||
url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
|
||||
}
|
||||
|
||||
.main-layout {
|
||||
display: grid;
|
||||
grid-template-columns: .35fr 1fr;
|
||||
flex-grow: 1;
|
||||
/* height: 100%; */
|
||||
}
|
||||
|
||||
.main-layout > div:nth-child(1) {
|
||||
border-right: 1px solid gray;
|
||||
}
|
||||
|
||||
.main-layout .file-menus {
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.main-layout .deck {
|
||||
border: 1px solid gray;
|
||||
border-top: none;
|
||||
@@ -36,30 +70,55 @@ a {
|
||||
border-top: 1px solid gray;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
|
||||
.deck-listing {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.deck-listing-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.deck-listing-box {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.deck-listing .flashcard {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid white;
|
||||
height: 80px;
|
||||
border-radius: .3rem;
|
||||
border: 1px solid white;
|
||||
border-top-left-radius: .3rem;
|
||||
border-top-right-radius: .3rem;
|
||||
border-bottom-left-radius: .3rem;
|
||||
border-bottom-right-radius: .3rem;
|
||||
}
|
||||
|
||||
.deck-listing .flashcard > * {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.deck-listing .answer {
|
||||
margin-top: -2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 80px;
|
||||
border: 1px solid white;
|
||||
border-top: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-left-radius: .3rem;
|
||||
border-bottom-right-radius: .3rem;
|
||||
}
|
||||
|
||||
.deck-listing .answer > * {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.repo-input {
|
||||
width: 99%;
|
||||
height: 25px;
|
||||
@@ -68,11 +127,19 @@ h1, h2, h3, h4 {
|
||||
|
||||
.mbase-actions {
|
||||
display: flex;
|
||||
gap: 0rem;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mbase-search {
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mbase-actions a {
|
||||
font-size: .8rem;
|
||||
display: block;
|
||||
@@ -82,11 +149,72 @@ h1, h2, h3, h4 {
|
||||
font-size: .9rem;
|
||||
display: flex;
|
||||
margin: 0;
|
||||
padding: 0 1rem;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
|
||||
.file-menus {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.file-menus > div {
|
||||
margin-bottom: 1.5rem;
|
||||
|
||||
}
|
||||
|
||||
.mbase-actions {
|
||||
height: 10%;
|
||||
}
|
||||
|
||||
.mbase-mdems {
|
||||
max-height: 40%;
|
||||
}
|
||||
|
||||
.mbase-decks {
|
||||
max-height: 40%;
|
||||
}
|
||||
|
||||
.top-menu {
|
||||
position: sticky;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
background: gray;
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.top-menu > div {
|
||||
cursor: pointer;
|
||||
border-right: 1px solid white;
|
||||
padding: 1px 10px;
|
||||
}
|
||||
|
||||
.top-menu .option {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.top-menu .option .list {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
background: gray;
|
||||
width: 150px;
|
||||
/* display: flex; */
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.top-menu .option .list > div {
|
||||
padding: 0 0 0 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.top-menu .option .list > div:nth-child(1) {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.top-menu .option .list > div {
|
||||
border-top: 1px solid white;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import './style.css';
|
||||
import './app.css';
|
||||
|
||||
import {GetRepoFiles} from '../wailsjs/go/main/App';
|
||||
import {GetRepoFiles, ParseFile} from '../wailsjs/go/main/App';
|
||||
import {main} from '../wailsjs/go/models';
|
||||
|
||||
interface DeckFile {
|
||||
@@ -9,49 +9,56 @@ interface DeckFile {
|
||||
IsDir: boolean;
|
||||
}
|
||||
|
||||
// console.log(await ParseFile("fjoewjf"));
|
||||
|
||||
function fetchFiles() {
|
||||
GetRepoFiles().then((result: main.File[]) => {
|
||||
GetRepoFiles("/home/jorenchik/Code/mdemory/memorybase/")
|
||||
.then((result: main.File[]) => {
|
||||
const files: DeckFile[] = result as DeckFile[]
|
||||
setDecklistFiles(files)
|
||||
});
|
||||
}
|
||||
fetchFiles()
|
||||
|
||||
let mbasePath = "/home/jorenchik/Code/mdemory/memorybase/"
|
||||
|
||||
async function fetchParsed(filename: string) {
|
||||
console.log(filename);
|
||||
try {
|
||||
console.log(await ParseFile(mbasePath + filename));
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
}
|
||||
// let time = new Date().getTime();
|
||||
// console.log(await ParseFile(mbasePath + filename));
|
||||
// console.log(new Date().getTime() - time)
|
||||
}
|
||||
|
||||
let decklist: Element | null = document.querySelector("#deck-list");
|
||||
function setDecklistFiles(files: DeckFile[]) {
|
||||
if (decklist) {
|
||||
// removeAnchors
|
||||
let deckFileAnchors = decklist.querySelectorAll(".deck-link")
|
||||
deckFileAnchors.forEach(i => {
|
||||
i.remove();
|
||||
});
|
||||
|
||||
// createAnchors
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let element = document.createElement('a');
|
||||
let angleHtml = ''
|
||||
if (files[i].IsDir) {
|
||||
angleHtml = "<span angle='true'>></span>"
|
||||
}
|
||||
element.setAttribute("href", "#")
|
||||
element.setAttribute("class", "deck-link")
|
||||
element.innerHTML = `
|
||||
<div class="deck">
|
||||
${ angleHtml }
|
||||
${files[i].Name}
|
||||
</div>
|
||||
`
|
||||
element.setAttribute("href", "#")
|
||||
element.setAttribute("class", "deck-link")
|
||||
decklist.appendChild(element)
|
||||
if (files[i].IsDir) {
|
||||
let angle: HTMLElement | null = element.querySelector("[angle='true']")
|
||||
element.addEventListener("click", _clickable => {
|
||||
let style: CSSStyleDeclaration | undefined = angle?.style
|
||||
if (style) {
|
||||
if (style["rotate"] == "90deg") {
|
||||
style["rotate"] = "";
|
||||
} else {
|
||||
style["rotate"] = "90deg";
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
element.addEventListener('click', _ => {
|
||||
fetchParsed(element.innerText);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
html {
|
||||
background-color: rgba(27, 38, 54, 1);
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
color: white;
|
||||
font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
|
||||
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Nunito";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local(""),
|
||||
url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100vh;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
import {main} from '../models';
|
||||
|
||||
export function GetRepoFiles():Promise<Array<main.File>>;
|
||||
export function GetRepoFiles(arg1:string):Promise<Array<main.File>>;
|
||||
|
||||
export function Greet(arg1:string):Promise<string>;
|
||||
|
||||
export function ParseFile(arg1:string):Promise<string>;
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
export function GetRepoFiles() {
|
||||
return window['go']['main']['App']['GetRepoFiles']();
|
||||
export function GetRepoFiles(arg1) {
|
||||
return window['go']['main']['App']['GetRepoFiles'](arg1);
|
||||
}
|
||||
|
||||
export function Greet(arg1) {
|
||||
return window['go']['main']['App']['Greet'](arg1);
|
||||
}
|
||||
|
||||
export function ParseFile(arg1) {
|
||||
return window['go']['main']['App']['ParseFile'](arg1);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@ module mdemory-app
|
||||
|
||||
go 1.22.5
|
||||
|
||||
require github.com/wailsapp/wails/v2 v2.9.1
|
||||
require (
|
||||
github.com/jorenchik/mdemory/src/compiler v0.0.0-00010101000000-000000000000
|
||||
github.com/wailsapp/wails/v2 v2.9.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bep/debounce v1.2.1 // indirect
|
||||
|
||||
Reference in New Issue
Block a user