fix: update gitignore to unignore logs view, update main.scss to use @use
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
# Logs
|
# Logs
|
||||||
logs
|
/logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
// /src/assets/styles/main.scss
|
// /src/assets/styles/main.scss
|
||||||
|
|
||||||
@import '@fontsource/vazirmatn/400.css';
|
@use '@fontsource/vazirmatn/400.css' as *;
|
||||||
@import '@fontsource/vazirmatn/500.css';
|
@use '@fontsource/vazirmatn/500.css' as *;
|
||||||
@import '@fontsource/vazirmatn/700.css';
|
@use '@fontsource/vazirmatn/700.css' as *;
|
||||||
|
|
||||||
|
@use './light-theme' as *;
|
||||||
|
@use './dark-theme' as *;
|
||||||
|
@use './rtl-overrides' as *;
|
||||||
|
|
||||||
|
|
||||||
@import './light-theme.scss';
|
|
||||||
@import './dark-theme.scss';
|
|
||||||
@import './rtl-overrides.scss';
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
<!-- /src/views/logs/LogListView.vue -->
|
||||||
|
<template>
|
||||||
|
<div class="log-list-view">
|
||||||
|
<PageHeader :title="$t('logs.title')" :subtitle="$t('logs.subtitle')" />
|
||||||
|
|
||||||
|
<DataTableWrapper
|
||||||
|
:items="items"
|
||||||
|
:totalCount="totalCount"
|
||||||
|
:page="queryParams.page"
|
||||||
|
:limit="queryParams.limit"
|
||||||
|
:sortBy="queryParams.sortBy"
|
||||||
|
:sortOrder="queryParams.sortOrder"
|
||||||
|
:loading="isLoading"
|
||||||
|
@page-change="onPageChange"
|
||||||
|
@sort-change="onSort"
|
||||||
|
@search-change="onSearch"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<div class="flex align-items-center gap-2 flex-wrap">
|
||||||
|
<Select
|
||||||
|
v-model="selectedAction"
|
||||||
|
:options="actionOptions"
|
||||||
|
optionLabel="label"
|
||||||
|
optionValue="value"
|
||||||
|
placeholder="فیلتر بر اساس عملیات"
|
||||||
|
showClear
|
||||||
|
class="w-14rem text-sm"
|
||||||
|
@change="onActionFilter"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
icon="pi pi-refresh"
|
||||||
|
text
|
||||||
|
rounded
|
||||||
|
v-tooltip.top="'بروزرسانی'"
|
||||||
|
:loading="isLoading"
|
||||||
|
@click="loadData"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<Column field="createdAt" header="زمان" style="min-width: 9rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
<span class="text-sm text-color">{{ formatJalaliWithTime(data.createdAt) }}</span>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column field="actorName" header="کاربر" style="min-width: 10rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
<div class="flex flex-column">
|
||||||
|
<span class="font-semibold text-color">
|
||||||
|
{{ data.actorName || data.actor?.name || data.actorUsername || '—' }}
|
||||||
|
</span>
|
||||||
|
<span v-if="data.actorUsername || data.actor?.username" class="text-xs text-muted" dir="ltr">
|
||||||
|
@{{ data.actorUsername || data.actor?.username }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column field="action" header="عملیات" style="min-width: 8rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
<Tag :value="getActionLabel(data.action)" :severity="getActionSeverity(data.action)" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column field="resource" header="بخش" style="min-width: 8rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
<span class="font-medium text-color">{{ getResourceLabel(data.resource) }}</span>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column field="description" header="شرح">
|
||||||
|
<template #body="{ data }">
|
||||||
|
<span class="text-sm text-color line-clamp-2" :title="data.description">
|
||||||
|
{{ data.description || '—' }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column field="statusCode" header="وضعیت" style="width: 6rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
<Tag
|
||||||
|
:value="toPersianDigits(data.statusCode || '-')"
|
||||||
|
:severity="data.statusCode >= 400 ? 'danger' : 'success'"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column field="method" header="متد" style="width: 5.5rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
<span class="text-xs font-bold" dir="ltr">{{ data.method }}</span>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
</DataTableWrapper>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { useDataTable } from '@/composables/useDataTable';
|
||||||
|
import { usePersianDate } from '@/composables/usePersianDate';
|
||||||
|
import { activityLogApi } from '@/api/activityLogApi';
|
||||||
|
import PageHeader from '@/components/common/PageHeader.vue';
|
||||||
|
import DataTableWrapper from '@/components/common/DataTableWrapper.vue';
|
||||||
|
import Button from 'primevue/button';
|
||||||
|
import Column from 'primevue/column';
|
||||||
|
import Tag from 'primevue/tag';
|
||||||
|
import Select from 'primevue/select';
|
||||||
|
|
||||||
|
const { toPersianDigits, formatJalaliWithTime } = usePersianDate();
|
||||||
|
|
||||||
|
const {
|
||||||
|
items,
|
||||||
|
totalCount,
|
||||||
|
isLoading,
|
||||||
|
queryParams,
|
||||||
|
loadData,
|
||||||
|
onPageChange,
|
||||||
|
onSort,
|
||||||
|
onSearch,
|
||||||
|
setFilter
|
||||||
|
} = useDataTable(activityLogApi.getAll, { action: '' });
|
||||||
|
|
||||||
|
const selectedAction = ref(null);
|
||||||
|
|
||||||
|
const actionOptions = [
|
||||||
|
{ label: 'ایجاد', value: 'create' },
|
||||||
|
{ label: 'ویرایش', value: 'update' },
|
||||||
|
{ label: 'حذف', value: 'delete' },
|
||||||
|
{ label: 'ورود', value: 'login' },
|
||||||
|
{ label: 'خروج', value: 'logout' },
|
||||||
|
{ label: 'ثبتنام در دوره/کلاس', value: 'enroll' },
|
||||||
|
{ label: 'حضور و غیاب', value: 'attendance' },
|
||||||
|
{ label: 'آپلود فایل', value: 'upload' },
|
||||||
|
{ label: 'تلاش مجدد', value: 'retry' },
|
||||||
|
{ label: 'سایر', value: 'other' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const ACTION_LABELS = Object.fromEntries(actionOptions.map((o) => [o.value, o.label]));
|
||||||
|
|
||||||
|
const RESOURCE_LABELS = {
|
||||||
|
auth: 'احراز هویت',
|
||||||
|
users: 'کاربران',
|
||||||
|
professors: 'اساتید',
|
||||||
|
courses: 'دورهها',
|
||||||
|
classes: 'کلاسها',
|
||||||
|
sessions: 'جلسات',
|
||||||
|
payments: 'پرداختها',
|
||||||
|
roles: 'نقشها',
|
||||||
|
notifications: 'اطلاعیهها',
|
||||||
|
certificates: 'گواهینامهها',
|
||||||
|
files: 'فایلها',
|
||||||
|
dashboard: 'داشبورد',
|
||||||
|
'contact-inquiries': 'درخواستهای تماس',
|
||||||
|
contact_inquiries: 'درخواستهای تماس',
|
||||||
|
contactInquiries: 'درخواستهای تماس'
|
||||||
|
};
|
||||||
|
|
||||||
|
const getActionLabel = (action) => ACTION_LABELS[action] || action || '—';
|
||||||
|
|
||||||
|
const getActionSeverity = (action) => {
|
||||||
|
const map = {
|
||||||
|
create: 'success',
|
||||||
|
update: 'info',
|
||||||
|
delete: 'danger',
|
||||||
|
login: 'contrast',
|
||||||
|
logout: 'secondary',
|
||||||
|
enroll: 'success',
|
||||||
|
attendance: 'info',
|
||||||
|
upload: 'warning',
|
||||||
|
retry: 'warning',
|
||||||
|
other: 'secondary'
|
||||||
|
};
|
||||||
|
return map[action] || 'secondary';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getResourceLabel = (resource) => RESOURCE_LABELS[resource] || resource || '—';
|
||||||
|
|
||||||
|
const onActionFilter = () => {
|
||||||
|
setFilter('action', selectedAction.value || '');
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.line-clamp-2 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user