linux-web-console/ui/web-console/src/app/data.service.ts

420 lines
13 KiB
TypeScript

import { Injectable } from '@angular/core';
import { HttpClient, HttpRequest, HttpEventType } from '@angular/common/http';
import { environment } from '../environments/environment';
import { Observable, Subject } from 'rxjs';
import { FileUploadItem } from './model/file-upload-item';
import { FolderUploadItem } from './model/folder-upload-item';
import { TerminalSession } from './model/terminal-session';
import { FolderTab } from './model/folder-tab';
import { NavigationTreeNode } from './model/navigation-tree-node';
import { EditorContext } from './model/editor-context';
import { FileOperationItem } from './model/file-operation-item';
import { SearchContext } from './model/search-context';
import { PosixPermissions } from './model/posix-permissions';
import { FileItem } from './model/file-item';
const MAX_ACTIVE_UPLOAD = 5;
@Injectable({
providedIn: 'root'
})
export class DataService {
jwtToken: string;
searchContext: SearchContext = new SearchContext();
editorContexts = {};
selectedEditorTab: string;
copiedFilePath = {
files: [],
cut: false
};
sharedMenuListener = new Subject();
newTabListener = new Subject<FolderTab>();
currentTabListener = new Subject<any>();
tree1: NavigationTreeNode = {
path: null,
name: "Bookmarks",
expanded: false,
children: null,
leafNode: false
};
tree2: NavigationTreeNode = {
path: null,
name: "Home",
expanded: true,
children: null,
leafNode: false
};
tree3: NavigationTreeNode = {
path: null,
name: "File system",
expanded: true,
children: null,
leafNode: false
};
posix: boolean;
tabs: FolderTab[] = [];
selectedTab: number;
uploads: any[] = [];
activeUploads: number = 0;
fileOperations: FileOperationItem[] = [];
fileOpMonitor: any;
fileOpenRequests = new Subject<FileItem>();
currentViewChanger = new Subject<string>();
viewTextRequests = new Subject<string>();
terminalSession: TerminalSession;
constructor(private http: HttpClient) {
this.fileOpMonitor = setInterval(() => {
if (this.fileOperations && this.fileOperations.length > 0) {
this.updateFileOpProgress();
}
}, 1000);
}
public connect(): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "app/terminal", {});
}
public listFiles(path: string): Observable<any> {
return this.http.get<any>(environment.BASE_URL + "app/folders/" + btoa(path));
}
public goUp(path: string): Observable<any> {
return this.http.get<any>(environment.BASE_URL + "app/folders/" + btoa(path)+"/parent");
}
public listHome(): Observable<any> {
return this.http.get<any>(environment.BASE_URL + "app/folders/home");
}
public downloadFiles(folder: string, files: string, tempToken: string) {
window.location.href = environment.BIN_URL + "download?folder=" + btoa(folder) + "&files=" + btoa(files) + "&token=" + tempToken;
}
public uploadNext() {
if (this.uploads.length > 0 && this.activeUploads < MAX_ACTIVE_UPLOAD) {
for (let i = 0; i < this.uploads.length; i++) {
if (!this.uploads[i].status) {
if (this.uploads[i] instanceof FileUploadItem) {
this.uploadFile(this.uploads[i]);
}
else {
this.uploadFolderPart(this.uploads[i]);
}
break;
}
}
}
}
public uploadFile(item: FileUploadItem) {
item.status = "Inprogress";
console.log("Starting upload of " + item.name);
let url = environment.BASE_URL + "app/upload/" + btoa(item.folder) + "/" + btoa(item.relativePath);
this.activeUploads++;
let req = new HttpRequest<any>("POST", url, item.file, {
reportProgress: true
});
item.subscription = this.http.request(req).subscribe((event: any) => {
if (event.type === HttpEventType.UploadProgress) {
item.bytesUploaded += event.loaded;
item.percent = Math.floor((item.bytesUploaded * 100) / item.size);
}
else if (event.type === HttpEventType.Response) {
for (let i = 0; i < this.uploads.length; i++) {
if (this.uploads[i] == item) {
this.uploads.splice(i, 1);
break;
}
}
this.activeUploads--;
this.uploadNext();
}
}, (error => {
item.status = 'Failed';
console.log("Error");
this.activeUploads--;
}));
}
public uploadItem(file: File, folder: string, relativePath: string): void {
console.log("adding for upload: " + file.name)
let item: FileUploadItem = new FileUploadItem();
item.relativePath = relativePath;
item.folder = folder;
item.file = file;
item.size = file.size;
item.name = file.name;
this.uploads.push(item);
this.uploadNext();
}
public cancelUpload(item: any) {
console.log("Cancelling: " + item.name);
item.subscription.unsubscribe();
for (let i = 0; i < this.uploads.length; i++) {
if (this.uploads[i] == item) {
this.uploads.splice(i, 1);
break;
}
}
this.uploadNext();
}
public uploadFolderPart(item: FolderUploadItem) {
item.status = "Inprogress";
console.log("Starting upload of " + item.name);
this.activeUploads++;
let url = environment.BASE_URL +
"app/upload/" +
btoa(item.basePath) + "/" + btoa(item.relatvePaths[item.needle]);
let req = new HttpRequest<any>("POST", url, item.files[item.needle], {
reportProgress: true
});
item.subscription = this.http.request(req).subscribe((event: any) => {
if (event.type === HttpEventType.UploadProgress) {
item.bytesUploaded += event.loaded;
item.percent = Math.floor((item.bytesUploaded * 100) / item.size);
}
else if (event.type === HttpEventType.Response) {
this.activeUploads--;
item.needle++;
if (item.needle < item.files.length) {
this.uploadFolderPart(item);
} else {
for (let i = 0; i < this.uploads.length; i++) {
if (this.uploads[i] == item) {
this.uploads.splice(i, 1);
break;
}
}
this.uploadNext();
}
}
}, (error => {
item.status = 'Failed';
console.log("Error");
this.activeUploads--;
}));
}
public uploadFolder(relatvePaths: string[], files: File[], basePath: string, name: string) {
let item = new FolderUploadItem();
item.name = name;
item.basePath = basePath;
item.bytesUploaded = 0;
item.files = files;
item.needle = 0;
item.percent = 0;
item.relatvePaths = relatvePaths;
item.size = 0;
for (let i = 0; i < files.length; i++) {
item.size += files[i].size;
}
this.uploads.push(item);
this.uploadNext();
}
public resizePty(appId: string, cols: number, rows: number, wp: number, hp: number) {
return this.http.post(environment.BASE_URL + "app/terminal/" + appId + "/resize", { "row": rows, "col": cols, "wp": wp, "hp": hp }).subscribe((rest: any) => {
console.log("Resized successfully");
});
}
public getHomeChildren(): Observable<any> {
return this.http.get(environment.BASE_URL + "app/folder/tree/home");
}
public getDirectoryChildren(path: string): Observable<any> {
return this.http.get(environment.BASE_URL + "app/folder/tree/path/" + btoa(path));
}
public getFsChildren(): Observable<any> {
return this.http.get(environment.BASE_URL + "app/folder/tree/fs");
}
public initMoveOrCopy(targetFolder: string, files: string[], cut: boolean) {
return this.http.post(environment.BASE_URL + "app/fs/" + cut, { "sourceFile": files, "targetFolder": targetFolder }).subscribe((resp: any) => {
let fileop: FileOperationItem = new FileOperationItem();
fileop.id = resp.id;
fileop.name = resp.name;
this.fileOperations.push(fileop);
console.log("Resized successfully");
if (cut) {
this.copiedFilePath.files = [];
this.copiedFilePath.cut = false;
}
});
}
public updateFileOpProgress() {
let idList: string[] = [];
for (let item of this.fileOperations) {
idList.push(item.id);
}
this.http.post(environment.BASE_URL + "app/fs/progress", idList).subscribe((resp: any[]) => {
console.log("update: " + JSON.stringify(resp));
for (let item of resp) {
let fileop: FileOperationItem = this.findFileOpItem(item.id);
if (fileop) {
fileop.progress = item.progress;
fileop.hasError = item.hasError;
fileop.name = item.name;
fileop.errors = item.errors;
if (item.status == "Finished") {
for (let i = 0; i < this.fileOperations.length; i++) {
if (this.fileOperations[i] === fileop) {
this.fileOperations.splice(i, 1);
break;
}
}
}
}
}
});
}
findFileOpItem(id: string) {
for (let item of this.fileOperations) {
if (item.id === id) {
return item;
}
}
}
cancelFileOperation(id: string) {
return this.http.post(environment.BASE_URL + "app/fs/cancel/" + id, {}).subscribe((rest: any) => {
for (let item of this.fileOperations) {
for (let i = 0; i < this.fileOperations.length; i++) {
if (this.fileOperations[i].id === id) {
this.fileOperations.splice(i, 1);
break;
}
}
}
console.log("cancellation request sent successfully");
});
}
renameFile(newName: string, oldName: string, folder: string): Observable<any> {
return this.http.post(environment.BASE_URL + "app/fs/rename", { oldName: oldName, newName: newName, folder: folder });
}
deleteFiles(items: string[]): Observable<any> {
return this.http.post(environment.BASE_URL + "app/fs/delete", items);
}
getText(path: string): Observable<string> {
return this.http.get<string>(environment.BASE_URL + "app/fs/files/" + btoa(path), { responseType: 'text' as 'json' });
}
setText(key: string): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "app/fs/files/" + btoa(key), this.editorContexts[key].session.getValue(), {
headers: {
"Content-Type": "text/plain"
}
});
}
startSearch(folder: string, searchText: string): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "app/fs/search", { folder, searchText });
}
getSearchResults(id: string, folderIndex = 0, fileIndex = 0): Observable<any> {
return this.http.get(environment.BASE_URL + "app/fs/search/" + id + "?fileIndex=" + fileIndex + "&folderIndex=" + folderIndex);
}
cancelSearch(id: string): Observable<any> {
return this.http.delete(environment.BASE_URL + "app/fs/search/" + id);
}
getPermissionDetails(file: string): Observable<PosixPermissions> {
return this.http.get<PosixPermissions>(environment.BASE_URL + "app/fs/posix/" + btoa(file));
}
setPermissionDetails(file: string, perm: PosixPermissions): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "app/fs/posix/" + btoa(file), perm);
}
getJwtToken() {
if (!this.jwtToken) {
this.jwtToken = window.localStorage.getItem("easy-web-shell.jwt-token");
}
return this.jwtToken;
}
signIn(user: string, pass: string): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "token", {}, { headers: { "Authorization": "Basic " + btoa(user + ":" + pass) } });
}
setToken(token: string, remember: boolean) {
this.jwtToken = token;
if (remember) {
window.localStorage.setItem("easy-web-shell.jwt-token", token);
}
}
checkToken(): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "auth", {});
}
clearOldToken() {
this.jwtToken = null;
window.localStorage.removeItem("easy-web-shell.jwt-token");
}
getConfig() {
return this.http.get<any>(environment.BASE_URL + "app/config");
}
setConfig(config: any) {
return this.http.post<any>(environment.BASE_URL + "app/config", config);
}
mkdir(dir: string, name: string): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "app/fs/mkdir", { name, dir });
}
touch(dir: string, name: string): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "app/fs/touch", { name, dir });
}
getTempToken(): Observable<any> {
return this.http.get<any>(environment.BASE_URL + "token/temp");
}
getSystemStats(): Observable<any> {
return this.http.get<any>(environment.BASE_URL + "app/sys/stats");
}
getProcessList(): Observable<any[]> {
return this.http.get<any[]>(environment.BASE_URL + "app/sys/procs");
}
killProcesses(pids: any[]): Observable<any> {
return this.http.post<any>(environment.BASE_URL + "app/sys/procs", pids);
}
}