Improve task manager etc

This commit is contained in:
syuilo 2020-11-01 22:09:16 +09:00
parent 21b6e23e98
commit 7060625adf
7 changed files with 108 additions and 23 deletions

View File

@ -169,15 +169,15 @@ export default defineComponent({
font-size: 32px;
&.success {
color: var(--accent);
color: var(--success);
}
&.error {
color: #ec4137;
color: var(--error);
}
&.warning {
color: #ecb637;
color: var(--warn);
}
> * {

View File

@ -7,7 +7,7 @@
<MkTab v-model:value="tab" :items="[{ label: 'Windows', value: 'windows', }, { label: 'Stream', value: 'stream', }, { label: 'Stream (Pool)', value: 'streamPool', }, { label: 'API', value: 'api', }]" style="border-bottom: solid 1px var(--divider);"/>
<div class="content">
<div v-if="tab === 'windows'" class="windows">
<div v-if="tab === 'windows'" class="windows" v-follow>
<div class="header">
<div>#ID</div>
<div>Component</div>
@ -19,7 +19,7 @@
<div><button class="_textButton" @click="killPopup(p)">Kill</button></div>
</div>
</div>
<div v-if="tab === 'stream'" class="stream">
<div v-if="tab === 'stream'" class="stream" v-follow>
<div class="header">
<div>#ID</div>
<div>Ch</div>
@ -36,7 +36,7 @@
<div>{{ c.out }}</div>
</div>
</div>
<div v-if="tab === 'streamPool'" class="streamPool">
<div v-if="tab === 'streamPool'" class="streamPool" v-follow>
<div class="header">
<div>#ID</div>
<div>Ch</div>
@ -48,6 +48,18 @@
<div>{{ p.users }}</div>
</div>
</div>
<div v-if="tab === 'api'" class="api" v-follow>
<div class="header">
<div>#ID</div>
<div>Endpoint</div>
<div>State</div>
</div>
<div v-for="req in apiRequests">
<div>#{{ req.id }}</div>
<div>{{ req.endpoint }}</div>
<div class="state" :class="req.state">{{ req.state }}</div>
</div>
</div>
</div>
<footer>
@ -65,6 +77,7 @@ import { faTerminal } from '@fortawesome/free-solid-svg-icons';
import XWindow from '@/components/ui/window.vue';
import MkTab from '@/components/tab.vue';
import MkButton from '@/components/ui/button.vue';
import follow from '@/directives/follow-append';
import * as os from '@/os';
export default defineComponent({
@ -74,6 +87,10 @@ export default defineComponent({
MkButton,
},
directives: {
follow
},
props: {
},
@ -105,6 +122,7 @@ export default defineComponent({
return {
tab: ref('stream'),
popups: os.popups,
apiRequests: os.apiRequests,
connections,
pools,
killPopup,
@ -125,9 +143,7 @@ export default defineComponent({
flex: 1;
overflow: auto;
> .windows,
> .stream,
> .streamPool {
> div {
display: table;
width: 100%;
padding: 16px;
@ -140,8 +156,31 @@ export default defineComponent({
opacity: 0.7;
}
> * {
> div {
display: table-cell;
white-space: nowrap;
&:not(:last-child) {
padding-right: 8px;
}
}
}
&.api {
> div {
> .state {
&.pending {
color: var(--warn);
}
&.success {
color: var(--success);
}
&.failed {
color: var(--error);
}
}
}
}
}

View File

@ -0,0 +1,25 @@
import { Directive } from 'vue';
import { getScrollContainer, getScrollPosition } from '@/scripts/scroll';
export default {
mounted(src, binding, vn) {
const ro = new ResizeObserver((entries, observer) => {
const pos = getScrollPosition(src);
const container = getScrollContainer(src);
const viewHeight = container.clientHeight;
const height = container.scrollHeight;
if (pos + viewHeight > height - 32) {
container.scrollTop = height;
}
});
ro.observe(src);
// TODO: 新たにプロパティを作るのをやめMapを使う
src._ro_ = ro;
},
unmounted(src, binding, vn) {
src._ro_.unobserve(src);
}
} as Directive;

View File

@ -2,7 +2,7 @@ import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vu
import { EventEmitter } from 'eventemitter3';
import Stream from '@/scripts/stream';
import { store } from '@/store';
import { apiUrl } from '@/config';
import { apiUrl, debug } from '@/config';
import MkPostFormDialog from '@/components/post-form-dialog.vue';
import MkWaitingDialog from '@/components/waiting-dialog.vue';
import { resolve } from '@/router';
@ -13,28 +13,26 @@ export const isMobile = /mobile|iphone|ipad|android/.test(ua);
export const stream = markRaw(new Stream());
export const pendingApiRequestsCount = ref(0);
export const apiRequests = ref([]); // for debug
export const windows = new Map();
export function api(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) {
pendingApiRequestsCount.value++;
if (_DEV_) {
performance.mark(_PERF_PREFIX_ + 'api:begin');
}
const onFinally = () => {
pendingApiRequestsCount.value--;
if (_DEV_) {
performance.mark(_PERF_PREFIX_ + 'api:end');
performance.measure(_PERF_PREFIX_ + 'api',
_PERF_PREFIX_ + 'api:begin',
_PERF_PREFIX_ + 'api:end');
}
};
const log = debug ? reactive({
id: apiRequests.value.length,
endpoint,
state: 'pending'
}) : null;
if (debug) {
apiRequests.value.push(log);
}
const promise = new Promise((resolve, reject) => {
// Append a credential
if (store.getters.isSignedIn) (data as any).i = store.state.i.token;
@ -51,10 +49,19 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
if (res.status === 200) {
resolve(body);
if (debug) {
log.state = 'success';
}
} else if (res.status === 204) {
resolve();
if (debug) {
log.state = 'success';
}
} else {
reject(body.error);
if (debug) {
log.state = 'failed';
}
}
}).catch(reject);
});

View File

@ -10,6 +10,10 @@
<MkInput v-model:value="dialogBody">
<span>Body</span>
</MkInput>
<MkRadio v-model="dialogType" value="info">Info</MkRadio>
<MkRadio v-model="dialogType" value="success">Success</MkRadio>
<MkRadio v-model="dialogType" value="warning">Warn</MkRadio>
<MkRadio v-model="dialogType" value="error">Error</MkRadio>
<MkSwitch v-model:value="dialogCancel">
<span>With cancel button</span>
</MkSwitch>
@ -133,6 +137,7 @@ import MkButton from '@/components/ui/button.vue';
import MkInput from '@/components/ui/input.vue';
import MkSwitch from '@/components/ui/switch.vue';
import MkTextarea from '@/components/ui/textarea.vue';
import MkRadio from '@/components/ui/radio.vue';
import * as os from '@/os';
export default defineComponent({
@ -141,6 +146,7 @@ export default defineComponent({
MkInput,
MkSwitch,
MkTextarea,
MkRadio,
},
data() {
@ -153,6 +159,7 @@ export default defineComponent({
},
dialogTitle: 'Hello',
dialogBody: 'World!',
dialogType: 'info',
dialogCancel: false,
dialogCancelByBgClick: true,
dialogInput: false,
@ -192,6 +199,7 @@ export default defineComponent({
async showDialog() {
this.dialogResult = null;
this.dialogResult = await os.dialog({
type: this.dialogType,
title: this.dialogTitle,
text: this.dialogBody,
showCancelButton: this.dialogCancel,

View File

@ -56,6 +56,9 @@
wallpaperOverlay: 'rgba(0, 0, 0, 0.5)',
badge: '#31b1ce',
messageBg: ':lighten<5<@bg',
success: '#86b300',
error: '#ec4137',
warn: '#ecb637',
htmlThemeColor: '@bg',
X1: ':alpha<0<@bg',
X2: ':darken<2<@panel',

View File

@ -56,6 +56,9 @@
wallpaperOverlay: 'rgba(255, 255, 255, 0.5)',
badge: '#31b1ce',
messageBg: '@panel',
success: '#86b300',
error: '#ec4137',
warn: '#ecb637',
htmlThemeColor: '@bg',
X1: ':alpha<0<@bg',
X2: ':darken<2<@panel',