Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
798cfe5
adding media manager to the panel.
Maphikza Nov 1, 2024
4ea8f8a
feat(settings): add subscription tiers management to relay settings
Maphikza Nov 12, 2024
1850a7e
adding subscription tier manager code files
Maphikza Nov 12, 2024
6348b6d
fix: remove inline comments causing URL parsing errors in wallet inte…
Maphikza Nov 14, 2024
ddc4365
updating useMedia hook to use the new expected response types from th…
Maphikza Nov 15, 2024
33912b4
updating the settings type in the hook and page to reflect the new ba…
Maphikza Nov 23, 2024
98e3ecd
removing redundant commented code.
Maphikza Nov 23, 2024
f6eada0
fix: correct timestamp parsing in Bitcoin price chart
Maphikza Dec 11, 2024
8fee63f
adding npmrc file
Maphikza Dec 11, 2024
d1b8725
fix: subscription tiers and file storage settings
Maphikza Dec 11, 2024
0a93dc6
Adding relay-settings component to make the relay settings page more …
Maphikza Dec 16, 2024
3a33682
Adding relay settings page
Maphikza Dec 16, 2024
5b466ab
Removing redundant code
Maphikza Dec 16, 2024
a5a19bb
Adding free tier activation
Maphikza Dec 17, 2024
7075c34
feat(ui): Implement dynamic trending creators with fallback
Maphikza Dec 18, 2024
7e2c5b4
adding supporting hook
Maphikza Dec 18, 2024
1d0e6ce
fix: resolve React Hook dependency warnings across multiple components
Maphikza Mar 2, 2025
b3ec30e
chore: make pre-commit hook executable
Maphikza Mar 2, 2025
0a412e2
feat(UI): Enhance subscription tiers with card-based design
Maphikza Mar 6, 2025
50f1d04
feat(hooks): rename useTrendingCreators to usePaidSubscribers and fix…
Maphikza Mar 24, 2025
85f8a83
feat(ui): enhance TrendingCreators component display logic
Maphikza Mar 24, 2025
ec3e402
feat(ui): create modern SubscriberDetailModal component
Maphikza Mar 24, 2025
92d051a
future proofing api
Maphikza Mar 24, 2025
80d3055
fix(ui): remove duplicate close button from SubscriberDetailModal
Maphikza Mar 24, 2025
33a2358
fix(ui): fix modal close button in SubscriberDetailModal
Maphikza Mar 24, 2025
55c9e2d
feat: Implement moderation notifications system
Maphikza Mar 28, 2025
ad34725
Improve notification system UI and behavior
Maphikza Mar 28, 2025
c88a708
Add payment notifications feature
Maphikza Mar 28, 2025
45f2e7d
fix(ui): Add scrollable containers to notification tabs
Maphikza Mar 30, 2025
e0d0ebc
Fix blocked pubkeys API compatibility issues and improve UI display
Maphikza Mar 31, 2025
323d84c
Add complete Blocked Pubkeys admin feature implementation with UI com…
Maphikza Mar 31, 2025
427886a
Add flagged pubkeys functionality with moderation stats integration
Maphikza Mar 31, 2025
3f95cf5
Enhance blocked pubkeys UI: add link-based navigation, improve flag c…
Maphikza Mar 31, 2025
e30dc25
Remove Media Manager from sidebar navigation
Maphikza Mar 31, 2025
a2c81bf
Rename 'Blocked Pubkeys' to 'Access Control' for improved UX
Maphikza Mar 31, 2025
0e177e8
feat(subscription-tiers): improve data limit input UX
Maphikza Apr 1, 2025
495630c
fix: Fix syntax errors in report notifications API calls
Maphikza Apr 2, 2025
980ce76
feat: Implement useReportNotifications hook with robust error handlin…
Maphikza Apr 2, 2025
4ca3c33
ui: Remove Content Reports from sidebar navigation to streamline UI -…
Maphikza Apr 2, 2025
3a9bbe5
feat: Add report notifications tab to header dropdown
Maphikza Apr 2, 2025
78ac569
Add Access Control to sidebar navigation
Maphikza Apr 9, 2025
7ffc8c0
Resolve merge conflicts with main
Maphikza Apr 9, 2025
78d9c22
Fix TypeError in TotalEarning by properly handling numeric conversions
Maphikza Apr 9, 2025
459185b
Fix potential TypeError in TotalEarningChart by ensuring numeric data…
Maphikza Apr 9, 2025
3e4ef1f
Update translations for navigation to use keys for Relay Dashboard an…
Maphikza Apr 9, 2025
5500ab1
Remove unused imports from RelaySettingsPage.tsx
Maphikza Apr 9, 2025
54748f1
Refactor: Rename TrendingCreators to PaidSubscribers for better seman…
Maphikza Apr 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.development
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
REACT_APP_BASE_URL=http://localhost:9002
REACT_APP_WALLET_BASE_URL=http://localhost:9003 # New wallet base URL
REACT_APP_WALLET_BASE_URL=http://localhost:9003
REACT_APP_ASSETS_BUCKET=http://localhost
REACT_APP_DEMO_MODE=false

