- Improved documentation

- Added images
    - Fixed mistakes
- Added build script for zip file
This commit is contained in:
Administrator 2021-07-29 14:37:02 +02:00
parent 45e5e759d9
commit 87353a48ff
24 changed files with 253 additions and 90 deletions

View File

@ -1,15 +1,14 @@
\chapter{Einleitung und Installation}\label{ch:einleitung}
Immer mehr Programme werden heutzutage nicht mehr als native App sondern als Webapp, die im Browser aufgerufen wird, genutzt.
Ein Beispiel dafür sind die Office Anwendungen von Microsoft, die als native Programme und als Web-Version verfügbar sind.
Immer mehr Programme werden heutzutage nicht mehr als native App, sondern als Webapp, die im Browser aufgerufen wird, genutzt.
Ein Beispiel dafür sind die Office-Anwendungen von Microsoft, die als native Programme und als Web-Version verfügbar sind.
Die Web-Version hat dabei den Vorteil, dass sie auch unter Linux oder anderen, eigentlich nicht unterstützten Betriebssystemen, funktioniert.
Dadurch können mehr Personen die Anwendung nutzen und oftmals ist auch die Entwicklung einfacher, weil nur für ein System (Browser) und nicht für mehrere Systeme (Windows, Linux, MacOS, \ldots) entwickelt werden muss.
\section{Installation}
\section{Installation}\label{sec:installation}
Der Webservice kann mittels Docker gestartet werden.
\begin{lstlisting}
\begin{lstlisting}[label={lst:lstlisting}]
docker run --rm -v "<path>:/app" -v "<path>/upload.ini:/usr/local/etc/php/conf.d/upload.ini" -w /app -p 8080:80 php:7.4-cli php -S 0.0.0.0:80 router.php
\end{lstlisting}
Die eigentliche App wird geöffnet, indem die Datei \glqq index.html\grqq~im Ordner \glqq Frontend\grqq~in einem kompatiblen Browser geöffnet wird.
Damit alles einwandfrei funktionieren kann, muss der Webservice entweder auf dem gleichen Gerät wie die eigentliche App laufen oder in der Datei \glqq Frontend/static/js/index.js\grqq~ muss die erste Zeile angepasst werden.

View File

@ -1,33 +1,33 @@
\chapter{Allgemeine Informationen}\label{ch:allgemeine_informationen}
Bei diesem Projekt wurden ausschließlich die Programmier- beziehungsweise Markupsprachen JavaScript, \gls{css} und \gls{html} verwendet.
Bei diesem Projekt wurden ausschließlich die Programmier- beziehungsweise Markup-Sprachen JavaScript, \gls{css} und \gls{html} verwendet.
Es handelt sich um eine Single-Page-App.
Das heißt, die komplette Funktionalität wurde in einer einzelnen \acrshort{html}-Datei und mehreren JavaScript beziehungsweise CSS Dateien umgesetzt.
Alle Funktionen wurden in folgenden Browsern getestet:
\section{Desktop}
\section{Desktop}\label{sec:desktop}
\begin{center}
\begin{tabular}{ c c c c c }
\bfseries{Browser} & \bfseries{Version} & \bfseries{funktioniert?} & \bfseries{Probleme} \\
\begin{tabular}{ l l l }
\bfseries{OS} & \bfseries{Browser} & \bfseries{funktioniert?} \\
\hline
Mozilla Firefox & 90.0b12 & \textcolor{green}{\cmark} & \\
Google Chrome & 91.0.4472.114 & \textcolor{red}{\xmark} & Audio + Video abspielen \\
Chromium & 91.0.4472.114 & \textcolor{red}{\xmark} & Audio + Video abspielen \\
Opera & 77.0.4054.203 & \textcolor{red}{\xmark} & Audio + Video abspielen \\
Microsoft Edge & & & \\
Internet Explorer & & &
Ubuntu 20.04 & Mozilla Firefox 90.0b12 & \textcolor{green}{\cmark} \\
Ubuntu 20.04 & Google Chrome 91.0.4472.114 & \textcolor{green}{\cmark} \\
Ubuntu 20.04 & Chromium 91.0.4472.114 & \textcolor{green}{\cmark} \\
Ubuntu 20.04 & Opera 77.0.4054.277 & \textcolor{red}{\xmark} Videos \\
\end{tabular}
\end{center}
\section{Mobile}
\section{Mobile}\label{sec:mobile}
\begin{center}
\begin{tabular}{ c c c }
Browser & Version & funktioniert? \\
Mozilla Firefox & & \\
Google Chrome & & \\
Safari & & \\
Opera & &
\begin{tabular}{ l l l }
\bfseries{OS} & \bfseries{Browser} & \bfseries{funktioniert?} \\
\hline
Android 11 & Mozilla Firefox 90.1.2 & \textcolor{green}{\cmark} \\
Android 11 & Google Chrome 92.0.4515.115 & \textcolor{green}{\cmark} \\
Android 11 & Opera 64.2.3282.60128 & \textcolor{green}{\cmark} \\
iOS 14.7.1 & Mozilla Firefox 35.0 & \textcolor{red}{\xmark} Scrollen \& Icons \\
iOS 14.7.1 & Safari 14 & \textcolor{red}{\xmark} Scrollen \& Icons
\end{tabular}
\end{center}

