Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-05-12 11:54:12 +03:00
parent a4f7d5b071
commit f9a035d11d
6 changed files with 122 additions and 181 deletions

View File

@@ -1,135 +0,0 @@
/* eslint-disable */
/**
* THIS FILE IS GENERATED AUTOMATICALLY.
* 1. DO NOT edit this file directly as it won't do anything.
* 2. EDIT the original quasar.config file INSTEAD.
* 3. DO NOT git commit this file. It should be ignored.
*
* This file is still here because there was an error in
* the original quasar.config file and this allows you to
* investigate the Node.js stack error.
*
* After you fix the original file, this file will be
* deleted automatically.
**/
// quasar.config.js
import { defineConfig } from "@quasar/app-webpack/wrappers";
var quasar_config_default = defineConfig(() => {
const apiBaseUrl = (process.env.VITE_API_BASE_URL || "/api").trim();
return {
/* =====================================================
APP INFO
===================================================== */
productName: "Baggi BSS",
productDescription: "Baggi Tekstil Business Support System",
/* =====================================================
BOOT FILES
===================================================== */
boot: ["dayjs", "locale", "resizeObserverGuard"],
/* =====================================================
GLOBAL CSS
===================================================== */
css: ["app.css"],
/* =====================================================
ICONS / FONTS
===================================================== */
extras: [
"roboto-font",
"material-icons"
],
/* =====================================================
BUILD (PRODUCTION)
===================================================== */
build: {
vueRouterMode: "hash",
env: {
VITE_API_BASE_URL: apiBaseUrl
},
esbuildTarget: {
browser: ["es2022", "firefox115", "chrome115", "safari14"],
node: "node20"
},
// Cache & performance
gzip: true,
preloadChunks: true
},
/* =====================================================
DEV SERVER (LOCAL)
===================================================== */
devServer: {
server: { type: "http" },
port: 9e3,
open: true,
client: {
overlay: {
errors: true,
warnings: false,
runtimeErrors: false
}
},
// DEV proxy (CORS'suz)
proxy: [
{
context: ["/api"],
target: "http://localhost:8080",
changeOrigin: true,
secure: false,
ws: true,
timeout: 0,
proxyTimeout: 0
}
]
},
/* =====================================================
QUASAR FRAMEWORK
===================================================== */
framework: {
config: {
notify: {
position: "top",
timeout: 2500
}
},
lang: "tr",
plugins: [
"Loading",
"Dialog",
"Notify"
]
},
animations: [],
/* =====================================================
SSR / PWA (DISABLED)
===================================================== */
ssr: {
prodPort: 3e3,
middlewares: ["render"],
pwa: false
},
pwa: {
workboxMode: "GenerateSW"
},
/* =====================================================
MOBILE / DESKTOP
===================================================== */
capacitor: {
hideSplashscreen: true
},
electron: {
preloadScripts: ["electron-preload"],
inspectPort: 5858,
bundler: "packager",
builder: {
appId: "baggisowtfaresystem"
}
},
bex: {
extraScripts: []
}
};
});
export {
quasar_config_default as default
};

View File

