Skip to content
This repository has been archived by the owner on Aug 1, 2024. It is now read-only.

Commit

Permalink
Merge pull request #91 from artemnih/d
Browse files Browse the repository at this point in the history
Features
  • Loading branch information
artemnih committed Apr 23, 2024
2 parents 7f49e80 + 1dc2631 commit 24bc70c
Show file tree
Hide file tree
Showing 16 changed files with 146 additions and 119 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ See list of available components [here](docs/COMPONENTS.md)
```

## APIs

All the communication with the server is done through the `ExplorerService` APIs. It provides methods for fetching data, creating, renaming, deleting files and directories.

```Typescript
import { ExplorerService } from 'ngx-explorer';
...
Expand Down
67 changes: 14 additions & 53 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion projects/ngx-explorer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ This is a front-end implementation only. There are no services at this point.
- Angular 17+

## How to use this
[More information can be found here](https://github.com/artemnih/ngx-explorer)

[More information can be found here](https://github.com/artemnih/ngx-explorer)
2 changes: 1 addition & 1 deletion projects/ngx-explorer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-explorer",
"version": "4.2.1",
"version": "4.3.0",
"peerDependencies": {
"@angular/common": "^17.2.0",
"@angular/core": "^17.2.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Directive, Inject, OnDestroy } from '@angular/core';
import { Directive, OnDestroy, inject } from '@angular/core';
import { Subscription } from 'rxjs';
import { INode } from '../../shared/types';
import { NAME_FUNCTION } from '../../shared/providers';
import { INode, NgeExplorerConfig } from '../../shared/types';
import { CONFIG, NAME_FUNCTION } from '../../shared/providers';
import { ExplorerService } from '../../services/explorer.service';

@Directive()
Expand All @@ -12,10 +12,11 @@ export class BaseView implements OnDestroy {
protected subs = new Subscription();
protected shiftSelectionStartId: number | undefined;

constructor(
protected explorerService: ExplorerService,
@Inject(NAME_FUNCTION) protected getName: (node: INode) => string
) {
protected explorerService: ExplorerService = inject(ExplorerService);
protected config: NgeExplorerConfig = inject(CONFIG);
protected getName: (node: INode) => string = inject(NAME_FUNCTION);

constructor() {
this.subs.add(
this.explorerService.openedDir$.subscribe((nodes) => {
this.items = nodes ? nodes.children : [];
Expand All @@ -36,7 +37,7 @@ export class BaseView implements OnDestroy {
const shiftKeyPressed = event.shiftKey;
const metaKeyPressed = event.metaKey || event.ctrlKey;

if (shiftKeyPressed) {
if (this.config.multipleSelection && shiftKeyPressed) {
if (this.selection.size === 0) {
this.selection.add(item.id);
this.shiftSelectionStartId = item.id;
Expand All @@ -53,7 +54,7 @@ export class BaseView implements OnDestroy {
}
}
} else {
if (metaKeyPressed) {
if (this.config.multipleSelection && metaKeyPressed) {
if (this.selection.has(item.id)) {
this.selection.delete(item.id);
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { NAME_FUNCTION } from '../../shared/providers';
import { ExplorerService } from '../../services/explorer.service';
import { Component, ViewEncapsulation } from '@angular/core';
import { BaseView } from '../base-view/base-view.directive';
import { DragDropDirective } from '../../directives/drag-drop.directive';
import { NgClass } from '@angular/common';
import { INode } from '../../shared/types';

@Component({
selector: 'nxe-icons',
Expand All @@ -20,7 +17,7 @@ export class IconsComponent extends BaseView {
leaf: 'nxe-doc',
};

constructor(explorerService: ExplorerService, @Inject(NAME_FUNCTION) getName: (node: INode) => string) {
super(explorerService, getName);
constructor() {
super();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { NAME_FUNCTION } from '../../shared/providers';
import { ExplorerService } from '../../services/explorer.service';
import { Component, ViewEncapsulation } from '@angular/core';
import { BaseView } from '../base-view/base-view.directive';
import { DragDropDirective } from '../../directives/drag-drop.directive';
import { NgClass } from '@angular/common';
import { INode } from '../../shared/types';

@Component({
selector: 'nxe-list',
Expand All @@ -20,7 +17,7 @@ export class ListComponent extends BaseView {
leaf: 'nxe-doc',
};

constructor(explorerService: ExplorerService, @Inject(NAME_FUNCTION) getName: (node: INode) => string) {
super(explorerService, getName);
constructor() {
super();
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
<div class="nxe-menu-bar">
<div class="nxe-menu-bar-left">
<button class="nxe-menu-bar-button" (click)="createDir()"><i class="nxe-folder" aria-hidden="true"></i>New Folder</button>
@if (featCreateDir) {
<button class="nxe-menu-bar-button" (click)="createDir()"><i class="nxe-folder" aria-hidden="true"></i>New Folder</button>
}

<button class="nxe-menu-bar-button" (click)="refresh()"><i class="nxe-arrows-cw" aria-hidden="true"></i> Refresh</button>
<button class="nxe-menu-bar-button" (click)="openUploader()"><i class="nxe-upload" aria-hidden="true"></i> Upload</button>
<button class="nxe-menu-bar-button" [disabled]="!(canDownload$ | async)" (click)="download()">
<i class="nxe-download" aria-hidden="true"></i> Download
</button>
<button class="nxe-menu-bar-button" [disabled]="!(canRename$ | async)" (click)="rename()">
<i class="nxe-edit" aria-hidden="true"></i> Rename
</button>
<button class="nxe-menu-bar-button" [disabled]="!(canDelete$ | async)" (click)="remove()">
<i class="nxe-trash-empty" aria-hidden="true"></i> Delete
</button>

@if (featUpload) {
<button class="nxe-menu-bar-button" (click)="openUploader()"><i class="nxe-upload" aria-hidden="true"></i> Upload</button>
}

@if (featDownload) {
<button class="nxe-menu-bar-button" [disabled]="!(canDownload$ | async)" (click)="download()">
<i class="nxe-download" aria-hidden="true"></i> Download
</button>
}

@if (featRename) {
<button class="nxe-menu-bar-button" [disabled]="!(canRename$ | async)" (click)="rename()">
<i class="nxe-edit" aria-hidden="true"></i> Rename
</button>
}

@if (featDelete) {
<button class="nxe-menu-bar-button" [disabled]="!(canDelete$ | async)" (click)="remove()">
<i class="nxe-trash-empty" aria-hidden="true"></i> Delete
</button>
}
</div>
<div class="nxe-menu-bar-right">
<nxe-view-switcher></nxe-view-switcher>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Component, ElementRef, Inject, ViewChild, ViewEncapsulation } from '@angular/core';
import { Component, ElementRef, ViewChild, ViewEncapsulation, inject } from '@angular/core';
import { map, take } from 'rxjs';
import { INode } from '../../shared/types';
import { INode, NgeExplorerConfig } from '../../shared/types';
import { ExplorerService } from '../../services/explorer.service';
import { ViewSwitcherComponent } from '../view-switcher/view-switcher.component';
import { NAME_FUNCTION } from '../../shared/providers';
import { CONFIG, NAME_FUNCTION } from '../../shared/providers';
import { AsyncPipe } from '@angular/common';

@Component({
Expand All @@ -17,15 +17,20 @@ import { AsyncPipe } from '@angular/common';
export class MenuBarComponent {
@ViewChild('uploader', { static: true }) uploader!: ElementRef;

protected explorerService: ExplorerService = inject(ExplorerService);
protected getName: (node: INode) => string = inject(NAME_FUNCTION);
protected config: NgeExplorerConfig = inject(CONFIG);

protected featDelete = this.config.features?.delete;
protected featUpload = this.config.features?.upload;
protected featDownload = this.config.features?.download;
protected featRename = this.config.features?.rename;
protected featCreateDir = this.config.features?.createDir;

protected canDownload$ = this.explorerService.selection$.pipe(map((n) => n.length === 1 && n[0].isLeaf));
protected canDelete$ = this.explorerService.selection$.pipe(map((n) => n.length > 0));
protected canRename$ = this.explorerService.selection$.pipe(map((n) => n.length === 1));

constructor(
private explorerService: ExplorerService,
@Inject(NAME_FUNCTION) private getName: (node: INode) => string
) {}

createDir() {
const name = prompt('Enter new name');
if (name) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "../vars.scss";
@import '../vars.scss';

$item-spacing: 10px;

Expand All @@ -9,6 +9,7 @@ $item-spacing: 10px;
margin-left: 0 !important;
}
overflow-y: scroll;
user-select: none;
}

.nxe-tree-ul {
Expand Down
26 changes: 23 additions & 3 deletions projects/ngx-explorer/src/lib/services/explorer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export class ExplorerService {
private readonly root$$ = new BehaviorSubject<INode>(this.internalTree);

/**
* An Observable that emits the currently selected nodes in the explorer.
* Subscribers can use this to react to changes in the selection.
*/
* An Observable that emits the currently selected nodes in the explorer.
* Subscribers can use this to react to changes in the selection.
*/
public readonly selection$ = this.selectedNodes$$.asObservable();

/**
Expand Down Expand Up @@ -89,6 +89,10 @@ export class ExplorerService {
* @param name The name of the new directory.
*/
public createDir(name: string) {
if (this.config.features?.createDir === false) {
throw new Error('Create directory feature is disabled');
}

const parent = this.openedNode$$.value;
this.dataService.createDir(parent!.data, name).subscribe(() => {
this.refresh();
Expand All @@ -107,6 +111,10 @@ export class ExplorerService {
* @param name The new name for the node.
*/
public rename(name: string) {
if (this.config.features?.rename === false) {
throw new Error('Rename feature is disabled');
}

const nodes = this.selectedNodes$$.value;
if (nodes.length > 1) {
throw new Error('Multiple selection rename not supported');
Expand All @@ -125,6 +133,10 @@ export class ExplorerService {
* Removes the currently selected nodes.
*/
public remove() {
if (this.config.features?.delete === false) {
throw new Error('Delete feature is disabled');
}

const selection = this.selectedNodes$$.value;
if (selection.length === 0) {
throw new Error('Nothing selected to remove');
Expand All @@ -141,6 +153,10 @@ export class ExplorerService {
* @param files The files to upload.
*/
public upload(files: FileList) {
if (this.config.features?.upload === false) {
throw new Error('Upload feature is disabled');
}

const node = this.openedNode$$.value!;
this.dataService.uploadFiles(node.data, files).subscribe(() => {
this.refresh();
Expand All @@ -151,6 +167,10 @@ export class ExplorerService {
* Downloads the currently selected file.
*/
public download() {
if (this.config.features?.download === false) {
throw new Error('Download feature is disabled');
}

const target = this.selectedNodes$$.value[0];
this.dataService.downloadFile(target.data).subscribe(() => {
this.refresh();
Expand Down
Loading

0 comments on commit 24bc70c

Please sign in to comment.