wip
This commit is contained in:
		
							parent
							
								
									b4a874766e
								
							
						
					
					
						commit
						bc17a0b2cb
					
				
					 13 changed files with 618 additions and 539 deletions
				
			
		| 
						 | 
					@ -1,6 +0,0 @@
 | 
				
			||||||
export default (bytes, digits = 0) => {
 | 
					 | 
				
			||||||
	const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
 | 
					 | 
				
			||||||
	if (bytes == 0) return '0Byte';
 | 
					 | 
				
			||||||
	const i = Math.floor(Math.log(bytes) / Math.log(1024));
 | 
					 | 
				
			||||||
	return (bytes / Math.pow(1024, i)).toFixed(digits).replace(/\.0+$/, '') + sizes[i];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,533 +0,0 @@
 | 
				
			||||||
<mk-server-home-widget data-melt={ data.design == 2 }>
 | 
					 | 
				
			||||||
	<template v-if="data.design == 0">
 | 
					 | 
				
			||||||
		<p class="title">%fa:server%%i18n:desktop.tags.mk-server-home-widget.title%</p>
 | 
					 | 
				
			||||||
		<button @click="toggle" title="%i18n:desktop.tags.mk-server-home-widget.toggle%">%fa:sort%</button>
 | 
					 | 
				
			||||||
	</template>
 | 
					 | 
				
			||||||
	<p class="initializing" v-if="initializing">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-cpu-and-memory-usage v-if="!initializing" show={ data.view == 0 } connection={ connection }/>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-cpu v-if="!initializing" show={ data.view == 1 } connection={ connection } meta={ meta }/>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-memory v-if="!initializing" show={ data.view == 2 } connection={ connection }/>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-disk v-if="!initializing" show={ data.view == 3 } connection={ connection }/>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-uptimes v-if="!initializing" show={ data.view == 4 } connection={ connection }/>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-info v-if="!initializing" show={ data.view == 5 } connection={ connection } meta={ meta }/>
 | 
					 | 
				
			||||||
	<style lang="stylus" scoped>
 | 
					 | 
				
			||||||
		:scope
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
			background #fff
 | 
					 | 
				
			||||||
			border solid 1px rgba(0, 0, 0, 0.075)
 | 
					 | 
				
			||||||
			border-radius 6px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			&[data-melt]
 | 
					 | 
				
			||||||
				background transparent !important
 | 
					 | 
				
			||||||
				border none !important
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> .title
 | 
					 | 
				
			||||||
				z-index 1
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				padding 0 16px
 | 
					 | 
				
			||||||
				line-height 42px
 | 
					 | 
				
			||||||
				font-size 0.9em
 | 
					 | 
				
			||||||
				font-weight bold
 | 
					 | 
				
			||||||
				color #888
 | 
					 | 
				
			||||||
				box-shadow 0 1px rgba(0, 0, 0, 0.07)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> [data-fa]
 | 
					 | 
				
			||||||
					margin-right 4px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> button
 | 
					 | 
				
			||||||
				position absolute
 | 
					 | 
				
			||||||
				z-index 2
 | 
					 | 
				
			||||||
				top 0
 | 
					 | 
				
			||||||
				right 0
 | 
					 | 
				
			||||||
				padding 0
 | 
					 | 
				
			||||||
				width 42px
 | 
					 | 
				
			||||||
				font-size 0.9em
 | 
					 | 
				
			||||||
				line-height 42px
 | 
					 | 
				
			||||||
				color #ccc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&:hover
 | 
					 | 
				
			||||||
					color #aaa
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&:active
 | 
					 | 
				
			||||||
					color #999
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> .initializing
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				padding 16px
 | 
					 | 
				
			||||||
				text-align center
 | 
					 | 
				
			||||||
				color #aaa
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> [data-fa]
 | 
					 | 
				
			||||||
					margin-right 4px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	</style>
 | 
					 | 
				
			||||||
	<script lang="typescript">
 | 
					 | 
				
			||||||
		this.mixin('os');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.data = {
 | 
					 | 
				
			||||||
			view: 0,
 | 
					 | 
				
			||||||
			design: 0
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.mixin('widget');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.mixin('server-stream');
 | 
					 | 
				
			||||||
		this.connection = this.serverStream.getConnection();
 | 
					 | 
				
			||||||
		this.connectionId = this.serverStream.use();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.initializing = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('mount', () => {
 | 
					 | 
				
			||||||
			this.mios.getMeta().then(meta => {
 | 
					 | 
				
			||||||
				this.update({
 | 
					 | 
				
			||||||
					initializing: false,
 | 
					 | 
				
			||||||
					meta
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('unmount', () => {
 | 
					 | 
				
			||||||
			this.serverStream.dispose(this.connectionId);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.toggle = () => {
 | 
					 | 
				
			||||||
			this.data.view++;
 | 
					 | 
				
			||||||
			if (this.data.view == 6) this.data.view = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Save widget state
 | 
					 | 
				
			||||||
			this.save();
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.func = () => {
 | 
					 | 
				
			||||||
			if (++this.data.design == 3) this.data.design = 0;
 | 
					 | 
				
			||||||
			this.save();
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	</script>
 | 
					 | 
				
			||||||
</mk-server-home-widget>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<mk-server-home-widget-cpu-and-memory-usage>
 | 
					 | 
				
			||||||
	<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none">
 | 
					 | 
				
			||||||
		<defs>
 | 
					 | 
				
			||||||
			<linearGradient id={ cpuGradientId } x1="0" x2="0" y1="1" y2="0">
 | 
					 | 
				
			||||||
				<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
				<stop offset="33%" stop-color="hsl(120, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
				<stop offset="66%" stop-color="hsl(60, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
				<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
			</linearGradient>
 | 
					 | 
				
			||||||
			<mask id={ cpuMaskId } x="0" y="0" riot-width={ viewBoxX } riot-height={ viewBoxY }>
 | 
					 | 
				
			||||||
				<polygon
 | 
					 | 
				
			||||||
					riot-points={ cpuPolygonPoints }
 | 
					 | 
				
			||||||
					fill="#fff"
 | 
					 | 
				
			||||||
					fill-opacity="0.5"/>
 | 
					 | 
				
			||||||
				<polyline
 | 
					 | 
				
			||||||
					riot-points={ cpuPolylinePoints }
 | 
					 | 
				
			||||||
					fill="none"
 | 
					 | 
				
			||||||
					stroke="#fff"
 | 
					 | 
				
			||||||
					stroke-width="1"/>
 | 
					 | 
				
			||||||
			</mask>
 | 
					 | 
				
			||||||
		</defs>
 | 
					 | 
				
			||||||
		<rect
 | 
					 | 
				
			||||||
			x="-1" y="-1"
 | 
					 | 
				
			||||||
			riot-width={ viewBoxX + 2 } riot-height={ viewBoxY + 2 }
 | 
					 | 
				
			||||||
			style="stroke: none; fill: url(#{ cpuGradientId }); mask: url(#{ cpuMaskId })"/>
 | 
					 | 
				
			||||||
		<text x="1" y="5">CPU <tspan>{ cpuP }%</tspan></text>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none">
 | 
					 | 
				
			||||||
		<defs>
 | 
					 | 
				
			||||||
			<linearGradient id={ memGradientId } x1="0" x2="0" y1="1" y2="0">
 | 
					 | 
				
			||||||
				<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
				<stop offset="33%" stop-color="hsl(120, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
				<stop offset="66%" stop-color="hsl(60, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
				<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
 | 
					 | 
				
			||||||
			</linearGradient>
 | 
					 | 
				
			||||||
			<mask id={ memMaskId } x="0" y="0" riot-width={ viewBoxX } riot-height={ viewBoxY }>
 | 
					 | 
				
			||||||
				<polygon
 | 
					 | 
				
			||||||
					riot-points={ memPolygonPoints }
 | 
					 | 
				
			||||||
					fill="#fff"
 | 
					 | 
				
			||||||
					fill-opacity="0.5"/>
 | 
					 | 
				
			||||||
				<polyline
 | 
					 | 
				
			||||||
					riot-points={ memPolylinePoints }
 | 
					 | 
				
			||||||
					fill="none"
 | 
					 | 
				
			||||||
					stroke="#fff"
 | 
					 | 
				
			||||||
					stroke-width="1"/>
 | 
					 | 
				
			||||||
			</mask>
 | 
					 | 
				
			||||||
		</defs>
 | 
					 | 
				
			||||||
		<rect
 | 
					 | 
				
			||||||
			x="-1" y="-1"
 | 
					 | 
				
			||||||
			riot-width={ viewBoxX + 2 } riot-height={ viewBoxY + 2 }
 | 
					 | 
				
			||||||
			style="stroke: none; fill: url(#{ memGradientId }); mask: url(#{ memMaskId })"/>
 | 
					 | 
				
			||||||
		<text x="1" y="5">MEM <tspan>{ memP }%</tspan></text>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	<style lang="stylus" scoped>
 | 
					 | 
				
			||||||
		:scope
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> svg
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				padding 10px
 | 
					 | 
				
			||||||
				width 50%
 | 
					 | 
				
			||||||
				float left
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&:first-child
 | 
					 | 
				
			||||||
					padding-right 5px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&:last-child
 | 
					 | 
				
			||||||
					padding-left 5px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> text
 | 
					 | 
				
			||||||
					font-size 5px
 | 
					 | 
				
			||||||
					fill rgba(0, 0, 0, 0.55)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					> tspan
 | 
					 | 
				
			||||||
						opacity 0.5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			&:after
 | 
					 | 
				
			||||||
				content ""
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				clear both
 | 
					 | 
				
			||||||
	</style>
 | 
					 | 
				
			||||||
	<script lang="typescript">
 | 
					 | 
				
			||||||
		import uuid from 'uuid';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.viewBoxX = 50;
 | 
					 | 
				
			||||||
		this.viewBoxY = 30;
 | 
					 | 
				
			||||||
		this.stats = [];
 | 
					 | 
				
			||||||
		this.connection = this.opts.connection;
 | 
					 | 
				
			||||||
		this.cpuGradientId = uuid();
 | 
					 | 
				
			||||||
		this.cpuMaskId = uuid();
 | 
					 | 
				
			||||||
		this.memGradientId = uuid();
 | 
					 | 
				
			||||||
		this.memMaskId = uuid();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('mount', () => {
 | 
					 | 
				
			||||||
			this.connection.on('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('unmount', () => {
 | 
					 | 
				
			||||||
			this.connection.off('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.onStats = stats => {
 | 
					 | 
				
			||||||
			stats.mem.used = stats.mem.total - stats.mem.free;
 | 
					 | 
				
			||||||
			this.stats.push(stats);
 | 
					 | 
				
			||||||
			if (this.stats.length > 50) this.stats.shift();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			const cpuPolylinePoints = this.stats.map((s, i) => `${this.viewBoxX - ((this.stats.length - 1) - i)},${(1 - s.cpu_usage) * this.viewBoxY}`).join(' ');
 | 
					 | 
				
			||||||
			const memPolylinePoints = this.stats.map((s, i) => `${this.viewBoxX - ((this.stats.length - 1) - i)},${(1 - (s.mem.used / s.mem.total)) * this.viewBoxY}`).join(' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			const cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ cpuPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
 | 
					 | 
				
			||||||
			const memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ memPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			const cpuP = (stats.cpu_usage * 100).toFixed(0);
 | 
					 | 
				
			||||||
			const memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.update({
 | 
					 | 
				
			||||||
				cpuPolylinePoints,
 | 
					 | 
				
			||||||
				memPolylinePoints,
 | 
					 | 
				
			||||||
				cpuPolygonPoints,
 | 
					 | 
				
			||||||
				memPolygonPoints,
 | 
					 | 
				
			||||||
				cpuP,
 | 
					 | 
				
			||||||
				memP
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	</script>
 | 
					 | 
				
			||||||
</mk-server-home-widget-cpu-and-memory-usage>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<mk-server-home-widget-cpu>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-pie ref="pie"/>
 | 
					 | 
				
			||||||
	<div>
 | 
					 | 
				
			||||||
		<p>%fa:microchip%CPU</p>
 | 
					 | 
				
			||||||
		<p>{ cores } Cores</p>
 | 
					 | 
				
			||||||
		<p>{ model }</p>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
	<style lang="stylus" scoped>
 | 
					 | 
				
			||||||
		:scope
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> mk-server-home-widget-pie
 | 
					 | 
				
			||||||
				padding 10px
 | 
					 | 
				
			||||||
				height 100px
 | 
					 | 
				
			||||||
				float left
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> div
 | 
					 | 
				
			||||||
				float left
 | 
					 | 
				
			||||||
				width calc(100% - 100px)
 | 
					 | 
				
			||||||
				padding 10px 10px 10px 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> p
 | 
					 | 
				
			||||||
					margin 0
 | 
					 | 
				
			||||||
					font-size 12px
 | 
					 | 
				
			||||||
					color #505050
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					&:first-child
 | 
					 | 
				
			||||||
						font-weight bold
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						> [data-fa]
 | 
					 | 
				
			||||||
							margin-right 4px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			&:after
 | 
					 | 
				
			||||||
				content ""
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				clear both
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	</style>
 | 
					 | 
				
			||||||
	<script lang="typescript">
 | 
					 | 
				
			||||||
		this.cores = this.opts.meta.cpu.cores;
 | 
					 | 
				
			||||||
		this.model = this.opts.meta.cpu.model;
 | 
					 | 
				
			||||||
		this.connection = this.opts.connection;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('mount', () => {
 | 
					 | 
				
			||||||
			this.connection.on('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('unmount', () => {
 | 
					 | 
				
			||||||
			this.connection.off('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.onStats = stats => {
 | 
					 | 
				
			||||||
			this.$refs.pie.render(stats.cpu_usage);
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	</script>
 | 
					 | 
				
			||||||
</mk-server-home-widget-cpu>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<mk-server-home-widget-memory>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-pie ref="pie"/>
 | 
					 | 
				
			||||||
	<div>
 | 
					 | 
				
			||||||
		<p>%fa:flask%Memory</p>
 | 
					 | 
				
			||||||
		<p>Total: { bytesToSize(total, 1) }</p>
 | 
					 | 
				
			||||||
		<p>Used: { bytesToSize(used, 1) }</p>
 | 
					 | 
				
			||||||
		<p>Free: { bytesToSize(free, 1) }</p>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
	<style lang="stylus" scoped>
 | 
					 | 
				
			||||||
		:scope
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> mk-server-home-widget-pie
 | 
					 | 
				
			||||||
				padding 10px
 | 
					 | 
				
			||||||
				height 100px
 | 
					 | 
				
			||||||
				float left
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> div
 | 
					 | 
				
			||||||
				float left
 | 
					 | 
				
			||||||
				width calc(100% - 100px)
 | 
					 | 
				
			||||||
				padding 10px 10px 10px 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> p
 | 
					 | 
				
			||||||
					margin 0
 | 
					 | 
				
			||||||
					font-size 12px
 | 
					 | 
				
			||||||
					color #505050
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					&:first-child
 | 
					 | 
				
			||||||
						font-weight bold
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						> [data-fa]
 | 
					 | 
				
			||||||
							margin-right 4px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			&:after
 | 
					 | 
				
			||||||
				content ""
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				clear both
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	</style>
 | 
					 | 
				
			||||||
	<script lang="typescript">
 | 
					 | 
				
			||||||
		import bytesToSize from '../../../common/scripts/bytes-to-size';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.connection = this.opts.connection;
 | 
					 | 
				
			||||||
		this.bytesToSize = bytesToSize;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('mount', () => {
 | 
					 | 
				
			||||||
			this.connection.on('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('unmount', () => {
 | 
					 | 
				
			||||||
			this.connection.off('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.onStats = stats => {
 | 
					 | 
				
			||||||
			stats.mem.used = stats.mem.total - stats.mem.free;
 | 
					 | 
				
			||||||
			this.$refs.pie.render(stats.mem.used / stats.mem.total);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.update({
 | 
					 | 
				
			||||||
				total: stats.mem.total,
 | 
					 | 
				
			||||||
				used: stats.mem.used,
 | 
					 | 
				
			||||||
				free: stats.mem.free
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	</script>
 | 
					 | 
				
			||||||
</mk-server-home-widget-memory>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<mk-server-home-widget-disk>
 | 
					 | 
				
			||||||
	<mk-server-home-widget-pie ref="pie"/>
 | 
					 | 
				
			||||||
	<div>
 | 
					 | 
				
			||||||
		<p>%fa:R hdd%Storage</p>
 | 
					 | 
				
			||||||
		<p>Total: { bytesToSize(total, 1) }</p>
 | 
					 | 
				
			||||||
		<p>Available: { bytesToSize(available, 1) }</p>
 | 
					 | 
				
			||||||
		<p>Used: { bytesToSize(used, 1) }</p>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
	<style lang="stylus" scoped>
 | 
					 | 
				
			||||||
		:scope
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> mk-server-home-widget-pie
 | 
					 | 
				
			||||||
				padding 10px
 | 
					 | 
				
			||||||
				height 100px
 | 
					 | 
				
			||||||
				float left
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> div
 | 
					 | 
				
			||||||
				float left
 | 
					 | 
				
			||||||
				width calc(100% - 100px)
 | 
					 | 
				
			||||||
				padding 10px 10px 10px 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> p
 | 
					 | 
				
			||||||
					margin 0
 | 
					 | 
				
			||||||
					font-size 12px
 | 
					 | 
				
			||||||
					color #505050
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					&:first-child
 | 
					 | 
				
			||||||
						font-weight bold
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						> [data-fa]
 | 
					 | 
				
			||||||
							margin-right 4px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			&:after
 | 
					 | 
				
			||||||
				content ""
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				clear both
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	</style>
 | 
					 | 
				
			||||||
	<script lang="typescript">
 | 
					 | 
				
			||||||
		import bytesToSize from '../../../common/scripts/bytes-to-size';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.connection = this.opts.connection;
 | 
					 | 
				
			||||||
		this.bytesToSize = bytesToSize;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('mount', () => {
 | 
					 | 
				
			||||||
			this.connection.on('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('unmount', () => {
 | 
					 | 
				
			||||||
			this.connection.off('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.onStats = stats => {
 | 
					 | 
				
			||||||
			stats.disk.used = stats.disk.total - stats.disk.free;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.$refs.pie.render(stats.disk.used / stats.disk.total);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.update({
 | 
					 | 
				
			||||||
				total: stats.disk.total,
 | 
					 | 
				
			||||||
				used: stats.disk.used,
 | 
					 | 
				
			||||||
				available: stats.disk.available
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	</script>
 | 
					 | 
				
			||||||
</mk-server-home-widget-disk>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<mk-server-home-widget-uptimes>
 | 
					 | 
				
			||||||
	<p>Uptimes</p>
 | 
					 | 
				
			||||||
	<p>Process: { process ? process.toFixed(0) : '---' }s</p>
 | 
					 | 
				
			||||||
	<p>OS: { os ? os.toFixed(0) : '---' }s</p>
 | 
					 | 
				
			||||||
	<style lang="stylus" scoped>
 | 
					 | 
				
			||||||
		:scope
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
			padding 10px 14px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> p
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				font-size 12px
 | 
					 | 
				
			||||||
				color #505050
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				&:first-child
 | 
					 | 
				
			||||||
					font-weight bold
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	</style>
 | 
					 | 
				
			||||||
	<script lang="typescript">
 | 
					 | 
				
			||||||
		this.connection = this.opts.connection;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('mount', () => {
 | 
					 | 
				
			||||||
			this.connection.on('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('unmount', () => {
 | 
					 | 
				
			||||||
			this.connection.off('stats', this.onStats);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.onStats = stats => {
 | 
					 | 
				
			||||||
			this.update({
 | 
					 | 
				
			||||||
				process: stats.process_uptime,
 | 
					 | 
				
			||||||
				os: stats.os_uptime
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	</script>
 | 
					 | 
				
			||||||
</mk-server-home-widget-uptimes>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<mk-server-home-widget-info>
 | 
					 | 
				
			||||||
	<p>Maintainer: <b>{ meta.maintainer }</b></p>
 | 
					 | 
				
			||||||
	<p>Machine: { meta.machine }</p>
 | 
					 | 
				
			||||||
	<p>Node: { meta.node }</p>
 | 
					 | 
				
			||||||
	<style lang="stylus" scoped>
 | 
					 | 
				
			||||||
		:scope
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
			padding 10px 14px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> p
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				font-size 12px
 | 
					 | 
				
			||||||
				color #505050
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	</style>
 | 
					 | 
				
			||||||
	<script lang="typescript">
 | 
					 | 
				
			||||||
		this.meta = this.opts.meta;
 | 
					 | 
				
			||||||
	</script>
 | 
					 | 
				
			||||||
</mk-server-home-widget-info>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<mk-server-home-widget-pie>
 | 
					 | 
				
			||||||
	<svg viewBox="0 0 1 1" preserveAspectRatio="none">
 | 
					 | 
				
			||||||
		<circle
 | 
					 | 
				
			||||||
			riot-r={ r }
 | 
					 | 
				
			||||||
			cx="50%" cy="50%"
 | 
					 | 
				
			||||||
			fill="none"
 | 
					 | 
				
			||||||
			stroke-width="0.1"
 | 
					 | 
				
			||||||
			stroke="rgba(0, 0, 0, 0.05)"/>
 | 
					 | 
				
			||||||
		<circle
 | 
					 | 
				
			||||||
			riot-r={ r }
 | 
					 | 
				
			||||||
			cx="50%" cy="50%"
 | 
					 | 
				
			||||||
			riot-stroke-dasharray={ Math.PI * (r * 2) }
 | 
					 | 
				
			||||||
			riot-stroke-dashoffset={ strokeDashoffset }
 | 
					 | 
				
			||||||
			fill="none"
 | 
					 | 
				
			||||||
			stroke-width="0.1"
 | 
					 | 
				
			||||||
			riot-stroke={ color }/>
 | 
					 | 
				
			||||||
		<text x="50%" y="50%" dy="0.05" text-anchor="middle">{ (p * 100).toFixed(0) }%</text>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	<style lang="stylus" scoped>
 | 
					 | 
				
			||||||
		:scope
 | 
					 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> svg
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				height 100%
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> circle
 | 
					 | 
				
			||||||
					transform-origin center
 | 
					 | 
				
			||||||
					transform rotate(-90deg)
 | 
					 | 
				
			||||||
					transition stroke-dashoffset 0.5s ease
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				> text
 | 
					 | 
				
			||||||
					font-size 0.15px
 | 
					 | 
				
			||||||
					fill rgba(0, 0, 0, 0.6)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	</style>
 | 
					 | 
				
			||||||
	<script lang="typescript">
 | 
					 | 
				
			||||||
		this.r = 0.4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.render = p => {
 | 
					 | 
				
			||||||
			const color = `hsl(${180 - (p * 180)}, 80%, 70%)`;
 | 
					 | 
				
			||||||
			const strokeDashoffset = (1 - p) * (Math.PI * (this.r * 2));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.update({
 | 
					 | 
				
			||||||
				p,
 | 
					 | 
				
			||||||
				color,
 | 
					 | 
				
			||||||
				strokeDashoffset
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	</script>
 | 
					 | 
				
			||||||
</mk-server-home-widget-pie>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,127 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="cpu-memory">
 | 
				
			||||||
 | 
						<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`" preserveAspectRatio="none">
 | 
				
			||||||
 | 
							<defs>
 | 
				
			||||||
 | 
								<linearGradient :id="cpuGradientId" x1="0" x2="0" y1="1" y2="0">
 | 
				
			||||||
 | 
									<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
									<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
								</linearGradient>
 | 
				
			||||||
 | 
								<mask :id="cpuMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
 | 
				
			||||||
 | 
									<polygon
 | 
				
			||||||
 | 
										:points="cpuPolygonPoints"
 | 
				
			||||||
 | 
										fill="#fff"
 | 
				
			||||||
 | 
										fill-opacity="0.5"/>
 | 
				
			||||||
 | 
									<polyline
 | 
				
			||||||
 | 
										:points="cpuPolylinePoints"
 | 
				
			||||||
 | 
										fill="none"
 | 
				
			||||||
 | 
										stroke="#fff"
 | 
				
			||||||
 | 
										stroke-width="1"/>
 | 
				
			||||||
 | 
								</mask>
 | 
				
			||||||
 | 
							</defs>
 | 
				
			||||||
 | 
							<rect
 | 
				
			||||||
 | 
								x="-1" y="-1"
 | 
				
			||||||
 | 
								:width="viewBoxX + 2" :height="viewBoxY + 2"
 | 
				
			||||||
 | 
								:style="`stroke: none; fill: url(#${ cpuGradientId }); mask: url(#${ cpuMaskId })`"/>
 | 
				
			||||||
 | 
							<text x="1" y="5">CPU <tspan>{{ cpuP }}%</tspan></text>
 | 
				
			||||||
 | 
						</svg>
 | 
				
			||||||
 | 
						<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`" preserveAspectRatio="none">
 | 
				
			||||||
 | 
							<defs>
 | 
				
			||||||
 | 
								<linearGradient :id="memGradientId" x1="0" x2="0" y1="1" y2="0">
 | 
				
			||||||
 | 
									<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
									<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
								</linearGradient>
 | 
				
			||||||
 | 
								<mask :id="memMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
 | 
				
			||||||
 | 
									<polygon
 | 
				
			||||||
 | 
										:points="memPolygonPoints"
 | 
				
			||||||
 | 
										fill="#fff"
 | 
				
			||||||
 | 
										fill-opacity="0.5"/>
 | 
				
			||||||
 | 
									<polyline
 | 
				
			||||||
 | 
										:points="memPolylinePoints"
 | 
				
			||||||
 | 
										fill="none"
 | 
				
			||||||
 | 
										stroke="#fff"
 | 
				
			||||||
 | 
										stroke-width="1"/>
 | 
				
			||||||
 | 
								</mask>
 | 
				
			||||||
 | 
							</defs>
 | 
				
			||||||
 | 
							<rect
 | 
				
			||||||
 | 
								x="-1" y="-1"
 | 
				
			||||||
 | 
								:width="viewBoxX + 2" :height="viewBoxY + 2"
 | 
				
			||||||
 | 
								:style="`stroke: none; fill: url(#${ memGradientId }); mask: url(#${ memMaskId })`"/>
 | 
				
			||||||
 | 
							<text x="1" y="5">MEM <tspan>{{ memP }}%</tspan></text>
 | 
				
			||||||
 | 
						</svg>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					import uuid from 'uuid';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: ['connection'],
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								viewBoxX: 50,
 | 
				
			||||||
 | 
								viewBoxY: 30,
 | 
				
			||||||
 | 
								stats: [],
 | 
				
			||||||
 | 
								cpuGradientId: uuid(),
 | 
				
			||||||
 | 
								cpuMaskId: uuid(),
 | 
				
			||||||
 | 
								memGradientId: uuid(),
 | 
				
			||||||
 | 
								memMaskId: uuid(),
 | 
				
			||||||
 | 
								cpuPolylinePoints: '',
 | 
				
			||||||
 | 
								memPolylinePoints: '',
 | 
				
			||||||
 | 
								cpuPolygonPoints: '',
 | 
				
			||||||
 | 
								memPolygonPoints: '',
 | 
				
			||||||
 | 
								cpuP: '',
 | 
				
			||||||
 | 
								memP: ''
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						mounted() {
 | 
				
			||||||
 | 
							this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						beforeDestroy() {
 | 
				
			||||||
 | 
							this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							onStats(stats) {
 | 
				
			||||||
 | 
								stats.mem.used = stats.mem.total - stats.mem.free;
 | 
				
			||||||
 | 
								this.stats.push(stats);
 | 
				
			||||||
 | 
								if (this.stats.length > 50) this.stats.shift();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.cpuPolylinePoints = this.stats.map((s, i) => `${this.viewBoxX - ((this.stats.length - 1) - i)},${(1 - s.cpu_usage) * this.viewBoxY}`).join(' ');
 | 
				
			||||||
 | 
								this.memPolylinePoints = this.stats.map((s, i) => `${this.viewBoxX - ((this.stats.length - 1) - i)},${(1 - (s.mem.used / s.mem.total)) * this.viewBoxY}`).join(' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ this.cpuPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
 | 
				
			||||||
 | 
								this.memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ this.memPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.cpuP = (stats.cpu_usage * 100).toFixed(0);
 | 
				
			||||||
 | 
								this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					.cpu-memory
 | 
				
			||||||
 | 
						> svg
 | 
				
			||||||
 | 
							display block
 | 
				
			||||||
 | 
							padding 10px
 | 
				
			||||||
 | 
							width 50%
 | 
				
			||||||
 | 
							float left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:first-child
 | 
				
			||||||
 | 
								padding-right 5px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:last-child
 | 
				
			||||||
 | 
								padding-left 5px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> text
 | 
				
			||||||
 | 
								font-size 5px
 | 
				
			||||||
 | 
								fill rgba(0, 0, 0, 0.55)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> tspan
 | 
				
			||||||
 | 
									opacity 0.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&:after
 | 
				
			||||||
 | 
							content ""
 | 
				
			||||||
 | 
							display block
 | 
				
			||||||
 | 
							clear both
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										68
									
								
								src/web/app/desktop/views/components/widgets/server.cpu.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/web/app/desktop/views/components/widgets/server.cpu.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,68 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="cpu">
 | 
				
			||||||
 | 
						<x-pie class="pie" :value="usage"/>
 | 
				
			||||||
 | 
						<div>
 | 
				
			||||||
 | 
							<p>%fa:microchip%CPU</p>
 | 
				
			||||||
 | 
							<p>{{ cores }} Cores</p>
 | 
				
			||||||
 | 
							<p>{{ model }}</p>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					import XPie from './server.pie.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						components: {
 | 
				
			||||||
 | 
							'x-pie': XPie
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						props: ['connection', 'meta'],
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								usage: 0
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						mounted() {
 | 
				
			||||||
 | 
							this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						beforeDestroy() {
 | 
				
			||||||
 | 
							this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							onStats(stats) {
 | 
				
			||||||
 | 
								this.usage = stats.cpu_usage;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					.cpu
 | 
				
			||||||
 | 
						> .pie
 | 
				
			||||||
 | 
							padding 10px
 | 
				
			||||||
 | 
							height 100px
 | 
				
			||||||
 | 
							float left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> div
 | 
				
			||||||
 | 
							float left
 | 
				
			||||||
 | 
							width calc(100% - 100px)
 | 
				
			||||||
 | 
							padding 10px 10px 10px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> p
 | 
				
			||||||
 | 
								margin 0
 | 
				
			||||||
 | 
								font-size 12px
 | 
				
			||||||
 | 
								color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:first-child
 | 
				
			||||||
 | 
									font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> [data-fa]
 | 
				
			||||||
 | 
										margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&:after
 | 
				
			||||||
 | 
							content ""
 | 
				
			||||||
 | 
							display block
 | 
				
			||||||
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										76
									
								
								src/web/app/desktop/views/components/widgets/server.disk.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/web/app/desktop/views/components/widgets/server.disk.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,76 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="disk">
 | 
				
			||||||
 | 
						<x-pie class="pie" :value="usage"/>
 | 
				
			||||||
 | 
						<div>
 | 
				
			||||||
 | 
							<p>%fa:R hdd%Storage</p>
 | 
				
			||||||
 | 
							<p>Total: {{ total | bytes(1) }}</p>
 | 
				
			||||||
 | 
							<p>Available: {{ available | bytes(1) }}</p>
 | 
				
			||||||
 | 
							<p>Used: {{ used | bytes(1) }}</p>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					import XPie from './server.pie.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						components: {
 | 
				
			||||||
 | 
							'x-pie': XPie
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						props: ['connection'],
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								usage: 0,
 | 
				
			||||||
 | 
								total: 0,
 | 
				
			||||||
 | 
								used: 0,
 | 
				
			||||||
 | 
								available: 0
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						mounted() {
 | 
				
			||||||
 | 
							this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						beforeDestroy() {
 | 
				
			||||||
 | 
							this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							onStats(stats) {
 | 
				
			||||||
 | 
								stats.disk.used = stats.disk.total - stats.disk.free;
 | 
				
			||||||
 | 
								this.usage = stats.disk.used / stats.disk.total;
 | 
				
			||||||
 | 
								this.total = stats.disk.total;
 | 
				
			||||||
 | 
								this.used = stats.disk.used;
 | 
				
			||||||
 | 
								this.available = stats.disk.available;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					.disk
 | 
				
			||||||
 | 
						> .pie
 | 
				
			||||||
 | 
							padding 10px
 | 
				
			||||||
 | 
							height 100px
 | 
				
			||||||
 | 
							float left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> div
 | 
				
			||||||
 | 
							float left
 | 
				
			||||||
 | 
							width calc(100% - 100px)
 | 
				
			||||||
 | 
							padding 10px 10px 10px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> p
 | 
				
			||||||
 | 
								margin 0
 | 
				
			||||||
 | 
								font-size 12px
 | 
				
			||||||
 | 
								color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:first-child
 | 
				
			||||||
 | 
									font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> [data-fa]
 | 
				
			||||||
 | 
										margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&:after
 | 
				
			||||||
 | 
							content ""
 | 
				
			||||||
 | 
							display block
 | 
				
			||||||
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										25
									
								
								src/web/app/desktop/views/components/widgets/server.info.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/web/app/desktop/views/components/widgets/server.info.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="info">
 | 
				
			||||||
 | 
						<p>Maintainer: <b>{{ meta.maintainer }}</b></p>
 | 
				
			||||||
 | 
						<p>Machine: {{ meta.machine }}</p>
 | 
				
			||||||
 | 
						<p>Node: {{ meta.node }}</p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: ['meta']
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="info" scoped>
 | 
				
			||||||
 | 
					.uptimes
 | 
				
			||||||
 | 
						padding 10px 14px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> p
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
							font-size 12px
 | 
				
			||||||
 | 
							color #505050
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,76 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="memory">
 | 
				
			||||||
 | 
						<x-pie class="pie" :value="usage"/>
 | 
				
			||||||
 | 
						<div>
 | 
				
			||||||
 | 
							<p>%fa:flask%Memory</p>
 | 
				
			||||||
 | 
							<p>Total: {{ total | bytes(1) }}</p>
 | 
				
			||||||
 | 
							<p>Used: {{ used | bytes(1) }}</p>
 | 
				
			||||||
 | 
							<p>Free: {{ free | bytes(1) }}</p>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					import XPie from './server.pie.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						components: {
 | 
				
			||||||
 | 
							'x-pie': XPie
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						props: ['connection'],
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								usage: 0,
 | 
				
			||||||
 | 
								total: 0,
 | 
				
			||||||
 | 
								used: 0,
 | 
				
			||||||
 | 
								free: 0
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						mounted() {
 | 
				
			||||||
 | 
							this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						beforeDestroy() {
 | 
				
			||||||
 | 
							this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							onStats(stats) {
 | 
				
			||||||
 | 
								stats.mem.used = stats.mem.total - stats.mem.free;
 | 
				
			||||||
 | 
								this.usage = stats.mem.used / stats.mem.total;
 | 
				
			||||||
 | 
								this.total = stats.mem.total;
 | 
				
			||||||
 | 
								this.used = stats.mem.used;
 | 
				
			||||||
 | 
								this.free = stats.mem.free;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					.memory
 | 
				
			||||||
 | 
						> .pie
 | 
				
			||||||
 | 
							padding 10px
 | 
				
			||||||
 | 
							height 100px
 | 
				
			||||||
 | 
							float left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> div
 | 
				
			||||||
 | 
							float left
 | 
				
			||||||
 | 
							width calc(100% - 100px)
 | 
				
			||||||
 | 
							padding 10px 10px 10px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> p
 | 
				
			||||||
 | 
								margin 0
 | 
				
			||||||
 | 
								font-size 12px
 | 
				
			||||||
 | 
								color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:first-child
 | 
				
			||||||
 | 
									font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> [data-fa]
 | 
				
			||||||
 | 
										margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&:after
 | 
				
			||||||
 | 
							content ""
 | 
				
			||||||
 | 
							display block
 | 
				
			||||||
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										61
									
								
								src/web/app/desktop/views/components/widgets/server.pie.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/web/app/desktop/views/components/widgets/server.pie.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,61 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<svg viewBox="0 0 1 1" preserveAspectRatio="none">
 | 
				
			||||||
 | 
						<circle
 | 
				
			||||||
 | 
							:r="r"
 | 
				
			||||||
 | 
							cx="50%" cy="50%"
 | 
				
			||||||
 | 
							fill="none"
 | 
				
			||||||
 | 
							stroke-width="0.1"
 | 
				
			||||||
 | 
							stroke="rgba(0, 0, 0, 0.05)"/>
 | 
				
			||||||
 | 
						<circle
 | 
				
			||||||
 | 
							:r="r"
 | 
				
			||||||
 | 
							cx="50%" cy="50%"
 | 
				
			||||||
 | 
							:stroke-dasharray="Math.PI * (r * 2)"
 | 
				
			||||||
 | 
							:stroke-dashoffset="strokeDashoffset"
 | 
				
			||||||
 | 
							fill="none"
 | 
				
			||||||
 | 
							stroke-width="0.1"
 | 
				
			||||||
 | 
							:stroke="color"/>
 | 
				
			||||||
 | 
						<text x="50%" y="50%" dy="0.05" text-anchor="middle">{{ (p * 100).toFixed(0) }}%</text>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							value: {
 | 
				
			||||||
 | 
								type: Number,
 | 
				
			||||||
 | 
								required: true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								r: 0.4
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						computed: {
 | 
				
			||||||
 | 
							color(): string {
 | 
				
			||||||
 | 
								return `hsl(${180 - (this.value * 180)}, 80%, 70%)`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							strokeDashoffset(): number {
 | 
				
			||||||
 | 
								return (1 - this.value) * (Math.PI * (this.r * 2));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					svg
 | 
				
			||||||
 | 
						display block
 | 
				
			||||||
 | 
						height 100%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> circle
 | 
				
			||||||
 | 
							transform-origin center
 | 
				
			||||||
 | 
							transform rotate(-90deg)
 | 
				
			||||||
 | 
							transition stroke-dashoffset 0.5s ease
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> text
 | 
				
			||||||
 | 
							font-size 0.15px
 | 
				
			||||||
 | 
							fill rgba(0, 0, 0, 0.6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="uptimes">
 | 
				
			||||||
 | 
						<p>Uptimes</p>
 | 
				
			||||||
 | 
						<p>Process: {{ process ? process.toFixed(0) : '---' }}s</p>
 | 
				
			||||||
 | 
						<p>OS: {{ os ? os.toFixed(0) : '---' }}s</p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: ['connection'],
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								process: 0,
 | 
				
			||||||
 | 
								os: 0
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						mounted() {
 | 
				
			||||||
 | 
							this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						beforeDestroy() {
 | 
				
			||||||
 | 
							this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							onStats(stats) {
 | 
				
			||||||
 | 
								this.process = stats.process_uptime;
 | 
				
			||||||
 | 
								this.os = stats.os_uptime;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					.uptimes
 | 
				
			||||||
 | 
						padding 10px 14px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> p
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
							font-size 12px
 | 
				
			||||||
 | 
							color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:first-child
 | 
				
			||||||
 | 
								font-weight bold
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										127
									
								
								src/web/app/desktop/views/components/widgets/server.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/web/app/desktop/views/components/widgets/server.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,127 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="mkw-server" :data-melt="props.design == 2">
 | 
				
			||||||
 | 
						<template v-if="props.design == 0">
 | 
				
			||||||
 | 
							<p class="title">%fa:server%%i18n:desktop.tags.mk-server-home-widget.title%</p>
 | 
				
			||||||
 | 
							<button @click="toggle" title="%i18n:desktop.tags.mk-server-home-widget.toggle%">%fa:sort%</button>
 | 
				
			||||||
 | 
						</template>
 | 
				
			||||||
 | 
						<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
 | 
				
			||||||
 | 
						<template v-if="!fetching">
 | 
				
			||||||
 | 
							<x-cpu-memory v-show="props.view == 0" :connection="connection"/>
 | 
				
			||||||
 | 
							<x-cpu v-show="props.view == 1" :connection="connection" :meta="meta"/>
 | 
				
			||||||
 | 
							<x-memory v-show="props.view == 2" :connection="connection"/>
 | 
				
			||||||
 | 
							<x-disk v-show="props.view == 3" :connection="connection"/>
 | 
				
			||||||
 | 
							<x-uptimes v-show="props.view == 4" :connection="connection"/>
 | 
				
			||||||
 | 
							<x-info v-show="props.view == 5" :connection="connection" :meta="meta"/>
 | 
				
			||||||
 | 
						</template>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import define from '../../../../common/define-widget';
 | 
				
			||||||
 | 
					import XCpuMemory from './server.cpu-memory.vue';
 | 
				
			||||||
 | 
					import XCpu from './server.cpu.vue';
 | 
				
			||||||
 | 
					import XMemory from './server.memory.vue';
 | 
				
			||||||
 | 
					import XDisk from './server.disk.vue';
 | 
				
			||||||
 | 
					import XUptimes from './server.uptimes.vue';
 | 
				
			||||||
 | 
					import XInfo from './server.info.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default define({
 | 
				
			||||||
 | 
						name: 'server',
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							design: 0,
 | 
				
			||||||
 | 
							view: 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}).extend({
 | 
				
			||||||
 | 
						components: {
 | 
				
			||||||
 | 
							'x-cpu-and-memory': XCpuMemory,
 | 
				
			||||||
 | 
							'x-cpu': XCpu,
 | 
				
			||||||
 | 
							'x-memory': XMemory,
 | 
				
			||||||
 | 
							'x-disk': XDisk,
 | 
				
			||||||
 | 
							'x-uptimes': XUptimes,
 | 
				
			||||||
 | 
							'x-info': XInfo
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								fetching: true,
 | 
				
			||||||
 | 
								meta: null,
 | 
				
			||||||
 | 
								connection: null,
 | 
				
			||||||
 | 
								connectionId: null
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						mounted() {
 | 
				
			||||||
 | 
							(this as any).os.getMeta().then(meta => {
 | 
				
			||||||
 | 
								this.meta = meta;
 | 
				
			||||||
 | 
								this.fetching = false;
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.connection = (this as any).os.streams.serverStream.getConnection();
 | 
				
			||||||
 | 
							this.connectionId = (this as any).os.streams.serverStream.use();
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						beforeDestroy() {
 | 
				
			||||||
 | 
							(this as any).os.streams.serverStream.dispose(this.connectionId);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							toggle() {
 | 
				
			||||||
 | 
								if (this.props.design == 5) {
 | 
				
			||||||
 | 
									this.props.design = 0;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									this.props.design++;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							func() {
 | 
				
			||||||
 | 
								this.toggle();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					.mkw-server
 | 
				
			||||||
 | 
						background #fff
 | 
				
			||||||
 | 
						border solid 1px rgba(0, 0, 0, 0.075)
 | 
				
			||||||
 | 
						border-radius 6px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&[data-melt]
 | 
				
			||||||
 | 
							background transparent !important
 | 
				
			||||||
 | 
							border none !important
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .title
 | 
				
			||||||
 | 
							z-index 1
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
							padding 0 16px
 | 
				
			||||||
 | 
							line-height 42px
 | 
				
			||||||
 | 
							font-size 0.9em
 | 
				
			||||||
 | 
							font-weight bold
 | 
				
			||||||
 | 
							color #888
 | 
				
			||||||
 | 
							box-shadow 0 1px rgba(0, 0, 0, 0.07)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> [data-fa]
 | 
				
			||||||
 | 
								margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> button
 | 
				
			||||||
 | 
							position absolute
 | 
				
			||||||
 | 
							z-index 2
 | 
				
			||||||
 | 
							top 0
 | 
				
			||||||
 | 
							right 0
 | 
				
			||||||
 | 
							padding 0
 | 
				
			||||||
 | 
							width 42px
 | 
				
			||||||
 | 
							font-size 0.9em
 | 
				
			||||||
 | 
							line-height 42px
 | 
				
			||||||
 | 
							color #ccc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:hover
 | 
				
			||||||
 | 
								color #aaa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:active
 | 
				
			||||||
 | 
								color #999
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> .fetching
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
							padding 16px
 | 
				
			||||||
 | 
							text-align center
 | 
				
			||||||
 | 
							color #aaa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							> [data-fa]
 | 
				
			||||||
 | 
								margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										8
									
								
								src/web/app/filters/bytes.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/web/app/filters/bytes.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Vue.filter('bytes', (v, digits = 0) => {
 | 
				
			||||||
 | 
						const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
 | 
				
			||||||
 | 
						if (v == 0) return '0Byte';
 | 
				
			||||||
 | 
						const i = Math.floor(Math.log(v) / Math.log(1024));
 | 
				
			||||||
 | 
						return (v / Math.pow(1024, i)).toFixed(digits).replace(/\.0+$/, '') + sizes[i];
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										1
									
								
								src/web/app/filters/index.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/web/app/filters/index.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					require('./bytes');
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,9 @@ require('./common/views/directives');
 | 
				
			||||||
// Register global components
 | 
					// Register global components
 | 
				
			||||||
require('./common/views/components');
 | 
					require('./common/views/components');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Register global filters
 | 
				
			||||||
 | 
					require('./filters');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Vue.mixin({
 | 
					Vue.mixin({
 | 
				
			||||||
	destroyed(this: any) {
 | 
						destroyed(this: any) {
 | 
				
			||||||
		if (this.$el.parentNode) {
 | 
							if (this.$el.parentNode) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue