Creating a Voiceover Portfolio Using Toolips.jl (Part Two)
Written on
Chapter 1: Introduction to the Admin Dashboard
Welcome back! In this segment, we will further develop a voiceover portfolio project designed for a friend. If you haven't read the previous installment, where I set up the front-end user application, you can find that article linked here.
As mentioned at the end of the last article, today's focus will be on establishing a remote connection using ToolipsRemote, which will enable us to create a new root with an admin interface. The initial step involves integrating ToolipsRemote, an extension that facilitates remote server connections from the Julia REPL.
using Toolips
using ToolipsSession
using ToolipsDefaults
using ToolipsMarkdown
using Random
using SHA
using ToolipsRemote
Next, I'll develop a function for handling incoming remote inputs. This function will accept a Connection and two strings: the first for the input command and the second for the user sending the data. It will establish a new route when the "open" command is issued, as well as manage password settings and route closures. Here’s the function I devised:
function serve_remote(c::Connection, m::String, user::String)
if m == "open"
auth = randstring(32)
c["/admin"] = admin_panel
push!(adminpanelkey, sha256(auth))
write!(c, "$websiteurl/admin?key=$auth")
elseif m == "close"
c["/admin"] = fourofourelseif contains(m, "pwd")
pwd = split(m, " ")[2]
ToolipsRemote.set_pwd!(c, "kevin" => string(pwd))
end
end
A module-wide variable, adminpanelkey, holds the current key argument. From here, creating the new link and returning a new URL is straightforward. This function will serve as the primary argument for our Remote extension. Additionally, I will add a message of the day (motd) to guide users on how to use this function, along with a default user login for initial access.
extensions = [Logger(), Files(), Session(), Remote(serve_remote, ["kevin" => "default"],
motd = """# Welcome, Kevin.
Greetings from your friend, Emmy. Upon logging in, use the open and close commands to control your admin panel. To change your password, enter pwd (your password here) (without spaces).""")
]
Now, I need to implement the admin panel function, which will require the key for authentication and compare it against the stored key hash.
function admin_panel(c::Connection)
if sha256(string(getarg(c, :key))) == adminpanelkey[1]
c[:Logger].log("successful authentication")end
end
If everything operates correctly, we should be able to access the admin panel URL using the "open" command, close it with "close", and change the password using "pwd". Let’s put that to the test!
julia> using ToolipsRemote
julia> connect("http://127.0.0.1:8000")
Upon logging in, we will receive a greeting and instructions. After entering the user credentials, the connection should establish successfully, allowing us to utilize the "open" command to retrieve the admin panel URL.
🔗 kevin> open
open http://127.0.0.1:8000/admin?key=FaBRYN3igS5m6BIURwTatMswZPUFv7JG
Now, let’s attempt to remove this new route, which should set the route to a 404 error.
🔗 kevin> close
While this may appear concerning, visiting the admin URL will now display a 404 error.
Next, we will change the password and try to connect from a different REPL.
🔗 kevin> pwd example
From the alternate REPL, we should be able to connect again.
julia> connect("http://127.0.0.1:8000")
With the remote section of this project completed, we’re nearing the final stages of development. The remaining tasks include building the administrator panel and serializing our saved data for future access.
Chapter 2: Developing the Admin Panel
To begin with the admin panel, we will implement a markdown box and an audio upload feature, necessitating the use of ToolipsUploader. Additionally, we must integrate the /admin route into our Toolips session's active routes.
extensions = [Logger(), Files(), Session(["/", "/admin"]), Remote(serve_remote, ["kevin" => "default"],
Returning to our admin function, we will again draft our stylesheet.
function admin_panel(c::Connection)
if sha256(string(getarg(c, :key))) == adminpanelkey[1]
#==
Styles
==#
styles::Component{:sheet} = stylesheet("kevinsvoice", scheme)
styles[:children]["section"]["background-color"] = scheme.background
write!(c, styles)
#==
Body
==#
bod = body("main")
style!(bod, "background-color" => "#080508")
else
write!(c, "Authentication failed. Please provide the correct key.")end
end
Next, I will create a new TMD editor, which is relatively simple. We just need to create a new editable area along with a container for the two inputs and an audio uploader. However, a challenge arises since ToolipsUploader currently supports only small files, making it likely impossible to upload complete audio files at this moment.
function admin_panel(c::Connection)
if sha256(string(getarg(c, :key))) == adminpanelkey[1]
#==
Styles
==#
styles::Component{:sheet} = stylesheet("kevinsvoice", scheme)
styles[:children]["section"]["background-color"] = scheme.background
write!(c, styles)
#==
Body
==#
bod = body("main")
style!(bod, "background-color" => "#080508")
#==
Admin Panel
==#
panel = section("adminsection", align = "center")
style!(panel, "margin-top" => "10px")
textb = a("textb", contenteditable = true)
style!(textb, "width" => "20px !important",
"padding" => "10px !important", "background-color" => "white",
"color" => "gray !important")
audiouploader = fileinput(c, "audiouploader") do fm
splitpath = split(fm.file.dir, "/")
fname = string(splitpath[length(splitpath)])
cp(fm.file.dir, "public/audio/$fname", force = true)
end
style!(audiouploader, "text-color" => "white")
push!(panel, textb, br(), audiouploader)
#==
Write Output
==#
push!(bod, panel)
write!(c, bod)
else
write!(c, "Authentication failed. Please provide the correct key.")end
end
The ToolipsUploader is undergoing significant updates, and a polling file uploader will soon enhance its functionality, allowing for larger audio uploads. However, I believe this new admin dashboard effectively illustrates the project's current state.
This project is progressing quite well from my perspective. I am currently working on the polling file uploader, which is already in progress! Thank you for following along with this exciting project! Wishing you a fantastic day!