From 9a7d23d24d39ad1aa1a35cc8df98f8abc43c3991 Mon Sep 17 00:00:00 2001 From: bruno Date: Thu, 27 Oct 2022 13:10:16 -0400 Subject: [PATCH] add dashbord and right colomn right page --- .nimble | 0 code/database_utils.nim | 36 ++- code/joplin_utils.nim | 319 +++++++++++++++--------- code/password_utils.nim | 8 +- code/utils.nim | 22 ++ code/web_utils.nim | 39 ++- config.nims | 3 +- config/config.cfg | 2 +- data/dashbord.xlsx | Bin 0 -> 9358 bytes data/toto.txt | 1 + install_requirment.sh | 12 + main.nim | 175 +++++++++----- public/css/styles.css | 520 ++++++++++++++++++++++------------------ tmpl/snippet_icons.nim | 26 +- tmpl/website.tmpl | 63 ++++- 15 files changed, 763 insertions(+), 463 deletions(-) create mode 100644 .nimble create mode 100644 code/utils.nim create mode 100644 data/dashbord.xlsx create mode 100644 data/toto.txt diff --git a/.nimble b/.nimble new file mode 100644 index 0000000..e69de29 diff --git a/code/database_utils.nim b/code/database_utils.nim index 5eb94fb..8ab25a6 100644 --- a/code/database_utils.nim +++ b/code/database_utils.nim @@ -12,13 +12,13 @@ import os import logging import parsecfg -import db_sqlite +import db_sqlite import ../code/password_utils # --==--==--==--==--==--==--==--==--==--==-- # -# PROC : Generate Database +# PROC : Generate Database # --==--==--==--==--==--==--==--==--==--==-- # proc generateDB*() = echo "Generating database" @@ -26,11 +26,11 @@ proc generateDB*() = # Load the connection details let dict = loadConfig("config/config.cfg") - db_user = dict.getSectionValue("Database","user") - db_pass = dict.getSectionValue("Database","pass") - db_name = dict.getSectionValue("Database","name") - db_host = dict.getSectionValue("Database","host") - db_folder = dict.getSectionValue("Database","folder") + db_user = dict.getSectionValue("Database", "user") + db_pass = dict.getSectionValue("Database", "pass") + db_name = dict.getSectionValue("Database", "name") + db_host = dict.getSectionValue("Database", "host") + db_folder = dict.getSectionValue("Database", "folder") dbexists = if fileExists(db_host): true else: false if dbexists: @@ -41,7 +41,8 @@ proc generateDB*() = # Open DB echo " - Opening database" - var db = open(connection=db_host, user=db_user, password=db_pass, database=db_name) + var db = open(connection = db_host, user = db_user, password = db_pass, + database = db_name) # Person table contains information about the # registrered users @@ -74,6 +75,20 @@ proc generateDB*() = );""")): echo " - Database: session table already exists" + # Sesion table contains information about the search + # + if not db.tryExec(sql(""" + create table if not exists search( + id integer primary key, + search_title varchar(300) not null, + query varchar(300) not null, + search_type varchar(100) not null, + creation timestamp not null default (STRFTIME('%s', 'now')), + lastModified timestamp not null default (STRFTIME('%s', 'now')), + foreign key (userid) references person(id) + );""")): + echo " - Database: search table already exists" + # --==--==--==--==--==--==--==--==--==--==-- # # PROC : Create Administrator User @@ -108,9 +123,10 @@ proc createAdminUser*(db: DbConn, args: seq[string]) = let password = makePassword(iPwd, salt) # Insert user into database - if insertID(db, sql"INSERT INTO person (name, email, password, salt, status) VALUES (?, ?, ?, ?, ?)", $iName, $iEmail, password, salt, "Admin") > 0: + if insertID(db, sql"INSERT INTO person (name, email, password, salt, status) VALUES (?, ?, ?, ?, ?)", + $iName, $iEmail, password, salt, "Admin") > 0: echo "Admin user added" else: error("Something went wrong") - info("Admin added.") \ No newline at end of file + info("Admin added.") diff --git a/code/joplin_utils.nim b/code/joplin_utils.nim index 468afc4..ee5b199 100644 --- a/code/joplin_utils.nim +++ b/code/joplin_utils.nim @@ -15,10 +15,13 @@ import std/json import httpcore import strutils import strformat +import std/times import std/options import std/httpclient import std/asyncdispatch +import utils # Joplin utils procedures and types + from os import sleep from posix import read, write, fdatasync, close @@ -37,16 +40,18 @@ type type joplin_tags* = object id*, parent_id*, title*: seq[string] - created_time*, updated_time*, user_created_time*, user_updated_time*, is_shared*: seq[int] + created_time*, updated_time*, user_created_time*, user_updated_time*, + is_shared*: seq[int] req*: Request # --==--==--==--==--==--==--==--==--==--==-- # # TYPE : Setup joplin_notebooks data # --==--==--==--==--==--==--==--==--==--==-- # type - joplin_notebooks* = object + joplin_notebooks* = object id*, parent_id*, title*, share_id*, icon*: seq[string] - created_time*, updated_time*, user_created_time*, user_updated_time*, is_shared*: seq[int] + created_time*, updated_time*, user_created_time*, user_updated_time*, + is_shared*: seq[int] req*: Request @@ -54,10 +59,29 @@ type # TYPE : Setup joplin_notes data # --==--==--==--==--==--==--==--==--==--==-- # type - joplin_notes* = object - id*, parent_id*, title*, body*, author*, source_url*, source*, source_application*, application_data*, share_id*, conflict_original_id*, body_html*, base_url*: seq[string] - created_time*, updated_time*, is_conflict*, is_todo*, todo_due*, todo_completed*, user_created_time*, user_updated_time*, markup_language*, is_shared*: seq[int] - latitude*, longitude*, altitude*, order*:seq[float] + joplin_notes* = object + id*, parent_id*, title*, body*, author*, source_url*, source*, + source_application*, application_data*, share_id*, + conflict_original_id*, body_html*, base_url*: seq[string] + updated_time*, is_conflict*, is_todo*, todo_due*, + todo_completed*, user_created_time*, user_updated_time*, + markup_language*, is_shared*: seq[int] + latitude*, longitude*, altitude*, order*: seq[float] + created_time*: seq[string] + req*: Request + +# --==--==--==--==--==--==--==--==--==--==-- # +# TYPE : Setup joplin_note data +# --==--==--==--==--==--==--==--==--==--==-- # +type + joplin_note* = object + id*, parent_id*, title*, body*, author*, source_url*, source*, + source_application*, application_data*, conflict_original_id*, + master_key_id*, share_id*, encryption_cipher_text * : string + created_time*, updated_time*, user_created_time*, user_updated_time*, + is_conflict*, is_todo*, todo_due*, todo_completed*, markup_language*, + is_shared*, encryption_applied*: int + latitude*, longitude*, altitude*, order*: float req*: Request # --==--==--==--==--==--==--==--==--==--==-- # @@ -73,7 +97,7 @@ type # DURATION : duration variables # --==--==--==--==--==--==--==--==--==--==-- # let - resetDuration = initDuration(seconds=2) + resetDuration = initDuration(seconds = 2) deciSecondDuration* = initDuration(milliseconds = 100) qtrsecondDuration* = initDuration(milliseconds = 250) @@ -86,7 +110,7 @@ var # --==--==--==--==--==--==--==--==--==--==-- # -# PROC : reset HTTP client +# PROC : reset HTTP client # --==--==--==--==--==--==--==--==--==--==-- # proc resetHttpClient() = if (getTime().utc - lastConnection) > resetDuration: @@ -99,13 +123,13 @@ proc resetHttpClient() = except: echo("Attempted to close clients. Probably do not exist.") echo("Current exception: ", getCurrentExceptionMsg()) - client = newHttpClient(timeout=500) + client = newHttpClient(timeout = 500) # --==--==--==--==--==--==--==--==--==--==--==--==--==-==--==--==- # # PROC : use the joplin API ping to validate service availibility # --==--==--==--==--==--==--==--==--==--==--==--==--==-==--==--==- # -proc ping_joplin*(token:string): Future[joplin_ping] {.async.} = - +proc ping_joplin*(token: string): Future[joplin_ping] {.async.} = + var j_p: joplin_ping var client = newAsyncHttpClient() var url: string @@ -114,7 +138,7 @@ proc ping_joplin*(token:string): Future[joplin_ping] {.async.} = url = fmt"http://localhost:41184/ping?token={token}" var json = await client.getContent(url) j_p.ping_result.add(json) - + echo j_p.ping_result[0] if j_p.ping_result[0] == "JoplinClipperServer": @@ -133,17 +157,17 @@ proc ping_joplin*(token:string): Future[joplin_ping] {.async.} = echo("Current Exception: ", getCurrentException().name) echo("Current Exception Msg: ", getCurrentExceptionMsg()) echo("Sleeping for 1 seconds at: ", getTime().utc) - j_p.ping_status = false + j_p.ping_status = false return j_p # parse jason #let joplin_notes_Json = parseJson(json) -# --==--==--==--==--==--==--==--==--==--==-- # -# PROC : get all joplin NOTEBOOKS -# --==--==--==--==--==--==--==--==--==--==-- # -proc get_joplin_notebooks*(token:string): Future[joplin_notebooks] {.async.} = - + # --==--==--==--==--==--==--==--==--==--==-- # + # PROC : get all joplin NOTEBOOKS + # --==--==--==--==--==--==--==--==--==--==-- # +proc get_joplin_notebooks*(token: string): Future[joplin_notebooks] {.async.} = + # Variables var j_nb: joplin_notebooks var has_more: bool = true @@ -151,15 +175,15 @@ proc get_joplin_notebooks*(token:string): Future[joplin_notebooks] {.async.} = var url: string var client = newAsyncHttpClient() var pingCheck: joplin_ping - + pingCheck = waitFor ping_joplin(token) - # check the joplin status befor query + # check the joplin status befor query if pingCheck.ping_status: - # make sure to check all pages + # make sure to check all pages while has_more == true: - + # request joplin API for notebooks url = fmt"http://localhost:41184/folders?page={page}&token={token}" echo("URL notebooks : ", url) @@ -168,10 +192,10 @@ proc get_joplin_notebooks*(token:string): Future[joplin_notebooks] {.async.} = # parse jason let joplin_notebooks_Json = parseJson(json) - # valider qu'il n'y a plus de page + # valider qu'il n'y a plus de page if not joplin_notebooks_Json["has_more"].getBool: - has_more = false - + has_more = false + # store json info into an object var count: int = 1 for nb in joplin_notebooks_Json["items"]: @@ -179,18 +203,18 @@ proc get_joplin_notebooks*(token:string): Future[joplin_notebooks] {.async.} = j_nb.parent_id.add(nb["parent_id"].getstr) j_nb.title.add(nb["title"].getstr) count += 1 - + # aller à la page suivante - page += 1 + page += 1 return j_nb # --==--==--==--==--==--==--==--==--==--==-- # -# PROC : get all joplin NOTES +# PROC : get all joplin NOTES # --==--==--==--==--==--==--==--==--==--==-- # -proc get_joplin_notes*(token:string): Future[joplin_notes] {.async.} = - +proc get_joplin_notes*(token: string): Future[joplin_notes] {.async.} = + # Variables var j_notes: joplin_notes var has_more: bool = true @@ -200,43 +224,113 @@ proc get_joplin_notes*(token:string): Future[joplin_notes] {.async.} = var pingCheck: joplin_ping pingCheck = waitFor ping_joplin(token) - # check the joplin status befor query + # check the joplin status befor query if pingCheck.ping_status: - # make sure to check all pages + # make sure to check all pages while has_more == true: - + # request joplin API for Notes - url = fmt"http://localhost:41184/notes?page={page}&token={token}" + url = fmt"http://localhost:41184/notes?page={page}&fields=id,parent_id,title,created_time,updated_time&token={token}" echo("URL notes : ", url) var json = await client.getContent(url) # parse jason let joplin_notes_Json = parseJson(json) - # valider qu'il n'y a plus de page + # valider qu'il n'y a plus de page if not joplin_notes_Json["has_more"].getBool: - has_more = false - + has_more = false + + #echo joplin_notes_Json + # store json info into an object var count: int = 1 + var epochTime: int + var humanTime: Time for nb in joplin_notes_Json["items"]: j_notes.id.add(nb["id"].getstr) j_notes.parent_id.add(nb["parent_id"].getstr) j_notes.title.add(nb["title"].getstr) + #epochTime = nb["created_time"].getInt + #humanTime = fromUnix(convert(Milliseconds, Seconds, epochTime)) + + j_notes.created_time.add(convertEpochToHumanTime(nb[ + "created_time"].getInt)) count += 1 - + # aller à la page suivante - page += 1 + page += 1 return j_notes +# --==--==--==--==--==--==--==--==--==--==-- # +# PROC : get joplin NOTE +# --==--==--==--==--==--==--==--==--==--==-- # +proc get_joplin_note*(token: string, noteid: string): Future[ + joplin_note] {.async.} = + + # Variables + var j_note: joplin_note + var has_more: bool = true + var page: int = 1 + var url: string + var client = newAsyncHttpClient() + + # Check joplin connection availibility + var pingCheck: joplin_ping + pingCheck = waitFor ping_joplin(token) + + + # Query for a selected note + url = fmt"http://localhost:41184/notes/{noteid}?fields=id,parent_id,title,body,created_time,updated_time,is_conflict,latitude,longitude,altitude,author,source_url,is_todo,todo_due,todo_completed,source,source_application,application_data,order,user_created_time,user_updated_time,encryption_cipher_text,encryption_applied,markup_language,is_shared,share_id,conflict_original_id,master_key_id&token={token}" + echo("URL notes : ", url) + var jsonNote = await client.getContent(url) + + # parse jason + let joplin_note_Json = parseJson(jsonNote) + + # get all informations for a selected note + j_note.id = joplin_note_Json["id"].getstr + j_note.parent_id = joplin_note_Json["parent_id"].getstr + j_note.title = joplin_note_Json["title"].getstr + j_note.body = joplin_note_Json["body"].getstr + j_note.author = joplin_note_Json["author"].getstr + j_note.source_url = joplin_note_Json["source_url"].getstr + j_note.source = joplin_note_Json["source"].getstr + j_note.source_application = joplin_note_Json["source_application"].getstr + j_note.application_data = joplin_note_Json["application_data"].getstr + j_note.share_id = joplin_note_Json["share_id"].getstr + j_note.conflict_original_id = joplin_note_Json["conflict_original_id"].getstr + j_note.created_time = joplin_note_Json["created_time"].getInt + j_note.updated_time = joplin_note_Json["updated_time"].getInt + j_note.is_conflict = joplin_note_Json["is_conflict"].getInt + j_note.latitude = joplin_note_Json["latitude"].getFloat + j_note.longitude = joplin_note_Json["longitude"].getFloat + j_note.altitude = joplin_note_Json["altitude"].getFloat + j_note.is_todo = joplin_note_Json["is_todo"].getInt + j_note.todo_due = joplin_note_Json["todo_due"].getInt + j_note.todo_completed = joplin_note_Json["todo_completed"].getInt + j_note.order = joplin_note_Json["order"].getFloat + j_note.user_created_time = joplin_note_Json["user_created_time"].getInt + j_note.user_updated_time = joplin_note_Json["user_updated_time"].getInt + j_note.encryption_cipher_text = joplin_note_Json[ + "encryption_cipher_text"].getstr + j_note.encryption_applied = joplin_note_Json["encryption_applied"].getInt + j_note.markup_language = joplin_note_Json["markup_language"].getInt + j_note.is_shared = joplin_note_Json["is_shared"].getInt + j_note.master_key_id = joplin_note_Json["master_key_id"].getstr + + + echo j_note + return j_note + # --==--==--==--==--==--==--==--==--==--==-- # # PROC : get all joplin TAGS # --==--==--==--==--==--==--==--==--==--==-- # -proc get_joplin_tags*(token:string): Future[joplin_tags] {.async.} = - +proc get_joplin_tags*(token: string): Future[joplin_tags] {.async.} = + # Variables var j_tags: joplin_tags var has_more: bool = true @@ -246,12 +340,12 @@ proc get_joplin_tags*(token:string): Future[joplin_tags] {.async.} = var pingCheck: joplin_ping pingCheck = waitFor ping_joplin(token) - # check the joplin status befor query + # check the joplin status befor query if pingCheck.ping_status: - # make sure to check all pages + # make sure to check all pages while has_more == true: - + # request joplin API for notebooks url = fmt"http://localhost:41184/tags?page={page}&token={token}" echo("URL tags : ", url) @@ -260,10 +354,10 @@ proc get_joplin_tags*(token:string): Future[joplin_tags] {.async.} = # parse jason let joplin_tags_Json = parseJson(json) - # valider qu'il n'y a plus de page + # valider qu'il n'y a plus de page if not joplin_tags_Json["has_more"].getBool: - has_more = false - + has_more = false + # store json info into an object var count: int = 1 for nb in joplin_tags_Json["items"]: @@ -271,9 +365,9 @@ proc get_joplin_tags*(token:string): Future[joplin_tags] {.async.} = j_tags.parent_id.add(nb["parent_id"].getstr) j_tags.title.add(nb["title"].getstr) count += 1 - + # aller à la page suivante - page += 1 + page += 1 return j_tags @@ -287,42 +381,41 @@ proc get_joplin_cli_token*(): string = var result = execCmdEx("joplin config api.token") if result.exitCode == 0: - let param1 = result.output - let flagSplit = param1.split(" = ") - flagName = flagSplit[0] - flagValue = flagSplit[1] - + let param1 = result.output + let flagSplit = param1.split(" = ") + flagName = flagSplit[0] + flagValue = flagSplit[1] + return flagValue # --==--==--==--==--==--==--==--==--==--==-- # # PROC : launch any program and get PID # --==--==--==--==--==--==--==--==--==--==-- # -proc launchProgram(app:string = "", workingPath:string = "", arguments:array[2, string]):int {.thread.} = - - var p = startProcess(joinPath(workingPath,app), workingPath, arguments) - let pid = p.processID() - var outhdl = outputHandle(p) - var inputhdl = inputHandle(p) - var errhdl = errorHandle(p) - return pid +proc launchProgram(app: string = "", workingPath: string = "", arguments: array[ + 2, string]): int {.thread.} = + + var p = startProcess(joinPath(workingPath, app), workingPath, arguments) + let pid = p.processID() + var outhdl = outputHandle(p) + var inputhdl = inputHandle(p) + var errhdl = errorHandle(p) + return pid # --==--==--==--==--==--==--==--==--==--==-- # # PROC : Start joplin cli # --==--==--==--==--==--==--==--==--==--==-- # -proc joplin_cli_start*():int {.thread.} = - - let joplinProcessId = launchProgram("joplin","/usr/bin/",["server","start"]) - return joplinProcessId +proc joplin_cli_start*(): int {.thread.} = + + let joplinProcessId = launchProgram("joplin", "/usr/bin/", ["server", "start"]) + return joplinProcessId # --==--==--==--==--==--==--==--==--==--==-- # # PROC : stop Joplin Terminal # --==--==--==--==--==--==--==--==--==--==-- # -proc joplin_cli_stop*():int {.thread.} = - let joplinProcessId = launchProgram("joplin","/usr/bin/",["server","stop"]) - return joplinProcessId - - +proc joplin_cli_stop*(): int {.thread.} = + let joplinProcessId = launchProgram("joplin", "/usr/bin/", ["server", "stop"]) + return joplinProcessId # --==--==--==--==--==--==--==--==--==--==-- # @@ -333,53 +426,45 @@ proc joplin_cli_status*(): bool = var result = execCmdEx("joplin server status") if result.exitCode == 0: - if "Server is not running" in result.output : - echo "Joplin Terminal cli status is down : ", result.output - rc = false + if "Server is not running" in result.output: + echo "Joplin Terminal cli status is down : ", result.output + rc = false else: - echo "Joplin Terminal cli status is up : ", result.output - rc = true + echo "Joplin Terminal cli status is up : ", result.output + rc = true else: - echo "Error validate joplin terminal status : ", result.output + echo "Error validate joplin terminal status : ", result.output return rc - # --==--==--==--==--==--==--==--==--==--==-- # -# PROC : start Joplin Terminal +# PROC : start or stop Joplin Terminal # --==--==--==--==--==--==--==--==--==--==-- # -# proc joplin_cli_start*(): bool = -# var rc = false -# startProcess("joplin","/usr/bin", @["server", "start"]) -# #var result = execCmdEx("ls -l /usr/bin/joplin") +proc joplin_cli_start_stop*(): int = + var isStart: int = 0 + var sleep_delay_frame: int = 50 + var sleep_max: int = 5000 -# if joplin_cli_status() == true: -# echo "Joplin Terminal started successfully : ",result.output -# rc = true -# else: -# echo "Joplin Terminal didn't start : ",result.output -# rc = false -# return rc + if joplin_cli_status() == false: + isStart = joplin_cli_start() + while joplin_cli_status() == false: + sleep(sleep_delay_frame) + echo "Joplin client Terminal started: ", isStart + + else: + echo "Joplin client Terminal is alredy started !" + #if joplin_cli_status() == true: + isStart = joplin_cli_stop() + while joplin_cli_status() == true: + sleep(sleep_delay_frame) + echo "Joplin client Terminal stopped: ", isStart + + return isStart # --==--==--==--==--==--==--==--==--==--==-- # -# PROC : stop Joplin Terminal -# --==--==--==--==--==--==--==--==--==--==-- # -# proc joplin_cli_stop*(): bool = -# var rc = false -# var result = execCmdEx("joplin server stop") - -# if result.exitCode == 0: -# # echo result.output -# rc = true -# else: -# rc = false -# return rc - - -# --==--==--==--==--==--==--==--==--==--==-- # -# PROC : +# PROC : # --==--==--==--==--==--==--==--==--==--==-- # # proc get_joplin_tags_json*(token:string): Future[] {.async.} = @@ -389,7 +474,7 @@ proc joplin_cli_status*(): bool = # # url = fmt"http://localhost:41184/tags/{id}?fields=id,parent_id,title,created_time,updated_time,user_created_time,user_updated_time,is_shared&token={token}" # # http://localhost:41184/tags?token=e5f6644fbf6a97ddc55648dae72b11caecda6c6642d8ce0d3b20129b89b196385737eb908923542c3343649ebbf865b55bda031ab4c3a16edc7723ef2ad77d8f - + # # Variables # var j_tags: joplin_tags # var has_more: bool = true @@ -398,14 +483,14 @@ proc joplin_cli_status*(): bool = # var client = newAsyncHttpClient() # var pingCheck: joplin_ping # pingCheck = waitFor ping_joplin(token) - -# # check the joplin status befor query + +# # check the joplin status befor query # if pingCheck.ping_status: -# # make sure to check all pages +# # make sure to check all pages # while has_more == true: - + # # request joplin API for notebooks # url = fmt"http://localhost:41184/tags?page={page}&token={token}" # echo("URL tags : ", url) @@ -414,10 +499,10 @@ proc joplin_cli_status*(): bool = # # parse jason # let joplin_tags_Json = parseJson(json) -# # valider qu'il n'y a plus de page +# # valider qu'il n'y a plus de page # if not joplin_tags_Json["has_more"].getBool: -# has_more = false - +# has_more = false + # # store json info into an object # var count: int = 1 # for nb in joplin_tags_Json["items"]: @@ -425,8 +510,8 @@ proc joplin_cli_status*(): bool = # echo nb["parent_id"].getstr # echo nb["title"].getstr # count += 1 - + # # aller à la page suivante # page += 1 - + diff --git a/code/password_utils.nim b/code/password_utils.nim index 548dce3..16b1bd8 100644 --- a/code/password_utils.nim +++ b/code/password_utils.nim @@ -25,7 +25,7 @@ let useUrandom = urandom.open("/dev/urandom") ## : Generate random salt. Uses cryptographically secure /dev/urandom ## : on platforms where it is available, and Nim's random module in other cases. # --==--==--==--==--==--==--==--==--==--==--=--==--==--=--==--==--=--==--==-- # -proc makeSalt*(): string = +proc makeSalt*(): string = result = "" if useUrandom: var randomBytes: array[0..127, char] @@ -42,7 +42,7 @@ proc makeSalt*(): string = # PROC : Make session key ## Creates a random key to be used to authorize a session. # --==--==--==--==--==--==--==--==--==--==-- # -proc makeSessionKey*(): string = +proc makeSessionKey*(): string = let random = makeSalt() return bcrypt.hash(random, genSalt(8)) @@ -51,6 +51,6 @@ proc makeSessionKey*(): string = # PROC : make password ## Creates an MD5 hash by combining password and salt # --==--==--==--==--==--==--==--==--==--==-- # -proc makePassword*(password, salt: string, comparingTo = ""): string = +proc makePassword*(password, salt: string, comparingTo = ""): string = let bcryptSalt = if comparingTo != "": comparingTo else: genSalt(8) - result = hash(getMD5(salt & getMD5(password)), bcryptSalt) \ No newline at end of file + result = hash(getMD5(salt & getMD5(password)), bcryptSalt) diff --git a/code/utils.nim b/code/utils.nim new file mode 100644 index 0000000..cc161da --- /dev/null +++ b/code/utils.nim @@ -0,0 +1,22 @@ +# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- # +# Bruno Charest +# 2022-10-25 +# +# __ DESCRIPTIONS __ +# utils : procedures generals utils +# +# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- # + +import std/times + +# --==--==--==--==--==--==--==--==--==--==--==--==--==--==-- # +# PROC : Convert epoch millisecond time to human readable time +# --==--==--==--==--==--==--==--==--==--==--==--==--==--==-- # +proc convertEpochToHumanTime*(epochTime: int): string = + var humanTime: Time + var dateTime: string + humanTime = fromUnix(convert(Milliseconds, Seconds, epochTime)) + dateTime = format(humanTime, "yyyy-MM-dd' 'HH:mm") + # echo dateTime + return dateTime + diff --git a/code/web_utils.nim b/code/web_utils.nim index 6d87de7..0dfc3d9 100644 --- a/code/web_utils.nim +++ b/code/web_utils.nim @@ -11,23 +11,38 @@ import joplin_utils # --==--==--==--==--==--==--==--==--==--==-- # -# TYPE : Selected Option for master web page +# TYPE : Selected Option for master web page # --==--==--==--==--==--==--==--==--==--==-- # -type +type selectedOption* = enum - newNote="New Note", search="Search", shortcuts="Shortcuts", notes="Notes", notebooks="Notesbooks", tags="Tags" + newNote = "New Note", search = "Search", shortcuts = "Shortcuts", + notes = "Notes", notebooks = "Notesbooks", tags = "Tags", + notes_selectednote = "Notes-SelectedNote", dashbord = "Dashboard" # --==--==--==--==--==--==--==--==--==--==-- # -# TYPE : Data Informations for Left Colomn +# TYPE : Data Informations for Left Colomn # --==--==--==--==--==--==--==--==--==--==-- # type ColomnLeftData* = ref object of RootObj - j_status*: bool - option*: selectedOption - j_notes*: joplin_notes - j_notebooks*: joplin_notebooks - j_tags*: joplin_tags - req*: Request + j_status*: bool + option*: selectedOption + j_notes*: joplin_notes + j_notes_nb*: int + j_notebooks*: joplin_notebooks + j_notebooks_nb*: int + j_tags*: joplin_tags + j_tags_nb*: int + req*: Request + +# --==--==--==--==--==--==--==--==--==--==-- # +# TYPE : Data Informations for Right Colomn +# --==--==--==--==--==--==--==--==--==--==-- # +type ColomnRightData* = ref object of RootObj + j_status*: bool + option*: selectedOption + j_SelectedNote*: joplin_note + j_notebooksNote*: joplin_notebooks + j_tagsNote*: joplin_tags + req*: Request + - - \ No newline at end of file diff --git a/config.nims b/config.nims index 7ef108c..1f8a302 100644 --- a/config.nims +++ b/config.nims @@ -2,4 +2,5 @@ switch("d","release") # switch("d","ssl") # --threads:on --opt:size -switch("passL","-s") \ No newline at end of file +switch("passL","-s") +hint("Name",false) \ No newline at end of file diff --git a/config/config.cfg b/config/config.cfg index ecee9e7..af3d5da 100644 --- a/config/config.cfg +++ b/config/config.cfg @@ -26,7 +26,7 @@ port = "7000" #Joplin DESKTOP token #token = "e5f6644fbf6a97ddc55648dae72b11caecda6c6642d8ce0d3b20129b89b196385737eb908923542c3343649ebbf865b55bda031ab4c3a16edc7723ef2ad77d8f" # Joplin CLI token -token = "5b05f489016ce8a001ec83a7968419368eb9206340a18f73119c79e2154ab267ddec424658920bb6f88961c170a2680cd07fbd83f38e1c0c8df907a9aed22427" +token = "76d06ec328466c872f3a944f8237fd96f18d2b953ff013c8689304b7384f2f2232b3aedff079902217760e8fa180d1b89d2650ee1819dd628678fccdc0a140a6" joplin_server = "https://joplinlab.bcmaison.cf" joplin_server_user = "joplinlab@zohomail.com" joplin_server_pwd = "Chab30017405" \ No newline at end of file diff --git a/data/dashbord.xlsx b/data/dashbord.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..41e27249789f7bf80afa6ac39e3532cb4282f31b GIT binary patch literal 9358 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 literal 0 HcmV?d00001 diff --git a/data/toto.txt b/data/toto.txt new file mode 100644 index 0000000..42e5029 --- /dev/null +++ b/data/toto.txt @@ -0,0 +1 @@ +SQLiteDatabase \ No newline at end of file diff --git a/install_requirment.sh b/install_requirment.sh index 598d7a0..f243f6d 100644 --- a/install_requirment.sh +++ b/install_requirment.sh @@ -19,3 +19,15 @@ joplin config locale en_US # --==--==--==--==--==--==--==--==--==--==-- # joplin config api.token cat .config/joplin/settings.json + +# --==--==--==--==--==--==--==--==--==--==-- # +# install nim module requirment +# --==--==--==--==--==--==--==--==--==--==-- # +nimble install jester +nimble install bcrypt +nimble install templates + + # --==--==--==--==--==--==--==--==--==--==-- # +# install packages requirment +# --==--==--==--==--==--==--==--==--==--==-- # + sudo apt install libzip4 \ No newline at end of file diff --git a/main.nim b/main.nim index 11bdedb..6ac4343 100644 --- a/main.nim +++ b/main.nim @@ -16,20 +16,21 @@ # --==--==--==--==--==--==--==--==--==--==-- # # Import section # --==--==--==--==--==--==--==--==--==--==-- # -import os # Used to get arguments -import uri # We need to encode urls: encodeUrl() -import times # Time and date -import jester # Our webserver -import logging # Logging utils -import strutils # Basic functions -import parsecfg # Parse CFG (config) files -import std/json # json manipulation +import os # Used to get arguments +import uri # We need to encode urls: encodeUrl() +import xlsx # read dashbord.xlsx +import times # Time and date +import jester # Our webserver +import logging # Logging utils +import strutils # Basic functions +import parsecfg # Parse CFG (config) files +import std/json # json manipulation import db_sqlite # SQLite import code/database_utils # Utils used in the database import code/password_utils # Our file with password utils -import code/joplin_utils # Joplin utils procedures and types -import code/web_utils # Web utils procedures and types +import code/joplin_utils # Joplin utils procedures and types +import code/web_utils # Web utils procedures and types # --==--==--==--==--==--==--==--==--==--==-- # # First we'll load config files @@ -41,14 +42,14 @@ let dict = loadConfig("config/config.cfg") # --==--==--==--==--==--==--==--==--==--==-- # # Database -let db_user = dict.getSectionValue("Database", "user") -let db_pass = dict.getSectionValue("Database", "pass") -let db_name = dict.getSectionValue("Database", "name") -let db_host = dict.getSectionValue("Database", "host") +let db_user = dict.getSectionValue("Database", "user") +let db_pass = dict.getSectionValue("Database", "pass") +let db_name = dict.getSectionValue("Database", "name") +let db_host = dict.getSectionValue("Database", "host") # Website -let mainURL = dict.getSectionValue("Server", "url") -let mainPort = parseInt dict.getSectionValue("Server", "port") +let mainURL = dict.getSectionValue("Server", "url") +let mainPort = parseInt dict.getSectionValue("Server", "port") let mainWebsite = dict.getSectionValue("Server", "website") # Joplin @@ -79,27 +80,23 @@ type # --==--==--==--==--==--==--==--==--==--==-- # # proc init : initialisation variables # --==--==--==--==--==--==--==--==--==--==-- # -proc init(c: var TData, cld: var ColomnLeftData) = +proc init(c: var TData, cld: var ColomnLeftData, crd: var ColomnRightData) = ## Empty out user session data c.userpass = "" c.username = "" - c.userid = "" + c.userid = "" c.loggedIn = false c.notification = 0 - - ## default option - # cld.option = notes - # --==--==--==--==--==--==--==--==--==--==-- # -# function : loggedIn +# function : loggedIn # --==--==--==--==--==--==--==--==--==--==-- # func loggedIn(c: TData): bool = ## Check if user is logged in by verifying that c.username exists c.username.len > 0 # --==--==--==--==--==--==--==--==--==--==-- # -# proc checkLoggedIn +# proc checkLoggedIn # --==--==--==--==--==--==--==--==--==--==-- # proc checkLoggedIn(c: var TData) = ## Check if user is logged in @@ -113,21 +110,24 @@ proc checkLoggedIn(c: var TData) = # Update the value lastModified for the user in the # table session where the sid and IP match. If there's # any results (above 0) assign values - if execAffectedRows(db, sql("UPDATE session SET lastModified = " & $toInt(epochTime()) & " " & "WHERE ip = ? AND key = ?"), c.req.ip, sid) > 0: + if execAffectedRows(db, sql("UPDATE session SET lastModified = " & $toInt( + epochTime()) & " " & "WHERE ip = ? AND key = ?"), c.req.ip, sid) > 0: # Get user data based on userID from session table # Assign values to user details - `c` - c.userid = getValue(db, sql"SELECT userid FROM session WHERE ip = ? AND key = ?", c.req.ip, sid) + c.userid = getValue(db, sql"SELECT userid FROM session WHERE ip = ? AND key = ?", + c.req.ip, sid) # Get user data based on userID from person table let row = getRow(db, sql"SELECT name, email, status FROM person WHERE id = ?", c.userid) # Assign user data - c.username = row[0] - c.email = toLowerAscii(row[1]) + c.username = row[0] + c.email = toLowerAscii(row[1]) # Update our session table with info about activity - discard tryExec(db, sql"UPDATE person SET lastOnline = ? WHERE id = ?", toInt(epochTime()), c.userid) + discard tryExec(db, sql"UPDATE person SET lastOnline = ? WHERE id = ?", + toInt(epochTime()), c.userid) else: # If the user is not found in the session table @@ -158,14 +158,15 @@ proc login(c: var TData, email, pass: string): tuple[b: bool, s: string] = # and salt. if row[2] == makePassword(pass, row[4], row[2]): # Assign the values - c.userid = row[0] + c.userid = row[0] c.username = row[1] c.userpass = row[2] - c.email = toLowerAscii(row[3]) + c.email = toLowerAscii(row[3]) # Generate session key and save it let key = makeSessionKey() - exec(db, sql"INSERT INTO session (ip, key, userid) VALUES (?, ?, ?)", c.req.ip, key, row[0]) + exec(db, sql"INSERT INTO session (ip, key, userid) VALUES (?, ?, ?)", + c.req.ip, key, row[0]) info("Login successful") return (true, key) @@ -196,16 +197,19 @@ template createTFD() = # Assign the c to TDATA var cld {.inject.}: ColomnLeftData + var crd {.inject.}: ColomnRightData # New instance of c new(c) new(cld) + new(crd) # Set standard values - init(c,cld) + init(c, cld, crd) # Get users request c.req = request cld.req = request + crd.req = request # Check for cookies (we need the cookie named sid) if cookies(request).len > 0: @@ -229,7 +233,8 @@ when isMainModule: # Connect to DB try: # We are using the values which we assigned earlier - db = open(connection=db_host, user=db_user, password=db_pass, database=db_name) + db = open(connection = db_host, user = db_user, password = db_pass, + database = db_name) info("Connection to DB is established.") except: fatal("Connection to DB could not be established.") @@ -262,7 +267,7 @@ include "tmpl/tests/test_viewtree.tmpl" # Setup routes (URL's) # --==--==--==--==--==--==--==--==--==--==-- # routes: - + # default route # --==--==--==--==--==--==--==--==--==--==-- # get "/": @@ -274,20 +279,30 @@ routes: get "/secret": createTFD() echo c.loggedIn - echo @"msg" - if c.loggedIn: + var isStart: int = 0 - # Start joplin terminal cli if stropped - if @"msg" == "startStopJoplin": - if joplin_cli_status() == false: - var isStart = joplin_cli_start() - echo "Joplin client Terminal started: ",isStart - # echo joplin_cli_status() - if joplin_cli_status() == true: - var isStart = joplin_cli_stop() - echo "Joplin client Terminal stopped: ",isStart - # echo joplin_cli_status() - redirect("/secret") + + # if joplin_cli_status() == false: + # isStart = joplin_cli_start() + + + echo "MESSAGE :", @"msg" + echo "NOTE_ID :", @"noteid" + let selectedNoteId = @"noteid" + var url_note = "/secret?msg=notes" + + + # URL msg and note id if exist noteid + if selectedNoteId != "": + url_note = "/secret?msg=notes¬eid=" & selectedNoteId + + if c.loggedIn: + # Start joplin terminal cli if stropped + if @"msg" == "startStopJoplin": + var isStart = joplin_cli_start_stop() + + + redirect(url_note) # if Joplin application work var checkJoplin = waitFor ping_joplin(joplin_token) @@ -299,51 +314,81 @@ routes: # determine the section to uptade if @"msg" == "newNote": cld.option = newNote - echo "Todo" + echo "=> Section newNote" elif @"msg" == "search": cld.option = search - echo "Todo" + echo "=> Section search" elif @"msg" == "shortcuts": cld.option = shortcuts - echo "Todo" + echo "=> Section shortcuts" elif @"msg" == "notebooks": + echo "=> Section notebooks" cld.option = notebooks cld.j_notebooks = waitFor get_joplin_notebooks(joplin_token) elif @"msg" == "notes": + echo "=> Section notes" cld.option = notes cld.j_notes = waitFor get_joplin_notes(joplin_token) + cld.j_notes_nb = cld.j_notes.id.len() + + # for i in 0 .. (cld.j_notes.id.len() - 1): + # echo cld.j_notes.id[i] + # echo cld.j_notes.created_time[i] + + if selectedNoteId != "": + crd.j_SelectedNote = waitFor get_joplin_note(joplin_token, selectedNoteId) elif @"msg" == "tags": + echo "=> Section tags" cld.option = tags cld.j_tags = waitFor get_joplin_tags(joplin_token) + elif @"msg" == "dashbord": + echo "=> Section dashbord" + #cld.option = dashbord + + let + data = parseExcel("data/dashbord.xlsx", header = true) + sheetName = "dashbord" + echo data[sheetName] + + let rows = data[sheetName].toSeq(true) + for row in rows: + echo "position: " & row[0] + echo "URL externe: " & row[1] + + elif @"msg" == "sendFeedBack": echo "Todo" - - resp Http200, {"Access-Control-Allow-Origin": "http://127.0.0.1:7000"}, genSecret(c,cld) - + + resp Http200, {"Access-Control-Allow-Origin": "http://127.0.0.1:7000"}, + genSecret(c, cld, crd) + # Login route # --==--==--==--==--==--==--==--==--==--==-- # get "/login": createTFD() - resp Http200, {"Access-Control-Allow-Origin": "http://127.0.0.1:7000"}, genLogin(c, @"msg") + resp Http200, {"Access-Control-Allow-Origin": "http://127.0.0.1:7000"}, + genLogin(c, @"msg") # action route during login # --==--==--==--==--==--==--==--==--==--==-- # post "/dologin": createTFD() - let (loginB, loginS) = login(c, replace(toLowerAscii(@"email"), " ", ""), replace(@"password", " ", "")) + let (loginB, loginS) = login(c, replace(toLowerAscii(@"email"), " ", ""), + replace(@"password", " ", "")) if loginB: when defined(dev): jester.setCookie("sid", loginS, daysForward(7)) else: - jester.setCookie("sid", loginS, daysForward(7), samesite = Lax, secure = true, httpOnly = true) + jester.setCookie("sid", loginS, daysForward(7), samesite = Lax, + secure = true, httpOnly = true) #jester.setCookie("sid", loginS, daysForward(7), samesite = Lax, secure = true, httpOnly = true) redirect("/secret") @@ -363,7 +408,7 @@ routes: # if joplin_cli_status() == false: # joplin_cli_start() - + # --==--==--==--==--==--==--==--==--==--==-- # @@ -380,22 +425,22 @@ routes: # --==--==--==--==--==--==--==--==--==--==-- # get "/test_pingjoplin": createTFD() - + var pingCheck: joplin_ping pingCheck = waitFor ping_joplin(joplin_token) echo pingCheck.ping_status - + resp test_ping(c, pingCheck) # Test geting list of all notebooks # --==--==--==--==--==--==--==--==--==--==-- # get "/test_notebooks": createTFD() - cld.j_notebooks = waitFor get_joplin_notebooks(joplin_token) + cld.j_notebooks = waitFor get_joplin_notebooks(joplin_token) resp test_notebooks(c, cld) # Test geting list of all notes - # --==--==--==--==--==--==--==--==--==--==-- # + # --==--==--==--==--==--==--==--==--==--==-- # get "/test_notes": createTFD() cld.j_notes = waitFor get_joplin_notes(joplin_token) @@ -408,13 +453,13 @@ routes: cld.j_tags = waitFor get_joplin_tags(joplin_token) resp test_tags(c, cld) - # Test a viewtree + # Test a viewtree # --==--==--==--==--==--==--==--==--==--==-- # get "/test_viewtree": createTFD() resp test_viewtree(c) - # Test geting all tags as JSON output + # Test geting all tags as JSON output # --==--==--==--==--==--==--==--==--==--==-- # get "/test_tags_json": createTFD() @@ -426,4 +471,4 @@ routes: # # ## # # END TESTS SECTION ## -# # ## +# # ## diff --git a/public/css/styles.css b/public/css/styles.css index bd7dcd5..d203180 100755 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -2,449 +2,493 @@ [ FONT ]*/ @font-face { - font-family: Poppins-Regular; - src: url('../fonts/poppins/Poppins-Regular.ttf'); + font-family: Poppins-Regular; + src: url('../fonts/poppins/Poppins-Regular.ttf'); } @font-face { - font-family: Poppins-Medium; - src: url('../fonts/poppins/Poppins-Medium.ttf'); + font-family: Poppins-Medium; + src: url('../fonts/poppins/Poppins-Medium.ttf'); } @font-face { - font-family: Poppins-Bold; - src: url('../fonts/poppins/Poppins-Bold.ttf'); + font-family: Poppins-Bold; + src: url('../fonts/poppins/Poppins-Bold.ttf'); } @font-face { - font-family: Poppins-SemiBold; - src: url('../fonts/poppins/Poppins-SemiBold.ttf'); + font-family: Poppins-SemiBold; + src: url('../fonts/poppins/Poppins-SemiBold.ttf'); } - -html, body { - margin: 0; - font-family: Poppins-Regular, sans-serif; - height:100%; +html, +body { + margin: 0; + font-family: Poppins-Regular, sans-serif; + height: 100%; } *, *::before, *::after { - box-sizing: border-box; - margin: 0; - padding: 0; + box-sizing: border-box; + margin: 0; + padding: 0; } a { - font-family: Poppins-Regular; - font-size: 14px; - line-height: 1.7; - color: #666666; - margin: 0px; - transition: all 0.4s; - -webkit-transition: all 0.4s; - -o-transition: all 0.4s; - -moz-transition: all 0.4s; + font-family: Poppins-Regular; + font-size: 14px; + line-height: 1.7; + color: #666666; + margin: 0px; + transition: all 0.4s; + -webkit-transition: all 0.4s; + -o-transition: all 0.4s; + -moz-transition: all 0.4s; } :root { - --accent-color: #0053b8; - --lightest-gray: rgb(244, 244, 244); - --light-gray: rgb(144, 144, 144); - --medium-gray: rgb(96, 96, 96); - --dark-gray: rgb(13, 13, 13); - --animation-duration: 200ms; - --animation-timing-curve: ease-in-out; - --blue-joplin-color: #0053b8; - --light-blue-joplin-color: rgb(237, 241, 243); - --header-height: 55px; + --accent-color: #0053b8; + --lightest-gray: rgb(244, 244, 244); + --light-gray: rgb(144, 144, 144); + --medium-gray: rgb(96, 96, 96); + --dark-gray: rgb(13, 13, 13); + --animation-duration: 200ms; + --animation-timing-curve: ease-in-out; + --blue-joplin-color: #0053b8; + /* --blue-joplin-color: #b83100; */ + --light-blue-joplin-color: rgb(237, 241, 243); + --header-height: 55px; } .header { - display: flex; - align-items: center; - position: sticky; - top: 0; - background-color: white; - box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.4); - padding: 0 0.5rem; - height: var(--header-height); + display: flex; + align-items: center; + position: sticky; + top: 0; + background-color: white; + box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.4); + padding: 0 0.5rem; + height: var(--header-height); } .login { - font-size: large; - fill: var(--blue-joplin-color); - /* max-width: fit-content; */ - position: absolute; - top: 30%; - left: 50%; - transform: translate(-52%, -50%); - + font-size: large; + fill: var(--blue-joplin-color); + /* max-width: fit-content; */ + position: absolute; + top: 30%; + left: 50%; + transform: translate(-52%, -50%); } + /* Create two equal columns that floats next to each other */ + .column { - float: left; - padding: 10px; - height: calc(100vh - var(--header-height)); - /* height: auto; */ - /* flex: 50%; */ - width: 100%; + float: left; + padding: 10px; + height: calc(100vh - var(--header-height)); + /* height: auto; */ + /* flex: 50%; */ + width: 100%; } .column .scrollbar { - /* margin-left: 30px; */ - /* float: left; */ - /* min-height: 100px; */ - height: 800px; - background: #fff; - overflow-y: scroll; - /* margin-bottom: 25px; */ + /* margin-left: 30px; */ + /* float: left; */ + /* min-height: 100px; */ + height: 800px; + background: #fff; + overflow-y: scroll; + /* margin-bottom: 25px; */ } .left { - width: 25%; + width: 25%; } .right { - width: 75%; + width: 75%; } .row { - display: flex; - width: 100%; + display: flex; + width: 100%; } + /* Clear floats after the columns */ + .row:after { - content: ""; - display: table; - clear: both; + content: ""; + display: table; + clear: both; } .menu-icon-btn { - background: none; - border: none; - padding: 0; + background: none; + border: none; + padding: 0; } .notifBell-btn { - background: none; - border: none; - padding: 0; + background: none; + border: none; + padding: 0; } .menu-icon { - width: 25px; - height: 25px; - fill: var(--medium-gray); - cursor: pointer; + width: 25px; + height: 25px; + fill: var(--medium-gray); + cursor: pointer; } .menu-icon:hover { - fill: var(--dark-gray); + fill: var(--dark-gray); } .sidebar { - flex-shrink: 0; - overflow: hidden; - width: 75px; - border-right: 1px solid var(--light-gray); - display: flex; - flex-direction: column; - height: calc(100vh - var(--header-height)); - padding-top: 1rem; - align-items: center; - justify-content: stretch; - transition: width var(--animation-duration) var(--animation-timing-curve); - position: sticky; - left: 0; - top: var(--header-height); + flex-shrink: 0; + overflow: hidden; + width: 75px; + border-right: 1px solid var(--light-gray); + display: flex; + flex-direction: column; + height: calc(100vh - var(--header-height)); + padding-top: 1rem; + align-items: center; + justify-content: stretch; + transition: width var(--animation-duration) var(--animation-timing-curve); + position: sticky; + left: 0; + top: var(--header-height); } .sidebar .hidden-sidebar { - opacity: 0; - width: 0; - transition: opacity var(--animation-duration) var(--animation-timing-curve); + opacity: 0; + width: 0; + transition: opacity var(--animation-duration) var(--animation-timing-curve); } .sidebar.open .hidden-sidebar { - width: 100%; - height: auto; - opacity: 1; + width: 100%; + height: auto; + opacity: 1; } .sidebar .top-sidebar { - display: flex; - flex-direction: column; - align-items: center; + display: flex; + flex-direction: column; + align-items: center; } .sidebar .channel-logo { - display: block; - width: 30px; - height: 30px; - transition: var(--animation-duration) var(--animation-timing-curve); + display: block; + width: 30px; + height: 30px; + transition: var(--animation-duration) var(--animation-timing-curve); } .sidebar.open .channel-logo { - width: 90px; - height: 90px; + width: 90px; + height: 90px; } .sidebar .channel-logo>img { - width: 100%; - height: 100%; + width: 100%; + height: 100%; } .middle-sidebar { - overflow-y: auto; - overflow-x: hidden; - flex-grow: 1; - margin: 1rem 0; + overflow-y: auto; + overflow-x: hidden; + flex-grow: 1; + margin: 1rem 0; } .middle-sidebar, .bottom-sidebar { - width: 100%; + width: 100%; } .container { - display: flex; - height: 94%; + display: flex; + height: 94%; } .vertical-center { - margin: 0; - position: absolute; - top: 50%; - -ms-transform: translateY(-50%); - transform: translateY(-50%); - /* border: 5px solid #FFFF00; */ - text-align: center; + margin: 0; + position: absolute; + top: 50%; + -ms-transform: translateY(-50%); + transform: translateY(-50%); + /* border: 5px solid #FFFF00; */ + text-align: center; } .content { - /* margin: 1rem; */ - width: 1200px; - min-height: 100px; - height: auto; - margin: 80px auto 0px auto; - /* background-color: black; */ - padding: 10px 10px; - display:table; - overflow:hidden; - height:100%; + /* margin: 1rem; */ + width: 1200px; + min-height: 100px; + height: auto; + margin: 80px auto 0px auto; + /* background-color: black; */ + padding: 10px 10px; + display: table; + overflow: hidden; + height: 100%; } .sidebar-list { - margin: 0; - padding: 0; - display: flex; - flex-direction: column; - align-items: center; - list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + align-items: center; + list-style: none; } .sidebar.open .sidebar-link { - justify-content: flex-start; + justify-content: flex-start; } +.svg-icon path, +.svg-icon polygon, +.svg-icon rect, .sidebar-icon { - width: 25px; - height: 25px; - flex-shrink: 0; - fill: var(--blue-joplin-color); + width: 25px; + height: 25px; + flex-shrink: 0; + fill: var(--blue-joplin-color); +} + +.svg-icon { + width: 25px; + height: 25px; +} + +.svg-icon circle { + stroke: #4691f6; + stroke-width: 1; } .sidebar-list .hidden-sidebar { - margin-left: 1.5rem; - white-space: nowrap; + margin-left: 1.5rem; + white-space: nowrap; } .sidebar-link { - display: flex; - width: 100%; - padding: 0.5rem 0; - color: var(--light-gray); - text-decoration: none; - align-items: center; - padding-left: 25px; + display: flex; + width: 100%; + padding: 0.5rem 0; + color: var(--light-gray); + text-decoration: none; + align-items: center; + padding-left: 25px; +} + +.sidebar-note-link { + display: flex; + width: 100%; + /* padding: 10px; */ + color: var(--blue-joplin-color); + text-decoration: none; + font-size: 16px; + align-items: left; + padding-left: 15px; +} + +.sidebar-note-date { + display: flex; + width: 100%; + /* padding: 0.1rem 0; */ + color: var(--light-gray); + text-decoration: none; + font-size: 12px; + align-items: left; + padding-left: 15px; + padding-bottom: 10px; } .sidebar-list-item { - position: relative; - width: 100%; - fill: var(--light-gray); + position: relative; + width: 100%; + fill: var(--light-gray); } .sidebar-list-item.active { - fill: var(--accent-color); - background-color: var(--light-blue-joplin-color); + fill: var(--accent-color); + background-color: var(--light-blue-joplin-color); } .sidebar-list-item:hover { - background-color: var(--light-blue-joplin-color); + background-color: var(--light-blue-joplin-color); +} + +.columnLeftJoplinNotes:hover { + background-color: var(--light-blue-joplin-color); } .sidebar-list-item.active::before { - content: ""; - background-color: var(--accent-color); - height: 100%; - left: 0; - width: 3px; - position: absolute; + content: ""; + background-color: var(--accent-color); + height: 100%; + left: 0; + width: 3px; + position: absolute; } .sidebar.open { - width: 200px; + width: 200px; } .your-channel { - color: var(--dark-gray); - font-size: 1.5rem; - font-weight: bold; - margin-bottom: 0.15rem; - margin-top: 0.5rem; + color: var(--dark-gray); + font-size: 1.5rem; + font-weight: bold; + margin-bottom: 0.15rem; + margin-top: 0.5rem; } .channel-name { - color: var(--medium-gray); - font-size: 1.0rem; + color: var(--medium-gray); + font-size: 1.0rem; } .sidebar .top-sidebar { - height: 30px; - transition: height var(--animation-duration) var(--animation-timing-curve); + height: 30px; + transition: height var(--animation-duration) var(--animation-timing-curve); } .sidebar.open .top-sidebar { - height: 150px; + height: 150px; } .sidebar .top-sidebar .hidden-sidebar { - text-align: center; - width: 100%; + text-align: center; + width: 100%; } .force-overflow { - min-height: 450px; + min-height: 450px; } .scrollbar-primary::-webkit-scrollbar { - width: 6px; - background-color: #F5F5F5; + width: 6px; + background-color: #F5F5F5; } .scrollbar-primary::-webkit-scrollbar-thumb { - border-radius: 10px; - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #4285F4; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #4285F4; } .scrollbar-danger::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #F5F5F5; - border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #F5F5F5; + border-radius: 10px; } .scrollbar-danger::-webkit-scrollbar { - width: 12px; - background-color: #F5F5F5; + width: 12px; + background-color: #F5F5F5; } .scrollbar-danger::-webkit-scrollbar-thumb { - border-radius: 10px; - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #ff3547; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #ff3547; } .scrollbar-warning::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #F5F5F5; - border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #F5F5F5; + border-radius: 10px; } .scrollbar-warning::-webkit-scrollbar { - width: 12px; - background-color: #F5F5F5; + width: 12px; + background-color: #F5F5F5; } .scrollbar-warning::-webkit-scrollbar-thumb { - border-radius: 10px; - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #FF8800; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #FF8800; } .scrollbar-success::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #F5F5F5; - border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #F5F5F5; + border-radius: 10px; } .scrollbar-success::-webkit-scrollbar { - width: 12px; - background-color: #F5F5F5; + width: 12px; + background-color: #F5F5F5; } .scrollbar-success::-webkit-scrollbar-thumb { - border-radius: 10px; - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #00C851; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #00C851; } .scrollbar-info::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #F5F5F5; - border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #F5F5F5; + border-radius: 10px; } .scrollbar-info::-webkit-scrollbar { - width: 12px; - background-color: #F5F5F5; + width: 12px; + background-color: #F5F5F5; } .scrollbar-info::-webkit-scrollbar-thumb { - border-radius: 10px; - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #33b5e5; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #33b5e5; } .scrollbar-default::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #F5F5F5; - border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #F5F5F5; + border-radius: 10px; } .scrollbar-default::-webkit-scrollbar { - width: 12px; - background-color: #F5F5F5; + width: 12px; + background-color: #F5F5F5; } .scrollbar-default::-webkit-scrollbar-thumb { - border-radius: 10px; - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #2BBBAD; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #2BBBAD; } .scrollbar-secondary::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #F5F5F5; - border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #F5F5F5; + border-radius: 10px; } .scrollbar-secondary::-webkit-scrollbar { - width: 12px; - background-color: #F5F5F5; + width: 12px; + background-color: #F5F5F5; } .scrollbar-secondary::-webkit-scrollbar-thumb { - border-radius: 10px; - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); - background-color: #aa66cc; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); + background-color: #aa66cc; } .fancytree-container { - outline: none; -} \ No newline at end of file + outline: none; +} \ No newline at end of file diff --git a/tmpl/snippet_icons.nim b/tmpl/snippet_icons.nim index be787ba..b8d0812 100644 --- a/tmpl/snippet_icons.nim +++ b/tmpl/snippet_icons.nim @@ -3,7 +3,7 @@ import templates # --==--==--==--==--==--==--==--==--==--==-- # # SVG : Menu icon # --==--==--==--==--==--==--==--==--==--==-- # -proc Menu_icon* (): string = tmpli html""" +proc Menu_icon*(): string = tmpli html""" @@ -119,7 +119,7 @@ proc Notebooks_icon*(): string = tmpli html""" """ # --==--==--==--==--==--==--==--==--==--==-- # -# SVG : All tags icon +# SVG : Tags icon # --==--==--==--==--==--==--==--==--==--==-- # proc Tags_icon*(): string = tmpli html""" """ +# --==--==--==--==--==--==--==--==--==--==-- # +# SVG : Dashbord icon +# --==--==--==--==--==--==--==--==--==--==-- # +proc Dashbord_icon*(): string = tmpli html""" + + + + """ + # --==--==--==--==--==--==--==--==--==--==-- # # SVG : Settings icon # --==--==--==--==--==--==--==--==--==--==-- # @@ -191,4 +211,4 @@ proc SendFeedback_icon*(): string = tmpli html""" - """ \ No newline at end of file + """ diff --git a/tmpl/website.tmpl b/tmpl/website.tmpl index ffcb660..44af9da 100644 --- a/tmpl/website.tmpl +++ b/tmpl/website.tmpl @@ -13,7 +13,7 @@ # # import snippet_html # import snippet_icons -#proc genSecret(c: var TData, columnLeftInfo: var ColomnLeftData): string = +#proc genSecret(c: var TData, columnLeftInfo: var ColomnLeftData, ColomnRightInfo: var ColomnRightData): string = # result = "" @@ -22,7 +22,7 @@ - Document + Joplin-TheNewWeb @@ -63,6 +63,7 @@ # var active_notes: string = "" # var active_notebooks: string = "" # var active_tags: string = "" + # var active_dashbord: string = "" # var active_settings: string = "" # var active_sendFeedBack: string = "" # if columnLeftInfo.option == newNote: @@ -77,6 +78,8 @@ # active_notebooks = "active" # elif columnLeftInfo.option == tags: # active_tags = "active" + # elif columnLeftInfo.option == dashbord: + # active_dashbord = "active" # end if + + + +
@@ -225,14 +240,15 @@
# elif columnLeftInfo.option == notes: -

Notes

+

Notes

${columnLeftInfo.j_notes_nb}
-
-
- # for i in columnLeftInfo.j_notes.title: -

${i}

- # end for -
+
+ # for i in 0 .. (columnLeftInfo.j_notes.id.len() - 1) : +
+ ${columnLeftInfo.j_notes.title[i]} + +
+ # end for
# elif columnLeftInfo.option == notebooks: @@ -254,14 +270,37 @@ # for i in columnLeftInfo.j_tags.title:

${i}

# end for +
+ + + # elif columnLeftInfo.option == dashbord: +

Dashboard

+
+
+
+ +

DASHBORD

+
# end if -
-

Column 2

-

Some text..

+
+ # if columnLeftInfo.option == newNote: +

New Note !!

+

Some text..

+ # elif columnLeftInfo.option == notes: + # if ColomnRightInfo.j_SelectedNote.id != "": +

${ColomnRightInfo.j_SelectedNote.title}

+
+
+

${ColomnRightInfo.j_SelectedNote.body}

+ # else : +

Click on note to see it !!

+ # end if + + # end if