1
0
mirror of https://github.com/bitwarden/desktop.git synced 2024-11-24 11:55:50 +01:00

Added support for viewing Sends'

This commit is contained in:
addison 2021-02-09 15:57:10 -05:00
parent 66b984122c
commit 30a7db2f20
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="inner-content">
<div class="box"> <div class="box">
<div class="box-header"> <div class="box-header">
{{'sendInformation' | i18n}} {{'editSend' | i18n}}
</div> </div>
<div class="box-content"> <div class="box-content">
<div class="box-content-row"> <div class="box-content-row" appBoxRow>
<span class="row-label">{{'name' | i18n}}</span> <label for="name">{{'name' | i18n}}</label>
{{send.name}} <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> </div>
</div> </div>

View File

@ -1,11 +1,12 @@
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { Component } from '@angular/core'; import { Component, Input } from '@angular/core';
import { EnvironmentService } from 'jslib/abstractions/environment.service'; import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service'; import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.service'; import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { SendService } from 'jslib/abstractions/send.service'; import { SendService } from 'jslib/abstractions/send.service';
import { UserService } from 'jslib/abstractions/user.service'; import { UserService } from 'jslib/abstractions/user.service';
@ -19,8 +20,13 @@ export class AddEditComponent extends BaseAddEditComponent {
constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService, constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService,
environmentService: EnvironmentService, datePipe: DatePipe, environmentService: EnvironmentService, datePipe: DatePipe,
sendService: SendService, userService: UserService, sendService: SendService, userService: UserService,
messagingService: MessagingService) { messagingService: MessagingService, policyService: PolicyService) {
super(i18nService, platformUtilsService, environmentService, 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="content">
<div class="list" *ngIf="filteredSends.length" infiniteScroll [infiniteScrollDistance]="1" <div class="list" *ngIf="filteredSends.length" infiniteScroll [infiniteScrollDistance]="1"
[infiniteScrollContainer]="'#items .content'" [fromRoot]="true" (scrolled)="loadMore()"> [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}}" href="#" title="{{'viewItem' | i18n}}"
[ngClass]="{'active': s.id === activeSendId}"> [ngClass]="{'active': s.id === activeSendId}">
<div class="icon" aria-hidden="true"> <div class="icon" aria-hidden="true">
@ -67,7 +67,7 @@
</button> </button>
</div> </div>
</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="logo" *ngIf="!action">
<div class="content"> <div class="content">
<div class="inner-content"> <div class="inner-content">

View File

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

View File

@ -1515,11 +1515,58 @@
"message": "Search Sends", "message": "Search Sends",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
}, },
"sendInformation": { "editSend": {
"message": "Send Information", "message": "Edit Send",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
}, },
"myVault": { "myVault": {
"message": "My Vault" "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 { &:hover, &:focus, &.active {
@include themify($themes) { @include themify($themes) {
background-color: themed('boxBackgroundHoverColor'); background-color: themed('boxBackgroundHoverColor');
> * {
background-color: themed('boxBackgroundHoverColor');
}
} }
} }

View File

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

View File

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