This commit is contained in:
2024-12-16 15:50:38 +09:00
13 changed files with 338 additions and 104 deletions

View File

@@ -0,0 +1,19 @@
<template>
<q-badge v-if="isOwner" color="purple">所有者</q-badge>
<q-badge v-else-if="isManager" color="primary">管理者</q-badge>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
interface Props {
user: { id: number };
domain: IDomainOwnerDisplay;
}
const props = defineProps<Props>();
const isOwner = computed(() => props.user.id === props.domain.owner.id);
const isManager = computed(() => props.user.id === props.domain.owner.id); // TODO
</script>

View File

@@ -2,7 +2,7 @@
<q-dialog :auto-close="false" :model-value="visible" persistent bordered>
<q-card class="dialog-content" >
<q-toolbar class="bg-grey-4">
<q-toolbar-title>{{domain.name}}のドメイン利用権限設定</q-toolbar-title>
<q-toolbar-title>{{ dialogTitle }}</q-toolbar-title>
<q-btn flat round dense icon="close" @click="close" />
</q-toolbar>
@@ -18,11 +18,17 @@
:options="canSharedUserFilteredOptions"
clearable
:placeholder="canSharedUserFilter ? '' : domain.domainActive ? '権限を付与するユーザーを選択' : 'ドメインが無効なため、権限を付与できません'"
@filter="filterFn"
:display-value="canSharedUserFilter?`${canSharedUserFilter.fullName} ${canSharedUserFilter.email}`:''">
@filter="filterFn">
<template v-slot:selected-item="scope">
<span v-if="canSharedUserFilter">
{{ canSharedUserFilter.fullName }} {{ canSharedUserFilter.email }}
<role-label :domain="domain" :user="scope.opt"></role-label>
</span>
</template>
<template v-slot:after>
<q-btn :disable="!canSharedUserFilter" :loading="addLoading" label="付与" color="primary" @click="shareTo(canSharedUserFilter as IUserDisplay)" />
<q-btn :disable="!canSharedUserFilter" :loading="addLoading" label="付与" color="primary" @click="shareTo(canSharedUserFilter as IUserDisplayWithShareRole)" />
</template>
<template v-slot:option="scope">
@@ -30,14 +36,27 @@
<q-item-section avatar>{{scope.opt.id}}</q-item-section>
<q-item-section>{{scope.opt.fullName}}</q-item-section>
<q-item-section>{{scope.opt.email}}</q-item-section>
<q-item-section side>
<div style="width: 4em;">
<role-label :domain="domain" :user="scope.opt"></role-label>
</div>
</q-item-section>
</q-item>
</template>
</q-select>
<sharing-user-list class="q-mt-md" style="height: 330px" :users="sharedUsers" :loading="loading" title="ドメイン利用権限を持つユーザー">
<sharing-user-list class="q-mt-md" style="height: 330px" :users="sharedUsers" :loading="loading" :title="userListTitle">
<template v-slot:body-cell-role="{ row }">
<q-td>
<role-label :domain="domain" :user="row"></role-label>
</q-td>
</template>
<template v-slot:actions="{ row }">
<q-btn title="解除" flat color="primary" padding="xs" size="1em" :loading="row.id == removingUser?.id" icon="person_off" @click="removeShareTo(row)" />
<q-btn round title="解除" flat color="primary" padding="xs" size="1em" :loading="row.isRemoving" icon="person_off" @click="removeShareTo(row)" />
</template>
</sharing-user-list>
</q-card-section>
<q-card-actions align="right" class="text-primary">
@@ -54,11 +73,22 @@ import { IDomainOwnerDisplay } from '../../types/DomainTypes';
import { IUser, IUserDisplay } from '../../types/UserTypes';
import { api } from 'boot/axios';
import SharingUserList from 'components/ShareDomain/SharingUserList.vue';
import RoleLabel from 'components/ShareDomain/RoleLabel.vue';
import { Dialog } from 'quasar'
interface Props {
modelValue: boolean;
domain: IDomainOwnerDisplay;
dialogTitle: string;
userListTitle: string;
shareApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
removeSharedApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
getSharedApi: (domain: IDomainOwnerDisplay) => Promise<any>;
}
interface IUserDisplayWithShareRole extends IUserDisplay {
isRemoving: boolean;
role: number;
}
const props = defineProps<Props>();
@@ -69,17 +99,16 @@ const emit = defineEmits<{
}>();
const addLoading = ref(false);
const removingUser = ref<IUserDisplay>();
const loading = ref(true);
const visible = ref(props.modelValue);
const allUsers = ref<IUserDisplay[]>([]);
const sharedUsers = ref<IUserDisplay[]>([]);
const allUsers = ref<IUserDisplayWithShareRole[]>([]);
const sharedUsers = ref<IUserDisplayWithShareRole[]>([]);
const sharedUsersIdSet = new Set<number>();
const canSharedUsers = ref<IUserDisplay[]>([]);
const canSharedUserFilter = ref<IUserDisplay>();
const canSharedUserFilteredOptions = ref<IUserDisplay[]>([]);
const canSharedUsers = ref<IUserDisplayWithShareRole[]>([]);
const canSharedUserFilter = ref<IUserDisplayWithShareRole>();
const canSharedUserFilteredOptions = ref<IUserDisplayWithShareRole[]>([]);
const filterFn = (val:string, update: (cb: () => void) => void) => {
update(() => {
@@ -99,7 +128,12 @@ watch(
visible.value = newValue;
sharedUsers.value = [];
canSharedUserFilter.value = undefined
loading.value = false;
addLoading.value = false;
if (newValue) {
if (Object.keys(allUsers.value).length == 0) {
await getUsers();
}
await loadShared();
}
}
@@ -130,7 +164,7 @@ const checkClose = () => {
}).onCancel(() => {
close();
}).onOk(() => {
shareTo(canSharedUserFilter.value as IUserDisplay);
shareTo(canSharedUserFilter.value as IUserDisplayWithShareRole);
});
};
@@ -138,35 +172,42 @@ const close = () => {
emit('close');
};
const shareTo = async (user: IUserDisplay) => {
const shareTo = async (user: IUserDisplayWithShareRole) => {
addLoading.value = true;
loading.value = true;
await api.post(`api/domain/${user.id}?domainid=${props.domain.id}`)
await props.shareApi(user, props.domain);
await loadShared();
canSharedUserFilter.value = undefined;
loading.value = false;
addLoading.value = false;
}
const removeShareTo = async (user: IUserDisplay) => {
removingUser.value = user;
const removeShareTo = async (user: IUserDisplayWithShareRole) => {
loading.value = true;
await api.delete(`api/domain/${props.domain.id}/${user.id}`)
user.isRemoving = true;
await props.removeSharedApi(user, props.domain);
await loadShared();
loading.value = false;
removingUser.value = undefined;
};
const loadShared = async () => {
loading.value = true;
sharedUsersIdSet.clear();
const { data } = await api.get(`/api/domainshareduser/${props.domain.id}`);
const { data } = await props.getSharedApi(props.domain);
sharedUsers.value = data.data.map((item: IUser) => {
const val = itemToDisplay(item);
sharedUsersIdSet.add(val.id);
// for sort
if (isOwner(item.id)) {
val.role = 2;
} else if (isManager(item.id)) {
val.role = 1;
} else {
val.role = 0;
}
return val;
});
}).reverse().sort((a: IUserDisplayWithShareRole, b: IUserDisplayWithShareRole) => b.role - a.role);
canSharedUsers.value = allUsers.value.filter((item) => !sharedUsersIdSet.has(item.id));
canSharedUserFilteredOptions.value = canSharedUsers.value;
@@ -174,14 +215,15 @@ const loadShared = async () => {
loading.value = false;
}
onMounted(async () => {
await getUsers();
})
function isOwner(userId: number) {
return userId === props.domain?.owner?.id
}
function isManager(userId: number) {
return false // TODO
}
const getUsers = async () => {
if (Object.keys(allUsers.value).length > 0) {
return;
}
loading.value = true;
const result = await api.get(`api/v1/users`);
allUsers.value = result.data.data.map(itemToDisplay);
@@ -198,13 +240,16 @@ const itemToDisplay = (item: IUser) => {
email: item.email,
isSuperuser: item.is_superuser,
isActive: item.is_active,
} as IUserDisplay
role: 0,
} as IUserDisplayWithShareRole
}
</script>
<style lang="scss">
.dialog-content {
width: 60vw;
width: 700px !important;
max-width: 80vw !important;
max-height: 80vh;
.q-select {
min-width: 0 !important;

View File

@@ -0,0 +1,56 @@
<template>
<share-domain-dialog
:dialogTitle="`「${domain.name}」のドメイン管理権限設定`"
userListTitle="ドメイン管理権限を持つユーザー"
:domain="domain"
:share-api="shareApi"
:remove-shared-api="removeSharedApi"
:get-shared-api="getSharedApi"
:model-value="modelValue"
@update:modelValue="updateModelValue"
@close="close"
/>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
import ShareDomainDialog from 'components/ShareDomain/ShareDomainDialog.vue';
import { IUserDisplay } from '../../types/UserTypes';
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
import { api } from 'boot/axios';
interface Props {
modelValue: boolean;
domain: IDomainOwnerDisplay;
}
const props = defineProps<Props>();
async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
return api.post(`api/managedomain`, {
userid: user.id,
domainid: domain.id,
});
}
async function removeSharedApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
return api.delete(`api/managedomain/${domain.id}/${user.id}`);
}
async function getSharedApi(domain: IDomainOwnerDisplay) {
return api.get(`/api/managedomainuser/${domain.id}`);
}
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void;
(e: 'close'): void;
}>();
const updateModelValue = (value: boolean) => {
emit('update:modelValue', value);
};
const close = () => {
emit('close');
};
</script>

