Merge pull request #720 from bitwarden/Send

View Sends
This commit is contained in:
Addison Beck 2021-02-10 12:21:23 -05:00 committed by GitHub
commit 0b7621141c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 185 additions and 17 deletions

2
jslib

@ -1 +1 @@
Subproject commit a16d8f7de7abe63532bcf7452cb7517f9174189a
Subproject commit ee164bebc65aa56e41a122eb4ece8971eb23119b

View File

@ -1,13 +1,95 @@
<div class="content">
<div class="content" *ngIf="send">
<div class="inner-content">
<div class="box">
<div class="box-header">
{{'sendInformation' | i18n}}
{{'editSend' | i18n}}
</div>
<div class="box-content">
<div class="box-content-row">
<span class="row-label">{{'name' | i18n}}</span>
{{send.name}}
<div class="box-content-row" appBoxRow>
<label for="name">{{'name' | i18n}}</label>
<input id="name" type="text" name="Name" [(ngModel)]="send.name" appAutofocus>
</div>
<div class="box-content-row" appBoxRow *ngIf="send.type === sendType.File">
<label for="file">{{'file' | i18n}}</label>
<input id="file" type="text" name="file" [(ngModel)]="send.file.fileName" readonly>
</div>
<div class="box-content-row" appBoxRow *ngIf="send.type === sendType.Text">
<label for="text">{{'text' | i18n}}</label>
<input id="text" type="text" name="text" [(ngModel)]="send.text.text">
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow *ngIf="send.type === sendType.Text">
<label for="hideText">{{'textHiddenByDefault' | i18n}}</label>
<input id="hideText" name="hideText" type="checkbox" [(ngModel)]="send.text.hidden">
</div>
</div>
</div>
<div class="box">
<div class="box-header">
{{'options' | i18n}}
</div>
<div class="box-content">
<div class="box-content-row" appBoxRow *ngIf="editMode">
<label for="deletionDate">{{'deletionDate' | i18n}}</label>
<input id="deletionDate" type="datetime-local" name="deletionDate"
[(ngModel)]="deletionDate" required placeholder="MM/DD/YYYY HH:MM AM/PM">
<div class="subtext">{{'deletionDateDesc' | i18n}}</div>
</div>
<div class="box-content-row" appBoxRow>
<label for="expirationDate">{{'expirationDate' | i18n}}</label>
<input id="expirationDate" type="datetime-local" name="expirationDate" [(ngModel)]="send.expirationDate">
<div class="subtext">{{'expirationDateDesc' | i18n}}</div>
</div>
</div>
</div>
<div class="box">
<div class="box-content">
<div class="box-content-row" appBoxRow>
<label for="maxAccessCount">{{'maxAccessCount' | i18n}}</label>
<input id="maxAccessCount" type="number" name="maxAccessCount" [(ngModel)]="send.maxAccessCount">
<div class="subtext">{{'maxAccessCountDesc' | i18n}}</div>
</div>
<div class="box-content-row" appBoxRow>
<label for="accessCount">{{'currentAccessCount' | i18n}}</label>
<input id="accessCount" type="text" name="accessCount" [(ngModel)]="send.accessCount" readonly>
</div>
</div>
</div>
<div class="box">
<div class="box-content">
<div class="box-content-row" appBoxRow>
<label for="password">{{'password' | i18n}}</label>
<input id="password" type="password" name="password" [(ngModel)]="send.password">
<div class="subtext">{{'sendPasswordDesc' | i18n}}</div>
</div>
</div>
</div>
<div class="box">
<div class="box-header">
{{'notes' | i18n}}
</div>
<div class="box-content">
<div class="box-content-row" appBoxRow>
<textarea id="notes" name="notes" [(ngModel)]="send.notes" rows="6"></textarea>
<small class="subtext">{{'sendNotesDesc' | i18n}}</small>
</div>
</div>
</div>
<div class="box">
<div class="box-content">
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="disabled">{{'disableSend' | i18n}}</label>
<input id="disabled" type="checkbox" name="disabled" [(ngModel)]="send.disabled">
</div>
</div>
</div>
<div class="box">
<div class="box-header">
{{'share' | i18n}}
</div>
<div class="box-content">
<div class="box-content-row" appBoxRow>
<label for="url">{{'sendLink' | i18n}}</label>
<input id="url" name="url" [ngModel]="link" readonly>
</div>
</div>
</div>

View File

@ -1,11 +1,12 @@
import { DatePipe } from '@angular/common';
import { Component } from '@angular/core';
import { Component, Input } from '@angular/core';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { SendService } from 'jslib/abstractions/send.service';
import { UserService } from 'jslib/abstractions/user.service';
@ -19,8 +20,13 @@ export class AddEditComponent extends BaseAddEditComponent {
constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService,
environmentService: EnvironmentService, datePipe: DatePipe,
sendService: SendService, userService: UserService,
messagingService: MessagingService) {
messagingService: MessagingService, policyService: PolicyService) {
super(i18nService, platformUtilsService, environmentService,
datePipe, sendService, userService, messagingService);
datePipe, sendService, userService, messagingService, policyService);
}
async refresh() {
const send = await this.loadSend();
this.send = await send.decrypt();
}
}

View File

