web/satellite: create access grant: bucket names selection logic

WHAT:
bucket names selection logic for create access grant flow

WHY:
bucket based access grant restriction

Change-Id: I922811ce43afbc0bf0c2c9bcaea755657257f26f
This commit is contained in:
VitaliiShpital 2020-11-17 16:03:49 +02:00 committed by Vitalii Shpital
parent 4e49b00c6c
commit 6f35ee98e6
7 changed files with 193 additions and 31 deletions

View File

@ -54,8 +54,6 @@ export default class CreateAccessGrant extends Vue {
&__container {
background: #fff;
border-radius: 6px;
width: 835px;
height: 470px;
display: flex;
align-items: center;
position: relative;

View File

@ -69,7 +69,7 @@ export default class ProgressBar extends Vue {
flex-direction: column;
align-items: flex-start;
background: #f5f6fa;
height: calc(100% - 110px);
height: 360px;
border-radius: 6px 0 0 6px;
&__item {

View File

@ -0,0 +1,64 @@
v// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="bucket-bullet">
<p class="bucket-bullet__label">{{ name }}</p>
<UnselectIcon class="bucket-bullet__icon" @click.stop="toggleBucketSelection(name)"/>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import UnselectIcon from '@/../static/images/accessGrants/unselect.svg';
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
@Component({
components: {
UnselectIcon,
},
})
export default class BucketNameBullet extends Vue {
@Prop({default: ''})
public readonly name: string;
/**
* Toggles bucket selection.
*/
public toggleBucketSelection(name: string): void {
this.$store.dispatch(ACCESS_GRANTS_ACTIONS.TOGGLE_BUCKET_SELECTION, name);
}
}
</script>
<style scoped lang="scss">
.bucket-bullet {
padding: 5px 5px 5px 10px;
display: flex;
align-items: center;
background: #e7eaee;
border-radius: 50px;
margin: 0 5px 5px 0;
&__label {
font-family: 'font_bold', sans-serif;
font-style: normal;
font-weight: bold;
font-size: 9px;
line-height: 12px;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 190px;
letter-spacing: 0.05em;
color: #1b2533;
margin: 0;
}
&__icon {
cursor: pointer;
margin-left: 10px;
}
}
</style>

View File

@ -4,7 +4,7 @@
<template>
<div class="buckets-dropdown">
<div class="buckets-dropdown__container">
<p class="buckets-dropdown__container__all">
<p class="buckets-dropdown__container__all" @click.stop="selectAllBuckets">
All
</p>
<div
@ -12,12 +12,13 @@
v-for="(name, index) in allBucketNames"
:key="index"
>
<div class="buckets-dropdown__container__choices__item">
<div
class="buckets-dropdown__container__choices__item"
:class="{ selected: isNameSelected(name) }"
@click.stop="toggleBucketSelection(name)"
>
<div class="buckets-dropdown__container__choices__item__left">
<SelectionIcon
class="buckets-dropdown__container__choices__item__left__icon"
:class="{ selected: isNameSelected(name) }"
/>
<SelectionIcon class="buckets-dropdown__container__choices__item__left__icon"/>
<p class="buckets-dropdown__container__choices__item__left__label">{{ name }}</p>
</div>
<UnselectIcon
@ -36,6 +37,8 @@ import { Component, Vue } from 'vue-property-decorator';
import SelectionIcon from '@/../static/images/accessGrants/selection.svg';
import UnselectIcon from '@/../static/images/accessGrants/unselect.svg';
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
@Component({
components: {
SelectionIcon,
@ -43,6 +46,21 @@ import UnselectIcon from '@/../static/images/accessGrants/unselect.svg';
},
})
export default class BucketsDropdown extends Vue {
/**
* Clears selection of specific buckets and closes dropdown.
*/
public selectAllBuckets(): void {
this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CLEAR_SELECTION);
this.$emit('close');
}
/**
* Toggles bucket selection.
*/
public toggleBucketSelection(name: string): void {
this.$store.dispatch(ACCESS_GRANTS_ACTIONS.TOGGLE_BUCKET_SELECTION, name);
}
/**
* Indicates if bucket name is selected.
* @param name
@ -75,13 +93,6 @@ export default class BucketsDropdown extends Vue {
width: 0;
}
.selected {
.bucket-name-selection-path {
stroke: #0068dc;
}
}
.buckets-dropdown {
position: absolute;
z-index: 1120;
@ -123,6 +134,25 @@ export default class BucketsDropdown extends Vue {
&__choices {
&__item__unselect-icon {
opacity: 0;
}
.selected {
background-color: #f5f6fa;
.bucket-name-selection-path {
stroke: #0068dc !important;
}
&:hover {
.buckets-dropdown__container__choices__item__unselect-icon {
opacity: 1 !important;
}
}
}
&__item {
display: flex;
align-items: center;
@ -139,14 +169,6 @@ export default class BucketsDropdown extends Vue {
}
}
&__unselect-icon {
opacity: 0;
&:hover {
opacity: 1;
}
}
&:hover {
background-color: #ecedf2;

View File

@ -95,7 +95,7 @@ export default class BucketsSelection extends Vue {
border-radius: 6px;
border: 1px solid rgba(56, 75, 101, 0.4);
font-family: 'font_regular', sans-serif;
width: 100%;
width: 235px;
&__toggle-container {
position: relative;

View File

@ -4,7 +4,7 @@
<template>
<div class="permissions">
<BackIcon class="permissions__back-icon" @click="onBackClick"/>
<h1 class="permissions__title">Permissions</h1>
<h1 class="permissions__title">Access Permissions</h1>
<p class="permissions__sub-title">
Assign permissions to this Access Grant.
</p>
@ -28,29 +28,51 @@
</div>
</div>
<div class="permissions__content__right">
<div class="permissions__content__right__buckets">
<p class="permissions__content__right__buckets__label">Buckets</p>
<div class="permissions__content__right__buckets-select">
<p class="permissions__content__right__buckets-select__label">Buckets</p>
<BucketsSelection />
</div>
<div class="permissions__content__right__bucket-bullets">
<div
class="permissions__content__right__bucket-bullets__container"
v-for="(name, index) in selectedBucketNames"
:key="index"
>
<BucketNameBullet :name="name"/>
</div>
</div>
</div>
</div>
<VButton
class="permissions__button"
label="Continue in Browser"
width="100%"
height="48px"
:on-press="onContinueInBrowserClick"
/>
<p class="permissions__cli-link" @click.stop="onContinueInCLIClick">
Continue in CLI
</p>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import BucketNameBullet from '@/components/accessGrants/permissions/BucketNameBullet.vue';
import BucketsSelection from '@/components/accessGrants/permissions/BucketsSelection.vue';
import VButton from '@/components/common/VButton.vue';
import BackIcon from '@/../static/images/accessGrants/back.svg';
import { RouteConfig } from '@/router';
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
@Component({
components: {
BackIcon,
BucketsSelection,
BucketNameBullet,
VButton,
},
})
export default class PermissionsStep extends Vue {
@ -104,12 +126,44 @@ export default class PermissionsStep extends Vue {
* Redirects to previous step.
*/
public onBackClick(): void {
this.$router.push(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessGrant.with(RouteConfig.NameStep)).path);
const PREVIOUS_ROUTE_NUMBER: number = -1;
this.$router.go(PREVIOUS_ROUTE_NUMBER);
}
/**
* Holds on continue in CLI button click logic.
*/
public onContinueInCLIClick(): void {
// mock
return;
}
/**
* Holds on continue in browser button click logic.
*/
public onContinueInBrowserClick(): void {
// mock
return;
}
/**
* Returns stored selected bucket names.
*/
public get selectedBucketNames(): string[] {
return this.$store.state.accessGrantsModule.selectedBucketNames;
}
}
</script>
<style scoped lang="scss">
::-webkit-scrollbar,
::-webkit-scrollbar-track,
::-webkit-scrollbar-thumb {
margin: 0;
width: 0;
}
.permissions {
height: calc(100% - 60px);
width: calc(100% - 130px);
@ -171,7 +225,7 @@ export default class PermissionsStep extends Vue {
width: 100%;
margin-left: 100px;
&__buckets {
&__buckets-select {
display: flex;
align-items: center;
width: 100%;
@ -184,7 +238,30 @@ export default class PermissionsStep extends Vue {
margin: 0;
}
}
&__bucket-bullets {
display: flex;
align-items: center;
flex-wrap: wrap;
margin: 15px 0 0 85px;
max-height: 200px;
max-width: 235px;
overflow-x: hidden;
overflow-y: scroll;
}
}
}
&__button {
margin-top: 60px;
}
&__cli-link {
cursor: pointer;
font-weight: 600;
font-size: 16px;
line-height: 23px;
color: #0068dc;
}
}
</style>

View File

@ -119,6 +119,7 @@ export function makeAccessGrantsModule(api: AccessGrantsApi): StoreModule<Access
});
},
[CLEAR_SELECTION](state: AccessGrantsState) {
state.selectedBucketNames = [];
state.selectedAccessGrantsIds = [];
state.page.accessGrants = state.page.accessGrants.map((accessGrant: AccessGrant) => {
accessGrant.isSelected = false;