View File

@@ -0,0 +1,56 @@
<template>
<share-domain-dialog
:dialogTitle="`「${domain.name}」のドメイン利用権限設定`"
userListTitle="ドメイン利用権限を持つユーザー"
:domain="domain"
:share-api="shareApi"
:remove-shared-api="removeSharedApi"
:get-shared-api="getSharedApi"
:model-value="modelValue"
@update:modelValue="updateModelValue"
@close="close"
/>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
import ShareDomainDialog from 'components/ShareDomain/ShareDomainDialog.vue';
import { IUserDisplay } from '../../types/UserTypes';
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
import { api } from 'boot/axios';
interface Props {
modelValue: boolean;
domain: IDomainOwnerDisplay;
}
const props = defineProps<Props>();
async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
return api.post(`api/userdomain`, {
userid: user.id,
domainid: domain.id,
});
}
async function removeSharedApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
return api.delete(`api/domain/${domain.id}/${user.id}`);
}
async function getSharedApi(domain: IDomainOwnerDisplay) {
return api.get(`/api/domainshareduser/${domain.id}`);
}
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void;
(e: 'close'): void;
}>();
const updateModelValue = (value: boolean) => {
emit('update:modelValue', value);
};
const close = () => {
emit('close');
};
</script>

View File

@@ -10,10 +10,17 @@
</q-input>
</template>
<template v-slot:body-cell-actions="props">
<q-td :props="props">
<slot name="actions" :row="props.row"></slot>
</q-td>
<template v-for="col in columns" :key="col.name" v-slot:[`body-cell-${col.name}`]="props">
<slot :name="`body-cell-${col.name}`" :row="props.row" :column="props.col">
<!-- 默认内容 -->
<q-td v-if="col.name !== 'actions'" :props="props" >
<span>{{ props.row[col.name] }}</span>
</q-td>
<!-- actions -->
<q-td v-else auto-width :props="props">
<slot name="actions" :row="props.row"></slot>
</q-td>
</slot>
</template>
</q-table>
</template>
@@ -37,9 +44,10 @@ const columns = [
{ name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true },
{ name: 'fullName', label: '名前', field: 'fullName', align: 'left', sortable: true },
{ name: 'email', label: '電子メール', field: 'email', align: 'left', sortable: true },
{ name: 'role', label: '', field: 'role', align: 'left', sortable: false },
{ name: 'actions', label: '', field: 'actions', sortable: false },
];
const filter = ref('');
const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 10 });
const pagination = ref({ rowsPerPage: 10 });
</script>

