Implement sub-tree sharing; read-only pages

This commit is contained in:
garrettmills
2020-02-14 00:14:09 -06:00
parent 1eda3d0b30
commit 9f361896ee
21 changed files with 394 additions and 95 deletions

View File

@@ -0,0 +1,98 @@
<ion-header>
<ion-toolbar>
<ion-title>{{ title }}</ion-title>
<ion-buttons slot="end">
<ion-button (click)="dismissModal(false)">
<ion-icon name="close"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-grid>
<ion-row>
<ion-col size="12">
<h4>Create Sharing Link</h4>
<p>You can share this sub-tree of your notes by generating a sharing link. You can choose to allow the recipient to have view, edit, or manage access to this sub-tree. Sharing links are one time use only and require a Noded account.</p>
<ion-buttons>
<ion-button fill="outline" color="medium" (click)="getShareLink('view')">
<ion-icon name="link" color="dark"></ion-icon>&nbsp;&nbsp;View
</ion-button>
<ion-button fill="outline" color="medium" (click)="getShareLink('update')">
<ion-icon name="link" color="dark"></ion-icon>&nbsp;&nbsp;Edit
</ion-button>
<ion-button fill="outline" color="medium" (click)="getShareLink('manage')">
<ion-icon name="link" color="dark"></ion-icon>&nbsp;&nbsp;Manage
</ion-button>
</ion-buttons>
</ion-col>
</ion-row>
<ion-row *ngIf="generatedLink">
<ion-col size="12">
<ion-item>
<ion-label position="floating">Share this link to give access:</ion-label>
<ion-input [(ngModel)]="generatedLink" [readonly]="true"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row *ngIf="isShared">
<ion-col size="12">
<h4>Shared With</h4>
<ion-list>
<ion-item *ngFor="let group of sharingInfo.view; let i = index">
<ion-icon slot="start" name="contact"></ion-icon>
<ion-label>
{{ sharingInfo.view[i].username }}&nbsp;&nbsp;<span class="share-token">VIEW</span>
</ion-label>
<ion-buttons slot="end">
<ion-button fill="invisible" (click)="setShareLevel(sharingInfo.view[i], 'update')">
<ion-icon name="create" color="medium"></ion-icon>
</ion-button>
<ion-button fill="invisible" (click)="setShareLevel(sharingInfo.view[i], 'manage')">
<ion-icon name="build" color="medium"></ion-icon>
</ion-button>
<ion-button fill="invisible" (click)="unsharePage(sharingInfo.view[i])">
<ion-icon name="close" color="medium"></ion-icon>
</ion-button>
</ion-buttons>
</ion-item>
<ion-item *ngFor="let group of sharingInfo.update; let i = index">
<ion-icon slot="start" name="contact"></ion-icon>
<ion-label>
{{ sharingInfo.update[i].username }}&nbsp;&nbsp;<span class="share-token">VIEW</span>&nbsp;&nbsp;<span class="share-token">EDIT</span>
</ion-label>
<ion-buttons slot="end">
<ion-button fill="invisible" (click)="setShareLevel(sharingInfo.update[i], 'view')">
<ion-icon name="eye" color="medium"></ion-icon>
</ion-button>
<ion-button fill="invisible" (click)="setShareLevel(sharingInfo.update[i], 'manage')">
<ion-icon name="build" color="medium"></ion-icon>
</ion-button>
<ion-button fill="invisible" (click)="unsharePage(sharingInfo.update[i])">
<ion-icon name="close" color="medium"></ion-icon>
</ion-button>
</ion-buttons>
</ion-item>
<ion-item *ngFor="let group of sharingInfo.manage; let i = index">
<ion-icon slot="start" name="contact"></ion-icon>
<ion-label>
{{ sharingInfo.manage[i].username }}&nbsp;&nbsp;<span class="share-token">VIEW</span>&nbsp;&nbsp;<span class="share-token">EDIT</span>&nbsp;&nbsp;<span class="share-token">MANAGE</span>
</ion-label>
<ion-buttons slot="end">
<ion-button fill="invisible" (click)="setShareLevel(sharingInfo.manage[i], 'view')">
<ion-icon name="eye" color="medium"></ion-icon>
</ion-button>
<ion-button fill="invisible" (click)="setShareLevel(sharingInfo.manage[i], 'update')">
<ion-icon name="create" color="medium"></ion-icon>
</ion-button>
<ion-button fill="invisible" (click)="unsharePage(sharingInfo.manage[i])">
<ion-icon name="close" color="medium"></ion-icon>
</ion-button>
</ion-buttons>
</ion-item>
</ion-list>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>

View File

@@ -0,0 +1,8 @@
.share-token {
background-color: #dedede;
color: #555;
padding: 5px;
font-size: 10pt;
font-style: italic;
font-family: monospace;
}

View File

@@ -0,0 +1,77 @@
import {Component, Input, OnInit} from '@angular/core';
import {ModalController} from '@ionic/angular';
import {ApiService} from '../../../service/api.service';
import {Observable} from 'rxjs';
@Component({
selector: 'app-selector',
templateUrl: './selector.component.html',
styleUrls: ['./selector.component.scss'],
})
export class SelectorComponent implements OnInit {
@Input() node: any;
public sharingInfo: {
view: Array<{username: string, id: string, level: 'view'|'update'|'manage'}>,
update: Array<{username: string, id: string, level: 'view'|'update'|'manage'}>,
manage: Array<{username: string, id: string, level: 'view'|'update'|'manage'}>,
} = {view: [], update: [], manage: []};
public generatedLink = '';
constructor(
protected modals: ModalController,
protected api: ApiService,
) {}
public get title() {
return this.node ? `Share ${this.node.name}` : 'Manage Sharing';
}
public get isShared() {
return (this.sharingInfo.view.length > 0) || (this.sharingInfo.update.length > 0) || (this.sharingInfo.manage.length > 0);
}
ngOnInit() {
this.loadShareInfo().subscribe(data => {
this.sharingInfo = data;
});
}
dismissModal(success: boolean) {
this.modals.dismiss();
}
loadShareInfo(): Observable<{
view: Array<{username: string, id: string, level: 'view'|'update'|'manage'}>,
update: Array<{username: string, id: string, level: 'view'|'update'|'manage'}>,
manage: Array<{username: string, id: string, level: 'view'|'update'|'manage'}>,
}> {
return new Observable(sub => {
this.api.get(`/share/page/${this.node.id}/info`).subscribe(result => {
sub.next(result.data);
sub.complete();
});
});
}
setShareLevel(group, level) {
this.api.post(`/share/page/${this.node.id}/share`, { user_id: group.id, level }).subscribe(result => {
this.loadShareInfo().subscribe(data => {
this.sharingInfo = data;
});
});
}
unsharePage(group) {
this.api.post(`/share/page/${this.node.id}/revoke`, { user_id: group.id }).subscribe(result => {
this.loadShareInfo().subscribe(data => {
this.sharingInfo = data;
});
});
}
getShareLink(level) {
this.api.get(`/share/page/${this.node.id}/link/${level}`).subscribe(result => {
this.generatedLink = result.data.link;
});
}
}