You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
9.1 KiB
315 lines
9.1 KiB
import { Component } from '@angular/core';
|
|
import { TreeService } from '../Helper/tree.service';
|
|
import { getEmail, gotoPage } from '../Helper/Helpers';
|
|
import { Router } from '@angular/router';
|
|
|
|
@Component({
|
|
selector: 'app-create-image',
|
|
imports: [],
|
|
templateUrl: './create-image.component.html',
|
|
styleUrl: './create-image.component.css'
|
|
})
|
|
export class CreateImageComponent {
|
|
|
|
private root: TreeService = new TreeService("Root", "", true, 1, null);
|
|
private allFiles: File[] | null = null;
|
|
|
|
constructor(private router: Router) {}
|
|
|
|
// initialize
|
|
ngOnInit() : void {
|
|
|
|
// create the root and refresh the file tree
|
|
this.RefreshFileTree();
|
|
}
|
|
|
|
RefreshFileTree() {
|
|
|
|
const filetree = document.getElementById('FileTree') as HTMLUListElement;
|
|
filetree.innerHTML = '';
|
|
|
|
// create list and add the root
|
|
const list = document.createElement('ul');
|
|
|
|
// go through full tree
|
|
const fulllist = this.AddListItem(list, this.root);
|
|
filetree.appendChild(fulllist);
|
|
|
|
this.ClearInputs();
|
|
}
|
|
|
|
// uploading files through dropbox
|
|
onFileChange(event: any) {
|
|
const files: FileList = event.target.files;
|
|
if (files.length > 0) {
|
|
if (!this.allFiles) this.allFiles = []; // set the array up if it's null
|
|
for (let i=0; i < files.length; i++) {
|
|
this.allFiles?.push(files[i]);
|
|
|
|
// add to tree
|
|
if (this.AddFileToTree(files[i], false, "", "")) return;
|
|
}
|
|
// reset files inside dropbox?
|
|
this.RefreshFileTree();
|
|
this.ClearInputs();
|
|
}
|
|
}
|
|
|
|
// add the file to the tree
|
|
AddFileToTree(file: File | null, dir: boolean, filename: string, contents: string) : boolean{
|
|
const elements = document.querySelectorAll('.selected-node');
|
|
|
|
// make sure a parent node is selected
|
|
if (elements.length == 0) {
|
|
alert('Must select a Directory');
|
|
this.ClearInputs();
|
|
return true;
|
|
}
|
|
|
|
// make sure all the nodes selected are directories
|
|
for (let i=0; i < elements.length; i++) {
|
|
let li = elements[i] as HTMLLIElement;
|
|
if (li.firstChild?.textContent?.substring(0,4) !== "(D)-") {
|
|
alert('Must select a directory');
|
|
this.ClearInputs();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// loop through all the elements adding the name of the file to the tree
|
|
for (let i=0; i < elements.length; i++) {
|
|
|
|
// get the parent node selected
|
|
let li = elements[i] as HTMLLIElement;
|
|
let results = this.getNodeNumFromClass(li);
|
|
let parentname: string = (results[0]).toString();
|
|
let parentnum: number = Number(results[1]);
|
|
let node = this.root.getNodeByName(parentname,parentnum);
|
|
|
|
// if the parent node isnt a directory, dont add it
|
|
if (node?.getDir() == false) {
|
|
alert('can only add files/folders to directories');
|
|
this.ClearInputs();
|
|
return true;
|
|
}
|
|
|
|
// make sure the filename isnt taken already
|
|
if (!node?.IsNameTaken(filename)) {
|
|
|
|
// get the number of nodes of this name for nodenum
|
|
let nodes: TreeService[] = [];
|
|
nodes = this.root.getNodesSameName(filename, nodes);
|
|
let nodenum = nodes.length + 1;
|
|
|
|
// add the node to the tree
|
|
if (file == null) { // not using dropbox
|
|
let newFile = new TreeService(filename, contents, dir, nodenum, node);
|
|
node?.AddChild(newFile);
|
|
}
|
|
else { // using dropbox
|
|
let FileObjName : string = file?.name!;
|
|
let newFile = new TreeService(FileObjName, "", false, nodenum, node);
|
|
node?.AddChild(newFile);
|
|
}
|
|
|
|
}
|
|
else {
|
|
alert('That file name is already under this directory');
|
|
this.ClearInputs();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
// get the file stuff through creating a new file
|
|
getFile(dir: boolean) {
|
|
let nameElement = document.getElementById('filename') as HTMLInputElement;
|
|
let filename: string = nameElement.value;
|
|
let contentsElement = document.getElementById('filecontents') as HTMLTextAreaElement;
|
|
let contents : string = contentsElement.value;
|
|
|
|
if(this.AddFileToTree(null, dir, filename, contents)) return;
|
|
this.RefreshFileTree();
|
|
}
|
|
|
|
|
|
// use recursion to go through the tree adding each child
|
|
AddListItem(list: HTMLUListElement, node: TreeService) {
|
|
|
|
// add node to current list
|
|
const nodeitem = document.createElement('li');
|
|
const spanitem = document.createElement('span');
|
|
|
|
if (node.getDir()) spanitem.textContent = '(D)-' + node.getName();
|
|
else spanitem.textContent = node.getName();
|
|
|
|
// add the name and nodenum to the class list
|
|
spanitem.classList.add(node.getName() + node.getNodeNum());
|
|
|
|
spanitem.addEventListener('click', function(nodeitem) {
|
|
const listitem = nodeitem.target as HTMLLIElement;
|
|
listitem?.classList.toggle('selected-node');
|
|
});
|
|
|
|
nodeitem.appendChild(spanitem);
|
|
// add to list
|
|
list.appendChild(nodeitem);
|
|
|
|
// if node has children
|
|
if (node.getChildren().length > 0) {
|
|
let nodechildren = node.getChildren();
|
|
const childlist = document.createElement('ul');
|
|
for (var i=0; i < nodechildren.length; i++) {
|
|
let child = nodechildren[i];
|
|
list.appendChild(this.AddListItem(childlist, child));
|
|
}
|
|
}
|
|
|
|
// return the whole list
|
|
return list;
|
|
}
|
|
|
|
// get nodenum from class list
|
|
getNodeNumFromClass(item : HTMLLIElement) {
|
|
|
|
// get the class list of the selected item
|
|
const WholeClassList = item.classList;
|
|
const namenum = WholeClassList[0];
|
|
|
|
// break up the string into the two parts
|
|
const index = namenum.search(/\d/);
|
|
const name = namenum.substring(0,index);
|
|
let num : number = Number(namenum.substring(index));
|
|
|
|
const results = [name,num];
|
|
return results;
|
|
}
|
|
|
|
// delete a file from the tree
|
|
DeleteFile() {
|
|
|
|
const items = document.querySelectorAll('.selected-node');
|
|
|
|
// go through each item selected and remove it from parent
|
|
for (var i=0; i < items.length; i++) {
|
|
|
|
let li = items[i] as HTMLLIElement;
|
|
|
|
// get the name and num from class list
|
|
let results = this.getNodeNumFromClass(li);
|
|
let name : string = results[0].toString();
|
|
let num : number = Number(results[1]);
|
|
|
|
let node = this.root.getNodeByName(name,num);
|
|
|
|
// if root then delete everything
|
|
if (node?.getName() === 'Root') {
|
|
this.root.DeleteTheChildren();
|
|
this.RefreshFileTree();
|
|
return;
|
|
}
|
|
|
|
// remove the correct nodes
|
|
const parent = node?.getParent();
|
|
const newchildren = parent?.getChildren().filter(child => child.getName() !== node?.getName());
|
|
parent?.setChildren(newchildren!);
|
|
}
|
|
|
|
// refresh the tree visual
|
|
this.RefreshFileTree();
|
|
}
|
|
|
|
// Create the actual Image
|
|
CreateImage() {
|
|
|
|
const imagename = this.getImageName();
|
|
if (imagename === true) return;
|
|
|
|
this.root.DeleteParentRef();
|
|
this.SendTree(imagename);
|
|
|
|
}
|
|
|
|
// get the name of the image and add the time to it
|
|
getImageName() {
|
|
const imgElement = document.getElementById('ImageName') as HTMLInputElement;
|
|
const imgname = imgElement.value;
|
|
|
|
// make sure name is included
|
|
if (imgname === undefined || imgname === null || imgname === '') {
|
|
alert('Must include a name for the image');
|
|
return true;
|
|
}
|
|
|
|
// docker states all image names must be lowercase, so have to check for that
|
|
if (/[A-Z]/.test(imgname) === true) {
|
|
alert('Image name must be all lowercase');
|
|
return true;
|
|
}
|
|
|
|
// get the current time to add to the name so no images have same name
|
|
let time = new Date().toLocaleTimeString([], {
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
hour12: false
|
|
});
|
|
|
|
// get rid of the colons and add the time to the image name
|
|
time = time.replace(/:/g,'');
|
|
return imgname + time;
|
|
}
|
|
|
|
// send the full tree structure to the server side
|
|
async SendTree(imgname : string) {
|
|
|
|
const data = {
|
|
root: this.root, imgname: imgname, email: getEmail()
|
|
};
|
|
|
|
// create a form data to hold both JSON and the files
|
|
const formdata = new FormData();
|
|
|
|
// append each file to the form data with the key files
|
|
this.allFiles?.forEach((file : File) => {
|
|
formdata.append("files", file, file.name);
|
|
console.log(file.name);
|
|
});
|
|
|
|
formdata.append('data', JSON.stringify(data));
|
|
|
|
// send the post request
|
|
const res = await fetch('api/images/AddImage', {
|
|
method: 'POST',
|
|
body: formdata
|
|
});
|
|
|
|
if (res.ok) {
|
|
// go back to modify contest
|
|
}
|
|
}
|
|
|
|
// clear the input fields after each addition/error
|
|
ClearInputs() {
|
|
|
|
// contents of file
|
|
let contentElement = document.getElementById('filecontents') as HTMLTextAreaElement;
|
|
contentElement.value = '';
|
|
|
|
// name of file
|
|
let filenameElement = document.getElementById('filename') as HTMLInputElement;
|
|
filenameElement.value = '';
|
|
|
|
// file input box
|
|
let fileinputElement = document.getElementById('FileInput') as HTMLInputElement;
|
|
fileinputElement.value = '';
|
|
}
|
|
|
|
// go back to Modify Contest
|
|
navtoPageMC() {
|
|
gotoPage(this.router, '/modify-contest');
|
|
}
|
|
}
|