Skip to content

Commit

Permalink
feat: device management
Browse files Browse the repository at this point in the history
  • Loading branch information
ChingCdesu committed Oct 7, 2023
1 parent 42fbddc commit 63ff645
Show file tree
Hide file tree
Showing 6 changed files with 360 additions and 5 deletions.
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions src/components/home/Content/Admin/Devices.vue

This file was deleted.

141 changes: 141 additions & 0 deletions src/components/home/Content/Admin/Devices/DeviceEditModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<script lang="ts" setup>
import { Community } from "@/api/v1/dtos/community";
import { ref } from "vue";
import {
NCard,
NForm,
NButton,
NSpace,
NInput,
NCheckbox,
NFormItem,
NText,
FormInst,
FormRules,
} from "naive-ui";
import {
addCommunity,
// updateCommunityInfo,
} from "@/api/v1/management/communities";
import { useI18n } from "vue-i18n";
const props = defineProps<{
community?: Community;
isNew: boolean;
}>();
const emit = defineEmits<{
(e: "close"): void;
(e: "updated", community: Community): void;
}>();
const { t } = useI18n();
const community = ref<Partial<Community>>(props.community ?? {});
const formRef = ref<FormInst | undefined>();
const rules: FormRules = {
name: {
required: true,
message: t("message.common.required", {
field: t("message.admin.community.column.name"),
}),
trigger: "blur",
},
subnet: {
required: true,
message: t("message.common.required", {
field: t("message.admin.community.column.subnet"),
}),
trigger: "blur",
},
};
function handleSubmit() {
formRef.value?.validate((errors) => {
if (errors) {
return;
}
if (props.isNew) {
handleAdd();
} else {
handleUpdate();
}
});
}
async function handleAdd() {
const response = await addCommunity({
name: community.value.name!,
subnet: community.value.subnet!,
encryption: community.value.encryption!,
});
emit("updated", response.data.data!);
}
function handleUpdate() {
// updateCommunityInfo(community.value.id!, {
// name: community.value.name!,
// subnet: community.value.subnet!,
// encryption: community.value.encryption!,
// });
}
</script>

<template>
<NCard class="w-1/2">
<template #header>
<NText>
{{
props.isNew
? $t("message.admin.community.edit.createNewCommunity")
: $t("message.admin.community.edit.editCommunity")
}}
</NText>
</template>
<template #default>
<NForm
label-placement="left"
label-width="auto"
ref="formRef"
:model="community"
:rules="rules"
>
<NFormItem
:label="$t('message.admin.community.column.name')"
required
path="name"
>
<NInput v-model:value="community.name" />
</NFormItem>
<NFormItem
:label="$t('message.admin.community.column.subnet')"
required
path="subnet"
>
<NInput v-model:value="community.subnet" />
</NFormItem>
<NFormItem
:label="$t('message.admin.community.authority.private')"
path="encryption"
>
<NCheckbox v-model:checked="community.encryption" />
</NFormItem>
</NForm>
</template>
<template #footer>
<NSpace align="center" justify="end">
<NButton type="primary" @click="handleSubmit">
{{
isNew ? $t("message.common.create") : $t("message.common.update")
}}
</NButton>
<NButton @click="emit('close')">
{{ $t("message.common.cancel") }}
</NButton>
</NSpace>
</template>
</NCard>
</template>
197 changes: 197 additions & 0 deletions src/components/home/Content/Admin/Devices/Devices.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
<script lang="ts" setup>
import { Device } from "@/api/v1/dtos/devices";
import {
DataTableColumns,
NDataTable,
NTag,
NTime,
NButton,
NSpace,
NModal,
useDialog,
} from "naive-ui";
import { h, ref, onMounted, type Ref, reactive } from "vue";
import { useI18n } from "vue-i18n";
import { listDevices, deleteDevice } from "@/api/v1/management/devices";
import { listCommunities } from "@/api/v1/management/communities";
import { Icon } from "@vicons/utils";
import { Edit, Trash, Refresh, Plus } from "@vicons/tabler";
import DeviceEditModal from "./DeviceEditModal.vue";
const { t } = useI18n();
const dialog = useDialog();
const communities: Ref<Device[]> = ref([]);
const showEditModal = ref(false);
const editIsNew = ref(false);
const editingDevice: Ref<Device | undefined> = ref();
const pagination = reactive({
page: 1,
pageSize: 10,
itemCount: 0,
showSizePicker: true,
pageSizes: [5, 10, 20],
onChange(page: number) {
pagination.page = page;
},
onUpdatePageSize: (pageSize: number) => {
pagination.pageSize = pageSize;
pagination.page = 1;
},
});
const columns: DataTableColumns<Device> = [
{
title: t("message.admin.device.column.name"),
key: "name",
},
{
title: t("message.admin.device.column.status"),
key: "isOnline",
render(row) {
return h(
NTag,
{
type: row.isOnline ? "success" : "error",
},
() => t(`message.admin.device.status.${row.isOnline ? "online" : "offline"}`)
);
}
},
{
title: t("message.admin.device.column.community"),
key: "community",
render(row) {
return row.community.name;
},
},
{
title: t("message.admin.device.column.mac"),
key: "mac",
render(row) {
return row.mac?.toUpperCase() ?? '-';
},
},
{
title: t("message.admin.device.column.ip"),
key: "ip",
render(row) {
return row.ip ?? '-';
},
},
{
title: t("message.admin.device.column.createdAt"),
key: "createdAt",
render(row) {
return h(NTime, {
time: new Date(row.createdAt),
});
},
},
{
title: t("message.admin.device.column.updatedAt"),
key: "updatedAt",
render(row) {
return h(NTime, {
time: new Date(row.updatedAt),
});
},
},
{
title: t("message.admin.device.column.action"),
key: "actions",
render(row) {
return h(NSpace, () => [
() => h(
NButton,
{
type: "warning",
secondary: true,
onClick() {
handleEdit(row);
},
},
() => h(Icon, () => h(Edit)),
),
h(
NButton,
{
type: "error",
secondary: true,
onClick() {
handleRemove(row);
},
},
() => h(Icon, () => h(Trash))
),
]);
},
},
];
async function getCommunities() {
const res = await listCommunities({
page: pagination.page,
limit: pagination.pageSize,
});
communities.value = res.data.data?.data ?? [];
pagination.itemCount = res.data.data?.meta.itemCount ?? 0;
}
function handleEdit(device: Device) {}
function handleRemove(device: Device) {
dialog.warning({
title: t("message.admin.device.remove.confirm"),
content: t("message.admin.device.remove.confirmTip"),
positiveText: t("message.common.confirm"),
negativeText: t("message.common.cancel"),
onPositiveClick() {
deleteDevice(device.id).then(getCommunities);
},
});
}
function handleAdd() {
editIsNew.value = true;
editingDevice.value = undefined;
showEditModal.value = true;
}
onMounted(getCommunities);
</script>

<template>
<div class="p-4">
<NSpace justify="end" align="center" class="mb-4">
<NButton quaternary circle @click="handleAdd">
<template #icon>
<Plus />
</template>
</NButton>
<NButton quaternary circle @click="getCommunities">
<template #icon>
<Refresh />
</template>
</NButton>
</NSpace>
<NDataTable
:columns="columns"
:data="communities"
:pagination="pagination"
/>
<NModal v-model:show="showEditModal">
<DeviceEditModal
:is-new="editIsNew"
:device="editingDevice"
@close="showEditModal = false"
@updated="
showEditModal = false;
getCommunities();
"
/>
</NModal>
</div>
</template>
File renamed without changes.
22 changes: 21 additions & 1 deletion src/i18n/locales/zh-cn.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,24 @@ message:
remove:
removeCommunity: 删除社群
confirm: 确认删除社群?
confirmTip: "注意:删除社群会同时删除该社群下的所有设备,且无法恢复!"
confirmTip: "注意:删除社群会同时删除该社群下的所有设备,且无法恢复!"
device:
column:
name: 设备名称
status: 状态
community: 所属社群
mac: MAC地址
ip: IP地址
protocol: 连接协议
owner: 归属于
lastSeen: 最后连接于
status:
online: 在线
offline: 离线
edit:
createNewDevice: 添加新设备
editDevice: 编辑设备
remove:
removeDevice: 删除设备
confirm: 确认删除设备?
confirmTip: "注意:删除设备后无法恢复!"

0 comments on commit 63ff645

Please sign in to comment.