@@ -173,6 +173,7 @@ import { usePermissionStore } from 'stores/permissionStore'
import { useI18n } from 'src/composables/useI18n' import { useI18n } from 'src/composables/useI18n'
import { UI_LANGUAGE_OPTIONS } from 'src/i18n/languages' import { UI_LANGUAGE_OPTIONS } from 'src/i18n/languages'
import { useLocaleStore } from 'src/stores/localeStore' import { useLocaleStore } from 'src/stores/localeStore'
import { activityLogsMenuItem, getAuthUserId } from 'src/modules/activityLogs'
/* ================= STORES ================= */ /* ================= STORES ================= */
@@ -365,18 +366,6 @@ const menuItems = [
permission: 'system:update' permission: 'system:update'
}, },
{
label: 'Loglar',
to: '/app/activity-logs',
permission: 'system:read'
},
{
label: 'Test Mail',
to: '/app/test-mail',
permission: 'system:update'
},
{ {
label: 'Piyasa Mail Eşleştirme', label: 'Piyasa Mail Eşleştirme',
to: '/app/market-mail-mapping', to: '/app/market-mail-mapping',
@@ -385,6 +374,27 @@ const menuItems = [
] ]
}, },
{
label: 'SüperAdmin',
icon: 'admin_panel_settings',
onlyUserIds: activityLogsMenuItem.onlyUserIds,
children: [
{
label: 'Log İzleme',
to: activityLogsMenuItem.to,
permission: activityLogsMenuItem.permission,
onlyUserIds: activityLogsMenuItem.onlyUserIds
},
{
label: 'Test Mail',
to: '/app/test-mail',
permission: 'system:update',
onlyUserIds: activityLogsMenuItem.onlyUserIds
}
]
},
{ {
label: 'Dil Çeviri', label: 'Dil Çeviri',
icon: 'translate', icon: 'translate',
@@ -416,6 +426,16 @@ const menuItems = [
/* ================= FILTERED MENU ================= */ /* ================= FILTERED MENU ================= */
function isAllowedForUser (item) {
const only = item?.onlyUserIds
if (!Array.isArray(only) || only.length === 0) return true
const id = getAuthUserId(auth.user)
if (id == null) return false
return only.includes(id)
}
const filteredMenu = computed(() => { const filteredMenu = computed(() => {
if (!perm.loaded) return [] if (!perm.loaded) return []
@@ -424,9 +444,10 @@ const filteredMenu = computed(() => {
.map(item => { .map(item => {
if (item.children) { if (item.children) {
if (!isAllowedForUser(item)) return null
const children = item.children.filter(c => const children = item.children.filter(c =>
perm.hasApiPermission(c.permission) isAllowedForUser(c) && perm.hasApiPermission(c.permission)
) )
if (!children.length) return null if (!children.length) return null
@@ -437,6 +458,10 @@ const filteredMenu = computed(() => {
} }
} }
if (!isAllowedForUser(item)) {
return null
}
if (!perm.hasApiPermission(item.permission)) { if (!perm.hasApiPermission(item.permission)) {
return null return null
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<q-page v-if="canReadUser" class="act-page with-bg"> <q-page v-if="isAllowed" class="act-page with-bg">
<!-- ======================================================= <!-- =======================================================
🔍 FILTER BAR 🔍 FILTER BAR
@@ -218,14 +218,14 @@
<script setup> <script setup>
import { ref,onMounted, watch } from 'vue' import { ref, computed, onMounted, watch } from 'vue'
import { date } from 'quasar' import { date } from 'quasar'
import { useActivityLogStore } from 'src/stores/activityLogStore' import { useActivityLogStore } from 'src/stores/activityLogStore'
import { useAuthStore } from 'stores/authStore.js' import { useAuthStore } from 'stores/authStore.js'
import { usePermission } from 'src/composables/usePermission' import { usePermission } from 'src/composables/usePermission'
import { isActivityLogsAllowedUser } from 'src/modules/activityLogs'
const { canRead, canUpdate } = usePermission() const { canUpdate } = usePermission()
const canReadUser = canRead('user')
const canUpdateUser = canUpdate('user') const canUpdateUser = canUpdate('user')
const diffDialog = ref(false) const diffDialog = ref(false)
@@ -236,6 +236,7 @@ const selectedDiff = ref({
}) })
const store = useActivityLogStore() const store = useActivityLogStore()
const auth = useAuthStore() const auth = useAuthStore()
const isAllowed = computed(() => isActivityLogsAllowedUser(auth.user))
const categoryOptions = [ const categoryOptions = [
{ label: 'Auth', value: 'auth' }, { label: 'Auth', value: 'auth' },

View File

@@ -1,5 +1,6 @@
<template> <template>
<q-page v-if="canReadOrder" class="pcmm-page q-pa-md"> <q-page v-if="canReadOrder" class="pcmm-page q-pa-md">
<div class="pcmm-top">
<div class="pcmm-header row items-center q-col-gutter-md"> <div class="pcmm-header row items-center q-col-gutter-md">
<div class="col"> <div class="col">
<div class="text-h6">Maliyet Parca Eslestirme</div> <div class="text-h6">Maliyet Parca Eslestirme</div>
@@ -20,7 +21,9 @@
</div> </div>
<q-separator class="q-my-md" /> <q-separator class="q-my-md" />
</div>
<div class="pcmm-table-wrap">
<q-table <q-table
class="ol-table pcmm-table" class="ol-table pcmm-table"
flat flat
@@ -34,6 +37,7 @@
no-data-label="Kayit bulunamadi" no-data-label="Kayit bulunamadi"
:rows-per-page-options="[0]" :rows-per-page-options="[0]"
hide-bottom hide-bottom
sticky-header
> >
<template #header-cell="props"> <template #header-cell="props">
<q-th :props="props"> <q-th :props="props">
@@ -280,6 +284,7 @@
</q-td> </q-td>
</template> </template>
</q-table> </q-table>
</div>
</q-page> </q-page>
<q-page v-else class="q-pa-md flex flex-center"> <q-page v-else class="q-pa-md flex flex-center">
@@ -862,6 +867,11 @@ onMounted(async () => {
<style scoped> <style scoped>
.pcmm-page { .pcmm-page {
background: #fafafa; background: #fafafa;
/* Prevent page scroll; table body will scroll inside .pcmm-table-wrap */
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
} }
.pcmm-header { .pcmm-header {
@@ -869,6 +879,16 @@ onMounted(async () => {
margin: 0 auto; margin: 0 auto;
} }
.pcmm-top {
flex: 0 0 auto;
}
.pcmm-table-wrap {
flex: 1 1 auto;
min-height: 0; /* important for flex overflow scrolling */
overflow: auto;
}
.pcmm-form { .pcmm-form {
max-width: 1200px; max-width: 1200px;
margin: 0 auto; margin: 0 auto;
@@ -905,6 +925,14 @@ onMounted(async () => {
line-height: 1.15; line-height: 1.15;
} }
/* Keep q-table top controls visible while scrolling (like sticky headers). */
.pcmm-table :deep(.q-table__top) {
position: sticky;
top: 0;
z-index: 3;
background: #fafafa;
}
.pcmm-header-cell { .pcmm-header-cell {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;

View File

@@ -5,6 +5,7 @@ import routes from 'src/router/routes.js'
import { useAuthStore } from 'stores/authStore' import { useAuthStore } from 'stores/authStore'
import { usePermissionStore } from 'stores/permissionStore' import { usePermissionStore } from 'stores/permissionStore'
import { getAuthUserId } from 'src/modules/activityLogs'
export default route(function () { export default route(function () {
@@ -54,6 +55,16 @@ export default route(function () {
return next('/first-password-change') return next('/first-password-change')
} }
/* ================= USER ID RESTRICTIONS ================= */
const onlyUserIds = to.meta?.onlyUserIds
if (Array.isArray(onlyUserIds) && onlyUserIds.length > 0) {
const id = getAuthUserId(auth.user)
if (id == null || !onlyUserIds.includes(id)) {
return next('/unauthorized')
}
}
/* ================= ADMIN ================= */ /* ================= ADMIN ================= */

View File

@@ -1,3 +1,5 @@
import { activityLogsRoute } from 'src/modules/activityLogs'
// src/router/routes.js // src/router/routes.js
const routes = [ const routes = [
@@ -53,6 +55,21 @@ const routes = [
] ]
}, },
/* ==========================================================
🚫 UNAUTHORIZED
========================================================== */
{
path: '/unauthorized',
component: () => import('layouts/EmptyLayout.vue'),
children: [
{
path: '',
name: 'unauthorized',
component: () => import('pages/Unauthorized.vue')
}
]
},
/* ========================================================== /* ==========================================================
🏠 MAIN APP 🏠 MAIN APP
@@ -110,6 +127,10 @@ const routes = [
meta: { permission: 'system:update' } meta: { permission: 'system:update' }
}, },
/* ================= ACTIVITY LOGS ================= */
activityLogsRoute,
/* ================= FINANCE ================= */ /* ================= FINANCE ================= */
@@ -203,23 +224,13 @@ const routes = [
}, },
/* ================= LOGS ================= */
{
path: 'activity-logs',
name: 'activity-logs',
component: () => import('pages/ActivityLogs.vue'),
meta: { permission: 'system:read' }
},
/* ================= TEST MAIL ================= */ /* ================= TEST MAIL ================= */
{ {
path: 'test-mail', path: 'test-mail',
name: 'test-mail', name: 'test-mail',
component: () => import('pages/TestMail.vue'), component: () => import('pages/TestMail.vue'),
meta: { permission: 'system:update' } meta: { permission: 'system:update', onlyUserIds: [5] }
}, },
{ {