(
+ GroupAddEditComponent, this.addEditModalRef);
+
+ childComponent.organizationId = this.organizationId;
+ childComponent.groupId = group != null ? group.id : null;
+ childComponent.onSavedGroup.subscribe(() => {
+ this.modal.close();
+ this.load();
+ });
+ childComponent.onDeletedGroup.subscribe(() => {
+ this.modal.close();
+ this.load();
+ });
+
+ this.modal.onClosed.subscribe(() => {
+ this.modal = null;
+ });
+ }
+
+ add() {
+ this.edit(null);
+ }
+
+ async delete(group: GroupResponse) {
+ const confirmed = await this.platformUtilsService.showDialog(
+ this.i18nService.t('deleteGroupConfirmation'), group.name,
+ this.i18nService.t('yes'), this.i18nService.t('no'), 'warning');
+ if (!confirmed) {
+ return false;
+ }
+
+ try {
+ await this.apiService.deleteGroup(this.organizationId, group.id);
+ this.analytics.eventTrack.next({ action: 'Deleted Group' });
+ this.toasterService.popAsync('success', null,
+ this.i18nService.t('deletedThing', this.i18nService.t('group').toLocaleLowerCase(), group.name));
+ await this.load();
+ } catch { }
+ }
}
diff --git a/src/app/vault/bulk-share.component.ts b/src/app/vault/bulk-share.component.ts
index 09ff609cbe2..7bc9e0d36ed 100644
--- a/src/app/vault/bulk-share.component.ts
+++ b/src/app/vault/bulk-share.component.ts
@@ -75,14 +75,12 @@ export class BulkShareComponent implements OnInit {
this.toasterService.popAsync('success', null, this.i18nService.t('sharedItems'));
}
- check(c: CollectionView) {
- (c as any).checked = !(c as any).checked;
+ check(c: CollectionView, select?: boolean) {
+ (c as any).checked = select == null ? !(c as any).checked : select;
}
- selectAll(select: false) {
+ selectAll(select: boolean) {
const collections = select ? this.collections : this.writeableCollections;
- for (const c of collections) {
- (c as any).checked = select;
- }
+ collections.forEach((c) => this.check(c, select));
}
}
diff --git a/src/app/vault/ciphers.component.ts b/src/app/vault/ciphers.component.ts
index 236e9046e52..50afe5e4965 100644
--- a/src/app/vault/ciphers.component.ts
+++ b/src/app/vault/ciphers.component.ts
@@ -38,8 +38,8 @@ export class CiphersComponent extends BaseCiphersComponent {
super(cipherService);
}
- checkCipher(c: CipherView) {
- (c as any).checked = !(c as any).checked;
+ checkCipher(c: CipherView, select?: boolean) {
+ (c as any).checked = select == null ? !(c as any).checked : select;
}
selectAll(select: boolean) {
@@ -48,7 +48,7 @@ export class CiphersComponent extends BaseCiphersComponent {
}
const selectCount = select && this.ciphers.length > MaxCheckedCount ? MaxCheckedCount : this.ciphers.length;
for (let i = 0; i < selectCount; i++) {
- (this.ciphers[i] as any).checked = select;
+ this.checkCipher(this.ciphers[i], select);
}
}
diff --git a/src/app/vault/collections.component.html b/src/app/vault/collections.component.html
index 41255fd1f48..e4862316f54 100644
--- a/src/app/vault/collections.component.html
+++ b/src/app/vault/collections.component.html
@@ -15,10 +15,10 @@
{{'collections' | i18n}}
-
diff --git a/src/app/vault/collections.component.ts b/src/app/vault/collections.component.ts
index c2201af28d7..fea8e6d98bd 100644
--- a/src/app/vault/collections.component.ts
+++ b/src/app/vault/collections.component.ts
@@ -44,7 +44,7 @@ export class CollectionsComponent implements OnInit, OnDestroy {
this.cipher = await this.cipherDomain.decrypt();
this.collections = await this.loadCollections();
- this.unselectAll();
+ this.selectAll(false);
if (this.collectionIds != null) {
this.collections.forEach((c) => {
(c as any).checked = this.collectionIds.indexOf(c.id) > -1;
@@ -53,7 +53,7 @@ export class CollectionsComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
- this.unselectAll();
+ this.selectAll(false);
}
async submit() {
@@ -67,20 +67,12 @@ export class CollectionsComponent implements OnInit, OnDestroy {
this.toasterService.popAsync('success', null, this.i18nService.t('editedItem'));
}
- check(c: CollectionView) {
- (c as any).checked = !(c as any).checked;
+ check(c: CollectionView, select?: boolean) {
+ (c as any).checked = select == null ? !(c as any).checked : select;
}
- selectAll() {
- for (const c of this.collections) {
- (c as any).checked = true;
- }
- }
-
- unselectAll() {
- for (const c of this.collections) {
- (c as any).checked = false;
- }
+ selectAll(select: boolean) {
+ this.collections.forEach((c) => this.check(c, select));
}
protected loadCipher() {
diff --git a/src/app/vault/share.component.ts b/src/app/vault/share.component.ts
index 5fcb459c15a..586fc044ed9 100644
--- a/src/app/vault/share.component.ts
+++ b/src/app/vault/share.component.ts
@@ -87,14 +87,12 @@ export class ShareComponent implements OnInit, OnDestroy {
await this.formPromise;
}
- check(c: CollectionView) {
- (c as any).checked = !(c as any).checked;
+ check(c: CollectionView, select?: boolean) {
+ (c as any).checked = select == null ? !(c as any).checked : select;
}
selectAll(select: false) {
const collections = select ? this.collections : this.writeableCollections;
- for (const c of collections) {
- (c as any).checked = select;
- }
+ collections.forEach((c) => this.check(c, select));
}
}
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
index 28d11f9f0b6..bfdba4c196e 100644
--- a/src/locales/en/messages.json
+++ b/src/locales/en/messages.json
@@ -591,6 +591,15 @@
"noItemsInList": {
"message": "There are no items to list."
},
+ "noCollectionsInList": {
+ "message": "There are no collections to list."
+ },
+ "noGroupsInList": {
+ "message": "There are no collections to list."
+ },
+ "noUsersInList": {
+ "message": "There are no users to list."
+ },
"newOrganization": {
"message": "New Organization"
},
@@ -1703,12 +1712,48 @@
"newGroup": {
"message": "New Group"
},
+ "addGroup": {
+ "message": "Add Group"
+ },
+ "editGroup": {
+ "message": "Edit Group"
+ },
+ "deleteGroupConfirmation": {
+ "message": "Are you sure you want to delete this group?"
+ },
+ "externalId": {
+ "message": "External Id"
+ },
+ "accessControl": {
+ "message": "Access Control"
+ },
+ "groupAccessAllItems": {
+ "message": "This group can access and modify all items."
+ },
+ "groupAccessSelectedCollections": {
+ "message": "This group can access only the selected collections."
+ },
+ "readOnly": {
+ "message": "Read Only"
+ },
"newCollection": {
"message": "New Collection"
},
+ "addCollection": {
+ "message": "Add Collection"
+ },
+ "editCollection": {
+ "message": "Edit Collection"
+ },
"inviteUser": {
"message": "Invite User"
},
+ "userAccessAllItems": {
+ "message": "This user can access and modify all items."
+ },
+ "userAccessSelectedCollections": {
+ "message": "This user can access only the selected collections."
+ },
"search": {
"message": "Search"
},
@@ -1789,7 +1834,7 @@
},
"createdThing": {
"message": "Created $THING$ $ID$.",
- "description": "Created item abe89f32.",
+ "description": "Created item 'Google'.",
"placeholders": {
"thing": {
"content": "$1",
@@ -1797,13 +1842,13 @@
},
"id": {
"content": "$2",
- "example": "abe89f32"
+ "example": "Google"
}
}
},
"editedThing": {
"message": "Edited $THING$ $ID$.",
- "description": "Edited item abe89f32.",
+ "description": "Edited item 'Google'.",
"placeholders": {
"thing": {
"content": "$1",
@@ -1811,13 +1856,13 @@
},
"id": {
"content": "$2",
- "example": "abe89f32"
+ "example": "Google"
}
}
},
"deletedThing": {
"message": "Deleted $THING$ $ID$.",
- "description": "Deleted item abe89f32.",
+ "description": "Deleted item 'Google'.",
"placeholders": {
"thing": {
"content": "$1",
@@ -1825,12 +1870,13 @@
},
"id": {
"content": "$2",
- "example": "abe89f32"
+ "example": "Google"
}
}
},
"sharedThing": {
"message": "Shared $THING$ $ID$.",
+ "description": "Shared item 'Google'.",
"placeholders": {
"thing": {
"content": "$1",
@@ -1838,12 +1884,13 @@
},
"id": {
"content": "$2",
- "example": "abe89f32"
+ "example": "'Google'"
}
}
},
"removedThing": {
"message": "Removed $THING$ $ID$.",
+ "description": "Shared item 'Google'.",
"placeholders": {
"thing": {
"content": "$1",
@@ -1851,7 +1898,7 @@
},
"id": {
"content": "$2",
- "example": "abe89f32"
+ "example": "Google"
}
}
},
@@ -1860,7 +1907,7 @@
"placeholders": {
"id": {
"content": "$1",
- "example": "abe89f32"
+ "example": "Google"
}
}
},
@@ -1869,7 +1916,7 @@
"placeholders": {
"id": {
"content": "$1",
- "example": "abe89f32"
+ "example": "Google"
}
}
},
@@ -1878,7 +1925,7 @@
"placeholders": {
"id": {
"content": "$1",
- "example": "abe89f32"
+ "example": "Google"
}
}
},
@@ -1887,7 +1934,7 @@
"placeholders": {
"id": {
"content": "$1",
- "example": "abe89f32"
+ "example": "John Smith"
}
}
},
@@ -1896,7 +1943,7 @@
"placeholders": {
"id": {
"content": "$1",
- "example": "abe89f32"
+ "example": "John Smith"
}
}
},
@@ -1905,7 +1952,7 @@
"placeholders": {
"id": {
"content": "$1",
- "example": "abe89f32"
+ "example": "John Smith"
}
}
},
diff --git a/src/scss/styles.scss b/src/scss/styles.scss
index 4c6ff6c5538..a3ba9b2a240 100644
--- a/src/scss/styles.scss
+++ b/src/scss/styles.scss
@@ -265,6 +265,10 @@ label:not(.form-check-label):not(.btn) {
}
.table.table-list {
+ thead th {
+ border-top: none;
+ }
+
tr:first-child {
td {
border: none;