master
yutent 2024-01-18 13:46:01 +08:00
parent 7131c4067e
commit 2b67ce3783
6 changed files with 63 additions and 8 deletions

View File

@ -54,6 +54,36 @@ class Docker:
} for it in out]
def services(self):
cmd = 'docker compose ls --format=json'
out = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE)
out = out.stdout.decode().strip().split("\n")
out = [json.loads(it) for it in out]
return out
def networks(self):
cmd = 'docker network ls --format=json'
out = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE)
out = out.stdout.decode().strip().split("\n")
out = [json.loads(it) for it in out]
return out
def volumns(self):
cmd = 'docker volume ls --format=json'
out = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE)
out = out.stdout.decode().strip().split("\n")
out = [json.loads(it) for it in out]
return out
def rm(self, id = ''):
cmd = 'docker rm ' + id
out = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE)

View File

@ -1,4 +1,4 @@
import{css as p,html as c,Component as l,bind as a,unbind as d,styleMap as f,offset as h,outsideClick as m,clearOutsideClick as x}from"wkit";import"../base/button.js";const w="\u8BF7\u786E\u8BA4\u4F60\u7684\u64CD\u4F5C!";class u extends l{static props={title:"str!",confirmButtonType:"str!primary"};static styles=[p`:host{display:inline-flex}.container{position:relative}.tooltip{display:none;position:fixed;z-index:9;justify-content:center;align-items:center;max-width:260px;min-width:32px;padding:8px 12px 12px;border-radius:3px;font-size:var(--wc-popconfirm-font, 14px);background:var(--wc-popconfirm-background, #fff);color:var(--wc-popconfirm-color, var(--color-dark-1));box-shadow:0 0 3px var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.3));word-break:break-all;-webkit-user-select:none;user-select:none}.tooltip::after{position:absolute;display:block;width:8px;height:8px;border-radius:2px;background:var(--wc-popconfirm-background, #fff);content:"";transform:rotate(45deg);box-shadow:-1px -1px 0 var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=left-top]::after{right:16px;bottom:-4px;box-shadow:1px 1px 0 var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=left-bottom]::after{right:16px;top:-4px}.tooltip[placement=right-top]::after{left:16px;bottom:-4px;box-shadow:1px 1px 0 var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=right-bottom]::after{left:16px;top:-4px}`,p`.title{display:flex;align-items:center;gap:6px;padding:8px 0;--wc-icon-size: 16px}.title wc-icon{flex-shrink:0;color:var(--wc-popconfirm-icon-color, var(--color-red-1))}:host([hide-icon]) .title wc-icon{display:none}.actions{display:flex;justify-content:flex-end;gap:4px;margin-top:8px}.actions wc-button{min-width:40px;height:20px;font-size:12px}.actions wc-button:first-child{--wc-button-border-color: none}`];#t=!1;#i(s){let{left:t,top:e}=h(this),n="left",o={display:"block"},r=document.documentElement.scrollTop;if(!this.#t){if(t<260||t>260&&window.innerWidth-t>260)n="right",o.left=t+"px";else{let i=window.innerWidth-t-this.clientWidth-12;i<0&&(i=0),o.right=i+"px"}if(e<160)e+=8+this.clientHeight,n+="-bottom",o.top=e+"px";else{let i=window.innerHeight-e+8;n+="-top",o.bottom=i+"px",r>0&&(o.transform=`translateY(-${r}px)`)}this.#t=!0,this.$refs.tips.setAttribute("placement",n),this.$refs.tips.style.cssText=f(o),this.$refs.tips.$animate()}}#o(){this.#t&&(this.#t=!1,this.$refs.tips.$animate(!0))}#e(){this.$emit("confirm"),this.#o()}mounted(){this._outFn=m(this,s=>this.#o()),this._scrollFn=a(document,"scroll",s=>{if(this.#t){let t=document.documentElement.scrollTop;this.$refs.tips.style.transform=`translateY(-${t}px)`}})}unmounted(){d(document,"scroll",this._scrollFn),x(this._outFn)}render(){return c`
import{css as p,html as c,Component as l,bind as a,unbind as f,styleMap as d,offset as h,outsideClick as m,clearOutsideClick as x}from"wkit";import"../base/button.js";const w="\u8BF7\u786E\u8BA4\u4F60\u7684\u64CD\u4F5C!";class u extends l{static props={title:"str!",confirmButtonType:"str!primary"};static styles=[p`:host{display:inline-flex}.container{position:relative}.tooltip{display:none;position:fixed;z-index:9;justify-content:center;align-items:center;max-width:260px;min-width:32px;padding:8px 12px 12px;border-radius:3px;font-size:var(--wc-popconfirm-font, 14px);background:var(--wc-popconfirm-background, #fff);color:var(--wc-popconfirm-color, var(--color-dark-1));box-shadow:0 0 3px var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.3));word-break:break-all;-webkit-user-select:none;user-select:none}.tooltip::after{position:absolute;display:block;width:8px;height:8px;border-radius:2px;background:var(--wc-popconfirm-background, #fff);content:"";transform:rotate(45deg);box-shadow:-1px -1px 0 var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=left-top]::after{right:16px;bottom:-4px;box-shadow:1px 1px 0 var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=left-bottom]::after{right:16px;top:-4px}.tooltip[placement=right-top]::after{left:16px;bottom:-4px;box-shadow:1px 1px 0 var(--wc-popconfirm-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=right-bottom]::after{left:16px;top:-4px}`,p`.title{display:flex;align-items:center;gap:6px;padding:8px 0;--wc-icon-size: 16px}.title wc-icon{flex-shrink:0;color:var(--wc-popconfirm-icon-color, var(--color-red-1))}:host([hide-icon]) .title wc-icon{display:none}.actions{display:flex;justify-content:flex-end;gap:4px;margin-top:8px}.actions wc-button{min-width:40px;height:20px;font-size:12px}.actions wc-button:first-child{--wc-button-border-color: none}`];#t=!1;#i(s){let{left:t,top:e}=h(this),n="left",o={display:"block"},r=document.documentElement.scrollTop;if(!this.#t){if(t<260||t>260&&window.innerWidth-t>260)n="right",t-=12,t<0&&(t=0),o.left=t+"px";else{let i=window.innerWidth-t-this.clientWidth-12;i<0&&(i=0),o.right=i+"px"}if(e<160)e+=8+this.clientHeight,n+="-bottom",o.top=e+"px";else{let i=window.innerHeight-e+8;n+="-top",o.bottom=i+"px",r>0&&(o.transform=`translateY(-${r}px)`)}this.#t=!0,this.$refs.tips.setAttribute("placement",n),this.$refs.tips.style.cssText=d(o),this.$refs.tips.$animate()}}#o(){this.#t&&(this.#t=!1,this.$refs.tips.$animate(!0))}#e(){this.$emit("confirm"),this.#o()}mounted(){this._outFn=m(this,s=>this.#o()),this._scrollFn=a(document,"scroll",s=>{if(this.#t){let t=document.documentElement.scrollTop;this.$refs.tips.style.transform=`translateY(-${t}px)`}})}unmounted(){f(document,"scroll",this._scrollFn),x(this._outFn)}render(){return c`
<main class="container">
<div class="wrapper" @click=${this.#i}>
<slot></slot>

View File

@ -1,4 +1,4 @@
import{css as a,html as n,Component as d,bind as s,styleMap as c,offset as f}from"wkit";class h extends d{static props={title:"str!"};static styles=[a`:host{display:inline-flex}.container{position:relative}.tooltip{display:none;position:fixed;z-index:9;justify-content:center;align-items:center;max-width:360px;min-width:32px;padding:6px 8px;border-radius:3px;font-size:var(--wc-tooltip-font, 14px);background:var(--wc-tooltip-background, #fff);color:var(--wc-tooltip-color, var(--color-dark-1));box-shadow:0 0 3px var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.3));word-break:break-all;-webkit-user-select:none;user-select:none}.tooltip::after{position:absolute;display:block;width:8px;height:8px;border-radius:2px;background:var(--wc-tooltip-background, #fff);content:"";transform:rotate(45deg);box-shadow:-1px -1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=left-top]::after{right:16px;bottom:-4px;box-shadow:1px 1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=left-bottom]::after{right:16px;top:-4px}.tooltip[placement=right-top]::after{left:16px;bottom:-4px;box-shadow:1px 1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=right-bottom]::after{left:16px;top:-4px}`];mounted(){s(this.$refs.wrap,"mouseenter",p=>{let{left:t,top:e}=f(this),i="left",o={display:"block"},l=document.documentElement.scrollTop;if(this.title.trim()!==""){if(t<360||t>360&&window.innerWidth-t>360)i="right",o.left=t+"px";else{let r=window.innerWidth-t-this.clientWidth;o.right=r+"px"}if(e<96)e+=8+this.clientHeight,i+="-bottom",o.top=e+"px";else{let r=window.innerHeight-e+8+l;i+="-top",o.bottom=r+"px"}this.$refs.tips.setAttribute("placement",i),this.$refs.tips.style.cssText=c(o),this.$refs.tips.$animate()}}),s(this.$refs.wrap,"mouseleave",p=>{this.$refs.tips.$animate(!0)})}render(){return n`
import{css as a,html as n,Component as d,bind as s,styleMap as c,offset as f}from"wkit";class h extends d{static props={title:"str!"};static styles=[a`:host{display:inline-flex}.container{position:relative}.tooltip{display:none;position:fixed;z-index:9;justify-content:center;align-items:center;max-width:360px;min-width:32px;padding:6px 8px;border-radius:3px;font-size:var(--wc-tooltip-font, 14px);background:var(--wc-tooltip-background, #fff);color:var(--wc-tooltip-color, var(--color-dark-1));box-shadow:0 0 3px var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.3));word-break:break-all;-webkit-user-select:none;user-select:none}.tooltip::after{position:absolute;display:block;width:8px;height:8px;border-radius:2px;background:var(--wc-tooltip-background, #fff);content:"";transform:rotate(45deg);box-shadow:-1px -1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=left-top]::after{right:16px;bottom:-4px;box-shadow:1px 1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=left-bottom]::after{right:16px;top:-4px}.tooltip[placement=right-top]::after{left:16px;bottom:-4px;box-shadow:1px 1px 0 var(--wc-tooltip-shadow, rgba(0, 0, 0, 0.1))}.tooltip[placement=right-bottom]::after{left:16px;top:-4px}`];mounted(){s(this.$refs.wrap,"mouseenter",p=>{let{left:t,top:i}=f(this),r="left",o={display:"block"},l=document.documentElement.scrollTop;if(this.title.trim()!==""){if(t<360||t>360&&window.innerWidth-t>360)r="right",t-=12,t<0&&(t=0),o.left=t+"px";else{let e=window.innerWidth-t-this.clientWidth-12;e<0&&(e=0),o.right=e+"px"}if(i<96)i+=8+this.clientHeight,r+="-bottom",o.top=i+"px";else{let e=window.innerHeight-i+8+l;r+="-top",o.bottom=e+"px"}this.$refs.tips.setAttribute("placement",r),this.$refs.tips.style.cssText=c(o),this.$refs.tips.$animate()}}),s(this.$refs.wrap,"mouseleave",p=>{this.$refs.tips.$animate(!0)})}render(){return n`
<main class="container">
<div class="wrapper" ref="wrap"><slot></slot></div>
<div class="tooltip" ref="tips" #animation=${{}}>

View File

@ -19,10 +19,20 @@ export default createStore({
name: '镜像管理',
icon: 'menu'
},
{
id: 'services',
name: '服务管理',
icon: 'calendar'
},
{
id: 'volumes',
name: '磁盘管理',
icon: 'pie'
},
{
id: 'networks',
name: '网络管理',
icon: 'share'
}
]
})

View File

@ -151,7 +151,6 @@ class Home extends Component {
it.state === 'running' ? '🟢' : it.state === 'created' ? '⚪' : '🔴'
})
console.log(list)
this.containers = list
}
@ -172,7 +171,6 @@ class Home extends Component {
}
async #remove(item) {
console.log(item)
await removeContainer(item.id)
this.#fetch()
}
@ -230,7 +228,9 @@ class Home extends Component {
<span class="text-ell">${it.port}</span>
</wc-tooltip>
</section>
<section class="field center">${it.state}</section>
<section class="field center">
<wc-tooltip title=${it.status}>${it.state}</wc-tooltip>
</section>
<section class="field flex gap-12 center">
<span class="action ${it.state === '🟢' ? 'red' : 'green'}"
>${it.state === '🟢' ? '⏹' : '⏸'}</span

View File

@ -5,7 +5,7 @@
*/
import { html, css, Component, classMap, nextTick, outsideClick } from 'wkit'
import { noop, getImages } from '../utils/index.js'
import { getImages, removeImage } from '../utils/index.js'
class Images extends Component {
static props = {
@ -94,7 +94,7 @@ class Images extends Component {
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
color: var(--color-teal-1);
color: var(--color-blue-1);
}
}
@ -114,6 +114,11 @@ class Images extends Component {
async mounted() {
let list = await getImages()
this.#fetch()
}
async #fetch() {
let list = await getImages()
this.images = list
}
@ -126,6 +131,11 @@ class Images extends Component {
this.$requestUpdate()
}
async #remove(item) {
await removeImage(item.id)
this.#fetch()
}
render() {
let list = this.images
let txt = this.#input
@ -165,7 +175,12 @@ class Images extends Component {
<wc-time stamp=${new Date(it.created).getTime()}></wc-time>
</section>
<section class="field center">
<wc-icon name="trash"></wc-icon>
<wc-popconfirm
title="是否要删除此容器?"
@confirm=${ev => this.#remove(it)}
>
<span class="action">🗑</span>
</wc-popconfirm>
</section>
</li>
`