parent
1eda3d0b30
commit
9f361896ee
@ -1,67 +0,0 @@
|
|||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
||||||
import { TestBed, async } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { Platform } from '@ionic/angular';
|
|
||||||
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
|
|
||||||
import { StatusBar } from '@ionic-native/status-bar/ngx';
|
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
|
||||||
|
|
||||||
let statusBarSpy, splashScreenSpy, platformReadySpy, platformSpy;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']);
|
|
||||||
splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']);
|
|
||||||
platformReadySpy = Promise.resolve();
|
|
||||||
platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy });
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [AppComponent],
|
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
||||||
providers: [
|
|
||||||
{ provide: StatusBar, useValue: statusBarSpy },
|
|
||||||
{ provide: SplashScreen, useValue: splashScreenSpy },
|
|
||||||
{ provide: Platform, useValue: platformSpy },
|
|
||||||
],
|
|
||||||
imports: [ RouterTestingModule.withRoutes([])],
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should create the app', async () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.debugElement.componentInstance;
|
|
||||||
expect(app).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should initialize the app', async () => {
|
|
||||||
TestBed.createComponent(AppComponent);
|
|
||||||
expect(platformSpy.ready).toHaveBeenCalled();
|
|
||||||
await platformReadySpy;
|
|
||||||
expect(statusBarSpy.styleDefault).toHaveBeenCalled();
|
|
||||||
expect(splashScreenSpy.hide).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have menu labels', async () => {
|
|
||||||
const fixture = await TestBed.createComponent(AppComponent);
|
|
||||||
await fixture.detectChanges();
|
|
||||||
const app = fixture.nativeElement;
|
|
||||||
const menuItems = app.querySelectorAll('ion-label');
|
|
||||||
expect(menuItems.length).toEqual(2);
|
|
||||||
expect(menuItems[0].textContent).toContain('Home');
|
|
||||||
expect(menuItems[1].textContent).toContain('List');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have urls', async () => {
|
|
||||||
const fixture = await TestBed.createComponent(AppComponent);
|
|
||||||
await fixture.detectChanges();
|
|
||||||
const app = fixture.nativeElement;
|
|
||||||
const menuItems = app.querySelectorAll('ion-item');
|
|
||||||
expect(menuItems.length).toEqual(2);
|
|
||||||
expect(menuItems[0].getAttribute('ng-reflect-router-link')).toEqual('/home');
|
|
||||||
expect(menuItems[1].getAttribute('ng-reflect-router-link')).toEqual('/list');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -0,0 +1,6 @@
|
|||||||
|
<ion-list>
|
||||||
|
<ion-item *ngFor="let menuItem of menuItems; let i = index" button (click)="onSelect(menuItems[i].value)">
|
||||||
|
<ion-icon slot="start" [name]="menuItems[i].icon"></ion-icon>
|
||||||
|
<ion-label>{{ menuItems[i].name }}</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-list>
|
@ -0,0 +1,22 @@
|
|||||||
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
|
import {PopoverController} from '@ionic/angular';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'common-option-menu',
|
||||||
|
templateUrl: './option-menu.component.html',
|
||||||
|
styleUrls: ['./option-menu.component.scss'],
|
||||||
|
})
|
||||||
|
export class OptionMenuComponent implements OnInit {
|
||||||
|
@Input() menuItems: Array<{name: string, icon: string, value: string, type?: string}> = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected popover: PopoverController,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
async onSelect(value) {
|
||||||
|
await this.popover.dismiss(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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> View
|
||||||
|
</ion-button>
|
||||||
|
<ion-button fill="outline" color="medium" (click)="getShareLink('update')">
|
||||||
|
<ion-icon name="link" color="dark"></ion-icon> Edit
|
||||||
|
</ion-button>
|
||||||
|
<ion-button fill="outline" color="medium" (click)="getShareLink('manage')">
|
||||||
|
<ion-icon name="link" color="dark"></ion-icon> 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 }} <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 }} <span class="share-token">VIEW</span> <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 }} <span class="share-token">VIEW</span> <span class="share-token">EDIT</span> <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>
|
@ -0,0 +1,8 @@
|
|||||||
|
.share-token {
|
||||||
|
background-color: #dedede;
|
||||||
|
color: #555;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 10pt;
|
||||||
|
font-style: italic;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue