Created
June 20, 2024 11:07
-
-
Save NanamiNakano/59858f5b733c40b3341d96110ac7f40d to your computer and use it in GitHub Desktop.
Forward Rule Page
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script setup lang="ts"> | |
import type { QueryParams, RuleData } from "@nanaminakano/pfsdk" | |
const pfClient = usePfClient() | |
const toast = useToast() | |
const loading = ref(true) | |
const tableRowData = ref<RuleData[]>([]) | |
const tableColumns = [{ | |
key: "id", | |
label: "#", | |
}, { | |
key: "user_id", | |
label: "User ID", | |
}, { | |
key: "node_id", | |
label: "Node ID", | |
}, { | |
key: "name", | |
label: "Name", | |
}, { | |
key: "mode", | |
label: "Mode", | |
}, { | |
key: "protocol", | |
label: "Protocol", | |
}, { | |
key: "bind", | |
label: "Bound Port", | |
}, { | |
key: "targets", | |
label: "Targets", | |
}, { | |
key: "proxy_protocol", | |
label: "Proxy Protocol", | |
}, { | |
key: "status", | |
label: "Status", | |
}, { | |
key: "actions", | |
}] | |
const actionItems = (row: RuleData) => [ | |
[{ | |
label: "Edit", | |
icon: "i-tabler-pencil", | |
click: () => { slideIsOpen.value = true }, | |
}, { | |
label: "Delete", | |
icon: "i-tabler-trash", | |
click: async () => { | |
loading.value = true | |
await pfClient.forwardRule.delete(row.id).then(async (rps) => { | |
if (rps.Ok) { | |
toast.add({ title: "Delete successfully" }) | |
await fetchAll() | |
} | |
else { | |
toast.add({ title: "Delete unsuccessfully", description: rps.Msg, color: "red" }) | |
} | |
}) | |
loading.value = false | |
}, | |
}]] | |
const selected = ref<RuleData[]>([]) | |
const slideIsOpen = ref(false) | |
async function fetchAll(query?: QueryParams) { | |
loading.value = true | |
await pfClient.forwardRule.getRuleList(query).then((rps) => { | |
if (rps.Ok) { | |
tableRowData.value = rps.Data! | |
} | |
else { | |
tableRowData.value = [] | |
toast.add({ title: "Unable to load data", color: "red" }) | |
} | |
}) | |
loading.value = false | |
} | |
const filters = tableColumns.filter(item => !!item.label) as { key: string, label: string }[] | |
onMounted(async () => { | |
await fetchAll() | |
}) | |
</script> | |
<template> | |
<div class="flex flex-col space-y-2"> | |
<div class="flex space-x-2"> | |
<UButton label="New" /> | |
</div> | |
<RSearch | |
:filters="filters" | |
@search="(params) => { fetchAll(params) }" | |
/> | |
<RTable | |
v-model="selected" | |
:row-data="tableRowData" | |
:columns="tableColumns" | |
:actions="actionItems" | |
:loading="loading" | |
/> | |
<USlideover v-model="slideIsOpen"> | |
<div class="p-4 flex-1"> | |
<UButton | |
color="gray" | |
variant="ghost" | |
size="sm" | |
icon="i-tabler-x" | |
class="flex sm:hidden absolute end-5 top-5 z-10" | |
square | |
padded | |
@click="slideIsOpen = false" | |
/> | |
<USkeleton class="h-full" /> | |
</div> | |
</USlideover> | |
</div> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script setup lang="ts"> | |
import type { QueryParams } from "@nanaminakano/pfsdk" | |
const props = defineProps<{ | |
filters: { | |
key: string | |
label: string | |
select?: { key: number, label: string }[] | |
}[] | |
}>() | |
const emit = defineEmits(["search"]) | |
const search = ref("") | |
const precisely = ref(true) | |
const params = computed(() => { | |
return { | |
filter: props.filters[filterKey.value].key, | |
search: search.value, | |
exact: precisely.value, | |
} as QueryParams | |
}) | |
const filterKey = ref(0) | |
const dropdown = computed(() => { | |
return props.filters.map((item, index) => ({ | |
key: item.key, | |
label: item.label, | |
click: () => { | |
filterKey.value = index | |
if (props.filters[index].select) { | |
precisely.value = true | |
} | |
}, | |
})) | |
}) | |
</script> | |
<template> | |
<div class="flex space-x-2 items-center"> | |
<UDropdown :items="[dropdown]"> | |
<UButton | |
color="white" | |
:label="`${filters[filterKey].label}`" | |
trailing-icon="i-tabler-chevron-down" | |
/> | |
</UDropdown> | |
<TablerIcon name="equal" /> | |
<UDropdown | |
v-if="filters[filterKey].select" | |
:items="[filters[filterKey].select!]" | |
/> | |
<UInput | |
v-else | |
v-model="search" | |
/> | |
<UButton | |
:label="$t('r.search.search')" | |
@click="emit('search', params)" | |
/> | |
<div>{{ $t("r.search.precisely") }}</div> | |
<UToggle | |
v-model="precisely" | |
:disabled="!!filters[filterKey].select" | |
on-icon="i-tabler-check" | |
off-icon="i-tabler-x" | |
/> | |
</div> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script setup lang="ts" generic="T extends { [key: string]: any}"> | |
import type { DropdownItem } from "#ui/types" | |
const props = defineProps<{ | |
rowData: T[] | |
columns: { key: string, label?: string }[] | |
actions: (row: T) => DropdownItem[][] | |
loading: boolean | |
}>() | |
const model = defineModel({ type: Array }) | |
const tablePage = ref(1) | |
const tablePageCount = ref(10) | |
const tableRows = computed(() => ( | |
props.rowData.slice((tablePage.value - 1) * tablePageCount.value, (tablePage.value) * tablePageCount.value) | |
)) | |
const pageDropdown = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(item => ({ | |
label: (item * 5).toString(), | |
click: () => { | |
tablePageCount.value = item * 5 | |
tablePage.value = 1 | |
}, | |
}))] | |
</script> | |
<template> | |
<div class="flex flex-col space-y-2"> | |
<UTable | |
v-model="model" | |
:rows="tableRows" | |
:columns="columns" | |
:loading="loading" | |
class="border-gray-300 dark:border-gray-600 border rounded" | |
> | |
<template #actions-data="{ row }"> | |
<UDropdown :items="actions(row)"> | |
<UButton | |
color="gray" | |
variant="ghost" | |
icon="i-tabler-dots" | |
/> | |
</UDropdown> | |
</template> | |
</UTable> | |
<div class="flex justify-between"> | |
<div>{{ $t("r.table.count", [tableRows.length, rowData.length]) }}</div> | |
<div class="flex space-x-2"> | |
<UDropdown | |
:items="pageDropdown" | |
:ui="{ | |
width: 'w-24', | |
}" | |
> | |
<UButton | |
color="white" | |
:label="`${$t('r.table.pageCount', [tablePageCount])}`" | |
trailing-icon="i-tabler-chevron-down" | |
/> | |
</UDropdown> | |
<UPagination | |
v-model="tablePage" | |
:page-count="tablePageCount" | |
:total="rowData.length" | |
/> | |
</div> | |
</div> | |
</div> | |
</template> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment