Notification UiToast, UiActivity, Desktop düzenlemesi
Fazla Console.Log kaldırıldı.
This commit is contained in:
parent
8feab2184a
commit
524a88274b
21 changed files with 73 additions and 70 deletions
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
public static class NotificationChannels
|
||||
{
|
||||
public const string Sms = "Sms";
|
||||
public const string Mail = "Mail";
|
||||
public const string Rocket = "Rocket";
|
||||
public const string Desktop = "Desktop";
|
||||
public const string UiActivity = "UiActivity";
|
||||
public const string UiToast = "UiToast";
|
||||
public const string WhatsApp = "WhatsApp";
|
||||
public const string Sms = "Sms"; //SMS (ABP Sms + Posta Guvercini)
|
||||
public const string Mail = "Mail"; //Email (ABP Emailing + Amazon SES)
|
||||
public const string Rocket = "Rocket"; //Rocket.Chat (HTTP API)
|
||||
public const string Desktop = "Desktop";
|
||||
public const string UiActivity = "UiActivity"; //UI Activity (ABP UI Activity)
|
||||
public const string UiToast = "UiToast"; //UI Toast (ABP UI Toast) Ayarlar/Sistem/Bildirimler/Chrome açık olması gerekiyor.
|
||||
public const string WhatsApp = "WhatsApp"; //WhatsApp (HTTP API, template-based)
|
||||
// public const string Telegram = "Telegram";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4453,12 +4453,12 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
|||
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
|
||||
new () { Key="Sms",Name="Sms" },
|
||||
new () { Key="Mail",Name="Mail" },
|
||||
new () { Key="WhatsApp",Name="WhatsApp" },
|
||||
new () { Key="Rocket",Name="Rocket" },
|
||||
new () { Key="Desktop",Name="Desktop" },
|
||||
new () { Key="UiActivity",Name="UiActivity" },
|
||||
new () { Key="UiToast",Name="UiToast" },
|
||||
new () { Key="WhatsApp",Name="WhatsApp" },
|
||||
new () { Key="Telegram",Name="Telegram" },
|
||||
new () { Key="Desktop",Name="Desktop" },
|
||||
// new () { Key="Telegram",Name="Telegram" },
|
||||
}),
|
||||
}),
|
||||
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||
|
|
|
|||
|
|
@ -90,12 +90,6 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
|
|||
// hooks.add("useEffect");
|
||||
// }
|
||||
|
||||
console.log(
|
||||
"🪝 Active hooks detected:",
|
||||
Array.from(hooks),
|
||||
"for component:",
|
||||
selectedComponent.id
|
||||
);
|
||||
setActiveHooks(hooks);
|
||||
}
|
||||
}, [selectedComponent, currentCode]);
|
||||
|
|
@ -131,13 +125,6 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
|
|||
const handleApplyPropChanges = () => {
|
||||
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
|
||||
const allUpdates = {
|
||||
...pendingProperties,
|
||||
|
|
@ -146,7 +133,6 @@ const PropertyPanel: React.FC<PropertyPanelProps> = ({
|
|||
|
||||
// Apply property and event changes together
|
||||
if (Object.keys(allUpdates).length > 0) {
|
||||
console.log("🔧 PropertyPanel: Applying combined updates:", allUpdates);
|
||||
onPropertiesChange(selectedComponent.id, allUpdates);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ type NotificationList = {
|
|||
}
|
||||
|
||||
const notificationHeight = 'h-72'
|
||||
const notificationInterval = 120000
|
||||
const notificationInterval = 120000 // 2 minutes
|
||||
|
||||
const notificationTypeAvatar = (creatorId: string, tenantId?: string) => {
|
||||
return <Avatar shape="circle" src={AVATAR_URL(creatorId, tenantId)} />
|
||||
|
|
@ -75,16 +75,20 @@ const _Notification = ({ className }: { className?: string }) => {
|
|||
const [noResult, setNoResult] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const [toastNotificationList, setToastNotificationList] = useState<string[]>([])
|
||||
const toastNotificationInterval = useRef<NodeJS.Timer>()
|
||||
const [desktopNotificationList, setDesktopNotificationList] = useState<string[]>([])
|
||||
const desktopNotificationInterval = useRef<NodeJS.Timer>()
|
||||
const toastNotificationList = useRef<string[]>([])
|
||||
const toastNotificationInterval = useRef<ReturnType<typeof setInterval>>()
|
||||
const desktopNotificationList = useRef<string[]>([])
|
||||
const desktopNotificationInterval = useRef<ReturnType<typeof setInterval>>()
|
||||
|
||||
const { bgTheme } = useThemeClass()
|
||||
const { larger } = useResponsive()
|
||||
|
||||
const direction = useStoreState((state) => state.theme.direction)
|
||||
const tabHasFocus = useStoreState((a) => a.base.common.tabHasFocus)
|
||||
const tabHasFocusRef = useRef(tabHasFocus)
|
||||
useEffect(() => {
|
||||
tabHasFocusRef.current = tabHasFocus
|
||||
}, [tabHasFocus])
|
||||
|
||||
const getReactNotificationCount = useCallback(async () => {
|
||||
const resp = await getList({
|
||||
|
|
@ -175,22 +179,23 @@ const _Notification = ({ className }: { className?: string }) => {
|
|||
const resp = await getList({
|
||||
channels: [NotificationChannels.UiToast],
|
||||
isListRequest: false,
|
||||
isSent: false,
|
||||
maxResultCount: 1000,
|
||||
})
|
||||
const items = resp.data.items ?? []
|
||||
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) {
|
||||
toast.push(
|
||||
<Notify
|
||||
type="success"
|
||||
duration={0}
|
||||
closable={true}
|
||||
onClose={async () => {
|
||||
await updateRead(notification.id, true)
|
||||
}}
|
||||
>
|
||||
{notification.message}
|
||||
</Notify>,
|
||||
|
|
@ -200,13 +205,16 @@ const _Notification = ({ className }: { className?: string }) => {
|
|||
)
|
||||
|
||||
await updateSent(notification.id, true)
|
||||
await updateRead(notification.id, true)
|
||||
}
|
||||
setToastNotificationList([])
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (tabHasFocusRef.current) {
|
||||
getToastNotifications()
|
||||
}
|
||||
toastNotificationInterval.current = setInterval(async () => {
|
||||
if (tabHasFocus) {
|
||||
if (tabHasFocusRef.current) {
|
||||
await getToastNotifications()
|
||||
}
|
||||
}, notificationInterval)
|
||||
|
|
@ -214,41 +222,68 @@ const _Notification = ({ className }: { className?: string }) => {
|
|||
return () => {
|
||||
clearInterval(toastNotificationInterval.current)
|
||||
}
|
||||
}, [toastNotificationList, tabHasFocus])
|
||||
}, [])
|
||||
|
||||
//Desktop
|
||||
const getDesktopNotifications = async () => {
|
||||
if (!('Notification' in window) || window.Notification.permission !== 'granted') return
|
||||
|
||||
const resp = await getList({
|
||||
channels: [NotificationChannels.Desktop],
|
||||
isListRequest: false,
|
||||
isSent: false,
|
||||
maxResultCount: 1000,
|
||||
})
|
||||
const items = resp.data.items ?? []
|
||||
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) {
|
||||
var options = {
|
||||
const title = notification.notificationType || 'Bildirim'
|
||||
const options = {
|
||||
body: notification.message,
|
||||
dir: 'ltr',
|
||||
requireInteraction: true,
|
||||
} 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 updateRead(notification.id, true)
|
||||
}
|
||||
setDesktopNotificationList([])
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
desktopNotificationInterval.current = setInterval(async () => {
|
||||
await getDesktopNotifications()
|
||||
}, notificationInterval)
|
||||
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 () => {
|
||||
await getDesktopNotifications()
|
||||
}, notificationInterval)
|
||||
}
|
||||
}
|
||||
|
||||
startDesktopNotifications()
|
||||
|
||||
return () => {
|
||||
clearInterval(desktopNotificationInterval.current)
|
||||
}
|
||||
}, [desktopNotificationList])
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Tooltip title={translate('::App.Notifications')}>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const NotificationChannels = {
|
|||
UiActivity: 'UiActivity',
|
||||
UiToast: 'UiToast',
|
||||
WhatsApp: 'WhatsApp',
|
||||
Telegram: 'Telegram',
|
||||
// Telegram: 'Telegram',
|
||||
}
|
||||
|
||||
export const NotificationChannelColors: Record<string, string> = {
|
||||
|
|
@ -17,7 +17,7 @@ export const NotificationChannelColors: Record<string, string> = {
|
|||
UiActivity: 'bg-lime-600',
|
||||
UiToast: 'bg-emerald-800',
|
||||
WhatsApp: 'bg-cyan-600',
|
||||
Telegram: 'bg-purple-900',
|
||||
// Telegram: 'bg-purple-900',
|
||||
}
|
||||
|
||||
export default NotificationChannels
|
||||
|
|
|
|||
|
|
@ -26,5 +26,6 @@ export interface NotificationRuleDto {
|
|||
export declare class NotificationFilterRequestDto extends PagedAndSortedResultRequestDto {
|
||||
channels?: string[]
|
||||
isRead?: boolean
|
||||
isSent?: boolean
|
||||
isListRequest: boolean
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,14 +60,10 @@ function loadDynamicComponent(
|
|||
|
||||
// Eğer manuel registered'da yoksa, database compiled komponentleri kontrol et
|
||||
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
|
||||
}
|
||||
|
||||
if (!DynamicComponent) {
|
||||
console.error(`Dynamic component not found: ${componentName}`)
|
||||
console.log('Available registered components:', Object.keys(registeredComponents))
|
||||
if (isComponentRegistered) {
|
||||
console.log('Database component registry available - checking...')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,6 @@ class DynamicServiceService {
|
|||
* Kodu test et (compile)
|
||||
*/
|
||||
async testCompile(data: TestCompileDto): Promise<CompileResult> {
|
||||
console.log('DynamicServiceService.testCompile called with data:', data)
|
||||
const response = await apiService.fetchData<CompileResult>({
|
||||
url: `${this.baseUrl}/test-compile`,
|
||||
method: 'POST',
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ class FileManagementService {
|
|||
// Upload a file directly with FormData (NoteModal pattern)
|
||||
async uploadFileDirectly(formData: FormData, tenantId?: string): Promise<{ data: FileItem }> {
|
||||
try {
|
||||
console.log('Uploading file directly with FormData')
|
||||
if (tenantId) {
|
||||
formData.append('tenantId', tenantId)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ export type Injections = typeof injections
|
|||
|
||||
const reduxStateSyncConfig: ReduxStateSyncConfig = {
|
||||
predicate: (action) => {
|
||||
// console.log({ action })
|
||||
const blacklist = [
|
||||
'persist/FLUSH',
|
||||
'persist/REHYDRATE',
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ export function useCoordinator() {
|
|||
};
|
||||
|
||||
const handleExamComplete = (session: ExamSession) => {
|
||||
console.log("Exam completed:", session);
|
||||
alert("Assessment completed successfully!");
|
||||
setCurrentPath("/admin/dashboard");
|
||||
setCurrentExam(null);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export const useExamTimer = ({
|
|||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let interval: NodeJS.Timeout;
|
||||
let interval: ReturnType<typeof setInterval>;
|
||||
|
||||
if (isRunning && !isPaused && timeRemaining > 0) {
|
||||
interval = setInterval(() => {
|
||||
|
|
|
|||
|
|
@ -92,8 +92,6 @@ export const useReports = () => {
|
|||
const currentTemplateResponse = await reportsService.getTemplateById(id)
|
||||
const currentTemplate = currentTemplateResponse.data as ReportTemplateDto
|
||||
|
||||
console.log('Current Template:', currentTemplate)
|
||||
|
||||
const updatedTemplate = { ...currentTemplate, ...updates }
|
||||
await reportsService.updateTemplate(id, updatedTemplate)
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,6 @@ const FileManager = () => {
|
|||
}
|
||||
|
||||
const response = await fileManagementService.getFolderPath(folderId, selectedTenant?.id)
|
||||
// console.log('Breadcrumb response for folderId:', folderId, response)
|
||||
const pathItems: BreadcrumbItem[] = [
|
||||
{ name: 'Files', path: '', id: undefined },
|
||||
...response.data.path.map((item) => ({
|
||||
|
|
|
|||
|
|
@ -324,8 +324,6 @@ const FileItem = forwardRef<HTMLDivElement, FileItemProps>((props, ref) => {
|
|||
const ImagePreview = ({ src, alt }: { src: string; alt: string }) => {
|
||||
const [imageError, setImageError] = useState(false)
|
||||
|
||||
console.log('Rendering ImagePreview with src:', src) // Debug için
|
||||
|
||||
return (
|
||||
<div className="w-full h-full bg-gray-100 dark:bg-gray-700 rounded flex items-center justify-center overflow-hidden">
|
||||
{!imageError ? (
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ const FileUploadModal = forwardRef<HTMLDivElement, FileUploadModalProps>((props,
|
|||
|
||||
// Upload files one by one
|
||||
for (const fileData of filesToUpload) {
|
||||
let progressInterval: NodeJS.Timeout | null = null
|
||||
let progressInterval: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
try {
|
||||
// Set status to uploading
|
||||
|
|
|
|||
|
|
@ -226,7 +226,6 @@ function FormFields({
|
|||
})
|
||||
setNull(resp?.data?.items)
|
||||
setFields(resp?.data?.items)
|
||||
console.log('getFields', resp?.data?.items)
|
||||
if (resp.data?.items) {
|
||||
setFieldList(
|
||||
resp?.data?.items.map((f: ColumnFormatEditDto) => ({
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ function RolesPermission({
|
|||
|
||||
const filteredData = { ...data, groups: filteredGroups }
|
||||
|
||||
console.log('Filtered permissions by tenant group:', tenantGroup, filteredData)
|
||||
setPermissionList(filteredData)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const LocationPicker: React.FC<LocationPickerProps> = ({ onSelect, onClose }) =>
|
|||
const searchInputRef = useRef<HTMLInputElement>(null)
|
||||
const autocompleteServiceRef = useRef<any>(null)
|
||||
const placesServiceRef = useRef<any>(null)
|
||||
const debounceTimerRef = useRef<NodeJS.Timeout>()
|
||||
const debounceTimerRef = useRef<ReturnType<typeof setTimeout>>()
|
||||
const scriptLoadedRef = useRef(false)
|
||||
|
||||
// Google Maps SDK'yı yükle
|
||||
|
|
|
|||
|
|
@ -83,8 +83,6 @@ const Payment: React.FC = () => {
|
|||
},
|
||||
} as OrderDto
|
||||
|
||||
console.log('Order data:', orderData)
|
||||
|
||||
const orderService = new OrderService()
|
||||
const result = await orderService.createOrder(orderData)
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ const Settings = () => {
|
|||
values.App_SiteManagement_Theme_Style.includes('.dark') ? 'dark' : 'light',
|
||||
)
|
||||
}
|
||||
console.log(values)
|
||||
const resp = await updateSettingValues(values)
|
||||
if (resp.status === 204) {
|
||||
await fetchData(activeGroupName)
|
||||
|
|
|
|||
Loading…
Reference in a new issue