Notification UiToast, UiActivity, Desktop düzenlemesi

Fazla Console.Log kaldırıldı.
This commit is contained in:
Sedat ÖZTÜRK 2026-05-11 15:19:27 +03:00
parent 8feab2184a
commit 524a88274b
21 changed files with 73 additions and 70 deletions

View file

@ -2,13 +2,12 @@
public static class NotificationChannels public static class NotificationChannels
{ {
public const string Sms = "Sms"; public const string Sms = "Sms"; //SMS (ABP Sms + Posta Guvercini)
public const string Mail = "Mail"; public const string Mail = "Mail"; //Email (ABP Emailing + Amazon SES)
public const string Rocket = "Rocket"; public const string Rocket = "Rocket"; //Rocket.Chat (HTTP API)
public const string Desktop = "Desktop"; public const string Desktop = "Desktop";
public const string UiActivity = "UiActivity"; public const string UiActivity = "UiActivity"; //UI Activity (ABP UI Activity)
public const string UiToast = "UiToast"; public const string UiToast = "UiToast"; //UI Toast (ABP UI Toast) Ayarlar/Sistem/Bildirimler/Chrome açık olması gerekiyor.
public const string WhatsApp = "WhatsApp"; public const string WhatsApp = "WhatsApp"; //WhatsApp (HTTP API, template-based)
// public const string Telegram = "Telegram"; // public const string Telegram = "Telegram";
} }

View file

@ -4453,12 +4453,12 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] { LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
new () { Key="Sms",Name="Sms" }, new () { Key="Sms",Name="Sms" },
new () { Key="Mail",Name="Mail" }, new () { Key="Mail",Name="Mail" },
new () { Key="WhatsApp",Name="WhatsApp" },
new () { Key="Rocket",Name="Rocket" }, new () { Key="Rocket",Name="Rocket" },
new () { Key="Desktop",Name="Desktop" },
new () { Key="UiActivity",Name="UiActivity" }, new () { Key="UiActivity",Name="UiActivity" },
new () { Key="UiToast",Name="UiToast" }, new () { Key="UiToast",Name="UiToast" },
new () { Key="WhatsApp",Name="WhatsApp" }, new () { Key="Desktop",Name="Desktop" },
new () { Key="Telegram",Name="Telegram" }, // new () { Key="Telegram",Name="Telegram" },
}), }),
}), }),
ColumnCustomizationJson = DefaultColumnCustomizationJson, ColumnCustomizationJson = DefaultColumnCustomizationJson,

View file