View File

@ -1,87 +1,167 @@
\chapter{Anforderungen}\label{ch:anforderungen}
\section{Laufzeitumgebung}
\subsection{Sprachen}
\section{Laufzeitumgebung}\label{sec:laufzeitumgebung}
\subsection{Sprachen}\label{subsec:sprachen}
Wie bereits erwähnt wurden bei diesem Projekt nur die Sprachen \gls{html}, \gls{css} und JavaScript verwendet
\subsection{Keine Bibliotheken}
\subsection{Keine Bibliotheken}\label{subsec:keine-bibliotheken}
Auf JavaScript Bibliotheken und Frameworks wie \glqq jQuery\grqq, \glqq React\grqq~oder \glqq Angular\grqq~wurde verzichtet.
Stattdessen wurden native JavaScript-Funktionen verwendet.
Auch das \gls{html}- bezieziehungsweise \gls{css}-Framework \glqq Bootstrap\grqq~wurde nicht verwendet.
Auch das \gls{html}- beziehungsweise \gls{css}-Framework \glqq Bootstrap\grqq~wurde nicht verwendet.
\section{Sicherheit}
\subsection{Authentifizierung}
\section{Sicherheit}\label{sec:sicherheit}
\subsection{Authentifizierung}\label{subsec:authentifizierung}
Damit nicht jede Person zugang zu den Daten hat, muss der Benutzer sich authentifizieren.
Dafür wird beim starten der Webapp ein Login-Fenster angezeigt.
Dafür wird beim Starten der Webapp ein Login-Fenster, wie in (Abbildung~\ref{fig:login}, angezeigt.
Sollte der Login am Server erfolgreich sein, wird der generierte Token in Session Storage gespeichert.
Das hat zur Folge, das der Login spätestens mit dem beenden der Browser-Session ungültig gemacht wird.
Das hat zur Folge, dass der Login spätestens mit dem Beenden der Browser-Session ungültig gemacht wird.
\subsection{Logout}
\begin{figure}
\centering
\includegraphics[width=0.4\textwidth]{images/login}
\caption{Login-Fenster}
\label{fig:login}
\end{figure}
\subsection{Logout}\label{subsec:logout}
Der Logout wird zum einen vom Server automatisch durchgeführt, wenn seit 600 Sekunden keine Aktivität mehr erkannt wurde.
Des Weiteren wird im Browser beim Login und bei jeder Aktivität ein Timeout gesetzt, sodass der Token in Session Storage automatisch nach diesen 600 Sekunden gelöscht wird.
Ein Logout-Button befindet sich oben rechts im Header (Abbildung~\ref{fig:logout}).
\section{Darstellung}
\subsection{Anpassung an Browserfenstern}
\begin{figure}
\centering
\includegraphics[width=0.2\textwidth]{images/logout}
\caption{Logout-Button}
\label{fig:logout}
\end{figure}
\section{Darstellung}\label{sec:darstellung}
\subsection{Anpassung an Browserfenstern}\label{subsec:anpassung-an-browserfenstern}
Da es unterschiedliche Bildschirme gibt, ist der Inhalt der App nicht überall gut lesbar.
Deshalb wurde mittels \gls{css} \glqq Media queries\grqq~dafür gesorgt, dass bei schmalen Geräten die Baum-Ansicht unter der Verzeichnis-Ansicht angezeigt wird.
Dadurch wird sichergestellt, dass auf Smartphones, die sowieso schon wenig Platz in der Breite haben, nicht noch mehr Platz \glqq verschwendet\grqq~wird.
\subsection{Usability}
\subsection{Usability}\label{subsec:usability}
Der Dateimanager ist von der Grundstruktur ähnlich aufgebaut wie der \glqq Windows Explorer\grqq~unter Windows oder \glqq Nautilus\grqq~unter Linux.
Nutzer, die diese Dateimanager schon genutzt haben, finden sich in der Webapp schnell zurecht.
\subsection{Fehlererkennung}
\subsection{Fehlererkennung}\label{subsec:fehlererkennung}
Auch wenn es eigentlich nicht vorkommen sollte, kann es immer wieder zu Fehlern kommen, weil die angefragte Datei zum Beispiel gelöscht wurde.
Die Fehlermeldungen des Servers werden von der App abgefangen und angezeigt.
Die Fehlermeldungen des Servers werden von der App abgefangen und angezeigt (Siehe Abbildung~\ref{fig:error}).
Eine Erfolgsmeldung (Abbildung~\ref{fig:success}) wird wie die Fehlermeldung angezeigt, aber mit grünem statt rotem Hintergrund.
\subsection{Verzeichnisse \& Dateitypen}
Verzeichnisse und Dateitypen werden in der Verzeichnisansicht durch unterschiedliche Icons angezeigt.
\begin{figure}
\centering
\includegraphics[width=\textwidth]{images/error}
\caption{Fehlermeldung}
\label{fig:error}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{images/succes}
\caption{Erfolgsmeldung}
\label{fig:success}
\end{figure}
\subsection{Verzeichnisse \& Dateitypen}\label{subsec:verzeichnisse-&-dateitypen}
Verzeichnisse und Dateitypen werden in der Verzeichnis-Ansicht durch unterschiedliche Icons angezeigt (Abbildung~\ref{fig:files}).
So wird sichergestellt, dass der Benutzer schnell herausfinden kann, um was es sich handelt.
\section{Navigation}
Die Navigation ist entweder über den Verzeichnis-Baum links beziehungsweise unten oder über die Datei-Ansicht rechts oder oben möglich.
\begin{figure}
\centering
\includegraphics[width=\textwidth]{images/files}
\caption{Dateiansicht mit unterschiedlichen Icons}
\label{fig:files}
\end{figure}
\section{Navigation}\label{sec:navigation}
Die Navigation ist entweder über den Verzeichnis-Baum links (Abbildung~\ref{fig:tree}) beziehungsweise unten oder über die Datei-Ansicht rechts oder oben möglich.
Um sich ein Verzeichnis nach oben zu bewegen, kann \glqq ..\grqq~verwendet werden.
Um ein oder mehrere Verzeichnisse nach oben zu gehen, kann der Pfad oberhalb der Dateien verwendet werden.
Direkt über der Datei-Ansicht wird das aktuelle Verzeichnis angezeigt (Siehe Abbildung~\ref{fig:path}).
\subsection{Verzeichnis öffnen}
Um ein Verzeichnis zu öffnen, kann das entsprechende Verzeichnis in der Verzeichnisansicht angeklickt werden.
\begin{figure}
\centering
\includegraphics[width=0.4\textwidth]{images/tree}
\caption{Verzeichnis-Baum}
\label{fig:tree}
\end{figure}
\section{Datei-Handling}
\subsubsection{MP4-Video-Datei abspielen}
Der Dateimanager kann mp4-Video-Dateien abspielen, indem diese in der Verzeichnisansicht angeklickt werden.
\begin{figure}
\centering
\includegraphics[width=\textwidth]{images/path}
\caption{Anzeige des aktuellen Verzeichnisses}
\label{fig:path}
\end{figure}
\subsection{Verzeichnis öffnen}\label{subsec:verzeichnis-oeffnen}
Um ein Verzeichnis zu öffnen, kann das entsprechende Verzeichnis in der Verzeichnis-Ansicht angeklickt werden.
\section{Datei-Handling}\label{sec:datei-handling}
\subsection{MP4-Video-Datei abspielen}\label{subsec:mp4-video-datei-abspielen}
Der Dateimanager kann mp4-Video-Dateien abspielen, indem diese in der Verzeichnis-Ansicht angeklickt werden.
\subsubsection{Audio-Datei abspielen}
Der Dateimanager kann Audio-Dateien abspielen, indem diese in der Verzeichnisansicht angeklickt werden.
Der Dateimanager kann Audio-Dateien abspielen, indem diese in der Verzeichnis-Ansicht angeklickt werden.
\subsubsection{Bild-Datei ansehen}
Der Dateimanager kann Bild-Dateien anzeigen, indem diese in der Verzeichnisansicht angeklickt werden.
Der Dateimanager kann Bild-Dateien anzeigen, indem diese in der Verzeichnis-Ansicht angeklickt werden.
\subsubsection{Text-Datei bearbeiten}
Der Dateimanager kann Text-Dateien bearbeiten, indem diese in der Verzeichnisansicht angeklickt werden.
Der Dateimanager kann Text-Dateien bearbeiten, indem diese in der Verzeichnis-Ansicht angeklickt werden.
Im neuen Fenster kann der Inhalt der Datei bearbeitet werden und wird mit einem Klick auf \glqq Save\grqq~gespeichert.
\subsubsection{Datei herunterladen}
Eine Datei kann heruntergeladen werden, indem in der Verzeichnisansicht das Kontextmenü mittels Rechtsklick geöffnet wird.
Eine Datei kann heruntergeladen werden, indem in der Verzeichnis-Ansicht das Kontextmenü (Abbildung~\ref{fig:context}) mittels Rechtsklick geöffnet wird.
Dann muss nur noch \glqq Herunterladen\grqq ausgewählt werden.
\subsubsection{Datei löschen}
Eine Datei kann gelöscht werden, indem in der Verzeichnisansicht das Kontextmenü mittels Rechtsklick geöffnet wird.
Eine Datei kann gelöscht werden, indem in der Verzeichnis-Ansicht das Kontextmenü (Abbildung~\ref{fig:context}) mittels Rechtsklick geöffnet wird.
Dann muss nur noch \glqq Löschen\grqq ausgewählt werden.
\begin{figure}
\centering
\includegraphics[width=0.6\textwidth]{images/context}
\caption{Kontextmenü}
\label{fig:context}
\end{figure}
\subsubsection{Text-Datei erstellen}
Um eine Text-Datei zu erstellen muss unten rechts über das \glqq +\grqq-Icon gehovert werden.
Um eine Text-Datei zu erstellen, muss unten rechts über das \glqq +\grqq-Icon gehovert werden (Abbildung~\ref{fig:hover}).
Bei den neu angezeigten Icons das zweite von oben anklicken, um die Datei zu erstellen.
Im Header des neuen Fensters kann der Dateiname festgelegt werden.
Der Rest ist gleich, wie beim bearbeiten von Text-Dateien.
Der Rest ist gleich wie beim Bearbeiten von Text-Dateien (Siehe Abbildung~\ref{fig:text}).
\begin{figure}
\centering
\includegraphics[width=\textwidth]{images/text}
\caption{Textdatei erstellen}
\label{fig:text}
\end{figure}
\subsubsection{Datei hochladen}
Um eine Datei hochzuladen muss unten rechts über das \glqq +\grqq-Icon gehovert werden.
Um eine Datei hochzuladen muss unten rechts über das \glqq +\grqq-Icon gehovert werden (Abbildung~\ref{fig:hover}).
Bei den neu angezeigten Icons das dritte von oben anklicken, um die Datei hochzuladen.
\section{Verzeichnis-Handling}
\subsection{Verzeichnis löschen}
Ein Verzeichnis kann gelöscht werden, indem in der Verzeichnisansicht das Kontextmenü mittels Rechtsklick geöffnet wird.
\section{Verzeichnis-Handling}\label{sec:verzeichnis-handling}
\subsection{Verzeichnis erstellen}
Um ein Verzeichnis zu erstellen, muss unten rechts über das \glqq +\grqq-Icon gehovert werden.
\subsection{Verzeichnis löschen}\label{subsec:verzeichnis-loeschen}
Ein Verzeichnis kann gelöscht werden, indem in der Verzeichnis-Ansicht das Kontextmenü mittels Rechtsklick geöffnet wird.
\subsection{Verzeichnis erstellen}\label{subsec:verzeichnis-erstellen}
Um ein Verzeichnis zu erstellen, muss unten rechts über das \glqq +\grqq-Icon gehovert werden (Abbildung~\ref{fig:hover}).
Bei den neu angezeigten Icons das oberste anklicken, um das Verzeichnis zu erstellen.
\begin{figure}
\centering
\includegraphics[width=0.2\textwidth]{images/hover}
\caption{Menü}
\label{fig:hover}
\end{figure}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -5,21 +5,22 @@
\include{customization/text-variables}
% Packages
\usepackage[ngerman]{babel} % for German language
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage[autostyle=true,german=quotes]{csquotes}
\usepackage{refcheck}
\usepackage{float} % for placing images where I want them
\usepackage{float}
\usepackage{fontspec} % for using own font
\usepackage{multicol}
\usepackage[includefoot,left=\pageMarginLeft,right=\pageMarginRight,top=\pageMarginTop,bottom=\pageMarginBottom,headsep=\baselineskip,footskip=\dimexpr2\baselineskip+3mm\relax]{geometry}
\usepackage{scrlayer-scrpage} % for header / footer
\usepackage{graphicx} % for including images
\usepackage[includeheadfoot,left=40mm,right=25mm,top=25mm,bottom=25mm,footskip=10mm]{geometry}
\usepackage[singlespacing=true]{scrlayer-scrpage} % for header / footer
\usepackage{graphicx}
\usepackage[hidelinks,pdftitle={\paperName},pdfauthor={\author},pdfsubject={\title},pdfpagemode=UseOutlines,pdfdisplaydoctitle=true,pdflang=german]{hyperref}
\usepackage{setspace} % for line spacing
\usepackage{xcolor} % for defining colors
\usepackage[acronym,toc]{glossaries} % for acronyms
\usepackage{listings} % for listings
\usepackage{parskip} % for no indent in each paragraph
\usepackage{setspace}
\usepackage{xcolor}
\usepackage[acronym,toc]{glossaries}
\usepackage{listings}
\usepackage{anyfontsize}
\usepackage[backend=biber,bibwarn=true,bibencoding=utf8,sortlocale=de_DE,style=numeric-comp]{biblatex}
\usepackage{amssymb}

BIN
Filemanager_20C_9829423.zip Normal file

Binary file not shown.

View File

@ -1,3 +1,4 @@
// Error view
function create_error_view(text) {
let id = get_random_id();
let error = document.createElement('div');
@ -17,6 +18,8 @@ function create_error_view(text) {
}, 10000);
}
// Success view
function create_success_view(text) {
let id = get_random_id();
let error = document.createElement('div');

View File

@ -18,6 +18,7 @@ function download_file(path, mimetype) {
});
}
function remove_file(filename) {
httpDeleteAsync(base_url + filename, null, function (response, code) {
if (code === 200) {

View File

@ -1,5 +1,6 @@
let tree = {};
// Recursively create data
function create_tree_data(curr_dir) {
let url = base_url + curr_dir;
@ -27,6 +28,8 @@ function create_tree_data(curr_dir) {
xmlHttp.send(null);
}
// Show tree
function create_tree_view() {
let html_tree = document.createElement('div');
html_tree.innerHTML = `<ul id="tree_ul"></ul>`;
@ -48,11 +51,14 @@ function create_tree_view() {
}
}
// Change directory
function tree_onclick(url) {
window.history.pushState('index', 'Filemanager', 'index.html?path=' + url);
path_changed();
}
function create_list_view(dataRoot, elementRoot, url) {
if (dataRoot) {
const list = document.createElement('ul');
@ -69,6 +75,7 @@ function create_list_view(dataRoot, elementRoot, url) {
}
}
function addPath(pathcomponents, arr) {
let component = pathcomponents.shift()
let comp = arr.find(item => item.text === component)

View File

@ -1,4 +1,4 @@
let base_url = 'http://localhost:8080'; //'http://192.168.178.98:8080';
let base_url = 'http://192.168.178.98:8080'; //'http://localhost:8080';
let file_path = [];
let timeout = null;
@ -15,15 +15,21 @@ window.addEventListener('load', function () {
}
});
// For / back buttons
window.addEventListener('popstate', function () {
path_changed();
});
// Function that is used to load content
function path_changed() {
let curr_dir = get_curr_path();
httpGetAsync(base_url + curr_dir, null, show_files);
}
// Login
function login() {
let username = document.getElementById("username").value;
let password = document.getElementById("password").value;
@ -46,6 +52,8 @@ function login() {
});
}
// Show content
function show_files(response, code) {
if (code === 200) {
// OK
@ -60,6 +68,8 @@ function show_files(response, code) {
}
}
// Go one dir up
function one_dir_back() {
let curr_dir = get_curr_path();
@ -74,17 +84,21 @@ function one_dir_back() {
return '';
}
// Save textfile
function save_file(filename, content) {
remove_modal();
httpPostAsync(base_url + filename, 'content=' + btoa(content), function (response, code) {
if (code === 200) {
create_success_view("Saved file successfully");
path_changed();
} else {
try_to_parse_error(response);
}
});
}
function add_folder() {
let content = `<input id="input" placeholder="Name" style="width: 100%; margin: 10px 0 10px 0;">`;
let footer = `<button onclick="api_create_folder(document.getElementById('input').value.trim())" type="button" value="Save">Save</button>
@ -92,6 +106,7 @@ function add_folder() {
create_modal('Create Folder', content, footer);
}
function add_file() {
let content = `<div style="width: 100%; height: max-content;">
<input id="input" placeholder="Name" style="width: calc(100% - 8px); margin: 10px 0 10px 0;">
@ -102,6 +117,7 @@ function add_file() {
create_modal('Create File', content, footer);
}
function upload_file() {
let content = `<form enctype="multipart/form-data"><input type="file" id="newFile" name="newFile" style="width: 100%; margin: 10px 0 10px 0;"></form><progress style="width: 100%;" min=0 max=100 value="0" id="upload_progress"/>`;
let footer = `<button onclick="api_upload_file();" type="button" value="Save">Save</button>
@ -109,6 +125,7 @@ function upload_file() {
create_modal('Upload File', content, footer);
}
function api_create_folder(name) {
httpPostAsync(base_url + get_curr_path() + '/' + name, 'type=dir', function (response, code) {
remove_modal();
@ -122,6 +139,7 @@ function api_create_folder(name) {
});
}
function api_upload_file() {
let formData = new FormData(document.getElementById('modal_content').children[0]);
let filename = document.getElementById('modal_content').children[0].children[0].files[0].name;
@ -131,6 +149,8 @@ function api_upload_file() {
});
}
// Get current path from url
function get_curr_path() {
let curr_dir = findGetParameter('path');
if (curr_dir === null) {

View File

@ -1,3 +1,4 @@
// open modal
function create_modal(title, content, footer) {
let div = document.createElement('div');
div.innerHTML = `<div id="modal">
@ -23,10 +24,13 @@ function create_modal(title, content, footer) {
document.body.appendChild(div.firstChild);
}
// remove modal
function remove_modal() {
document.getElementById('modal').remove();
}
// change content
function change_modal_content(content) {
document.getElementById("modal_content").innerHTML = content;
}

View File

@ -8,20 +8,21 @@ function httpGetAsync(url, data, callback) {
}
callback(xmlHttp.responseText, xmlHttp.status);
}
}
};
xmlHttp.open("GET", url, true);
xmlHttp.setRequestHeader('Authorization', 'Basic ' + sessionStorage.getItem('authorization'));
xmlHttp.send(null);
xmlHttp.send();
}
function httpPostAsync(url, data, callback) {
const xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (this.readyState === 4) {
callback(xmlHttp.responseText, xmlHttp.status);
}
}
};
xmlHttp.open("POST", url, true);
xmlHttp.setRequestHeader('Authorization', 'Basic ' + sessionStorage.getItem('authorization'));
@ -29,19 +30,20 @@ function httpPostAsync(url, data, callback) {
xmlHttp.send(data);
}
function httpUploadAsync(url, data, callback) {
const xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (this.readyState === 4) {
callback(xmlHttp.responseText, xmlHttp.status);
}
}
};
xmlHttp.upload.addEventListener("progress", function (event) {
let progressBar = document.getElementById("upload_progress");
let progress = (event.loaded / event.total) * 100;
progressBar.value = progress;
console.log(progress)
console.log(progress);
});
xmlHttp.open("POST", url, true);
@ -49,19 +51,22 @@ function httpUploadAsync(url, data, callback) {
xmlHttp.send(data);
}
function httpDeleteAsync(url, data, callback) {
const xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (this.readyState === 4) {
callback(xmlHttp.responseText, xmlHttp.status);
}
}
};
xmlHttp.open("DELETE", url, true);
xmlHttp.setRequestHeader('Authorization', 'Basic ' + sessionStorage.getItem('authorization'));
xmlHttp.send();
}
// Timeout for logout
function startTimeout() {
return setTimeout(function () {
sessionStorage.removeItem('authorization');
@ -71,6 +76,8 @@ function startTimeout() {
}, 600000);
}
// Find get parameter in url
function findGetParameter(parameterName) {
let result = null,
tmp = [];
@ -84,16 +91,20 @@ function findGetParameter(parameterName) {
return result;
}
// Generate random id
function get_random_id() {
let s4 = function () {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
};
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
// Parse error
function try_to_parse_error(message) {
try {
message = JSON.parse(message);

View File

@ -1,3 +1,4 @@
// Show base after login
function create_base_view() {
let tmp;
tmp = document.createElement('div');
@ -20,10 +21,12 @@ function create_base_view() {
<button class="material-icon" onclick="add_file();" type="button">description</button>
<button class="material-icon" onclick="upload_file();" type="button">file_upload</button>
</div>
</div>`
</div>`;
document.getElementsByTagName('main')[0].appendChild(tmp);
}
// Show login
function create_login_view() {
let tmp = document.createElement('div');
tmp.innerHTML = `<div id="login">
@ -32,11 +35,11 @@ function create_login_view() {
<span id="error"></span>
<div>
<label for="username"></label>
<input type="text" name="username" id="username" placeholder="Username" value="admin">
<input type="text" name="username" id="username" placeholder="Username">
</div>
<div>
<label for="password"></label>
<input type="password" name="password" id="password" placeholder="Password" value="admin">
<input type="password" name="password" id="password" placeholder="Password">
</div>
<div>
<button type="button" value="Login" onclick="login();">Login</button>
@ -46,6 +49,8 @@ function create_login_view() {
document.getElementById("wrapper").innerHTML = tmp.innerHTML;
}
// Add logout button
function create_logout_view() {
let logout = document.createElement('div');
logout.id = 'logout';
@ -61,10 +66,12 @@ function create_logout_view() {
try_to_parse_error(response);
}
});
}
};
document.getElementsByClassName('app-header')[0].appendChild(logout);
}
// Get icon for filetype
function get_icon(type) {
switch (type.split('/')[0]) {
case 'application':
@ -88,6 +95,8 @@ function get_icon(type) {
}
}
// Create content
function create_main_view(data) {
let curr_dir = get_curr_path();
@ -118,7 +127,7 @@ function create_main_view(data) {
for (let i = 0; i < data.length; i++) {
if (data[i]['Type'] === 'dir') {
files.getElementsByTagName('tbody')[0].appendChild(add_table_row("folder", data[i]['Name'], "directory", curr_dir, true, function () {
let url = ''
let url;
if (curr_dir === '/') {
url = 'index.html?path=' + curr_dir + data[i]['Name'];
} else {
@ -134,7 +143,7 @@ function create_main_view(data) {
for (let i = 0; i < data.length; i++) {
if (data[i]['Type'] !== 'dir') {
files.getElementsByTagName('tbody')[0].appendChild(add_table_row(get_icon(data[i]['Type']), data[i]['Name'], data[i]['Type'], curr_dir, true, function () {
let url = ''
let url;
if (curr_dir === '/') {
url = '/' + data[i]['Name'];
} else {
@ -165,6 +174,8 @@ function create_main_view(data) {
});
}
// Create table row
function add_table_row(icon, name, type, path, context, click_function) {
let tr = document.createElement('tr');
@ -188,13 +199,15 @@ function add_table_row(icon, name, type, path, context, click_function) {
return tr;
}
// Open file
function show_file_view(data, type) {
switch (type.split('/')[0]) {
case 'audio':
create_modal(`File: <span>${data}</span>`, ``);
httpGetAsync(base_url + data + '?format=base64', null, function (response, code) {
if (code === 200) {
change_modal_content(`<audio controls><source src="data:audio;base64, ${response}">Your browser does not support the audio element.</audio>`);
change_modal_content(`<audio controls><source src="data:${type};base64, ${response}">Your browser does not support the audio element.</audio>`);
} else {
try_to_parse_error(response);
}
@ -204,7 +217,7 @@ function show_file_view(data, type) {
create_modal(`File: <span>${data}</span>`, ``);
httpGetAsync(base_url + data + '?format=base64', null, function (response, code) {
if (code === 200) {
change_modal_content(`<img style="width: 100%" src="data:image/png;base64, ${response}" alt="Image">`); /* TODO */
change_modal_content(`<img style="width: 100%" src="data:${type};base64, ${response}" alt="Image">`);
} else {
try_to_parse_error(response);
}
@ -224,7 +237,7 @@ function show_file_view(data, type) {
create_modal(`File: <span>${data}</span>`, ``);
httpGetAsync(base_url + data + '?format=base64', null, function (response, code) {
if (code === 200) {
change_modal_content(`<video controls style="width: 100%; height: 100%;"><source src="data:video;base64, ${response}">Your browser does not support the audio element.</video>`);
change_modal_content(`<video controls style="width: 100%; height: 100%;"><source src="data:${type};base64, ${response}">Your browser does not support the audio element.</video>`);
} else {
try_to_parse_error(response);
}

24
create_zip.sh Normal file
View File

@ -0,0 +1,24 @@
#!/bin/bash
# Remove old file
rm Filemanager_20C_9829423.zip
# Create doc
cd Documentation/ || exit
mkdir -p out
mkdir -p out/content
mkdir -p out/customization
mkdir -p out/images
mkdir -p out/includes
xelatex -file-line-error -interaction=nonstopmode -synctex=1 -output-directory=out main.tex
biber out/main
xelatex -file-line-error -interaction=nonstopmode -synctex=1 -output-directory=out main.tex
cd .. || exit
# Create zip
cp Documentation/out/main.pdf Documentation/out/documentation.pdf
cd Documentation/out/ && zip ../../Filemanager_20C_9829423.zip documentation.pdf && cd ../../
cd Frontend && zip -r ../Filemanager_20C_9829423.zip . && cd ../
# Clean up
rm -rf Documentation/out