mirror of
https://github.com/louislam/dockge.git
synced 2025-07-08 02:07:00 +02:00
182 lines
4.1 KiB
Vue
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>
|