@ -41,7 +41,7 @@
<div class="content">
<div class="list" *ngIf="filteredSends.length" infiniteScroll [infiniteScrollDistance]="1"
[infiniteScrollContainer]="'#items .content'" [fromRoot]="true" (scrolled)="loadMore()">
<a *ngFor="let s of filteredSends" appStopClick (click)="selectSend(s)"
<a *ngFor="let s of filteredSends" appStopClick (click)="selectSend(s.id)"
href="#" title="{{'viewItem' | i18n}}"
[ngClass]="{'active': s.id === activeSendId}">
<div class="icon" aria-hidden="true">
@ -67,7 +67,7 @@
</button>
</div>
</div>
<app-send-add-edit class="details" *ngIf="action == 'add' || action == 'edit'" [sendId]="sendId" [type]="selectedSendType"></app-send-add-edit>
<app-send-add-edit id="addEdit" class="details" *ngIf="action == 'add' || action == 'edit'" [sendId]="sendId" [type]="selectedSendType"></app-send-add-edit>
<div class="logo" *ngIf="!action">
<div class="content">
<div class="inner-content">

View File

@ -2,13 +2,16 @@ import {
Component,
NgZone,
OnInit,
ViewChild,
} from '@angular/core';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { SearchService } from 'jslib/abstractions/search.service';
import { SendService } from 'jslib/abstractions/send.service';
import { UserService } from 'jslib/abstractions/user.service';
import { SendComponent as BaseSendComponent } from 'jslib/angular/components/send/send.component';
@ -16,6 +19,8 @@ import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
import { SendView } from 'jslib/models/view/sendView';
import { AddEditComponent } from './add-edit.component';
enum Action {
None = '',
Add = 'add',
@ -27,15 +32,24 @@ enum Action {
templateUrl: 'send.component.html',
})
export class SendComponent extends BaseSendComponent implements OnInit {
@ViewChild(AddEditComponent) addEditComponent: AddEditComponent;
sendId: string;
action: Action = Action.None;
constructor(sendService: SendService, i18nService: I18nService,
platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService,
broadcasterService: BroadcasterService, ngZone: NgZone,
searchService: SearchService) {
searchService: SearchService, policyService: PolicyService,
userService: UserService) {
super(sendService, i18nService, platformUtilsService,
environmentService, broadcasterService, ngZone, searchService);
environmentService, broadcasterService, ngZone, searchService,
policyService, userService);
}
async ngOnInit() {
super.ngOnInit();
await this.load();
}
addSend() {
@ -47,9 +61,14 @@ export class SendComponent extends BaseSendComponent implements OnInit {
return;
}
selectSend(send: SendView) {
this.sendId = send.id;
async selectSend(sendId: string) {
this.sendId = sendId;
this.action = Action.Edit;
if (this.addEditComponent != null) {
this.addEditComponent.sendId = this.sendId;
await this.addEditComponent.refresh();
}
}
get selectedSendType() {

View File

@ -1515,11 +1515,58 @@
"message": "Search Sends",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendInformation": {
"message": "Send Information",
"editSend": {
"message": "Edit Send",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"myVault": {
"message": "My Vault"
},
"text": {
"message": "Text"
},
"deletionDate": {
"message": "Deletion Date"
},
"deletionDateDesc": {
"message": "The Send will be permanently deleted on the specified date and time.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"expirationDate": {
"message": "Expiration Date"
},
"expirationDateDesc": {
"message": "If set, access to this Send will expire on the specified date and time.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"maxAccessCount": {
"message": "Maximum Access Count"
},
"maxAccessCountDesc": {
"message": "If set, users will no longer be able to access this Send once the maximum access count is reached.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"currentAccessCount": {
"message": "Current Access Count"
},
"disableSend": {
"message": "Disable this Send so that no one can access it.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendPasswordDesc": {
"message": "Optionally require a password for users to access this Send.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendNotesDesc": {
"message": "Private notes about this Send.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"sendLink": {
"message": "Send Link",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"textHiddenByDefault": {
"message": "When accessing the Send, hide the text by default",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
}
}

View File

@ -102,6 +102,9 @@
&:hover, &:focus, &.active {
@include themify($themes) {
background-color: themed('boxBackgroundHoverColor');
> * {
background-color: themed('boxBackgroundHoverColor');
}
}
}

View File

@ -4,6 +4,14 @@ small {
font-size: $font-size-small;
}
.subtext {
font-size: $font-size-small;
@include themify($themes) {
color: themed('subtextColor') !important;
}
padding-top: 5px;
}
.bg-primary {
@include themify($themes) {
background-color: themed('primaryColor') !important;

View File

@ -88,6 +88,7 @@ $themes: (
passwordSpecialColor: #c40800,
calloutBorderColor: $border-color-dark,
calloutBackgroundColor: $background-color,
subtextColor: #6c757d,
),
dark: (
textColor: #ffffff,
@ -138,6 +139,7 @@ $themes: (
passwordSpecialColor: #ff7c70,
calloutBorderColor: #2f2f2f,
calloutBackgroundColor: #363636,
subtextColor: #938a82,
),
nord: (
textColor: $nord5,
@ -188,6 +190,7 @@ $themes: (
passwordSpecialColor: $nord12,
calloutBorderColor: $nord1,
calloutBackgroundColor: $nord2,
subtextColor: $nord4,
),
);