diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json
index 0f6ce311..26979817 100644
--- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json
+++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json
@@ -7528,7 +7528,7 @@
{
"key": "admin.changeLog",
"path": "/admin/changeLog",
- "componentPath": "@/views/docs/ChangeLog",
+ "componentPath": "@/views/version/ChangeLog",
"routeType": "protected",
"authority": []
},
diff --git a/api/src/Kurs.Platform.HttpApi.Host/appsettings.json b/api/src/Kurs.Platform.HttpApi.Host/appsettings.json
index 730d26dc..d9c43bff 100644
--- a/api/src/Kurs.Platform.HttpApi.Host/appsettings.json
+++ b/api/src/Kurs.Platform.HttpApi.Host/appsettings.json
@@ -7,7 +7,7 @@
"AttachmentsPath": "C:\\Private\\Projects\\sozsoft\\configs\\mail-queue\\attachments",
"CdnPath": "C:\\Private\\Projects\\sozsoft\\configs\\docker\\data\\cdn",
"ImportPath": "C:\\Private\\Projects\\sozsoft\\configs\\docker\\data\\import",
- "Version": "1.0.4"
+ "Version": "1.0.1"
},
"ConnectionStrings": {
"SqlServer": "Server=localhost;Database=KURS;User Id=sa;password=NvQp8s@l;Trusted_Connection=False;TrustServerCertificate=True;",
diff --git a/ui/.gitignore b/ui/.gitignore
index a470a897..a33db1d1 100644
--- a/ui/.gitignore
+++ b/ui/.gitignore
@@ -9,6 +9,7 @@ lerna-debug.log*
node_modules
dist
+dev-dist
dist-ssr
build
*.local
diff --git a/ui/dev-dist/sw.js b/ui/dev-dist/sw.js
index 6bd1fe1f..9ebb4717 100644
--- a/ui/dev-dist/sw.js
+++ b/ui/dev-dist/sw.js
@@ -82,7 +82,7 @@ define(['./workbox-a959eb95'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812"
}, {
"url": "/index.html",
- "revision": "0.agtbclbpej8"
+ "revision": "0.jq60tbu0hgg"
}], {});
workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("/index.html"), {
diff --git a/ui/package.json b/ui/package.json
index 8e272c87..eebdb31a 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -1,12 +1,12 @@
{
"name": "kurs-platform-ui",
"private": true,
- "version": "1.0.4",
+ "version": "1.0.1",
"elstarVersion": "2.1.6",
"type": "module",
"scripts": {
"start": "vite",
- "build": "vite build",
+ "build": "vite build && node scripts/write-version.js",
"preview": "vite preview",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.json",
"lint:fix": "npm run lint -- --fix",
diff --git a/ui/public/version.json b/ui/public/version.json
new file mode 100644
index 00000000..5fde58dd
--- /dev/null
+++ b/ui/public/version.json
@@ -0,0 +1,35 @@
+{
+ "commit": "6766d11",
+ "releases": [
+ {
+ "version": "1.0.5",
+ "buildDate": "2025-09-19",
+ "changeLog": [
+ "Form ekranındaki Butonlar güncellemeleri yapıldı",
+ "Edit Form ekranındaki Info butonu eklendi.",
+ "New Form ekranındaki Geri butonu eklendi."
+ ]
+ },
+ {
+ "version": "1.0.4",
+ "buildDate": "2025-09-19",
+ "changeLog": [
+ "Subformlar üzerinde extra filters ve Widget çalışmaları yapıldı."
+ ]
+ },
+ {
+ "version": "1.0.3",
+ "buildDate": "2025-09-19",
+ "changeLog": [
+ "Manage Grid üzerinde Extra filtre tanımlaması yapıldı."
+ ]
+ },
+ {
+ "version": "1.0.2",
+ "buildDate": "2025-09-16",
+ "changeLog": [
+ "Genel Static olan Url bilgileri kaldırıldı."
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/ui/scripts/write-version.js b/ui/scripts/write-version.js
new file mode 100644
index 00000000..bd247a51
--- /dev/null
+++ b/ui/scripts/write-version.js
@@ -0,0 +1,46 @@
+import fs from "fs"
+import { execSync } from "child_process"
+
+function safeExec(cmd) {
+ try {
+ return execSync(cmd, { stdio: ["pipe", "pipe", "ignore"] }).toString().trim()
+ } catch {
+ return null
+ }
+}
+
+// Tüm tag isimlerini al
+const rawTags = safeExec("git tag --list --sort=creatordate")
+
+if (!rawTags) {
+ console.log("> No git tags found, skipping version.json")
+ process.exit(0)
+}
+
+const tags = rawTags
+ .split("\n")
+ .filter(Boolean)
+ .map((tag) => {
+ const date = safeExec(`git log -1 --format=%ad --date=short ${tag}`)
+ const messageRaw = safeExec(`git tag -l --format="%(contents)" ${tag}`)
+
+ const changeLog = messageRaw
+ ? messageRaw.split("\n").map((s) => s.trim()).filter(Boolean)
+ : []
+
+ return {
+ version: tag.replace(/^v/, ""), // v1.0.5 → 1.0.5
+ buildDate: date,
+ changeLog
+ }
+ })
+
+const commit = safeExec("git rev-parse --short HEAD")
+
+const versionInfo = {
+ commit,
+ releases: tags.reverse()
+}
+
+fs.writeFileSync("public/version.json", JSON.stringify(versionInfo, null, 2))
+console.log("> Version file written to public/version.json:", versionInfo)
diff --git a/ui/src/components/UpdateNotifier.tsx b/ui/src/components/UpdateNotifier.tsx
deleted file mode 100644
index 219087c0..00000000
--- a/ui/src/components/UpdateNotifier.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-// src/components/UpdateNotifier.jsx
-import { useState, useEffect } from 'react'
-
-const UpdateNotifier = () => {
- const [updateAvailable, setUpdateAvailable] = useState(false)
-
- useEffect(() => {
- if ('serviceWorker' in navigator) {
- const checkUpdate = () => {
- navigator.serviceWorker.getRegistration().then(registration => {
- if (registration) {
- registration.addEventListener('updatefound', () => {
- setUpdateAvailable(true)
- })
- }
- })
- }
-
- checkUpdate()
- const interval = setInterval(checkUpdate, 30000) // 30 saniyede bir kontrol
- return () => clearInterval(interval)
- }
- }, [])
-
- const handleUpdate = () => {
- window.location.reload()
- }
-
- if (!updateAvailable) return null
-
- return (
-
-
Yeni güncelleme mevcut!
-
-
- )
-}
-
-export default UpdateNotifier
\ No newline at end of file
diff --git a/ui/src/components/layouts/Layouts.tsx b/ui/src/components/layouts/Layouts.tsx
index 199de8e6..278c74dd 100644
--- a/ui/src/components/layouts/Layouts.tsx
+++ b/ui/src/components/layouts/Layouts.tsx
@@ -15,7 +15,7 @@ import useLocale from '@/utils/hooks/useLocale'
import { useDynamicRoutes } from '@/routes/dynamicRoutesContext'
import { useLocation } from 'react-router-dom'
import { hasSubdomain } from '@/utils/subdomain'
-import UpdateNotifier from '../UpdateNotifier'
+import UpdateNotifier from '../../views/version/UpdateNotifier'
export type LayoutType =
| typeof LAYOUT_TYPE_CLASSIC
diff --git a/ui/src/components/template/Footer.tsx b/ui/src/components/template/Footer.tsx
index d93908f7..dbe6e955 100644
--- a/ui/src/components/template/Footer.tsx
+++ b/ui/src/components/template/Footer.tsx
@@ -1,13 +1,14 @@
-import classNames from 'classnames'
-import Container from '@/components/shared/Container'
-import { APP_NAME } from '@/constants/app.constant'
-import { PAGE_CONTAINER_GUTTER_X } from '@/constants/theme.constant'
-import { useStoreActions, useStoreState } from '@/store'
-import { Link, useNavigate } from 'react-router-dom'
-import { ROUTES_ENUM } from '@/routes/route.constant'
-import UiDialog from '@/views/shared/UiDialog'
+import { useEffect, useState } from "react"
+import classNames from "classnames"
+import Container from "@/components/shared/Container"
+import { APP_NAME } from "@/constants/app.constant"
+import { PAGE_CONTAINER_GUTTER_X } from "@/constants/theme.constant"
+import { useStoreActions, useStoreState } from "@/store"
+import { Link, useNavigate } from "react-router-dom"
+import { ROUTES_ENUM } from "@/routes/route.constant"
+import UiDialog from "@/views/shared/UiDialog"
-export type FooterPageContainerType = 'gutterless' | 'contained'
+export type FooterPageContainerType = "gutterless" | "contained"
type FooterProps = {
pageContainerType: FooterPageContainerType
@@ -21,7 +22,20 @@ const FooterContent = () => {
const apiConfig = useStoreState((state) => state.abpConfig.config?.extraProperties)
const uiMode = import.meta.env.MODE
- const reactAppVersion = import.meta.env.VITE_REACT_APP_VERSION
+
+ const [latestVersion, setLatestVersion] = useState(null)
+
+ // version.json'dan en güncel UI versiyonunu al
+ useEffect(() => {
+ fetch("/version.json?ts=" + Date.now())
+ .then((res) => res.json())
+ .then((data) => {
+ if (data?.releases?.length > 0) {
+ setLatestVersion(data.releases[0].version) // en güncel hep en üstte
+ }
+ })
+ .catch(() => setLatestVersion(null))
+ }, [])
return (
<>
@@ -40,24 +54,25 @@ const FooterContent = () => {
{apiConfig && (
API:
- {apiConfig['environment'].toString()}:{apiConfig['version'].toString()}
+ {apiConfig["environment"].toString()}:{apiConfig["version"].toString()}
)}
- {reactAppVersion != currentUiVersion && (
+
+ {latestVersion && latestVersion !== currentUiVersion && (
{
- setUiVersion(reactAppVersion )
+ setUiVersion(latestVersion)
navigate(ROUTES_ENUM.protected.admin.changeLog)
}}
title="🎉 Yeni Güncelleme"
>
- Sözsoft Kurs Platform Sistemi güncellendi.
+ Sözsoft Kurs Platform Sistemi v{latestVersion} sürümüne güncellendi.
Detayları, "Güncelleme Günlüğü" ekranında görebilirsiniz.
)}
@@ -65,12 +80,14 @@ const FooterContent = () => {
)
}
-export default function Footer({ pageContainerType = 'contained' }: FooterProps) {
+export default function Footer({ pageContainerType = "contained" }: FooterProps) {
return (