mirror of https://github.com/rancher/dashboard.git
290 lines
7.4 KiB
Vue
290 lines
7.4 KiB
Vue
<script>
|
|
import LazyImage from '@/components/LazyImage';
|
|
|
|
export default {
|
|
components: { LazyImage },
|
|
|
|
props: {
|
|
rows: {
|
|
type: Array,
|
|
required: true,
|
|
},
|
|
|
|
keyField: {
|
|
type: String,
|
|
default: 'key',
|
|
},
|
|
iconField: {
|
|
type: String,
|
|
default: 'icon',
|
|
},
|
|
nameField: {
|
|
type: String,
|
|
default: 'name',
|
|
},
|
|
descriptionField: {
|
|
type: String,
|
|
default: 'description',
|
|
},
|
|
sideLabelField: {
|
|
type: String,
|
|
default: 'sideLabel',
|
|
},
|
|
disabledField: {
|
|
type: String,
|
|
default: 'disabled',
|
|
},
|
|
|
|
noDataKey: {
|
|
type: String,
|
|
default: 'sortableTable.noRows',
|
|
},
|
|
|
|
colorFor: {
|
|
type: Function,
|
|
default() {
|
|
return (r, idx) => `color${ (idx % 8) + 1 }`;
|
|
},
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
isDisabled(idx) {
|
|
return this.rows[idx][this.disabledField] === true;
|
|
},
|
|
|
|
select(row, idx) {
|
|
if ( this.isDisabled(idx) ) {
|
|
return;
|
|
}
|
|
|
|
this.$emit('clicked', row, idx);
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="rows.length" class="grid">
|
|
<div
|
|
v-for="(r, idx) in rows"
|
|
:key="r[keyField]"
|
|
class="item"
|
|
:class="{'has-description': !!r[descriptionField], [colorFor(r, idx)]: true, disabled: r[disabledField] === true}"
|
|
@click="select(r, idx)"
|
|
>
|
|
<div class="side-label">
|
|
<label v-if="r[sideLabelField]">{{ r[sideLabelField] }}</label>
|
|
</div>
|
|
<div class="logo">
|
|
<LazyImage :src="r[iconField]" />
|
|
</div>
|
|
<h4 class="name">
|
|
{{ r[nameField] }}
|
|
</h4>
|
|
<div v-if="r[descriptionField]" class="description">
|
|
{{ r[descriptionField] }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else class="m-50 text-center">
|
|
<h1 v-t="noDataKey" />
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
$height: 110px;
|
|
$side: 15px;
|
|
$margin: 10px;
|
|
$logo: 60px;
|
|
|
|
.grid {
|
|
display: flex;
|
|
justify-content: flex-start;
|
|
flex-wrap: wrap;
|
|
margin: 0 -1*$margin;
|
|
|
|
@media only screen and (min-width: map-get($breakpoints, '--viewport-4')) {
|
|
.item {
|
|
width: 100%;
|
|
}
|
|
}
|
|
@media only screen and (min-width: map-get($breakpoints, '--viewport-7')) {
|
|
.item {
|
|
width: calc(50% - 2 * #{$margin});
|
|
}
|
|
}
|
|
@media only screen and (min-width: map-get($breakpoints, '--viewport-9')) {
|
|
.item {
|
|
width: calc(33.33333% - 2 * #{$margin});
|
|
}
|
|
}
|
|
@media only screen and (min-width: map-get($breakpoints, '--viewport-12')) {
|
|
.item {
|
|
width: calc(25% - 2 * #{$margin});
|
|
}
|
|
}
|
|
|
|
.item {
|
|
height: $height;
|
|
margin: $margin;
|
|
padding: $margin;
|
|
position: relative;
|
|
border-radius: calc( 1.5 * var(--border-radius));
|
|
|
|
&:hover:not(.disabled) {
|
|
box-shadow: 0 0 30px var(--shadow);
|
|
transition: box-shadow 0.1s ease-in-out;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.side-label {
|
|
transform: rotate(180deg);
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
bottom: 0;
|
|
min-width: calc(1.5 * var(--border-radius));
|
|
width: $side;
|
|
border-top-right-radius: calc( 1.5 * var(--border-radius));
|
|
border-bottom-right-radius: calc( 1.5 * var(--border-radius));
|
|
|
|
label {
|
|
text-align: center;
|
|
writing-mode: tb;
|
|
height: 100%;
|
|
padding: 0 2px;
|
|
display: block;
|
|
white-space: no-wrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
}
|
|
|
|
.logo {
|
|
text-align: center;
|
|
position: absolute;
|
|
left: $side+$margin;
|
|
top: ($height - $logo)/2;
|
|
width: $logo;
|
|
height: $logo;
|
|
border-radius: calc(2 * var(--border-radius));
|
|
overflow: hidden;
|
|
background-color: white;
|
|
|
|
img {
|
|
width: $logo - 4px;
|
|
height: $logo - 4px;
|
|
object-fit: contain;
|
|
position: relative;
|
|
top: 2px;
|
|
}
|
|
}
|
|
|
|
.side-label {
|
|
font-size: 10px;
|
|
}
|
|
|
|
&.rancher {
|
|
background: var(--app-rancher-bg);
|
|
|
|
.side-label {
|
|
background-color: var(--app-rancher-accent);
|
|
color: var(--app-rancher-accent-text);
|
|
}
|
|
&:hover:not(.disabled) {
|
|
background: var(--app-rancher-accent);
|
|
}
|
|
}
|
|
|
|
&.partner {
|
|
background: var(--app-partner-bg);
|
|
.side-label {
|
|
background-color: var(--app-partner-accent);
|
|
color: var(--app-partner-accent-text);
|
|
}
|
|
&:hover:not(.disabled) {
|
|
background: var(--app-partner-accent);
|
|
}
|
|
}
|
|
|
|
// @TODO figure out how to templatize these
|
|
&.color1 {
|
|
background: var(--app-color1-bg);
|
|
.side-label { background-color: var(--app-color1-accent); color: var(--app-color1-accent-text); }
|
|
&:hover:not(.disabled) { background: var(--app-color1-accent); }
|
|
}
|
|
&.color2 {
|
|
background: var(--app-color2-bg);
|
|
.side-label { background-color: var(--app-color2-accent); color: var(--app-color2-accent-text); }
|
|
&:hover:not(.disabled) { background: var(--app-color2-accent); }
|
|
}
|
|
&.color3 {
|
|
background: var(--app-color3-bg);
|
|
.side-label { background-color: var(--app-color3-accent); color: var(--app-color3-accent-text); }
|
|
&:hover:not(.disabled) { background: var(--app-color3-accent); }
|
|
}
|
|
&.color4 {
|
|
background: var(--app-color4-bg);
|
|
.side-label { background-color: var(--app-color4-accent); color: var(--app-color4-accent-text); }
|
|
&:hover:not(.disabled) { background: var(--app-color4-accent); }
|
|
}
|
|
&.color5 {
|
|
background: var(--app-color5-bg);
|
|
.side-label { background-color: var(--app-color5-accent); color: var(--app-color5-accent-text); }
|
|
&:hover:not(.disabled) { background: var(--app-color5-accent); }
|
|
}
|
|
&.color6 {
|
|
background: var(--app-color6-bg);
|
|
.side-label { background-color: var(--app-color6-accent); color: var(--app-color6-accent-text); }
|
|
&:hover:not(.disabled) { background: var(--app-color6-accent); }
|
|
}
|
|
&.color7 {
|
|
background: var(--app-color7-bg);
|
|
.side-label { background-color: var(--app-color7-accent); color: var(--app-color7-accent-text); }
|
|
&:hover:not(.disabled) { background: var(--app-color7-accent); }
|
|
}
|
|
&.color8 {
|
|
background: var(--app-color8-bg);
|
|
.side-label { background-color: var(--app-color8-accent); color: var(--app-color8-accent-text); }
|
|
&:hover:not(.disabled) { background: var(--app-color8-accent); }
|
|
}
|
|
|
|
&:hover:not(.disabled) {
|
|
background-position: right center;
|
|
}
|
|
|
|
.name {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
line-height: $height - (2 * $margin);
|
|
margin: 0;
|
|
margin-left: $side+$logo+$margin;
|
|
}
|
|
|
|
&.has-description .name {
|
|
margin-top: $margin;
|
|
line-height: initial;
|
|
}
|
|
|
|
.description {
|
|
margin-top: $margin;
|
|
margin-left: $side+$logo+$margin;
|
|
margin-right: $margin;
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 3;
|
|
line-clamp: 3;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
color: var(--text-muted);
|
|
}
|
|
}
|
|
|
|
.disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
}
|
|
</style>
|