web/satellite: table responsiveness added

added Resizable wrapper to track screen dimensions changes
items to render computable added
TODO:
implement file browser table resposiveness

Change-Id: I913d5cdb5285d6f0fb7135183ff299c37f01ad4a
This commit is contained in:
NickolaiYurchenko 2022-08-15 13:51:21 +03:00 committed by Storj Robot
parent d1d98af098
commit 3c0fc3a530
10 changed files with 142 additions and 28 deletions

View File

@ -83,6 +83,7 @@ export default class App extends Vue {
<style lang="scss">
html {
overflow: hidden;
font-size: 14px;
}
body {

View File

@ -3,7 +3,7 @@
<template>
<table-item
:item="{ name: itemData.name, date: itemData.localDate() }"
:item="itemToRender"
:on-click="onClick"
>
<th slot="options" v-click-outside="closeDropdown" class="grant-item__functional options overflow-visible" @click.stop="openDropdown">
@ -19,8 +19,9 @@
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Component, Prop } from 'vue-property-decorator';
import { AccessGrant } from '@/types/accessGrants';
import Resizable from "@/components/common/Resizable.vue";
import TableItem from "@/components/common/TableItem.vue";
import DeleteIcon from "../../../static/images/objects/delete.svg";
@ -34,7 +35,7 @@ import DotsIcon from "../../../static/images/objects/dots.svg";
DotsIcon,
},
})
export default class AccessGrantsItem extends Vue {
export default class AccessGrantsItem extends Resizable {
@Prop({ default: new AccessGrant('', '', new Date(), '') })
private readonly itemData: AccessGrant;
@Prop({ default: () => () => {} })
@ -44,6 +45,12 @@ export default class AccessGrantsItem extends Vue {
@Prop({ default: -1 })
public readonly dropdownKey: number;
public get itemToRender(): { [key: string]: string | string[] } {
if (!this.isMobile) return { name: this.itemData.name, date: this.itemData.localDate() };
return { info: [ this.itemData.name, `Created ${this.itemData.localDate()}` ] };
}
/**
* Closes dropdown.
*/

View File

@ -0,0 +1,34 @@
// Copyright (C) 2022 Storj Labs, Inc.
// See LICENSE for copying information.
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
// @vue/component
@Component
export default class Resizable extends Vue {
public screenWidth: number = window.innerWidth;
public screenHeight: number = window.innerHeight;
public get isMobile(): boolean {
return this.screenWidth <= 550;
}
public get isTablet(): boolean {
return !this.isMobile && this.screenWidth <= 800;
}
public mounted(): void {
window.addEventListener('resize', this.onResize);
}
public beforeDestroy(): void {
window.removeEventListener('resize', this.onResize);
}
private onResize(): void {
this.screenWidth = window.innerWidth;
this.screenHeight = window.innerHeight;
}
}
</script>

View File

@ -6,11 +6,14 @@
:class="{ 'selected': selected }"
@click="onClick"
>
<th v-if="selectable" class="icon">
<th v-if="selectable" class="icon select">
<v-table-checkbox :disabled="selectDisabled" :value="selected" @checkChange="onChange" />
</th>
<th v-for="(val, key, index) in item" :key="index" class="align-left data">
<p>{{ val }}</p>
<div v-if="Array.isArray(val)" class="few-items">
<p v-for="str in val" :key="str" class="array-val">{{ str }}</p>
</div>
<p v-else>{{ val }}</p>
</th>
<slot name="options" />
</tr>
@ -53,4 +56,22 @@ export default class TableItem extends Vue {
background: #f0f3f8;
}
}
.few-items {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.array-val {
font-family: 'font_regular', sans-serif;
font-size: 0.75rem;
line-height: 1.25rem;
&:first-of-type {
font-family: 'font_bold', sans-serif;
font-size: 0.875rem;
margin-bottom: 3px;
}
}
</style>

View File

@ -6,7 +6,7 @@
<table class="base-table" border="0" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th v-if="selectable" class="icon" />
<th v-if="selectable" class="icon select" />
<slot name="head" />
</tr>
</thead>
@ -62,7 +62,7 @@ export default class VTable extends Vue {
<style lang="scss">
.table-wrapper {
background: #fff;
box-shadow: 0 4px 32px rgb(0 0 0 / 4%);
box-shadow: 0 4px 2rem rgb(0 0 0 / 4%);
border-radius: 12px;
}
@ -73,7 +73,7 @@ export default class VTable extends Vue {
th {
box-sizing: border-box;
padding: 16px;
padding: 1.125rem;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
@ -84,9 +84,13 @@ export default class VTable extends Vue {
background: var(--c-block-gray);
text-transform: uppercase;
@media screen and (max-width: 550px) {
display: none;
}
tr {
height: 52px;
font-size: 12px;
font-size: 0.875rem;
color: #6b7280;
}
}
@ -100,8 +104,13 @@ export default class VTable extends Vue {
th {
font-family: 'font_regular', sans-serif;
color: #111827;
font-size: 14px;
font-size: 1rem;
border-top: solid 1px #e5e7eb;
@media screen and (max-width: 550px) {
border-top: none;
border-bottom: solid 1px #e5e7eb;
}
}
.data {
@ -132,9 +141,21 @@ export default class VTable extends Vue {
align-items: center;
justify-content: space-between;
padding: 15px 20px;
font-size: 14px;
line-height: 24px;
font-size: 1rem;
line-height: 1.7rem;
color: rgb(44 53 58 / 60%);
border-top: solid 1px #e5e7eb;
font-family: 'font-medium', sans-serif;
@media screen and (max-width: 550px) {
border-top: none;
}
}
@media screen and (max-width: 768px) {
.select {
display: none;
}
}
</style>

View File

@ -3,7 +3,7 @@
<template>
<table-item
:item="{ name: itemData.name, date: formattedDate }"
:item="itemToRender"
:on-click="onClick"
>
<th slot="options" v-click-outside="closeDropdown" class="bucket-item__functional options overflow-visible" @click.stop="openDropdown(dropdownKey)">
@ -33,9 +33,10 @@
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Component, Prop } from 'vue-property-decorator';
import TableItem from "@/components/common/TableItem.vue";
import Resizable from "@/components/common/Resizable.vue";
import DeleteIcon from '@/../static/images/objects/delete.svg';
import DetailsIcon from '@/../static/images/objects/details.svg';
import DotsIcon from '@/../static/images/objects/dots.svg';
@ -53,7 +54,7 @@ import { LocalData } from "@/utils/localData";
DetailsIcon,
},
})
export default class BucketItem extends Vue {
export default class BucketItem extends Resizable {
@Prop({ default: null })
public readonly itemData: Bucket;
@Prop({ default: () => () => {} })
@ -82,8 +83,14 @@ export default class BucketItem extends Vue {
/**
* Returns formatted date.
*/
public get formattedDate(): string | undefined {
return this.itemData.since.toLocaleString();
public get formattedDate(): string {
return this.itemData.since.toLocaleString() || '';
}
public get itemToRender(): { [key: string]: string | string[] } {
if (!this.isMobile) return { name: this.itemData.name, date: this.formattedDate };
return { info: [ this.itemData.name, `Created ${this.formattedDate}` ] };
}
public hideGuide(): void {
@ -121,9 +128,10 @@ export default class BucketItem extends Vue {
name: RouteConfig.Buckets.with(RouteConfig.BucketsDetails).name,
params: {
bucketName: this.itemData.name,
backRoute: this.$route.name ? this.$route.name : ''
backRoute: this.$route.name || ''
},
});
this.closeDropdown();
}
}

View File

@ -3,17 +3,18 @@
<template>
<table-item
:item="{ name: itemData.name, memberCount: itemData.memberCount, date: itemData.createdDate() }"
:item="itemToRender"
:on-click="onClick"
class="container__item"
/>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Component, Prop } from 'vue-property-decorator';
import { Project } from '@/types/projects';
import TableItem from "@/components/common/TableItem.vue";
import Resizable from "@/components/common/Resizable.vue";
// @vue/component
@Component({
@ -21,11 +22,17 @@ import TableItem from "@/components/common/TableItem.vue";
TableItem,
},
})
export default class ProjectsListItem extends Vue {
export default class ProjectsListItem extends Resizable {
@Prop({default: () => new Project('123', 'name', 'desc')})
private readonly itemData: Project;
@Prop({ default: () => (_: string) => {} })
public readonly onClick: (project: string) => void;
public get itemToRender(): { [key: string]: string | string[] } {
if (!this.isMobile) return { name: this.itemData.name, memberCount: this.itemData.memberCount.toString(), date: this.itemData.createdDate() };
return { info: [ this.itemData.name, `Created ${this.itemData.createdDate()}` ] };
}
}
</script>

View File

@ -4,7 +4,7 @@
<template>
<table-item
:class="{ 'owner': isProjectOwner }"
:item="{ name: itemData.name, date: itemData.localDate(), email: itemData.email }"
:item="itemToRender"
:selectable="true"
:select-disabled="isProjectOwner"
:selected="itemData.isSelected"
@ -14,22 +14,30 @@
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Component, Prop } from 'vue-property-decorator';
import { ProjectMember } from '@/types/projectMembers';
import TableItem from "@/components/common/TableItem.vue";
import Resizable from "@/components/common/Resizable.vue";
// @vue/component
@Component({
components: {TableItem}
components: { TableItem }
})
export default class ProjectMemberListItem extends Vue {
export default class ProjectMemberListItem extends Resizable {
@Prop({ default: new ProjectMember('', '', '', new Date(), '') })
public itemData: ProjectMember;
public get isProjectOwner(): boolean {
return this.itemData.user.id === this.$store.getters.selectedProject.ownerId;
}
public get itemToRender(): { [key: string]: string | string[] } {
if (!this.isMobile && !this.isTablet) return { name: this.itemData.name, date: this.itemData.localDate(), email: this.itemData.email };
// TODO: change after adding actions button to list item
return { name: this.itemData.name, email: this.itemData.email };
}
}
</script>

View File

@ -30,7 +30,7 @@
>
<template #head>
<th class="align-left">Name</th>
<th class="align-left">Date Added</th>
<th class="align-left date-added">Date Added</th>
<th class="align-left">Email</th>
</template>
<template #body>
@ -221,4 +221,11 @@ export default class ProjectMembersArea extends Vue {
}
}
}
@media screen and (max-width: 800px) and (min-width: 500px) {
.date-added {
display: none;
}
}
</style>

View File

@ -2,7 +2,7 @@
exports[` should render correctly 1`] = `
<tr class="owner">
<th class="icon"><label class="container"><input id="checkbox" disabled="disabled" type="checkbox" class="checkmark-input"> <span class="checkmark"></span></label></th>
<th class="icon select"><label class="container"><input id="checkbox" disabled="disabled" type="checkbox" class="checkmark-input"> <span class="checkmark"></span></label></th>
<th class="align-left data">
<p>testShortName</p>
</th>
@ -17,7 +17,7 @@ exports[` should render correctly 1`] = `
exports[` should render correctly with item row highlighted 1`] = `
<tr class="selected owner">
<th class="icon"><label class="container"><input id="checkbox" disabled="disabled" type="checkbox" class="checkmark-input"> <span class="checkmark"></span></label></th>
<th class="icon select"><label class="container"><input id="checkbox" disabled="disabled" type="checkbox" class="checkmark-input"> <span class="checkmark"></span></label></th>
<th class="align-left data">
<p>testShortName</p>
</th>