View File

@@ -6,9 +6,10 @@
<div class="text-h6 ellipsis">{{ item.name }}</div>
<div class="text-subtitle2">{{ item.url }}</div>
</div>
<div v-if="!isOwnerFunc(item.owner.id)" class="col-auto">
<div class="col-auto">
<!-- <q-badge color="secondary" text-color="white" align="middle" class="q-mb-xs" label="他人の所有" /> -->
<q-chip square color="secondary" text-color="white" icon="people" label="他人の所有" size="sm" />
<q-chip v-if="!isOwnerFunc(item.owner.id)" square color="secondary" text-color="white" icon="people" label="他人の所有" size="sm" />
<q-chip v-else square color="purple" text-color="white" icon="people" label="自分" size="sm" />
</div>
</div>
@@ -25,7 +26,7 @@
<div class="text-grey-7 text-caption text-weight-medium">
所有者
</div>
<div class="smaller-font-size">{{ item.owner.fullName }}</div>
<div class="smaller-font-size">{{ !isOwnerFunc(item.owner.id) ? item.owner.fullName : '自分' }}</div>
</div>
</div>
</q-card-section>

View File

@@ -28,6 +28,14 @@
</a>
</q-td>
</template>
<template v-slot:body-cell-version="p">
<q-td :props="p">
<div class="flex justify-between">
<span>{{ p.row.version }}</span>
<q-badge v-if="isVersionEditing(p.row)" color="orange-7">変更あり</q-badge>
</div>
</q-td>
</template>
<template v-slot:body-cell-actions="p">
<q-td :props="p">
<table-action-menu :row="p.row" minWidth="180px" max-width="200px" :actions="actionList" />
@@ -112,6 +120,11 @@ const getApps = async () => {
loading.value = false;
}
function isVersionEditing(app:IAppDisplay) {
// TODO
return false;
};
onMounted(async () => {
await getApps();
});