@ -90,12 +90,6 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
// hooks.add("useEffect"); // hooks.add("useEffect");
// } // }
console.log(
"🪝 Active hooks detected:",
Array.from(hooks),
"for component:",
selectedComponent.id
);
setActiveHooks(hooks); setActiveHooks(hooks);
} }
}, [selectedComponent, currentCode]); }, [selectedComponent, currentCode]);
@ -131,13 +125,6 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
const handleApplyPropChanges = () => { const handleApplyPropChanges = () => {
if (!selectedComponent) return; if (!selectedComponent) return;
console.log("🔄 PropertyPanel: Applying changes:", {
properties: pendingProperties,
events: pendingEvents,
hooks: pendingHooks,
selectedComponentId: selectedComponent.id,
});
// Combine all changes into a single update object // Combine all changes into a single update object
const allUpdates = { const allUpdates = {
...pendingProperties, ...pendingProperties,
@ -146,7 +133,6 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
// Apply property and event changes together // Apply property and event changes together
if (Object.keys(allUpdates).length > 0) { if (Object.keys(allUpdates).length > 0) {
console.log("🔧 PropertyPanel: Applying combined updates:", allUpdates);
onPropertiesChange(selectedComponent.id, allUpdates); onPropertiesChange(selectedComponent.id, allUpdates);
} }

View file

@ -37,7 +37,7 @@ type NotificationList = {
} }
const notificationHeight = 'h-72' const notificationHeight = 'h-72'
const notificationInterval = 120000 const notificationInterval = 120000 // 2 minutes
const notificationTypeAvatar = (creatorId: string, tenantId?: string) => { const notificationTypeAvatar = (creatorId: string, tenantId?: string) => {
return <Avatar shape="circle" src={AVATAR_URL(creatorId, tenantId)} /> return <Avatar shape="circle" src={AVATAR_URL(creatorId, tenantId)} />
@ -75,16 +75,20 @@ const _Notification = ({ className }: { className?: string }) => {
const [noResult, setNoResult] = useState(false) const [noResult, setNoResult] = useState(false)
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [toastNotificationList, setToastNotificationList] = useState<string[]>([]) const toastNotificationList = useRef<string[]>([])
const toastNotificationInterval = useRef<NodeJS.Timer>() const toastNotificationInterval = useRef<ReturnType<typeof setInterval>>()
const [desktopNotificationList, setDesktopNotificationList] = useState<string[]>([]) const desktopNotificationList = useRef<string[]>([])
const desktopNotificationInterval = useRef<NodeJS.Timer>() const desktopNotificationInterval = useRef<ReturnType<typeof setInterval>>()
const { bgTheme } = useThemeClass() const { bgTheme } = useThemeClass()
const { larger } = useResponsive() const { larger } = useResponsive()
const direction = useStoreState((state) => state.theme.direction) const direction = useStoreState((state) => state.theme.direction)
const tabHasFocus = useStoreState((a) => a.base.common.tabHasFocus) const tabHasFocus = useStoreState((a) => a.base.common.tabHasFocus)
const tabHasFocusRef = useRef(tabHasFocus)
useEffect(() => {
tabHasFocusRef.current = tabHasFocus
}, [tabHasFocus])
const getReactNotificationCount = useCallback(async () => { const getReactNotificationCount = useCallback(async () => {
const resp = await getList({ const resp = await getList({
@ -175,22 +179,23 @@ const _Notification = ({ className }: { className?: string }) => {
const resp = await getList({ const resp = await getList({
channels: [NotificationChannels.UiToast], channels: [NotificationChannels.UiToast],
isListRequest: false, isListRequest: false,
isSent: false,
maxResultCount: 1000, maxResultCount: 1000,
}) })
const items = resp.data.items ?? [] const items = resp.data.items ?? []
const newNotificationList = items.filter( const newNotificationList = items.filter(
(a) => !toastNotificationList.includes(a.id) && !a.isSent, (a) => !toastNotificationList.current.includes(a.id) && !a.isSent,
) )
setToastNotificationList(newNotificationList.map((a) => a.id)) toastNotificationList.current = [
...toastNotificationList.current,
...newNotificationList.map((a) => a.id),
]
for (const notification of newNotificationList) { for (const notification of newNotificationList) {
toast.push( toast.push(
<Notify <Notify
type="success" type="success"
duration={0} duration={0}
closable={true} closable={true}
onClose={async () => {
await updateRead(notification.id, true)
}}
> >
{notification.message} {notification.message}
</Notify>, </Notify>,
@ -200,13 +205,16 @@ const _Notification = ({ className }: { className?: string }) => {
) )
await updateSent(notification.id, true) await updateSent(notification.id, true)
await updateRead(notification.id, true)
} }
setToastNotificationList([])
} }
useEffect(() => { useEffect(() => {
if (tabHasFocusRef.current) {
getToastNotifications()
}
toastNotificationInterval.current = setInterval(async () => { toastNotificationInterval.current = setInterval(async () => {
if (tabHasFocus) { if (tabHasFocusRef.current) {
await getToastNotifications() await getToastNotifications()
} }
}, notificationInterval) }, notificationInterval)
@ -214,41 +222,68 @@ const _Notification = ({ className }: { className?: string }) => {
return () => { return () => {
clearInterval(toastNotificationInterval.current) clearInterval(toastNotificationInterval.current)
} }
}, [toastNotificationList, tabHasFocus]) }, [])
//Desktop //Desktop
const getDesktopNotifications = async () => { const getDesktopNotifications = async () => {
if (!('Notification' in window) || window.Notification.permission !== 'granted') return
const resp = await getList({ const resp = await getList({
channels: [NotificationChannels.Desktop], channels: [NotificationChannels.Desktop],
isListRequest: false, isListRequest: false,
isSent: false,
maxResultCount: 1000, maxResultCount: 1000,
}) })
const items = resp.data.items ?? [] const items = resp.data.items ?? []
const newNotificationList = items.filter( const newNotificationList = items.filter(
(a) => !desktopNotificationList.includes(a.id) && !a.isSent, (a) => !desktopNotificationList.current.includes(a.id) && !a.isSent,
) )
setDesktopNotificationList(newNotificationList.map((a) => a.id)) desktopNotificationList.current = [
...desktopNotificationList.current,
...newNotificationList.map((a) => a.id),
]
for (const notification of newNotificationList) { for (const notification of newNotificationList) {
var options = { const title = notification.notificationType || 'Bildirim'
const options = {
body: notification.message, body: notification.message,
dir: 'ltr', dir: 'ltr',
requireInteraction: true,
} as NotificationOptions } as NotificationOptions
new window.Notification(notification.notificationType, options)
if ('serviceWorker' in navigator && navigator.serviceWorker.controller) {
const reg = await navigator.serviceWorker.ready
await reg.showNotification(title, options)
} else {
new window.Notification(title, options)
}
await updateSent(notification.id, true) await updateSent(notification.id, true)
await updateRead(notification.id, true)
} }
setDesktopNotificationList([])
} }
useEffect(() => { useEffect(() => {
const startDesktopNotifications = async () => {
if (!('Notification' in window)) return
if (window.Notification.permission === 'default') {
await window.Notification.requestPermission()
}
if (window.Notification.permission === 'granted') {
await getDesktopNotifications()
desktopNotificationInterval.current = setInterval(async () => { desktopNotificationInterval.current = setInterval(async () => {
await getDesktopNotifications() await getDesktopNotifications()
}, notificationInterval) }, notificationInterval)
}
}
startDesktopNotifications()
return () => { return () => {
clearInterval(desktopNotificationInterval.current) clearInterval(desktopNotificationInterval.current)
} }
}, [desktopNotificationList]) }, [])
return ( return (
<Tooltip title={translate('::App.Notifications')}> <Tooltip title={translate('::App.Notifications')}>

View file

@ -6,7 +6,7 @@ const NotificationChannels = {
UiActivity: 'UiActivity', UiActivity: 'UiActivity',
UiToast: 'UiToast', UiToast: 'UiToast',
WhatsApp: 'WhatsApp', WhatsApp: 'WhatsApp',
Telegram: 'Telegram', // Telegram: 'Telegram',
} }
export const NotificationChannelColors: Record<string, string> = { export const NotificationChannelColors: Record<string, string> = {
@ -17,7 +17,7 @@ export const NotificationChannelColors: Record<string, string> = {
UiActivity: 'bg-lime-600', UiActivity: 'bg-lime-600',
UiToast: 'bg-emerald-800', UiToast: 'bg-emerald-800',
WhatsApp: 'bg-cyan-600', WhatsApp: 'bg-cyan-600',
Telegram: 'bg-purple-900', // Telegram: 'bg-purple-900',
} }
export default NotificationChannels export default NotificationChannels

View file

@ -26,5 +26,6 @@ export interface NotificationRuleDto {
export declare class NotificationFilterRequestDto extends PagedAndSortedResultRequestDto { export declare class NotificationFilterRequestDto extends PagedAndSortedResultRequestDto {
channels?: string[] channels?: string[]
isRead?: boolean isRead?: boolean
isSent?: boolean
isListRequest: boolean isListRequest: boolean
} }

View file

@ -60,14 +60,10 @@ function loadDynamicComponent(
// Eğer manuel registered'da yoksa, database compiled komponentleri kontrol et // Eğer manuel registered'da yoksa, database compiled komponentleri kontrol et
if (!DynamicComponent && isComponentRegistered && renderComponent && isComponentRegistered(componentName)) { if (!DynamicComponent && isComponentRegistered && renderComponent && isComponentRegistered(componentName)) {
// console.log(`Database component found: ${componentName}`)
// Database komponentini wrapper ile kullan
DynamicComponent = (props: any) => renderComponent(componentName, props) as React.ReactElement DynamicComponent = (props: any) => renderComponent(componentName, props) as React.ReactElement
} }
if (!DynamicComponent) { if (!DynamicComponent) {
console.error(`Dynamic component not found: ${componentName}`)
console.log('Available registered components:', Object.keys(registeredComponents))
if (isComponentRegistered) { if (isComponentRegistered) {
console.log('Database component registry available - checking...') console.log('Database component registry available - checking...')
} }

View file

@ -132,7 +132,6 @@ class DynamicServiceService {
* Kodu test et (compile) * Kodu test et (compile)
*/ */
async testCompile(data: TestCompileDto): Promise<CompileResult> { async testCompile(data: TestCompileDto): Promise<CompileResult> {
console.log('DynamicServiceService.testCompile called with data:', data)
const response = await apiService.fetchData<CompileResult>({ const response = await apiService.fetchData<CompileResult>({
url: `${this.baseUrl}/test-compile`, url: `${this.baseUrl}/test-compile`,
method: 'POST', method: 'POST',

View file

@ -62,7 +62,6 @@ class FileManagementService {
// Upload a file directly with FormData (NoteModal pattern) // Upload a file directly with FormData (NoteModal pattern)
async uploadFileDirectly(formData: FormData, tenantId?: string): Promise<{ data: FileItem }> { async uploadFileDirectly(formData: FormData, tenantId?: string): Promise<{ data: FileItem }> {
try { try {
console.log('Uploading file directly with FormData')
if (tenantId) { if (tenantId) {
formData.append('tenantId', tenantId) formData.append('tenantId', tenantId)
} }

View file

@ -36,7 +36,6 @@ export type Injections = typeof injections
const reduxStateSyncConfig: ReduxStateSyncConfig = { const reduxStateSyncConfig: ReduxStateSyncConfig = {
predicate: (action) => { predicate: (action) => {
// console.log({ action })
const blacklist = [ const blacklist = [
'persist/FLUSH', 'persist/FLUSH',
'persist/REHYDRATE', 'persist/REHYDRATE',

View file

@ -93,7 +93,6 @@ export function useCoordinator() {
}; };
const handleExamComplete = (session: ExamSession) => { const handleExamComplete = (session: ExamSession) => {
console.log("Exam completed:", session);
alert("Assessment completed successfully!"); alert("Assessment completed successfully!");
setCurrentPath("/admin/dashboard"); setCurrentPath("/admin/dashboard");
setCurrentExam(null); setCurrentExam(null);

View file

@ -42,7 +42,7 @@ export const useExamTimer = ({
}, []); }, []);
useEffect(() => { useEffect(() => {
let interval: NodeJS.Timeout; let interval: ReturnType<typeof setInterval>;
if (isRunning && !isPaused && timeRemaining > 0) { if (isRunning && !isPaused && timeRemaining > 0) {
interval = setInterval(() => { interval = setInterval(() => {

View file

@ -92,8 +92,6 @@ export const useReports = () => {
const currentTemplateResponse = await reportsService.getTemplateById(id) const currentTemplateResponse = await reportsService.getTemplateById(id)
const currentTemplate = currentTemplateResponse.data as ReportTemplateDto const currentTemplate = currentTemplateResponse.data as ReportTemplateDto
console.log('Current Template:', currentTemplate)
const updatedTemplate = { ...currentTemplate, ...updates } const updatedTemplate = { ...currentTemplate, ...updates }
await reportsService.updateTemplate(id, updatedTemplate) await reportsService.updateTemplate(id, updatedTemplate)

View file

@ -164,7 +164,6 @@ const FileManager = () => {
} }
const response = await fileManagementService.getFolderPath(folderId, selectedTenant?.id) const response = await fileManagementService.getFolderPath(folderId, selectedTenant?.id)
// console.log('Breadcrumb response for folderId:', folderId, response)
const pathItems: BreadcrumbItem[] = [ const pathItems: BreadcrumbItem[] = [
{ name: 'Files', path: '', id: undefined }, { name: 'Files', path: '', id: undefined },
...response.data.path.map((item) => ({ ...response.data.path.map((item) => ({

View file

@ -324,8 +324,6 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
const ImagePreview = ({ src, alt }: { src: string; alt: string }) => { const ImagePreview = ({ src, alt }: { src: string; alt: string }) => {
const [imageError, setImageError] = useState(false) const [imageError, setImageError] = useState(false)
console.log('Rendering ImagePreview with src:', src) // Debug için
return ( return (
<div className="w-full h-full bg-gray-100 dark:bg-gray-700 rounded flex items-center justify-center overflow-hidden"> <div className="w-full h-full bg-gray-100 dark:bg-gray-700 rounded flex items-center justify-center overflow-hidden">
{!imageError ? ( {!imageError ? (

View file

@ -93,7 +93,7 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
// Upload files one by one // Upload files one by one
for (const fileData of filesToUpload) { for (const fileData of filesToUpload) {
let progressInterval: NodeJS.Timeout | null = null let progressInterval: ReturnType<typeof setInterval> | null = null;
try { try {
// Set status to uploading // Set status to uploading

View file

@ -226,7 +226,6 @@ function FormFields({
}) })
setNull(resp?.data?.items) setNull(resp?.data?.items)
setFields(resp?.data?.items) setFields(resp?.data?.items)
console.log('getFields', resp?.data?.items)
if (resp.data?.items) { if (resp.data?.items) {
setFieldList( setFieldList(
resp?.data?.items.map((f: ColumnFormatEditDto) => ({ resp?.data?.items.map((f: ColumnFormatEditDto) => ({

View file

@ -91,7 +91,6 @@ function RolesPermission({
const filteredData = { ...data, groups: filteredGroups } const filteredData = { ...data, groups: filteredGroups }
console.log('Filtered permissions by tenant group:', tenantGroup, filteredData)
setPermissionList(filteredData) setPermissionList(filteredData)
} }

View file

@ -39,7 +39,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
const searchInputRef = useRef<HTMLInputElement>(null) const searchInputRef = useRef<HTMLInputElement>(null)
const autocompleteServiceRef = useRef<any>(null) const autocompleteServiceRef = useRef<any>(null)
const placesServiceRef = useRef<any>(null) const placesServiceRef = useRef<any>(null)
const debounceTimerRef = useRef<NodeJS.Timeout>() const debounceTimerRef = useRef<ReturnType<typeof setTimeout>>()
const scriptLoadedRef = useRef(false) const scriptLoadedRef = useRef(false)
// Google Maps SDK'yı yükle // Google Maps SDK'yı yükle

View file

@ -83,8 +83,6 @@ const Payment: React.FC = () => {
}, },
} as OrderDto } as OrderDto
console.log('Order data:', orderData)
const orderService = new OrderService() const orderService = new OrderService()
const result = await orderService.createOrder(orderData) const result = await orderService.createOrder(orderData)

View file

@ -65,7 +65,6 @@ const Settings = () => {
values.App_SiteManagement_Theme_Style.includes('.dark') ? 'dark' : 'light', values.App_SiteManagement_Theme_Style.includes('.dark') ? 'dark' : 'light',
) )
} }
console.log(values)
const resp = await updateSettingValues(values) const resp = await updateSettingValues(values)
if (resp.status === 204) { if (resp.status === 204) {
await fetchData(activeGroupName) await fetchData(activeGroupName)