F diff --git a/css/style.css b/css/style.css
--- a/css/style.css
+++ b/css/style.css
display: flex;
flex: 1 0 0;
align-items: stretch;
-
- user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
}
#page > * {
justify-content: center;
}
+ .filesystem > h2,
form > h2 {
color: #4d4d4d;
margin: 0;
border-top-right-radius: 0.5rem;
}
-
- .window h3 button,
- .window > h2 button
- {
- border: none;
- padding: 0.3rem 1rem;
- background: inherit;
- border-radius: 0;
- }
-
- .window h3 button:not(.pathentry):hover {
- background: white;
- }
-
- .window h3 > .separator {
- flex: 0 0 1px;
- align-self: stretch;
- background: #bbb;
- }
-
- .window > h2 > *:first-child {
- border-top-left-radius: 0.5rem;
- }
form p {
margin: 1rem 0px 0.3rem 0px;
}
+
.hero_form_error {
animation: fadein 0.2s;
background-color: #ff4d4d;
display: none;
}
- .window {
- margin: 0rem;
+ .filesystem {
+ background: #fafafa;
+ margin: 1rem;
padding: 0;
box-shadow: 0 0.8rem 1.3rem rgba(0,0,0,0.2);
border-radius: 0.5rem;
border: 1px solid #b9b9b9;
display: block;
- position: absolute;
- top: 0;
- left: 0;
- width: 800px;
- height: 600px;
-
- transition: opacity 0.3s;
- display: flex;
- flex-direction: column;
- }
-
- .foldercontents, .filecontents {
- background: rgba(250, 250, 250, .8);
- flex: 1 0 0;
- }
-
- .filecontents {
- padding: 0.8rem;
- font-size: 1.1rem;
- }
-
- .window h3,
- .window > h2 {
- color: #4d4d4d;
- background: #f0f0f0;
- margin: 0;
-
-
- display: flex;
- align-items: stretch;
- font-weight: normal;
- padding: 0rem;
- border-bottom: 1px solid #bbb;
- }
-
- .window > h2 {
- font-size: 1.3rem;
- border-top-left-radius: 0.5rem;
- border-top-right-radius: 0.5rem;
- cursor: grab;
- }
-
- .window h3 {
- font-size: 1.2rem;
- }
-
- .window.dragged {
- /* opacity: 0.9; */
}
.files {
display: flex;
flex-direction: column;
align-items: center;
- border: 1px solid rgba(0,0,0,0);
+ border: 1px solid #fafafa;
border-radius: 0.1rem;
}
}
.file:hover:not(.dragged) {
- background: rgba(255,255,255, 0.5);
+ background: white;
color: black;
border-color: #ddd;
}
filter: brightness(120%);
}
+ .filesystem > h2 {
+ display: flex;
+ align-items: stretch;
+ font-weight: normal;
+ padding: 0rem;
+ border-bottom: 1px solid #bbb;
+ font-size: 1.3rem;
+ }
+
+ .filesystem > h2 button {
+ border: none;
+ padding: 0.3rem 1rem;
+ background: inherit;
+ border-radius: 0;
+ }
+
+ .filesystem > h2 button:not(.pathentry):hover {
+ background: white;
+ }
+
+ .filesystem > h2 > .separator {
+ flex: 0 0 1px;
+ align-self: stretch;
+ background: #bbb;
+ }
+
+ .filesystem > h2 > *:first-child {
+ border-top-left-radius: 0.5rem;
+ }
+
.path {
display: flex;
align-items: stretch;
+ font-size: 0.8em;
}
.path > .separator {
background: #2e91db;
color: white;
}
-
- .backdrop {
- position: absolute;
- width: 100%;
- height: 100%;
-
- user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
- background-image: url("/img/backdrop.jpg");
- background-size: cover;
- }
F diff --git a/img/backdrop.jpg b/img/backdrop.jpg
deleted file mode 100644
B Binary files a/img/backdrop.jpg and /dev/null differ
F diff --git a/loggedin.js b/loggedin.js
--- a/loggedin.js
+++ b/loggedin.js
const upload_form = document.getElementById("upload_form");
const the_file = document.getElementById("the_file");
const filename_input = document.getElementById("filename");
- const current_directory = document.getElementById("current_directory");
+ const upload_btn = document.getElementById("upload_btn");
+ const the_path = document.getElementById("the_path");
+ const current_directory = document.getElementById("current_directory");
const upload_parent_directory = document.getElementById("upload_parent_directory");
the_file.onchange = on_file_added;
- var windows = [];
- var focus = null;
+ var pwd = [];
var context_menu = null;
var dragging = null;
body: new FormData(upload_form)
}).then((resp) => {
if (resp.status == 200) {
- openfile(true);
+ load_dir();
} else {
alert("Upload failed");
}
}
}
- function update_path_visuals() {
- var the_path = focus.visuals.getElementsByClassName('path')[0];
-
- while (the_path.children.length > 0)
+ function load_dir() {
+ while (the_path.children.length > 1)
the_path.removeChild(the_path.lastChild);
- for (let i = -1; i < focus.pwd.length; i++) {
- var d;
- if (i >= 0) {
- d = focus.pwd[i];
- var separator_div = document.createElement('div');
- separator_div.classList.add('separator');
- the_path.appendChild(separator_div);
- separator_div.innerText = "»";
- }
- else
- d = "Root";
+ for (let i = 0; i < pwd.length; i++) {
+ var d = pwd[i];
+ var separator_div = document.createElement('div');
+ separator_div.classList.add('separator');
+ the_path.appendChild(separator_div);
+ separator_div.innerText = "»";
var entry = document.createElement('button');
entry.classList.add('pathentry');
add_link_functionality(entry, i + 1);
}
- }
-
- function openfile_nondir() {
- var data = new FormData();
- data.append('folder', get_path(focus.pwd.length - 1));
- data.append('filename', focus.pwd[focus.pwd.length - 1]);
-
- var xhr = new XMLHttpRequest();
-
- focus.pwd.push();
-
- update_path_visuals();
-
- xhr.open('POST', '/php/readfile.php', true);
-
- focus.filecontents.innerText = "Loading...";
- focus.filecontents.style.display = 'block';
- focus.foldercontents.style.display = 'none';
-
- xhr.onload = function () {
- focus.filecontents.innerText = xhr.responseText;
- };
- xhr.send(data);
- }
-
- function opendir() {
-
- update_path_visuals();
var data = new FormData();
data.append('path', get_path());
};
xhr.send(data);
-
- focus.filecontents.style.display = 'none';
- focus.foldercontents.style.display = 'block';
- }
-
- function openfile(is_directory) {
- if (is_directory) {
- opendir();
- } else {
- openfile_nondir();
- }
}
function delete_file(filename) {
var xhr = new XMLHttpRequest();
xhr.open('POST', '/php/delete.php', true);
xhr.onload = function () {
- openfile(true);
+ load_dir();
};
xhr.send(data);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/php/rename.php', true);
xhr.onload = function () {
- openfile(true);
+ load_dir();
};
xhr.send(data);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/php/move.php', true);
xhr.onload = function () {
- openfile(true);
+ load_dir();
};
xhr.send(data);
}
- function new_folder() { var dirname = prompt(`Directory name`, "New Folder");
+ function new_folder() {
+ var dirname = prompt(`Directory name`, "New Folder");
if (!dirname)
return;
var xhr = new XMLHttpRequest();
xhr.open('POST', '/php/mkdir.php', true);
xhr.onload = function () {
- openfile(true);
+ load_dir();
};
xhr.send(data);
}
- function begin_drag_fileview(e, fileview) {
+ function begin_drag(e, fileview) {
if (dragging)
end_drag();
dragging_placeholder = document.createElement('div');
- dragging_fileview = fileview;
+ fileview.visuals.parentNode.insertBefore(dragging_placeholder, fileview.visuals);
dragging = fileview.visuals;
-
- // document.body.appendChild(dragging);
-
- begin_drag(e, fileview.visuals,);
- }
-
- function begin_drag(e, obj) {
-
- dragging = obj;
+ dragging_fileview = fileview;
dragging.classList.add("dragged");
var elemRect = dragging.getBoundingClientRect();
- dragging_offset_x = e.clientX - elemRect.left;
- dragging_offset_y = -e.clientY + elemRect.top;
-
- if (dragging_placeholder)
- obj.parentNode.insertBefore(dragging_placeholder, obj);
-
- dragging.style.left = (e.clientX - dragging_offset_x) + "px";
- dragging.style.top = (e.clientY + dragging_offset_y) + "px";
+ dragging_offset_x = elemRect.width - (elemRect.left - e.clientX);
+ dragging_offset_y = elemRect.top - e.clientY;
+ dragging.style.position = "absolute";
dragging.style.width = elemRect.width + "px";
dragging.style.height = elemRect.height + "px";
-
- dragging.style.position = "absolute";
document.body.appendChild(dragging);
- }
- function end_drag(_e) {
- if (dragging_placeholder) {
- dragging_placeholder.parentNode.insertBefore(dragging, dragging_placeholder);
- dragging_placeholder.remove();
- dragging_placeholder = null;
- }
-
- if (dragging_fileview) {
- dragging.style.removeProperty("position");
- dragging.style.removeProperty("width");
- dragging.style.removeProperty("height");
- dragging.style.removeProperty("left");
- dragging.style.removeProperty("top");
- dragging_fileview = null;
- }
+ dragging.style.left = (e.clientX - dragging_offset_x) + "px";
+ dragging.style.top = (e.clientY + dragging_offset_y) + "px";
+ }
+ function end_drag(e) {
+ dragging_placeholder.parentNode.insertBefore(dragging, dragging_placeholder);
+ dragging_placeholder.remove();
+ dragging.style.removeProperty("position");
+ dragging.style.removeProperty("width");
+ dragging.style.removeProperty("height");
+ dragging.style.removeProperty("left");
+ dragging.style.removeProperty("top");
dragging.classList.remove("dragged");
dragging = null;
}
function add_link_functionality(link, length) {
link.onclick = () => {
- focus.pwd.length = length,
- openfile(true);
+ pwd.length = length,
+ load_dir();
}
link.onmouseup = (e) => {
- if (dragging && dragging_fileview) {
+ if (dragging) {
var new_folder = get_path(length);
move_file(new_folder, dragging_fileview.filename);
end_drag();
}
}
- class Window {
- constructor(pwd) {
- this.pwd = pwd;
- }
- }
-
-
- function make_window(pwd) {
- var wnd = new Window(pwd);
- windows.push(wnd);
+ add_link_functionality(document.getElementById("home_path_entry"), 0);
- var wnd_html = document.createElement('div');
- wnd_html.classList.add('window');
-
- var h2 = document.createElement('h2');
- wnd_html.appendChild(h2);
+ function open_file(fileview) {
+ var data = new FormData();
+ data.append('folder', get_path());
+ data.append('filename', fileview.filename);
- h2.onmousedown = (e) => {
- begin_drag(e, wnd_html);
- e.preventDefault();
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', '/php/readfile.php', true);
+ xhr.onload = function () {
+ console.log(xhr.responseText);
};
-
- path = document.createElement('div');
- path.classList.add('path');
- h2.appendChild(path);
-
- wnd_html.style.width = "800px";
- wnd_html.style.height = "600px";
- wnd_html.style.position = "absolute";
- wnd_html.style.left = "300px";
- wnd_html.style.top = "300px";
-
- wnd.visuals = wnd_html;
-
- {
- wnd.foldercontents = document.createElement('div');
- wnd.foldercontents.classList.add('foldercontents');
- wnd_html.appendChild(wnd.foldercontents);
-
- var h3 = document.createElement('h3');
- wnd.foldercontents.appendChild(h3);
-
- var upload_btn = document.createElement('button');
- upload_btn.innerText = "Upload";
- upload_btn.onclick = () => { begin_upload(); }
- h3.appendChild(upload_btn);
-
- var separator = document.createElement('div');
- separator.classList.add('separator');
- h3.appendChild(separator);
-
- var new_folder_btn = document.createElement('button');
- new_folder_btn.innerText = "New Folder";
- new_folder_btn.onclick = () => { new_folder(); }
- h3.appendChild(new_folder_btn);
-
- separator = document.createElement('div');
- separator.classList.add('separator');
- h3.appendChild(separator);
-
- wnd.filegrid = document.createElement('div');
- wnd.filegrid.classList.add('files');
- wnd.foldercontents.appendChild(wnd.filegrid);
- }
-
- {
- wnd.filecontents = document.createElement('div');
- wnd.filecontents.classList.add('filecontents');
- wnd_html.appendChild(wnd.filecontents);
- }
-
- document.body.appendChild(wnd_html);
- return wnd;
+ xhr.send(data);
}
-
function add_file_visuals(fileview) {
var visuals = document.createElement('div');
fileview.visuals = visuals;
var filename = document.createElement('div');
if (fileview.is_directory) {
- if (fileview.filename == "trash")
- img.src="/mimeicons/user-trash.png";
- else
- img.src="/mimeicons/directory.png";
+ img.src="/mimeicons/directory.png";
+ visuals.onclick = () => {
+ pwd.push(fileview.filename);
+ load_dir();
+ }
} else {
img.src=`/mimeicons/${fileview.mimetype.replace("/", "-")}.png`;
- }
-
- visuals.onclick = () => {
- focus.pwd.push(fileview.filename);
- openfile(fileview.is_directory);
+ visuals.onclick = () => {
+ open_file(fileview);
+ }
}
visuals.oncontextmenu = (e) => {
if (!dragging) {
context(e, [
['Open', () => {
- focus.pwd.push(fileview.filename);
- openfile(fileview.is_directory);
+ if (fileview.is_directory) {
+ pwd.push(fileview.filename);
+ load_dir();
+ } else {
+ open_file(fileview);
+ }
}],
- ['Open in New Window', () => {alert('not implemented')}],
['Rename', () => { rename_file(fileview.filename); }],
['Share', () => {alert('not implemented')}],
['Delete', () => { delete_file(fileview.filename); }],
}
visuals.ondragstart = (e) => {
- begin_drag_fileview(e, fileview);
+ begin_drag(e, fileview);
e.preventDefault();
};
visuals.appendChild(img);
visuals.appendChild(filename);
- focus.filegrid.appendChild(visuals);
+ current_directory.appendChild(visuals);
}
function begin_upload() {
function get_path(max_length) {
if (max_length == undefined) {
- max_length = focus.pwd.length;
+ max_length = pwd.length;
}
var path = "/";
for (let i = 0; i < max_length; i++) {
- path += focus.pwd[i];
+ path += pwd[i];
if (i != max_length - 1)
path += "/";
}
}
}
- document.body.onmouseup = (_e) => {
+ document.body.onmouseup = (e) => {
if (dragging)
end_drag();
}
context_menu.remove();
}
-
- var root_window = make_window([]);
- focus = root_window;
- openfile(true);
+ load_dir();
F diff --git a/loggedin.php b/loggedin.php
--- a/loggedin.php
+++ b/loggedin.php
+ <div>
+ <div class="filesystem">
+ <h2 style="display: flex; gap: 0rem;">
+ <button id="upload_btn" onclick="begin_upload()">Upload</button>
+ <div class="separator"></div>
+ <button id="upload_btn" onclick="new_folder()">New Folder</button>
+ <div class="separator"></div>
+ <div class="path" id="the_path">
+ <button class="pathentry" id="home_path_entry">
+ <?php
+ $user=$_SESSION['user_object'];
+ echo $user->username;
+ ?>
+ 's files</button>
+ </div>
+ </h2>
- <div class="backdrop">
+ <div class="files" id="current_directory">
+ </div>
+ </div>
+
+ </div>
<form id="upload_form" style="display:none;" action="php/upload.php" method="post" enctype="multipart/form-data">
<input id="filename" name="filename">
F diff --git a/mimeicons/user-trash-full.png b/mimeicons/user-trash-full.png
deleted file mode 100644
B Binary files a/mimeicons/user-trash-full.png and /dev/null differ
F diff --git a/mimeicons/user-trash.png b/mimeicons/user-trash.png
deleted file mode 100644
B Binary files a/mimeicons/user-trash.png and /dev/null differ
F diff --git a/php/database.php b/php/database.php
--- a/php/database.php
+++ b/php/database.php
we remove the node and
1. move the file represented by the node to the trash folder
2. remove the file
+ 3. if node is a directory - delete all children nodes
depends on the conf file
*/
function delete_node_by_id(int $node_id)
}
}
+
+ function unlink_nodes(int $dir_id, int $node_id)
+ {
+ $prep=$this->pdo->prepare("delete from node_links
+ where directory_id=:dir_id and node_id=:node_id
+ ");
+ $prep->bindParam(':dir_id',$dir_id);
+ $prep->bindParam(':node_id',$node_id);
+ if($prep->execute()==false)
+ {
+ error_log("there was an error with the first statement in unlink_nodes");
+ return;
+ }
+ $prep=$this->pdo->prepare("select node_id
+ from node_links
+ where node_id=:id
+ ");
+ $prep->bindParam(':id',$node_id);
+ if($prep->execute()==false)
+ {
+ error_log("there was an error with the second statement in unlink_nodes");
+ return;
+ }
+ if(count($prep->fetchALL(PDO::FETCH_ASSOC))==0)
+ {
+ delete_node_by_id($node_id);
+ }
+
+
+ }
+
function create_home_directory():int
{
$ret=$this->create_dangling_directory();
F diff --git a/php/readfile.php b/php/readfile.php
--- a/php/readfile.php
+++ b/php/readfile.php
$dir = get_directory($folder, $user);
if (!$dir) {
- error_log("/php/readfile.php - invalid directory '$folder'");
+ error_log("/php/readfile.php - invalid directory");
http_response_code(409);
exit(0);
}
}
}
if (!$file_node) {
- error_log("/php/readfile.php - invalid filename '$filename'");
+ error_log("/php/readfile.php - invalid filename");
http_response_code(409);
exit(0);
}
F diff --git a/sql/fileshare.sql b/sql/fileshare.sql
--- a/sql/fileshare.sql
+++ b/sql/fileshare.sql
drop table if exists node_access;
drop table if exists users;
drop table if exists node_links;
+ drop table if exists trash;
+ drop trigger if exists delete_on_zero_links;
drop table if exists nodes;
node_id int not null,
name varchar(100) not null default 'no name',
note varchar(200) not null default "",
- check (directory_id != node_id),
foreign key (directory_id) references nodes(node_id) on delete cascade,
foreign key (node_id) references nodes(node_id) on delete cascade
);
+ create table trash (
+ node_id int not null,
+ foreign key (node_id) references nodes(node_id) on delete cascade
+ );
+
+ /*
+ create trigger delete_on_zero_links
+ after delete
+ on node_links
+ for each row
+ insert into trash(node_id)
+ select
+ if(old.node_id not in (select node_id from node_links),
+ old.node_id,
+ select node_id from nodes where 1=0
+ );
+
+ */