Files
dockge/frontend/src/components/StackListItem.vue
2023-12-26 04:12:44 +08:00

182 lines
4.1 KiB
Vue

<template>
<router-link :to="url" :class="{ 'dim' : !stack.isManagedByDockge }" class="item">
<Uptime :stack="stack" :fixed-width="true" class="me-2" />
<div class="title">
<span>{{ stackName }}</span>
<div v-if="$root.agentCount > 1" class="endpoint">{{ endpointDisplay }}</div>
</div>
</router-link>
</template>
<script>
import Uptime from "./Uptime.vue";
export default {
components: {
Uptime
},
props: {
/** Stack this represents */
stack: {
type: Object,
default: null,
},
/** If the user is in select mode */
isSelectMode: {
type: Boolean,
default: false,
},
/** How many ancestors are above this stack */
depth: {
type: Number,
default: 0,
},
/** Callback to determine if stack is selected */
isSelected: {
type: Function,
default: () => {}
},
/** Callback fired when stack is selected */
select: {
type: Function,
default: () => {}
},
/** Callback fired when stack is deselected */
deselect: {
type: Function,
default: () => {}
},
},
data() {
return {
isCollapsed: true,
};
},
computed: {
endpointDisplay() {
return this.$root.endpointDisplayFunction(this.stack.endpoint);
},
url() {
if (this.stack.endpoint) {
return `/compose/${this.stack.name}/${this.stack.endpoint}`;
} else {
return `/compose/${this.stack.name}`;
}
},
depthMargin() {
return {
marginLeft: `${31 * this.depth}px`,
};
},
stackName() {
return this.stack.name;
}
},
watch: {
isSelectMode() {
// TODO: Resize the heartbeat bar, but too slow
// this.$refs.heartbeatBar.resize();
}
},
beforeMount() {
},
methods: {
/**
* Changes the collapsed value of the current stack and saves
* it to local storage
* @returns {void}
*/
changeCollapsed() {
this.isCollapsed = !this.isCollapsed;
// Save collapsed value into local storage
let storage = window.localStorage.getItem("stackCollapsed");
let storageObject = {};
if (storage !== null) {
storageObject = JSON.parse(storage);
}
storageObject[`stack_${this.stack.id}`] = this.isCollapsed;
window.localStorage.setItem("stackCollapsed", JSON.stringify(storageObject));
},
/**
* Toggle selection of stack
* @returns {void}
*/
toggleSelection() {
if (this.isSelected(this.stack.id)) {
this.deselect(this.stack.id);
} else {
this.select(this.stack.id);
}
},
},
};
</script>
<style lang="scss" scoped>
@import "../styles/vars.scss";
.small-padding {
padding-left: 5px !important;
padding-right: 5px !important;
}
.collapse-padding {
padding-left: 8px !important;
padding-right: 2px !important;
}
.item {
text-decoration: none;
display: flex;
align-items: center;
min-height: 52px;
border-radius: 10px;
transition: all ease-in-out 0.15s;
width: 100%;
padding: 5px 8px;
&.disabled {
opacity: 0.3;
}
&:hover {
background-color: $highlight-white;
}
&.active {
background-color: #cdf8f4;
}
.title {
margin-top: -4px;
}
.endpoint {
font-size: 12px;
color: $dark-font-color3;
}
}
.collapsed {
transform: rotate(-90deg);
}
.animated {
transition: all 0.2s $easing-in;
}
.select-input-wrapper {
float: left;
margin-top: 15px;
margin-left: 3px;
margin-right: 10px;
padding-left: 4px;
position: relative;
z-index: 15;
}
.dim {
opacity: 0.5;
}
</style>