From 4323e875729f5746f2bfd8294f32b22f6b9d28cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Fri, 9 Oct 2026 15:24:53 +0300 Subject: [PATCH] Intranet -> Dashboard Diary --- .../seeds/data/Abp.Identity.Permissions.json | 10 + .../53294e77-a4fb-45e4-a80e-acf07b5d75be.json | 6 +- .../App.DeveloperKit.IntranetWidgets.json | 13 ++ .../data/App.Languages.LanguageText.json | 154 +++++++++++++ configs/seeds/docs/modules/App.Hr.md | 3 +- configs/seeds/docs/modules/App.Prj.md | 4 +- ui/src/views/intranet/DiaryModal.tsx | 215 ++++++++++++++++++ ui/src/views/intranet/widgets/Diary.tsx | 172 ++++++++++++++ .../DialogContext/DialogShowComponent.tsx | 1 + 9 files changed, 573 insertions(+), 5 deletions(-) create mode 100644 ui/src/views/intranet/DiaryModal.tsx create mode 100644 ui/src/views/intranet/widgets/Diary.tsx diff --git a/configs/seeds/data/Abp.Identity.Permissions.json b/configs/seeds/data/Abp.Identity.Permissions.json index 9be46d84..e2af5a46 100644 --- a/configs/seeds/data/Abp.Identity.Permissions.json +++ b/configs/seeds/data/Abp.Identity.Permissions.json @@ -15204,6 +15204,16 @@ "MultiTenancySide": 3, "Modules": "Prj" }, + { + "GroupName": "App.Prj", + "Name": "App.Prj.Diary.Widget", + "ParentName": "App.Prj.Diary", + "DisplayName": "App.Platform.Widget", + "Order": 7, + "IsEnabled": true, + "MultiTenancySide": 3, + "Modules": "Prj" + }, { "GroupName": "App.Prj", "Name": "App.Prj.ProjectSummary", diff --git a/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json b/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json index cf4356ea..e25fb724 100644 --- a/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json +++ b/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json @@ -9,7 +9,7 @@ "TenantId": null, "UserName": "system@sozsoft.com", "RequestDate": null, - "Status": "Ready to Start", + "Status": "Backlog", "Title": "Satınalma -> Malzeme Talepleri", "Description": "
Malzeme Talepleri : Satınalma yapılması için departmantların iç ve dış olmak üzere talep ettikleri ürünlerin kaydıdır. Talep eden, Talep Eden Departman, Mal Alımı olduğu zaman konulacak Depo ve Konum bilgisi ve Talep Tarihi bilgilerinden sonra Ürün ve talep edilen miktar bilgisi girilmeli. Ürün tanımında yer alan Birim bilgisi yine sistemle entegre şekilde gelmektedir. Termin Tarihi ürünün ne zaman ihtiyaç olduğu ve Talep Nedeni olarak ne amaçla istediği belirtilmelidir. Yine bu kaydın üst kısmında Taslak, Departman Onayı, Satınalma Onayı, Onaylandı, İşlemde, Tamamlandı gibi durumları da onay mekanizması Workflow gibi bir yöntemle yönetmeliyiz. Talepten sonra hemen talep edenin Departman Onaycısı onaylayacak bir liste üzerinden görmeli ve onaylamalı. Bu kişi Adm_T_Approver entity içerisindeki Onay Yeri : Satınalma ve Departman bazında gösterilecek) Sonrasında kayıt Satınalma departmanına düşmeli ondan sonra bu kayıt Satınalma Sorumlusu kabul etmeli ve Satınalma ile ilgili teklif toplama süreci başlamalı.
Taleplerim, Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler listesinden oluşmalı.
Red Nedenleri : Bazı Satınalma talepleri hem departman onaycısı hemde satınalma tarafından reddedilebilir. Reddetme sebepleri aşağıadki gibidir. Bu liste Satınalma -> Tanımlamalar menüsüne yerleştirilmelidir.
Departmanların satınalınacak malzemeleri kayıt altına alması, talebin önce departman satınalma onaycısı, sonra satınalma birimi tarafından onaylanması ve onaylı talebin teklif toplama sürecine aktarılması. Kullanıcılar: talep eden personel, departman onaycıları, satınalma ekibi.
\n\nWizard List ekranları + WorkflowDto onay akışı (§10.7 onaylı talep kalıbı). Talep başlığı ve satırları iki tablo; satırlar menüsüz alt form (List sekmesi). Beş liste görünümü aynı başlık tablosuna bağlı ayrı ListForm'lardır, her biri sabit DefaultFilter ile. Departman onaycıları kayıt sonrası prosedürle (InsertAfterCommand/UpdateAfterCommand) Yönetim › Tanımlamalar › Onaycılar ekranından (Adm_T_Approver, ApprovalArea = 'Purchase', talebin departmanı, aktif satırlar) okunup gizli DeptApproverUserNames kolonuna | ile birleştirilmiş kullanıcı adları olarak yazılır; akışta @DeptApproverUserNames olarak kullanılır.
Satınalma › Malzeme Talepleri › Taleplerim / Departman Onayı Bekleyenler / Satınalma Onayı Bekleyenler / Planlama Bekleyenler / Tüm Talepler ve Satınalma › Tanımlamalar › Red Nedenleri
| Seviye | Kod | Ad (TR / EN) | İkon | Durum |
|---|---|---|---|---|
| Kök | App.Prc | Satınalma / Purchasing | — | Var |
| Ara | App.Prc.Definitions | Tanımlamalar / Definitions | — | Var |
| Ekran | App.Prc.RejectionReason | Red Nedenleri / Rejection Reasons | FcCancel | Yeni |
| Ara | App.Prc.MaterialRequests | Malzeme Talepleri / Material Requests | FcList | Yeni |
| Ekran | App.Prc.MyMaterialRequest | Taleplerim / My Requests | FcDocument | Yeni |
| Ekran | App.Prc.MaterialRequestDeptApproval | Departman Onayı Bekleyenler / Awaiting Department Approval | FcApproval | Yeni |
| Ekran | App.Prc.MaterialRequestPurchaseApproval | Satınalma Onayı Bekleyenler / Awaiting Purchasing Approval | FcApproval | Yeni |
| Ekran | App.Prc.MaterialRequestPlanning | Planlama Bekleyenler / Awaiting Planning | FcPlanner | Yeni |
| Ekran | App.Prc.MaterialRequest | Tüm Talepler / All Requests | FcList | Yeni |
ModuleId: Prc · İzin grubu: App.Prc · Route: /admin/list/{ListFormCode}
Yetki: App.Prc › App.Prc.Definitions (Var) › App.Prc.RejectionReason (Yeni); App.Prc › App.Prc.MaterialRequests (Yeni) › her ekran (Yeni) › App.Prc.MaterialRequest › App.Prc.MaterialRequestLine (alt form).
\n\nTümü yeni, tenant + audit + soft delete.
\nPrc_T_RejectionReason — Tanım tablosu: Evet (red işleminde seçilir). Kolonlar: Name nvarchar(128) ✓, IsActive bit ✓ DEFAULT 1.
\nPrc_T_MaterialRequest — Tanım tablosu: Hayır (hareket kaydı).
\n| Kolon | Tip | Zorunlu | Not |
|---|---|---|---|
| RequestNo | nvarchar(32) | ✓ | SRO/00001, InsertBefore ile kiracı içinde sıralı |
| BranchId | uniqueidentifier | ✓ | → Sas_T_Branch (Şirket) |
| RequesterUserId | uniqueidentifier | ✓ | → AbpUsers, varsayılan @USERID |
| DepartmentId | uniqueidentifier | ✓ | → Hr_T_Department, şubeye cascade; varsayılan kullanıcının DepartmentId |
| WarehouseId | uniqueidentifier | → Inv_T_Warehouse, şubeye cascade | |
| LocationId | uniqueidentifier | → Inv_T_Location, depoya cascade | |
| RequestDate | datetime2 | ✓ | varsayılan @NOW |
| Description | nvarchar(MAX) | Genel Açıklama (dxTextArea) | |
| Status | nvarchar(32) | ✓ | Draft / DeptApproval / PurchaseApproval / Approved / InProgress / PartiallyDone / Done / Rejected; DEFAULT 'Draft' |
| DeptApproverUserNames | nvarchar(512) | Prosedür Adm_T_Approver'dan doldurur; formda \"Departman Onaycıları\" (salt okunur) | |
| ApproverId / ApprovalDate / ApprovalNote | uniqueidentifier / datetime2 / nvarchar(MAX) | Akışın son adım alanları | |
| DeptApprovedById / DeptApprovalDate / DeptApprovalNote | uniqueidentifier / datetime2 / nvarchar(MAX) | Departman adımı kopyası (prosedür) | |
| PurchaseApprovedById / PurchaseApprovalDate / PurchaseApprovalNote | uniqueidentifier / datetime2 / nvarchar(MAX) | Satınalma adımı kopyası (prosedür) | |
| RejectionReasonId | uniqueidentifier | → Prc_T_RejectionReason |
Prc_T_MaterialRequestLine — Tanım tablosu: Hayır.
\n| Kolon | Tip | Zorunlu | Not |
|---|---|---|---|
| MaterialRequestId | uniqueidentifier | ✓ | → Prc_T_MaterialRequest |
| ProductId | uniqueidentifier | ✓ | → Inv_T_Product (aktif) |
| Quantity | decimal(18,4) | ✓ | > 0 |
| UomId | nvarchar(64) | ✓ | → Adm_T_Uom; ürün seçilince üründen dolar |
| FulfillmentType | nvarchar(16) | ✓ | Purchase / Stock (Satınalma / Stoktan), DEFAULT 'Purchase' |
| DueDate | date | Termin Tarihi | |
| RequestReason | nvarchar(512) | Talep Nedeni | |
| PurchaserUserId | uniqueidentifier | Satınalma Sorumlusu → AbpUsers |
Var olan, yalnız okunur: Adm_T_Approver (onaycı kaynağı), Hr_T_Department, Inv_T_Warehouse, Inv_T_Location, Inv_T_Product, Adm_T_Uom.
| Sekme | Hedef | TabType | Menü | İlişki | Ekle / Düzenle / Sil | Yetki yolu |
|---|---|---|---|---|---|---|
| Talep Satırları | App.Prc.MaterialRequestLine | List | Menüsüz | Id → MaterialRequestId | ✓ / ✓ / ✓ | App.Prc › App.Prc.MaterialRequests › App.Prc.MaterialRequest › App.Prc.MaterialRequestLine |
Beş listenin hepsi aynı alt formu taşır. Onay / Red Bilgileri ana formda salt okunur ikinci grup.
\n\nPrc_SP_MaterialRequestAfterSave: talep no, onaycıları Adm_T_Approver'dan doldurma, durum ve adım kopyaları), 7 yeni ekran (Red Nedenleri, 5 liste, satır alt formu).RequesterUserId = @USERID; Departman Onayı Bekleyenler Status = 'DeptApproval' + ApprovalIsFilterUserName; Satınalma Onayı Bekleyenler Status = 'PurchaseApproval'; Planlama Bekleyenler Status IN ('Approved','InProgress','PartiallyDone'); Tüm Talepler filtresiz.@DeptApproverUserNames) → Approval \"Satınalma Onayı\" (rol Satınalma) → Inform talep sahibi → End \"Onaylandı\"; her ret → Inform → End \"Reddedildi\". ApprovalIsResetWorkflow: true.Prc_T_, kod App.Prc.* — mevcut Satınalma ekranlarıyla aynı.App.Prc.MaterialRequests başlıktaki \"Satınalma -> Malzeme Talepleri\" yolundan; beş liste onun altında.Adm_T_Approver'dan (Onay Yeri = Satınalma, talebin departmanı); birden çok onaycıdan herhangi biri onaylayabilir.Satınalma rolündeki kullanıcılar.SRO/ + 5 haneli kiracı sırası.Evet
" + "Analysis": "" } ] } diff --git a/configs/seeds/data/App.DeveloperKit.IntranetWidgets.json b/configs/seeds/data/App.DeveloperKit.IntranetWidgets.json index 9841d311..ea9170bb 100644 --- a/configs/seeds/data/App.DeveloperKit.IntranetWidgets.json +++ b/configs/seeds/data/App.DeveloperKit.IntranetWidgets.json @@ -158,6 +158,19 @@ "Order": 37, "Props": "", "IsActive": true + }, + { + "Id": "70166a4b-cdec-56d0-918c-a98581b02d62", + "Code": "diary", + "Name": "Work Diary", + "LabelKey": "App.DashboardWidget.Diary", + "SourceType": 0, + "ComponentName": "", + "PermissionName": "App.Prj.Diary.Widget", + "Column": 0, + "Order": 38, + "Props": "", + "IsActive": true } ] } diff --git a/configs/seeds/data/App.Languages.LanguageText.json b/configs/seeds/data/App.Languages.LanguageText.json index 06ebebcc..105faa5b 100644 --- a/configs/seeds/data/App.Languages.LanguageText.json +++ b/configs/seeds/data/App.Languages.LanguageText.json @@ -85712,6 +85712,160 @@ "Key": "App.DashboardWidget.MyTimesheet", "Value": "Puantajım" }, + { + "Id": "6bbf76da-186c-5a1b-be44-632559aed7f0", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary", + "Value": "My Diary" + }, + { + "Id": "9732cd75-149d-5356-9773-297d3865e7f1", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary", + "Value": "Güncem" + }, + { + "Id": "ab9c1bba-f0ea-5728-8924-b1fac77d2543", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.Hint", + "Value": "Write down what you worked on, by project and work package." + }, + { + "Id": "c10834f5-a148-556a-8320-3fa58bf797d0", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.Hint", + "Value": "Proje ve iş paketine göre yaptığın çalışmaları günceye yaz." + }, + { + "Id": "fd95069c-a741-5804-be4e-a2f3f4593e7a", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.Write", + "Value": "Write Diary" + }, + { + "Id": "2b0024a8-238f-51e9-959e-443a27c530f5", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.Write", + "Value": "Günce Yaz" + }, + { + "Id": "4a8e4698-86fe-517c-9835-8b36017508bf", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.EndBeforeStart", + "Value": "End time must be after the start time." + }, + { + "Id": "07942047-bc00-5b08-bdaa-a8ebf24840d9", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.EndBeforeStart", + "Value": "Bitiş zamanı başlangıçtan sonra olmalı." + }, + { + "Id": "72de8ab1-9ee9-56e5-bed6-390c0ecb620e", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.NoPermission", + "Value": "You are not authorized to add diary entries." + }, + { + "Id": "5f4dfa82-460f-5208-acdd-f4fbb548d218", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.NoPermission", + "Value": "Günce ekleme yetkiniz yok." + }, + { + "Id": "19063665-2b05-5a28-8c2f-762adcb59881", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.TodayHours", + "Value": "Today (h)" + }, + { + "Id": "61455ad0-2fc2-50d0-8fa0-4e3466f0d759", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.TodayHours", + "Value": "Bugün (sa)" + }, + { + "Id": "e4e1d710-fe63-5df9-bb35-efa85d6a43a0", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.WeekHours", + "Value": "This Week (h)" + }, + { + "Id": "f14385fa-48d1-5cb3-8914-c45dbae29813", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.WeekHours", + "Value": "Bu Hafta (sa)" + }, + { + "Id": "87eb6d48-d820-59c3-bc5f-b7a46f747dbf", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.TodayEntries", + "Value": "Entries Today" + }, + { + "Id": "10ea505d-1a2d-5c25-b5c5-d7c51fbf2940", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.TodayEntries", + "Value": "Bugünkü Kayıt" + }, + { + "Id": "8b431e51-134f-5a9e-a5b0-e51e2807c79e", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.Recent", + "Value": "Recent Entries" + }, + { + "Id": "5f4b2e77-8129-5a11-94d9-ffc5bd00087a", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.Recent", + "Value": "Son Güncelerim" + }, + { + "Id": "a3052970-151a-5ab5-aaf9-8a25de3d0729", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.Empty", + "Value": "No diary entries in the last 30 days." + }, + { + "Id": "f16782fe-6321-50e1-8759-feeeef8a2e4e", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.Empty", + "Value": "Son 30 günde günce yok." + }, + { + "Id": "427597d6-ee21-5c81-ae1e-322643a2adfe", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.HourShort", + "Value": "h" + }, + { + "Id": "36da653b-6691-57e9-9c29-8592044b6ee3", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.DashboardWidget.Diary.HourShort", + "Value": "sa" + }, { "Id": "340dd8e3-8d4b-5d19-a3b2-2aaf77205677", "CultureName": "en", diff --git a/configs/seeds/docs/modules/App.Hr.md b/configs/seeds/docs/modules/App.Hr.md index ee6a6823..5c08f9cd 100644 --- a/configs/seeds/docs/modules/App.Hr.md +++ b/configs/seeds/docs/modules/App.Hr.md @@ -2999,6 +2999,7 @@ Pano kutuları (seed): | `my-leave` | Sol / 35 | `App.Hr.MyLeaveRequest` | Custom `MyLeaveWidget`: izin bakiyesi, süren talepler → İzin Talebi Oluştur · Taleplerim · Bakiyem | | `team-leave` | Sol / 36 | `App.Hr.TeamLeaveRequest` | Custom `TeamLeaveWidget`: müdürün onayını bekleyen izin talepleri, bugün izinde olanlar → Onay Bekleyenler | | `my-timesheet` | Sol / 37 | `App.Hr.MyTimesheet` | Custom `MyTimesheetWidget`: seçilen ayın puantajı (net saat, geç/erken dk, fazla mesai, devamsız/izinli/raporlu) ve yıl toplamı, 270 saatlik fazla mesai çubuğu → Puantajım | +| `diary` | Sol / 38 | `App.Prj.Diary.Widget` | Builtin (`widgets/Diary.tsx`) Güncem: bugün / bu hafta saat, bugünkü kayıt, son 5 günce (son 30 gün); Günce Yaz butonu çekirdek `DiaryEntry` diyaloğunu açar, kapanınca özet yenilenir; kayıt Günce Listesi'ne (`App.Prj.Diary`) yazılır, kaydetmek için ayrıca `App.Prj.Diary` + `.Create` gerekir | | `social-wall` | Orta / 40 | `App.Hr.Intranet.SocialPost.Widget` | Sosyal duvar (Tümü / Paylaşımlarım, sonsuz kaydırma 10'arlı) | | `announcements` | Sağ / 50 | `App.Hr.Intranet.Announcement.Widget` | Sabitlenmiş duyurular (en fazla 3) | | `upcoming-events` | Sağ / 60 | `App.Hr.Intranet.Events.Event.Widget` | Bugünden sonraki yayınlanmış ilk 3 etkinlik | @@ -3006,7 +3007,7 @@ Pano kutuları (seed): | `team-performance` | Sağ / 80 | `App.Hr.TeamPerformanceReview` | Custom `TeamPerformanceWidget`: yöneticinin ekip değerlendirmeleri → Ekibimin Değerlendirmeleri | | `my-360-feedback` | Sağ / 90 | `App.Hr.My360Feedback` | Custom `My360FeedbackWidget`: kullanıcıya atanan 360 talepleri → 360 Taleplerim | -İlk altı kutu Builtin'dir (koddaki `Code`). `my-leave` / `team-leave` İzin Yönetimi'nin (İzin Yönetimi bölümü §3.3), `my-timesheet` Puantaj ve Devam Takibi'nin (Puantaj ve Devam Takibi bölümü §3.3), son üçü Performans Yönetimi'nin çalışana ait özetleridir: +İlk altı kutu ve `diary` Builtin'dir (koddaki `Code`). `my-leave` / `team-leave` İzin Yönetimi'nin (İzin Yönetimi bölümü §3.3), `my-timesheet` Puantaj ve Devam Takibi'nin (Puantaj ve Devam Takibi bölümü §3.3), son üçü Performans Yönetimi'nin çalışana ait özetleridir: İK menüsü İK departmanınındır, çalışan kendi değerlendirmesini buradan takip eder; listeler menüsüzdür ve kutudaki bağlantıyla açılır. Ayrıntı: Performans Yönetimi bölümü §3.3. diff --git a/configs/seeds/docs/modules/App.Prj.md b/configs/seeds/docs/modules/App.Prj.md index 09f5858a..d8ca32d0 100644 --- a/configs/seeds/docs/modules/App.Prj.md +++ b/configs/seeds/docs/modules/App.Prj.md @@ -163,6 +163,8 @@ Personelin proje ve iş paketine göre günlük yaptığı çalışmaları yazd `Proje › Günce Listesi`; ayrıca `Projeler` kartında Günce sekmesi (ProjectId ilişkisiyle). Widget'lar: toplam kayıt, bugünkü kayıt, toplam saat. +Intranet › Dashboard'daki **Güncem** kutusu (`diary`, builtin `ui/src/views/intranet/widgets/Diary.tsx`) kişinin son 30 günlük güncesini bu ekranın sorgusundan okur (`UserId` = oturumdaki kişi): bugün / bu hafta saat, bugünkü kayıt sayısı, son 5 günce; özet `App.Prj.Diary` okuma yetkisiyle görünür. Günce Yaz butonuyla çekirdek diyalog kayıt defterindeki `DiaryEntry` modalını (`ui/src/views/intranet/DiaryModal.tsx`) açar. Modal bu ekranın lookup'larını (Proje, projeye göre İş Paketi) ve ekleme ucunu (`list-form-data/insert`) kullanır; Kullanıcı oturumdaki kişi, Dakika başlangıç–bitiş farkıdır, düz metin satırları HTML paragrafına çevrilir. + ### 4. Veri modeli `Prj_T_Diary`: ProjectId, WorkPackageId (projeye göre süzülür), UserId, StartTime, EndTime, Minutes, Content (nvarchar(MAX), HTML). Kiracı + audit + soft delete. @@ -173,7 +175,7 @@ Dakika = (Bitiş − Başlangıç) saat × 60, yuvarlanır, negatif olamaz; form ### 6. Yetki ve görünürlük -`App.Prj › App.Prj.Diary` (+ C/U/D/E/I/N). Kayıtlar kiracı içinde tüm yetkililere görünür. +`App.Prj › App.Prj.Diary` (+ C/U/D/E/I/N, `.Widget`). Kayıtlar kiracı içinde tüm yetkililere görünür. `App.Prj.Diary.Widget` panodaki Günce kutusunu gösterir; modalda kaydetmek ekran yetkisini (`App.Prj.Diary` + `.Create`) ister, yoksa modal yetki uyarısı gösterir. ### 7. Entegrasyonlar diff --git a/ui/src/views/intranet/DiaryModal.tsx b/ui/src/views/intranet/DiaryModal.tsx new file mode 100644 index 00000000..3d2b82c2 --- /dev/null +++ b/ui/src/views/intranet/DiaryModal.tsx @@ -0,0 +1,215 @@ +import { useEffect, useState } from 'react' +import dayjs from 'dayjs' +import { Field, Form, Formik, FormikHelpers } from 'formik' +import * as Yup from 'yup' +import { + Button, + Dialog, + FormContainer, + FormItem, + Input, + Notification, + Select, + toast, +} from '@/components/ui' +import { dynamicFetch } from '@/services/form.service' +import { useStoreState } from '@/store/store' +import { useLocalization } from '@/utils/hooks/useLocalization' +import { usePermission } from '@/utils/hooks/usePermission' + +// Kayıt Günce Listesi ekranının kendi uçlarından geçer: lookup'lar ekranın sorgusunu, ekleme +// ekranın insert komutunu ve Create yetkisini kullanır. Modal yalnızca giriş arayüzüdür. +const LIST_FORM_CODE = 'App.Prj.Diary' +const DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:mm' + +interface LookupOption { + value: string + label: string +} + +interface DiaryValues { + projectId: string + workPackageId: string + startTime: string + endTime: string + content: string +} + +const loadLookup = async (listFormFieldName: string, filters: unknown[] | null = null) => { + const response = await dynamicFetch('list-form-select/lookup', 'POST', null, { + listFormCode: LIST_FORM_CODE, + listFormFieldName, + filters, + }) + const data = response?.data ?? [] + return (Array.isArray(data) ? data : [data]).map( + (item: { Key: string; Name: string }): LookupOption => ({ value: item.Key, label: item.Name }), + ) +} + +// Liste ekranındaki editör HTML'dir; düz metnin satırları paragrafa çevrilir. +const toHtml = (text: string) => + text + .split(/\r?\n/) + .filter((line) => line.trim()) + .map((line) => { + const element = document.createElement('p') + element.textContent = line + return element.outerHTML + }) + .join('') + +function DiaryModal({ open, onDialogClose }: { open: boolean; onDialogClose: () => void }) { + const { translate } = useLocalization() + const { checkPermission } = usePermission() + const userId = useStoreState((state) => state.auth.user.id) + const canCreate = checkPermission(`${LIST_FORM_CODE}.Create`) + + const [projects, setProjects] = useState