View File

@@ -29,9 +29,12 @@
<template v-slot:body-cell-id="p">
<q-td :props="p">
<div class="flex justify-between">
<div class="">
<span>{{ p.row.id }}</span>
<q-badge v-if="p.row.id === app.version" color="primary">適用中</q-badge>
<span class="q-ml-md" v-if="p.row.id === app.version">
<q-badge color="primary">適用中</q-badge>
<q-badge class="q-ml-xs" v-if="isVersionEditing()" color="orange-7">変更あり</q-badge>
</span>
</div>
</q-td>
</template>
@@ -54,14 +57,23 @@
<q-dialog v-model="confirmDialog" persistent>
<q-card>
<q-card-section class="row items-center">
<q-icon name="warning" color="warning" size="2em" />
<span class="q-ml-sm">削除してもよろしいですか</span>
<q-card-section class="q-pb-none">
<q-list>
<q-item>
<q-item-section avatar>
<q-icon name="warning" color="warning" size="2em" />
</q-item-section>
<q-item-section>
<div >現在のバージョンは未保存です</div>
<div >プルすると上書されますのでよろしいでしょうか</div>
</q-item-section>
</q-item>
</q-list>
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="Cancel" color="primary" v-close-popup />
<q-btn flat label="OK" color="primary" :loading="deleteUserLoading" @click="deleteApp" />
<q-btn flat label="キャンセル" color="primary" v-close-popup />
<q-btn flat label="上書きする" color="primary" :loading="deleteUserLoading" @click="doChangeVersion()" />
</q-card-actions>
</q-card>
</q-dialog>
@@ -132,6 +144,11 @@ const getVersions = async () => {
versionLoading.value = false;
}
function isVersionEditing() {
// TODO
return false;
};
onMounted(async () => {
let isSuccess = getAppById();
if (!isSuccess) {
@@ -150,25 +167,26 @@ onMounted(async () => {
});
async function changeVersion(version: IAppVersionDisplay) {
// TODO
versionLoading.value = true;
target.value = version;
if (!isVersionEditing()) {
await doChangeVersion(version);
} else {
confirmDialog.value = true;
}
}
async function doChangeVersion(version?: IAppVersionDisplay) {
if (!version) {
version = target.value as IAppVersionDisplay;
}
confirmDialog.value = false;
versionLoading.value = true;
await appStore.changeVersion(app.value, version);
await getApps();
getAppById();
versionLoading.value = false;
}
// const deleteApp = async () => {
// if (target.value?.id) {
// deleteUserLoading.value = true;
// await appStore.deleteApp(targetRow.value)
// await getApps();
// deleteUserLoading.value = false;
// confirmDialog.value = false;
// }
// }
async function toEditFlowPage() {
store.setApp({
appId: app.value.id,

View File

@@ -54,7 +54,7 @@
<q-breadcrumbs-el icon="widgets" label="アプリ管理" to="/app" />
<q-breadcrumbs-el>
<template v-slot>
<a class="full-width" :href="!store.appInfo?'':`${authStore.currentDomain.kintoneUrl}/k/${store.appInfo?.appId}`" target="_blank" title="Kiontoneへ">
<a class="full-width" :href="store.appInfo ? `${authStore.currentDomain.kintoneUrl}/k/${store.appInfo?.appId}` : ''" target="_blank" title="Kiontoneへ">
{{ store.appInfo?.name }}
<q-icon
class="q-ma-xs"
@@ -99,11 +99,12 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { IActionNode, ActionNode, IActionFlow, ActionFlow, RootAction, IActionProperty } from 'src/types/ActionTypes';
import { IActionNode, ActionNode, IActionFlow, ActionFlow, RootAction, IActionProperty, AppInfo } from 'src/types/ActionTypes';
import { IAppDisplay, IManagedApp, IVersionSubmit } from 'src/types/AppTypes';
import { storeToRefs } from 'pinia';
import { useFlowEditorStore } from 'stores/flowEditor';
import { useAuthStore } from 'stores/useAuthStore';
import { useAppStore } from 'stores/useAppStore';
import { api } from 'boot/axios';
import NodeItem from 'src/components/main/NodeItem.vue';
@@ -119,10 +120,11 @@ const deployLoading = ref(false);
const saveLoading = ref(false);
const initLoading = ref(true);
const drawerLeft = ref(false);
const versionSubmit = ref<IVersionSubmit>();
const versionSubmit = ref<IVersionSubmit>({} as IVersionSubmit);
const $q = useQuasar();
const store = useFlowEditorStore();
const authStore = useAuthStore();
const appStore = useAppStore();
const route = useRoute()
const appDg = ref();
@@ -262,18 +264,15 @@ const onSaveActionProps=(props:IActionProperty[])=>{
};
const onSaveVersion = async () => {
versionSubmit.value = { appId: store.appInfo?.appId }
if (!store.appInfo) return;
versionSubmit.value = { appId: store.appInfo.appId }
saveVersionAction.value = true;
}
const closeSaveVersionDg = async (val: 'OK'|'CANCEL') => {
if (val == 'OK') {
await onSaveAllFlow();
await api.post('api/apps', {
'appid': versionSubmit.value?.appId,
'versionname': versionSubmit.value?.name,
'comment': versionSubmit.value?.comment
})
await appStore.createVersion(versionSubmit.value);
}
}
@@ -395,9 +394,9 @@ const onClearFilter=()=>{
filter.value='';
}
onMounted(() => {
onMounted(async () => {
authStore.setLeftMenu(false);
fetchData();
await fetchData();
});
</script>

View File

@@ -112,28 +112,34 @@
<q-dialog v-model="confirm" persistent>
<q-card>
<!-- -1 loading -->
<q-card-section v-if="deleteLoadingState == -1" class="row items-center">
<q-spinner color="primary" size="2em"/>
<span class="q-ml-sm">ドメイン利用権限を確認中</span>
<span class="q-ml-sm">ドメイン利用/管理権限を確認中</span>
</q-card-section>
<q-card-section v-else-if="deleteLoadingState == 0" class="row items-center">
<q-icon name="warning" color="warning" size="2em" />
<span class="q-ml-sm">削除してもよろしいですか</span>
</q-card-section>
<q-card-section v-else class="row items-center">
<!-- > 0 can't delete -->
<q-card-section v-else-if="deleteLoadingState > 0" class="row items-center">
<q-icon name="error" color="negative" size="2em" />
<span class="q-ml-sm">ドメインは使用中です。削除してもよろしいですか?</span>
</q-card-section>
<!-- 0/-2 can delete -->
<q-card-section v-else class="row items-center">
<q-icon name="warning" color="warning" size="2em" />
<span class="q-ml-sm">削除してもよろしいですか?</span>
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="キャンセル" color="primary" v-close-popup />
<q-btn v-if="deleteLoadingState > 0" label="実行" color="primary" v-close-popup @click="openShareDg(editId)" />
<q-btn flat v-else label="OK" :disabled="deleteLoadingState" color="primary" v-close-popup @click="deleteDomain()" />
<!-- > 0 can't delete -->
<q-btn v-if="deleteLoadingState > 0" label="実行" color="primary" v-close-popup @click="openShareDg(SHARE_MANAGE, editId)" />
<!-- 0/-2 can delete -->
<q-btn flat v-else label="OK" :disabled="deleteLoadingState == -1" :loading="deleteLoadingState == -2" color="primary" @click="deleteDomain()" />
</q-card-actions>
</q-card>
</q-dialog>
<share-domain-dialog v-model="shareDg" :domain="shareDomain" @close="closeShareDg()" />
<share-usage-dialog v-model="shareDg" :domain="shareDomain" @close="shareDg = false" />
<share-manage-dialog v-model="shareManageDg" :domain="shareDomain" @close="shareManageDg = false" />
</div>
</template>
@@ -142,7 +148,8 @@
import { ref, onMounted, computed } from 'vue';
import { api } from 'boot/axios';
import { useAuthStore } from 'stores/useAuthStore';
import ShareDomainDialog from 'components/ShareDomain/ShareDomainDialog.vue';
import ShareUsageDialog from 'components/ShareDomain/ShareUsageDialog.vue';
import ShareManageDialog from 'components/ShareDomain/ShareManageDialog.vue';
import TableActionMenu from 'components/TableActionMenu.vue';
import { IDomain, IDomainDisplay, IDomainOwnerDisplay, IDomainSubmit } from '../types/DomainTypes';
@@ -171,7 +178,7 @@ const columns = [
const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
const loading = ref(false);
const addEditLoading = ref(false);
const deleteLoadingState = ref<number>(-1); // -1: loading, 0: allow, > 0: user count
const deleteLoadingState = ref<number>(-1); // -2: deleteLoading, -1: loading, 0: allow, > 0: user count
const filter = ref('');
const rows = ref<IDomainOwnerDisplay[]>([]);
@@ -191,6 +198,7 @@ const domainActive = ref(true);
const isCreate = ref(true);
let editId = ref(0);
const shareDg = ref(false);
const shareManageDg = ref(false);
const shareDomain = ref<IDomainOwnerDisplay>({} as IDomainOwnerDisplay);
const activeOptions = [
@@ -214,9 +222,13 @@ const activeFilterUpdate = (option: {value: number}) => {
}
}
const SHARE_USE = 'use';
const SHARE_MANAGE = 'manage';
const actionList = [
{ label: '編集', icon: 'edit_note', action: editRow },
{ label: '利用権限設定', icon: 'person_add_alt', action: openShareDg },
{ label: '利用権限設定', icon: 'person_add_alt', action: (row: IDomainOwnerDisplay) => {openShareDg(SHARE_USE, row)} },
{ label: '管理権限設定', icon: 'add_moderator', action: (row: IDomainOwnerDisplay) => {openShareDg(SHARE_MANAGE, row)} },
{ separator: true },
{ label: '削除', icon: 'delete_outline', class: 'text-red', action: removeRow },
];
@@ -269,15 +281,17 @@ async function removeRow(row: IDomainOwnerDisplay) {
}
const deleteDomain = () => {
deleteLoadingState.value = -2;
api.delete(`api/domain/${editId.value}`).then(({ data }) => {
if (!data.data) {
// TODO dialog
}
confirm.value = false;
deleteLoadingState.value = -1;
getDomain();
// authStore.setCurrentDomain();
})
editId.value = 0; // set in removeRow()
deleteLoadingState.value = -1;
};
function editRow(row) {
@@ -333,18 +347,18 @@ const onSubmit = () => {
})
}
function openShareDg(row: IDomainOwnerDisplay|number) {
function openShareDg(type: typeof SHARE_MANAGE|typeof SHARE_USE, row: IDomainOwnerDisplay|number) {
if (typeof row === 'number') {
row = rows.value.find(item => item.id === row) as IDomainOwnerDisplay;
}
shareDomain.value = row ;
shareDg.value = true;
shareDomain.value = row;
if (type === SHARE_USE) {
shareDg.value = true;
} else if (type === SHARE_MANAGE) {
shareManageDg.value = true;
}
};
function closeShareDg() {
shareDg.value = false;
}
const onReset = () => {
name.value = '';
url.value = '';

View File

@@ -112,7 +112,10 @@ const addUserDomainFinished = async (val: string) => {
const selected = addDomainRef.value.selected;
if (val == 'OK' && selected.length > 0) {
addUserDomainLoading.value = true;
const { data } = await api.post(`api/domain/${authStore.userId}?domainid=${selected[0].id}`)
const { data } = await api.post(`api/userdomain`, {
userid: authStore.userId,
domainid: selected[0].id,
});
if (rows.value.length === 0 && data.data) {
const domain = data.data;
await authStore.setCurrentDomain({

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
import { api } from 'boot/axios';
import { IAppDisplay, IAppVersion, IAppVersionDisplay, IManagedApp } from 'src/types/AppTypes';
import { IAppDisplay, IAppVersion, IAppVersionDisplay, IManagedApp, IVersionSubmit } from 'src/types/AppTypes';
import { IUser } from 'src/types/UserTypes';
import { date, Notify } from 'quasar'
@@ -35,15 +35,6 @@ export const useAppStore = defineStore('app', {
return this.apps.find((item: IAppDisplay) => item.id === id);
},
async getVersionsByAppId(app: IAppDisplay) {
const { data } = await api.get(`api/appversions/${app.id}`);
return data.data.map((item: IAppVersion) => versionToVersionDisplay(item));
},
async changeVersion(app: IAppDisplay, version: IAppVersionDisplay) {
await api.put(`api/appversions/${app.id}/${version.id}`);
},
async deleteApp(app: IAppDisplay) {
try {
await api.delete(`api/apps/${app.id}`);
@@ -59,6 +50,23 @@ export const useAppStore = defineStore('app', {
return true;
},
async getVersionsByAppId(app: IAppDisplay) {
const { data } = await api.get(`api/appversions/${app.id}`);
return data.data.map((item: IAppVersion) => versionToVersionDisplay(item));
},
async changeVersion(app: IAppDisplay, version: IAppVersionDisplay) {
await api.put(`api/appversions/${app.id}/${version.id}`);
},
async createVersion(versionSubmit: IVersionSubmit) {
await api.post('api/apps', {
'appid': versionSubmit.appId,
'versionname': versionSubmit.name,
'comment': versionSubmit.comment
})
},
reset() {
this.apps = [];
this.rowIds.clear();

View File

@@ -21,12 +21,6 @@ export interface IAppDisplay{
version:number;
}
export interface IVersionInfo {
id: string;
name?: string;
desc?: string;
}
export interface IVersionSubmit {
appId: string;
name?: string;