
\begin{DoxyItemize}
\item infos/maintainer = Tomislav Makar \href{mailto:tmakar23@gmail.com}{\texttt{ tmakar23@gmail.\+com}}
\end{DoxyItemize}\hypertarget{md_doc_tutorials_install_webui_doc_tutorials_install-webui_md}{}\doxysection{elektra-\/web}\label{md_doc_tutorials_install_webui_doc_tutorials_install-webui_md}
{\itshape an API and web user interface to remotely manage Elektra instances}

The configuration view of elektra-\/web is similar to the tree view of the \href{https://master.libelektra.org/src/tools/qt-gui}{\texttt{ qt-\/gui}}, but with dynamic fields rendered via key metadata.\hypertarget{md_doc_tutorials_install_webui_autotoc_md4428}{}\doxysubsection{Dependencies}\label{md_doc_tutorials_install_webui_autotoc_md4428}
Elektra-\/web requires\+:


\begin{DoxyItemize}
\item \href{https://libelektra.org/}{\texttt{ Elektra}} with the \href{https://master.libelektra.org/src/plugins/yajl/}{\texttt{ {\ttfamily yajl} plugin}} installed
\item A recent \href{https://nodejs.org/en/}{\texttt{ node.\+js}} installation (at least 6.\+x)
\item \href{https://go.dev/}{\texttt{ Go}} with version $>$ 1.\+13
\end{DoxyItemize}\hypertarget{md_doc_tutorials_install_webui_autotoc_md4429}{}\doxysubsection{Building with elektra-\/web Tool}\label{md_doc_tutorials_install_webui_autotoc_md4429}
To build Elektra with the elektra-\/web tool\+:


\begin{DoxyItemize}
\item Install Node.\+js, Go and dependencies for {\ttfamily yajl} plugin (see links above)
\item Configure libelektra build with the elektra-\/web tool, e.\+g. {\ttfamily cmake .. -\/DTOOLS=\char`\"{}kdb;web\char`\"{}}
\item Build libelektra\+: {\ttfamily make}
\item Install libelektra\+: {\ttfamily sudo make install}
\end{DoxyItemize}\hypertarget{md_doc_tutorials_install_webui_autotoc_md4430}{}\doxysubsection{Getting Started (docker)}\label{md_doc_tutorials_install_webui_autotoc_md4430}

\begin{DoxyItemize}
\item Create and run a new docker container\+: {\ttfamily docker run -\/d -\/it -\/p 33333\+:33333 -\/p 33334\+:33334 elektra/web}
\item You can now access the client on\+: \href{http://localhost:33334}{\texttt{ http\+://localhost\+:33334}}
\item You can also build it yourself in {\ttfamily scripts/docker/webui/} (see \href{\#building-docker-image}{\texttt{ Building Docker Image}})
\end{DoxyItemize}\hypertarget{md_doc_tutorials_install_webui_autotoc_md4431}{}\doxysubsection{Running from source}\label{md_doc_tutorials_install_webui_autotoc_md4431}

\begin{DoxyItemize}
\item Install dependencies (see above)
\item Clone libelektra repo and {\ttfamily cd libelektra/src/tools/web}
\item Install and start an elektrad instance\+:
\begin{DoxyItemize}
\item {\ttfamily cd elektrad}
\item {\ttfamily go build}
\item {\ttfamily ./elektrad} (replaces {\ttfamily kdb run-\/elektrad})
\end{DoxyItemize}
\item Install and start the client (connects to the elektrad instance)\+:
\begin{DoxyItemize}
\item {\ttfamily cd webui}
\item {\ttfamily npm install}
\item {\ttfamily npm start} (replaces {\ttfamily kdb run-\/webd})
\end{DoxyItemize}
\item You can now access the client on\+: \href{http://localhost:33334}{\texttt{ http\+://localhost\+:33334}}
\end{DoxyItemize}\hypertarget{md_doc_tutorials_install_webui_autotoc_md4432}{}\doxysubsection{Use-\/cases}\label{md_doc_tutorials_install_webui_autotoc_md4432}
\hypertarget{md_doc_tutorials_install_webui_autotoc_md4433}{}\doxysubsubsection{Running elektra-\/web on a Single Instance}\label{md_doc_tutorials_install_webui_autotoc_md4433}
If you do not want to configure multiple instances, you can set the {\ttfamily INSTANCE} environment variable to the server you want to configure. You can also set {\ttfamily user\+:/sw/elektra/web/\#0/current/instance} to the host. Make sure to enter a full HTTP URL, e.\+g. {\ttfamily \href{http://localhost:33333}{\texttt{ http\+://localhost\+:33333}}}.

If this configuration option is set, elektra-\/web will load the configuration page for that instance instead of the main overview page.

If you want to host elektra-\/web with the client and elektrad on the same instance, you must first start elektrad via {\ttfamily kdb run-\/elektrad}. Afterwards, you can run the client with\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{export INSTANCE="{}http://localhost:33333"{} \&\& npm start}

\end{DoxyCode}


It is also possible to set visibility by prefixing the host with {\ttfamily VISIBILITY@}.

For example ({\ttfamily advanced} visibility, {\ttfamily user} is default)\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{export INSTANCE="{}advanced@http://localhost:33333"{} \&\& npm start}

\end{DoxyCode}


Now, when you open \href{http://localhost:33334}{\texttt{ http\+://localhost\+:33334}} in your browser, the configuration page for the instance will be opened immediately.\hypertarget{md_doc_tutorials_install_webui_autotoc_md4434}{}\doxysubsection{Overview}\label{md_doc_tutorials_install_webui_autotoc_md4434}
Elektra web consists of multiple components\+:


\begin{DoxyItemize}
\item (multiple) servers running an elektra daemon (\`{}elektrad\`{})
\item a single server to communicate with the elektra daemons and serve the client (\`{}webd\`{})
\item a web browser that accesses the client (Web UI) on the \`{}webd\`{} server (\`{}client\`{})
\end{DoxyItemize}

\hypertarget{md_doc_tutorials_install_webui_autotoc_md4435}{}\doxysubsection{API}\label{md_doc_tutorials_install_webui_autotoc_md4435}


\href{https://apiblueprint.org/}{\texttt{ API blueprints}} are available for both APIs\+:


\begin{DoxyItemize}
\item \href{https://master.libelektra.org/doc/api_blueprints/elektrad.apib}{\texttt{ elektrad}}, documentation\+: \href{https://elektrad.docs.apiary.io/}{\texttt{ https\+://elektrad.\+docs.\+apiary.\+io/}}
\item \href{https://master.libelektra.org/doc/api_blueprints/webd.apib}{\texttt{ webd}}, documentation\+: \href{https://elektrawebd.docs.apiary.io/}{\texttt{ https\+://elektrawebd.\+docs.\+apiary.\+io/}}
\end{DoxyItemize}\hypertarget{md_doc_tutorials_install_webui_autotoc_md4436}{}\doxysubsection{Test REST API on localhost}\label{md_doc_tutorials_install_webui_autotoc_md4436}
In order to test the API on localhost, you have to start an elektrad instance. This is possible in two ways\+:


\begin{DoxyItemize}
\item manually (recommended if you would like to control elektrad manually or the eletrad-\/web tool is not installed)
\end{DoxyItemize}


\begin{DoxyCode}{0}
\DoxyCodeLine{cd libelektra/src/tools/web}
\DoxyCodeLine{cd elektrad}
\DoxyCodeLine{go build}
\DoxyCodeLine{./elektrad}

\end{DoxyCode}



\begin{DoxyItemize}
\item by installing elektrad tool together with Elektra (see section \href{\#building-with-elektra-web-tool}{\texttt{ Building with elektra-\/web Tool}})
\end{DoxyItemize}

Now the server is running on \href{http://localhost:33333}{\texttt{ http\+://localhost\+:33333}}. After that you can test the API with help of Postman or similar tools that allow sending REST API requests.

{\bfseries{Additional note}}\+: It is recommended to install the elektrad tool rather than starting the server manually. When Elektra is installed, the {\ttfamily kdb} command together with its tools is installed globally. For instance, whenever you would like to write a shell script which has to start a REST API server, you can just add {\ttfamily kdb run-\/elektrad} and execute it locally.

Examples\+:

First create a new key-\/value pair {\ttfamily user\+:/test} and set its value to 5. This can be done


\begin{DoxyItemize}
\item using the command line 
\begin{DoxyCode}{0}
\DoxyCodeLine{kdb set user:/test 5}

\end{DoxyCode}

\item through the rest API using curl 
\begin{DoxyCode}{0}
\DoxyCodeLine{curl -\/X PUT -\/H "{}Content-\/Type: text/plain"{} -\/-\/data "{}5"{} http://localhost:33333/kdb/user:/test}

\end{DoxyCode}

\end{DoxyItemize}

The output of the commandline tool will be {\ttfamily Set string to \char`\"{}5\char`\"{}} if the key did not exist before. If the specified key didn\textquotesingle{}t exist before, then the output will be {\ttfamily Create a new key user\+:/test with string \char`\"{}5\char`\"{}}. Elektrad will respond with code {\ttfamily 200}.

The command


\begin{DoxyCode}{0}
\DoxyCodeLine{curl http://localhost:33333/kdb/user:/test}
\DoxyCodeLine{\#> \{"{}exists"{}:true,"{}name"{}:"{}test"{},"{}path"{}:"{}user:/test"{},"{}ls"{}:["{}user:/test"{}],"{}value"{}:"{}5"{},"{}meta"{}:"{}"{}\}}

\end{DoxyCode}


will now return the value of the specified key {\ttfamily user\+:/test}, which is stored in the database.


\begin{DoxyCode}{0}
\DoxyCodeLine{\{}
\DoxyCodeLine{    "{}exists"{}: true,}
\DoxyCodeLine{    "{}name"{}: "{}test"{},}
\DoxyCodeLine{    "{}path"{}: "{}user:/test"{},}
\DoxyCodeLine{    "{}ls"{}: [}
\DoxyCodeLine{        "{}user:/test"{}}
\DoxyCodeLine{    ],}
\DoxyCodeLine{    "{}value"{}: "{}5"{},}
\DoxyCodeLine{    "{}meta"{}: "{}"{}}
\DoxyCodeLine{\}}

\end{DoxyCode}


The command


\begin{DoxyCode}{0}
\DoxyCodeLine{curl -\/X POST -\/H "{}Content-\/Type: application/json"{} -\/d '\{"{}meta"{}: [\{"{}key"{}: "{}metakey1"{}, "{}value"{}: "{}value1"{}\},\{"{}key"{}: "{}metakey2"{}, "{}value"{}: "{}value2"{}\}]\}' http://localhost:33333/kdbMetaBulk/user:/test}

\end{DoxyCode}


will now create multiple metakeys at once. In this case, it will create two ({\ttfamily metakey1} and {\ttfamily metakey2}).

The command


\begin{DoxyCode}{0}
\DoxyCodeLine{curl http://localhost:33333/kdb/user:/test}
\DoxyCodeLine{\#> \{"{}exists"{}:true,"{}name"{}:"{}test"{},"{}path"{}:"{}user:/test"{},"{}ls"{}:["{}user:/test"{}],"{}value"{}:"{}1"{},"{}meta"{}:\{"{}metakey1"{}:"{}value1"{},"{}metakey2"{}:"{}value2"{}\}\}}

\end{DoxyCode}


will now also return the two metakeys.


\begin{DoxyCode}{0}
\DoxyCodeLine{\{}
\DoxyCodeLine{    "{}exists"{}: true,}
\DoxyCodeLine{    "{}name"{}: "{}test"{},}
\DoxyCodeLine{    "{}path"{}: "{}user:/test"{},}
\DoxyCodeLine{    "{}ls"{}: [}
\DoxyCodeLine{        "{}user:/test"{}}
\DoxyCodeLine{    ],}
\DoxyCodeLine{    "{}value"{}: "{}5"{},}
\DoxyCodeLine{    "{}meta"{}: \{}
\DoxyCodeLine{        "{}metakey1"{}: "{}value1"{},}
\DoxyCodeLine{        "{}metakey2"{}: "{}value2"{}}
\DoxyCodeLine{    \}}
\DoxyCodeLine{\}}

\end{DoxyCode}
\hypertarget{md_doc_tutorials_install_webui_autotoc_md4437}{}\doxysubsection{Auth}\label{md_doc_tutorials_install_webui_autotoc_md4437}
Currently, webd does not support authentication. The best way to work around this is to use a reverse proxy (e.\+g. \href{https://www.nginx.com/resources/admin-guide/reverse-proxy/}{\texttt{ nginx reverse proxy}}).

Once you set up a reverse proxy on your web server, you can use it to authenticate users, e.\+g. by \href{https://www.digitalocean.com/community/tutorials/how-to-set-up-password-authentication-with-nginx-on-ubuntu-14-04}{\texttt{ username/password auth}}\hypertarget{md_doc_tutorials_install_webui_autotoc_md4438}{}\doxysubsection{Code Structure}\label{md_doc_tutorials_install_webui_autotoc_md4438}
{\ttfamily elektrad/} -\/ contains the daemon to interact with a single elektra instance ~\newline
 {\ttfamily webd/} -\/ contains a daemon to serve the client and interact with multiple elektra instances

{\ttfamily webui/} -\/ contains the elektra-\/web client (Web UI)


\begin{DoxyItemize}
\item {\ttfamily src/actions/} -\/ Redux actions to access the KDB or display notifications in the UI
\item {\ttfamily src/components/} -\/ React components
\begin{DoxyItemize}
\item {\ttfamily pages/} -\/ pages in the app
\begin{DoxyItemize}
\item {\ttfamily Home.\+jsx} -\/ the main page (overview of all instances)
\item {\ttfamily Configuration.\+jsx} -\/ configuration page (single instance)
\end{DoxyItemize}
\item {\ttfamily Tree\+Item/} -\/ contains all UI components related to a single item in the tree view
\begin{DoxyItemize}
\item {\ttfamily dialogs/} -\/ these dialogs are opened when certain actions are pressed (icons next to the tree items)
\begin{DoxyItemize}
\item {\ttfamily Add\+Dialog.\+jsx} -\/ dialog to create a new (sub-\/)key
\item {\ttfamily Duplicate\+Dialog.\+jsx} -\/ dialog to duplicate a key
\item {\ttfamily Edit\+Dialog.\+jsx} -\/ dialog to edit a key value
\item {\ttfamily Remove\+Dialog.\+jsx} -\/ dialog to confirm the removal of a key
\item {\ttfamily Settings\+Dialog.\+jsx} -\/ dialog to edit metadata (new metadata can be implemented here)
\item {\ttfamily $\ast$\+Sub\+Dialog.jsx} -\/ sub-\/dialogs of the Settings\+Dialog
\end{DoxyItemize}
\item {\ttfamily fields/} -\/ special input fields to display various values
\end{DoxyItemize}
\item {\ttfamily App.\+jsx} -\/ defines app structure and routes
\end{DoxyItemize}
\item {\ttfamily src/index.\+js} -\/ main entry point of the app (fetches instances and renders UI)
\item {\ttfamily src/containers/} -\/ contains components that are connected to Redux
\item {\ttfamily src/css/} -\/ contains CSS styles
\item {\ttfamily src/reducers/} -\/ contains Redux reducers (used to process actions)
\end{DoxyItemize}\hypertarget{md_doc_tutorials_install_webui_autotoc_md4439}{}\doxysubsection{Development Guides}\label{md_doc_tutorials_install_webui_autotoc_md4439}
\hypertarget{md_doc_tutorials_install_webui_autotoc_md4440}{}\doxysubsubsection{Updating Dependencies}\label{md_doc_tutorials_install_webui_autotoc_md4440}
Lockfiles ({\ttfamily package-\/lock.\+json}) can be updated by simply deleting the current lock file and running {\ttfamily npm install}, which creates a new lock file.

Check for outdated dependencies via {\ttfamily npm outdated}. Dependencies can then be updated by running {\ttfamily npm update}.\hypertarget{md_doc_tutorials_install_webui_autotoc_md4441}{}\doxysubsubsection{Building Docker Image}\label{md_doc_tutorials_install_webui_autotoc_md4441}
Run the following command in the {\ttfamily scripts/docker/web/} directory, replacing {\ttfamily 1.\+5.\+0} with the latest version\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{docker build -\/t elektra/web:1.5.0 -\/t elektra/web:latest .}

\end{DoxyCode}


Test the image\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{docker run -\/d -\/it -\/p 33333:33333 -\/p 33334:33334 elektra/web:1.5.0}

\end{DoxyCode}


Publish it to the docker registry\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{docker push elektra/web:1.5.0}

\end{DoxyCode}
\hypertarget{md_doc_tutorials_install_webui_autotoc_md4442}{}\doxysubsubsection{Adding Support for New Metadata}\label{md_doc_tutorials_install_webui_autotoc_md4442}

\begin{DoxyItemize}
\item Create a new sub dialog by, for example, copying the {\ttfamily Number\+Sub\+Dialog.\+jsx} file (or similar) to a new file in the {\ttfamily webui/src/components/\+Tree\+Item/dialogs} folder.
\item Include the sub dialog by adding it to the {\ttfamily Settings\+Dialog.\+jsx} file in the same folder. For example, it could be added before the Additional\+Metakeys\+Sub\+Dialog at the end of the file\+:
\end{DoxyItemize}


\begin{DoxyCode}{0}
\DoxyCodeLine{+     <NewSubDialog}
\DoxyCodeLine{+       onChange=\{this.handleEdit('check/something')\}}
\DoxyCodeLine{+       value=\{this.getMeta('check/something', '')\}}
\DoxyCodeLine{+       saved=\{this.getSaved('check/something')\}}
\DoxyCodeLine{+     />}
\DoxyCodeLine{      <AdditionalMetakeysSubDialog}
\DoxyCodeLine{        handleEdit=\{this.handleEdit.bind(this)\}}
\DoxyCodeLine{        getMeta=\{this.getMeta.bind(this)\}}
\DoxyCodeLine{        getSaved=\{this.getSaved.bind(this)\}}
\DoxyCodeLine{        meta=\{this.props.meta\}}
\DoxyCodeLine{        deleteMeta=\{this.props.deleteMeta\}}
\DoxyCodeLine{      />}
\DoxyCodeLine{    </FocusTrapDialog>}

\end{DoxyCode}



\begin{DoxyItemize}
\item Mark the meta keys as handled by adding them to the {\ttfamily HANDLED\+\_\+\+METADATA} array in {\ttfamily webui/src/components/\+Tree\+Item/dialogs/utils.\+js}\+:
\end{DoxyItemize}


\begin{DoxyCode}{0}
\DoxyCodeLine{export const HANDLED\_METADATA = [}
\DoxyCodeLine{  ...,}
\DoxyCodeLine{  'visibility',}
\DoxyCodeLine{  'binary',}
\DoxyCodeLine{+ 'check/something',}
\DoxyCodeLine{]}

\end{DoxyCode}



\begin{DoxyItemize}
\item Validation can then be added by handling metadata in the {\ttfamily webui/src/components/\+Tree\+Item/fields/validate\+Type.\+js} file to the {\ttfamily validate\+Type} function.
\item Rendering fields in a special way when certain metakeys are present can be done by adjusting the {\ttfamily render\+Special\+Value} function in the {\ttfamily webui/src/components/\+Tree\+Item/index.\+js} file. 
\end{DoxyItemize}