Expand Down
Empty file modified .husky/pre-commit
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
shamefully-hoist=true
147,529 changes: 147,529 additions & 0 deletions .yarn/releases/yarn-1.22.19.cjs

Large diffs are not rendered by default.

768 changes: 0 additions & 768 deletions .yarn/releases/yarn-3.1.1.cjs

This file was deleted.

12 changes: 12 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
enableGlobalCache: false

nodeLinker: node-modules

packageExtensions:
react-scripts@*:
dependencies:
typescript: 4.5.5
react@*:
peerDependencies:
react-dom: "*"

yarnPath: .yarn/releases/yarn-1.22.19.cjs
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"styled-components": "^5.3.0",
"typeface-lato": "^1.1.13",
"typeface-montserrat": "^1.1.13",
"typescript": "^5.4.5",
"typescript": "5.1.6",
"uuid": "^8.3.2",
"web-vitals": "^1.0.1",
"workbox-background-sync": "^5.1.3",
Expand Down Expand Up @@ -99,6 +99,7 @@
"not IE 11"
],
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/country-list": "^2.1.0",
"@types/leaflet": "^1.7.9",
"@types/react": "^18.0.28",
Expand Down Expand Up @@ -136,7 +137,7 @@
"@types/react": "^18.0.28",
"react-error-overlay": "6.0.9"
},
"packageManager": "yarn@3.1.1",
"packageManager": "yarn@1.22.19",
"keywords": [
"lightence",
"admin",
Expand Down
34 changes: 34 additions & 0 deletions sidebar-changes.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
diff --git a/src/components/layouts/main/sider/sidebarNavigation.tsx b/src/components/layouts/main/sider/sidebarNavigation.tsx
index fa18628..f2161cd 100644
--- a/src/components/layouts/main/sider/sidebarNavigation.tsx
+++ b/src/components/layouts/main/sider/sidebarNavigation.tsx
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
-import { DashboardOutlined, TableOutlined } from '@ant-design/icons';
+import { DashboardOutlined, TableOutlined, StopOutlined, FlagOutlined } from '@ant-design/icons';
import { ReactComponent as NestIcon } from '@app/assets/icons/hive.svg';
import { ReactComponent as BtcIcon } from '@app/assets/icons/btc.svg';
import { ReactComponent as StatsIcon } from '@app/assets/icons/stats.svg';
@@ -20,8 +20,8 @@ export const useSidebarNavigation = (): SidebarNavigationItem[] => {
return useMemo(() => {
const items: SidebarNavigationItem[] = [
{
title: 'common.relay-dashboard',
- key: 'relay-dashboard',
+ key: 'relay-dashboard',
url: '/',
icon: <NestIcon />,
},
@@ -31,6 +31,12 @@ export const useSidebarNavigation = (): SidebarNavigationItem[] => {
url: '/relay-settings',
icon: <StorageSettingsIcon />,
},
+ {
+ title: 'Access Control',
+ key: 'blocked-pubkeys',
+ url: '/blocked-pubkeys',
+ icon: <StopOutlined />,
+ },
{
title: 'Nostr Statistics',
key: 'dataTables',
22 changes: 22 additions & 0 deletions sidebar-clean.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--- a/src/components/layouts/main/sider/sidebarNavigation.tsx
+++ b/src/components/layouts/main/sider/sidebarNavigation.tsx
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
-import { DashboardOutlined, TableOutlined } from '@ant-design/icons';
+import { DashboardOutlined, TableOutlined, StopOutlined, FlagOutlined } from '@ant-design/icons';
import { ReactComponent as NestIcon } from '@app/assets/icons/hive.svg';
import { ReactComponent as BtcIcon } from '@app/assets/icons/btc.svg';
import { ReactComponent as StatsIcon } from '@app/assets/icons/stats.svg';
@@ -31,6 +31,12 @@ export const useSidebarNavigation = (): SidebarNavigationItem[] => {
url: '/relay-settings',
icon: <StorageSettingsIcon />,
},
+ {
+ title: 'Access Control',
+ key: 'blocked-pubkeys',
+ url: '/blocked-pubkeys',
+ icon: <StopOutlined />,
+ },
{
title: 'Nostr Statistics',
key: 'dataTables',
3 changes: 2 additions & 1 deletion src/api/activity.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ export const getUserActivities = (handleLogout: () => void): Promise<WalletTrans
}
// Assuming your backend response matches the WalletTransaction interface
// eslint-disable-next-line
console.log("User Activity Data: ", data)
return data.map((item: any) => ({
id: item.ID,
witness_tx_id: item.WitnessTxId,
witness_tx_id: item.Address,
date: new Date(item.Date).getTime(),
output: item.Output,
value: item.Value,
Expand Down
51 changes: 51 additions & 0 deletions src/api/blockedPubkeys.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import config from '@app/config/config';
import { readToken } from '@app/services/localStorage.service';

export interface BlockedPubkey {
pubkey: string;
reason: string;
blocked_at: string;
}

export const getBlockedPubkeys = async (): Promise<{ blocked_pubkeys: BlockedPubkey[], count: number }> => {
const token = readToken();
const response = await fetch(`${config.baseURL}/api/blocked-pubkeys`, {
headers: {
'Authorization': `Bearer ${token}`,
},
});

if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.json();
};

export const blockPubkey = async (pubkey: string, reason?: string): Promise<{ success: boolean, message: string }> => {
const token = readToken();
const response = await fetch(`${config.baseURL}/api/blocked-pubkeys`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ pubkey, reason }),
});

if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.json();
};

export const unblockPubkey = async (pubkey: string): Promise<{ success: boolean, message: string }> => {
const token = readToken();
// Strip the "blocked_pubkey:" prefix if it exists
const cleanPubkey = pubkey.replace('blocked_pubkey:', '');

const response = await fetch(`${config.baseURL}/api/blocked-pubkeys/${cleanPubkey}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
},
});

if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.json();
};
66 changes: 66 additions & 0 deletions src/api/moderationNotifications.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { httpApi } from './http.api';

export interface ModerationNotificationParams {
page?: number;
limit?: number;
filter?: 'all' | 'unread' | 'user';
pubkey?: string;
}

export interface ModerationNotification {
id: number;
pubkey: string;
event_id: string;
reason: string;
created_at: string;
is_read: boolean;
content_type: string;
media_url?: string;
thumbnail_url?: string;
}

export interface PaginationData {
currentPage: number;
pageSize: number;
totalItems: number;
totalPages: number;
hasNext: boolean;
hasPrevious: boolean;
}

export interface ModerationNotificationsResponse {
notifications: ModerationNotification[];
pagination: PaginationData;
}

export interface ModerationStats {
total_blocked: number;
total_blocked_today: number;
by_content_type: Array<{ type: string; count: number }>;
by_user: Array<{ pubkey: string; count: number }>;
recent_reasons: string[];
}

// Fetch moderation notifications with filtering and pagination
export const getModerationNotifications = async (
params: ModerationNotificationParams = {},
): Promise<ModerationNotificationsResponse> => {
const response = await httpApi.get<ModerationNotificationsResponse>('/api/moderation/notifications', { params });
return response.data;
};

// Mark a specific notification as read
export const markNotificationAsRead = async (id: number): Promise<void> => {
await httpApi.post('/api/moderation/notifications/read', { id: [id] });
};

// Mark all notifications as read
export const markAllNotificationsAsRead = async (): Promise<void> => {
await httpApi.post('/api/moderation/notifications/read-all');
};

// Get moderation statistics
export const getModerationStats = async (): Promise<ModerationStats> => {
const response = await httpApi.get<ModerationStats>('/api/moderation/stats');
return response.data;
};
32 changes: 32 additions & 0 deletions src/api/moderationStats.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import config from '@app/config/config';
import { readToken } from '@app/services/localStorage.service';

export interface TypeStat {
type: string; // Content type (image/video)
count: number; // Number of items
}

export interface UserStat {
pubkey: string; // User public key
count: number; // Number of blocked items
}

export interface ModerationStats {
total_blocked: number; // Total number of blocked events
total_blocked_today: number; // Number of events blocked today
by_content_type: TypeStat[]; // Breakdown by content type
by_user: UserStat[]; // Top users with blocked content
recent_reasons: string[]; // Recent blocking reasons
}

export const getModerationStats = async (): Promise<ModerationStats> => {
const token = readToken();
const response = await fetch(`${config.baseURL}/api/moderation/stats`, {
headers: {
'Authorization': `Bearer ${token}`,
},
});

if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.json();
};
36 changes: 13 additions & 23 deletions src/api/notifications.api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
export interface Message {
id: number;
description: string;
moderationData?: {
id: number;
pubkey: string;
event_id: string;
reason: string;
created_at: string;
is_read: boolean;
content_type: string;
media_url?: string;
thumbnail_url?: string;
};
}

export interface Mention extends Message {
Expand All @@ -12,26 +23,5 @@ export interface Mention extends Message {

export type Notification = Mention | Message;

export const notifications = [
{
id: 2,
description: 'header.notifications.loginAttempt',
},
{
id: 1,
description: 'header.notifications.successPayment',
},
{
id: 3,
description: 'header.notifications.serverError',
},
{
id: 4,
description: 'header.notifications.mention',
userName: 'Steve Manson',
userIcon:
'https://res.cloudinary.com/lapkinthegod/image/upload/v1629187274/young-male-doctor-white-uniform_x7dcrs.jpg',
place: 'medical-dashboard.latestScreenings.title',
href: `/#latest-screenings`,
},
];
// Export an empty array now that we're using real moderation notifications
export const notifications: Notification[] = [];
20 changes: 20 additions & 0 deletions src/api/paidSubscribers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export interface PaidSubscriber {
pubkey: string;
picture: string;
name?: string;
about?: string;
metadata?: {
subscriptionTier?: string;
subscribedSince?: string;
};
}

// This is a placeholder function if needed in the future
// Currently the hook directly fetches from the API
export const getPaidSubscribers = (): Promise<PaidSubscriber[]> => {
return new Promise((res) => {
setTimeout(() => {
res([]);
}, 0);
});
};
Loading
Loading