284 lines
8.6 KiB
Vue
284 lines
8.6 KiB
Vue
<template>
|
||
<modal-inner class="modal__inner-1--workspace-management" aria-label="管理文档空间">
|
||
<div class="modal__content">
|
||
<div class="modal__image">
|
||
<icon-database></icon-database>
|
||
</div>
|
||
<p><br>可以访问以下文档空间:</p>
|
||
<div class="workspace-entry flex flex--column" v-for="(workspace, id) in workspacesById" :key="id">
|
||
<div class="flex flex--column">
|
||
<div class="workspace-entry__header flex flex--row flex--align-center">
|
||
<div class="workspace-entry__icon">
|
||
<icon-provider :provider-id="workspace.providerId"></icon-provider>
|
||
</div>
|
||
<input class="text-input" type="text" v-if="editedId === id" v-focus @blur="submitEdit()" @keydown.enter="submitEdit()" @keydown.esc.stop="submitEdit(true)" v-model="editingName">
|
||
<div class="workspace-entry__name" v-else>{{workspace.name}}</div>
|
||
<div class="workspace-entry__buttons flex flex--row">
|
||
<button class="workspace-entry__button button" @click="edit(id)" v-title="'编辑名称'">
|
||
<icon-pen></icon-pen>
|
||
</button>
|
||
<template v-if="workspace.providerId === 'giteeAppData' || workspace.providerId === 'githubWorkspace'
|
||
|| workspace.providerId === 'giteeWorkspace' || workspace.providerId === 'gitlabWorkspace' || workspace.providerId === 'giteaWorkspace'">
|
||
<button class="workspace-entry__button button" @click="stopAutoSync(id)" v-if="workspace.autoSync == undefined || workspace.autoSync" v-title="'关闭自动同步'">
|
||
<icon-sync-auto></icon-sync-auto>
|
||
</button>
|
||
<button class="workspace-entry__button button" @click="startAutoSync(id)" v-if="workspace.autoSync != undefined && !workspace.autoSync" v-title="'启动自动同步'">
|
||
<icon-sync-stop></icon-sync-stop>
|
||
</button>
|
||
</template>
|
||
<button class="workspace-entry__button button" @click="remove(id)" v-title="'删除'">
|
||
<icon-delete></icon-delete>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="workspace-entry__row flex flex--row flex--align-center">
|
||
<div class="workspace-entry__url">
|
||
{{workspace.url}}
|
||
</div>
|
||
<div class="workspace-entry__buttons flex flex--row">
|
||
<button class="workspace-entry__button button" v-clipboard="workspace.url" @click="info('文档空间URL已复制到剪贴板!')" v-title="'复制URL'">
|
||
<icon-content-copy></icon-content-copy>
|
||
</button>
|
||
<a class="workspace-entry__button button" :href="workspace.url" target="_blank" v-title="'打开文档空间'">
|
||
<icon-open-in-new></icon-open-in-new>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
<div class="workspace-entry__row flex flex--row flex--align-center" v-if="workspace.locationUrl">
|
||
<div class="workspace-entry__url">
|
||
{{workspace.locationUrl}}
|
||
</div>
|
||
<div class="workspace-entry__buttons flex flex--row">
|
||
<button class="workspace-entry__button button" v-clipboard="workspace.locationUrl" @click="info('文档空间URL已复制到剪贴板!')" v-title="'复制URL'">
|
||
<icon-content-copy></icon-content-copy>
|
||
</button>
|
||
<a class="workspace-entry__button button" :href="workspace.locationUrl" target="_blank" v-title="'打开文档空间位置'">
|
||
<icon-open-in-new></icon-open-in-new>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<span class="workspace-entry__offline" v-if="availableOffline[id]">
|
||
离线可用
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal__button-bar">
|
||
<button class="button button--resolve" @click="config.resolve()">关闭</button>
|
||
</div>
|
||
</modal-inner>
|
||
</template>
|
||
|
||
<script>
|
||
import Vue from 'vue';
|
||
import { mapGetters, mapActions } from 'vuex';
|
||
import ModalInner from './common/ModalInner';
|
||
import workspaceSvc from '../../services/workspaceSvc';
|
||
import store from '../../store';
|
||
import badgeSvc from '../../services/badgeSvc';
|
||
import localDbSvc from '../../services/localDbSvc';
|
||
|
||
export default {
|
||
components: {
|
||
ModalInner,
|
||
},
|
||
data: () => ({
|
||
editedId: null,
|
||
editingName: '',
|
||
availableOffline: {},
|
||
}),
|
||
computed: {
|
||
...mapGetters('modal', [
|
||
'config',
|
||
]),
|
||
...mapGetters('workspace', [
|
||
'workspacesById',
|
||
'mainWorkspace',
|
||
'currentWorkspace',
|
||
]),
|
||
},
|
||
methods: {
|
||
...mapActions('notification', [
|
||
'info',
|
||
]),
|
||
edit(id) {
|
||
this.editedId = id;
|
||
this.editingName = this.workspacesById[id].name;
|
||
},
|
||
submitEdit(cancel) {
|
||
const workspace = this.workspacesById[this.editedId];
|
||
if (workspace) {
|
||
if (!cancel && this.editingName && this.editingName !== workspace.name) {
|
||
store.dispatch('workspace/patchWorkspacesById', {
|
||
[this.editedId]: {
|
||
...workspace,
|
||
name: this.editingName,
|
||
},
|
||
});
|
||
badgeSvc.addBadge('renameWorkspace');
|
||
} else {
|
||
this.editingName = workspace.name;
|
||
}
|
||
}
|
||
this.editedId = null;
|
||
},
|
||
async remove(id) {
|
||
if (id === this.mainWorkspace.id) {
|
||
this.info('您的主文档空间无法删除。');
|
||
} else if (id === this.currentWorkspace.id) {
|
||
this.info('请先关闭文档空间,然后再将其删除。');
|
||
} else {
|
||
try {
|
||
const workspace = this.workspacesById[id];
|
||
if (!workspace) {
|
||
return;
|
||
}
|
||
await store.dispatch('modal/open', {
|
||
type: 'removeWorkspace',
|
||
name: workspace.name,
|
||
});
|
||
workspaceSvc.removeWorkspace(id);
|
||
badgeSvc.addBadge('removeWorkspace');
|
||
} catch (e) { /* Cancel */ }
|
||
}
|
||
},
|
||
async stopAutoSync(id) {
|
||
const workspace = this.workspacesById[id];
|
||
if (!workspace) {
|
||
return;
|
||
}
|
||
await store.dispatch('modal/open', {
|
||
type: 'stopAutoSyncWorkspace',
|
||
name: workspace.name,
|
||
});
|
||
store.dispatch('workspace/patchWorkspacesById', {
|
||
[id]: {
|
||
...workspace,
|
||
autoSync: false,
|
||
},
|
||
});
|
||
badgeSvc.addBadge('stopAutoSyncWorkspace');
|
||
},
|
||
async startAutoSync(id) {
|
||
const workspace = this.workspacesById[id];
|
||
if (!workspace) {
|
||
return;
|
||
}
|
||
await store.dispatch('modal/open', {
|
||
type: 'autoSyncWorkspace',
|
||
name: workspace.name,
|
||
});
|
||
store.dispatch('workspace/patchWorkspacesById', {
|
||
[id]: {
|
||
...workspace,
|
||
autoSync: true,
|
||
},
|
||
});
|
||
badgeSvc.addBadge('autoSyncWorkspace');
|
||
},
|
||
},
|
||
created() {
|
||
Object.keys(this.workspacesById).forEach(async (workspaceId) => {
|
||
const cancel = localDbSvc.getWorkspaceItems(workspaceId, () => {
|
||
Vue.set(this.availableOffline, workspaceId, true);
|
||
cancel();
|
||
});
|
||
});
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
@import '../../styles/variables.scss';
|
||
|
||
.workspace-entry {
|
||
margin: 1.75em 0;
|
||
height: auto;
|
||
font-size: 17px;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
$button-size: 30px;
|
||
$small-button-size: 22px;
|
||
|
||
.workspace-entry__header {
|
||
line-height: $button-size;
|
||
|
||
.text-input {
|
||
border: 1px solid $link-color;
|
||
padding: 0 5px;
|
||
line-height: $button-size;
|
||
height: $button-size;
|
||
}
|
||
}
|
||
|
||
.workspace-entry__row {
|
||
border-top: 1px solid $hr-color;
|
||
line-height: $small-button-size;
|
||
}
|
||
|
||
.workspace-entry__icon {
|
||
height: 22px;
|
||
width: 22px;
|
||
margin-right: 0.75rem;
|
||
flex: none;
|
||
}
|
||
|
||
.workspace-entry__name {
|
||
width: 100%;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.workspace-entry__url {
|
||
width: 100%;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
opacity: 0.5;
|
||
font-size: 0.67em;
|
||
}
|
||
|
||
.workspace-entry__buttons {
|
||
margin-left: 0.75rem;
|
||
|
||
.workspace-entry__row & {
|
||
margin-left: 0.5rem;
|
||
}
|
||
}
|
||
|
||
.workspace-entry__button {
|
||
width: $button-size;
|
||
height: $button-size;
|
||
padding: 4px;
|
||
background-color: transparent;
|
||
opacity: 0.75;
|
||
|
||
.workspace-entry__row & {
|
||
width: $small-button-size;
|
||
height: $small-button-size;
|
||
padding: 4px;
|
||
}
|
||
|
||
&:active,
|
||
&:focus,
|
||
&:hover {
|
||
opacity: 1;
|
||
background-color: rgba(0, 0, 0, 0.1);
|
||
}
|
||
}
|
||
|
||
.workspace-entry__offline {
|
||
font-size: 0.8rem;
|
||
line-height: 1;
|
||
padding: 0.15em 0.35em;
|
||
border-radius: 3px;
|
||
color: #fff;
|
||
background-color: darken($error-color, 10);
|
||
}
|
||
</style>
|