mirror of
https://github.com/philipredstone/relnet.git
synced 2025-06-17 05:01:24 +02:00
public networks now display correctly
This commit is contained in:
parent
524dc010d0
commit
c078610c4d
@ -7,11 +7,16 @@ const port = window.location.port;
|
|||||||
const API_URL = protocol + '//' + hostname + (port ? ':' + port : '') + '/api';
|
const API_URL = protocol + '//' + hostname + (port ? ':' + port : '') + '/api';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
export interface NetworkOwner {
|
||||||
|
_id: string;
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Network {
|
export interface Network {
|
||||||
_id: string;
|
_id: string;
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
owner: string;
|
owner: string | NetworkOwner; // Can be either string ID or populated object
|
||||||
isPublic: boolean;
|
isPublic: boolean;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useNetworks } from '../../context/NetworkContext';
|
import { useNetworks } from '../../context/NetworkContext';
|
||||||
|
import { useAuth } from '../../context/AuthContext';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
const NetworkList: React.FC = () => {
|
const NetworkList: React.FC = () => {
|
||||||
const { networks, loading, error, createNetwork, deleteNetwork } = useNetworks();
|
const { networks, loading, error, createNetwork, deleteNetwork } = useNetworks();
|
||||||
|
const { user } = useAuth();
|
||||||
const [showCreateForm, setShowCreateForm] = useState(false);
|
const [showCreateForm, setShowCreateForm] = useState(false);
|
||||||
const [newNetworkName, setNewNetworkName] = useState('');
|
const [newNetworkName, setNewNetworkName] = useState('');
|
||||||
const [newNetworkDescription, setNewNetworkDescription] = useState('');
|
const [newNetworkDescription, setNewNetworkDescription] = useState('');
|
||||||
@ -153,40 +155,117 @@ const NetworkList: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<>
|
||||||
{networks.map((network) => (
|
{/* My Networks Section */}
|
||||||
<div key={network._id} className="bg-white rounded-lg shadow-md overflow-hidden">
|
<div className="mb-8">
|
||||||
<div className="p-4">
|
<h2 className="text-xl font-semibold mb-4">My Networks</h2>
|
||||||
<h2 className="text-xl font-bold mb-2">{network.name}</h2>
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{network.description && (
|
{networks
|
||||||
<p className="text-gray-600 mb-4">{network.description}</p>
|
.filter(network => {
|
||||||
)}
|
if (!user) return false;
|
||||||
<div className="flex items-center mb-4">
|
const ownerId = typeof network.owner === 'string'
|
||||||
<span className={`px-2 py-1 rounded-full text-xs ${network.isPublic ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`}>
|
? network.owner
|
||||||
{network.isPublic ? 'Public' : 'Private'}
|
: network.owner._id;
|
||||||
</span>
|
return ownerId === user.id;
|
||||||
<span className="text-xs text-gray-500 ml-2">
|
})
|
||||||
Created: {new Date(network.createdAt).toLocaleDateString()}
|
.map((network) => (
|
||||||
</span>
|
<div key={network._id} className="bg-white rounded-lg shadow-md overflow-hidden">
|
||||||
</div>
|
<div className="p-4">
|
||||||
<div className="flex space-x-2">
|
<h2 className="text-xl font-bold mb-2">{network.name}</h2>
|
||||||
<button
|
{network.description && (
|
||||||
className="flex-1 bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
|
<p className="text-gray-600 mb-4">{network.description}</p>
|
||||||
onClick={() => navigate(`/networks/${network._id}`)}
|
)}
|
||||||
>
|
<div className="flex items-center mb-4">
|
||||||
View
|
<span className={`px-2 py-1 rounded-full text-xs ${network.isPublic ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`}>
|
||||||
</button>
|
{network.isPublic ? 'Public' : 'Private'}
|
||||||
<button
|
</span>
|
||||||
className="flex-1 bg-red-500 hover:bg-red-700 text-white py-2 px-4 rounded"
|
<span className="text-xs text-gray-500 ml-2">
|
||||||
onClick={() => handleDeleteNetwork(network._id)}
|
Created: {new Date(network.createdAt).toLocaleDateString()}
|
||||||
>
|
</span>
|
||||||
Delete
|
</div>
|
||||||
</button>
|
<div className="flex space-x-2">
|
||||||
</div>
|
<button
|
||||||
|
className="flex-1 bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
|
||||||
|
onClick={() => navigate(`/networks/${network._id}`)}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="flex-1 bg-red-500 hover:bg-red-700 text-white py-2 px-4 rounded"
|
||||||
|
onClick={() => handleDeleteNetwork(network._id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{networks.filter(network => {
|
||||||
|
if (!user) return false;
|
||||||
|
const ownerId = typeof network.owner === 'string'
|
||||||
|
? network.owner
|
||||||
|
: network.owner._id;
|
||||||
|
return ownerId === user.id;
|
||||||
|
}).length === 0 && (
|
||||||
|
<p className="text-gray-600 mb-4">You haven't created any networks yet.</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Public Networks Section */}
|
||||||
|
{networks.some(network => {
|
||||||
|
if (!user) return false;
|
||||||
|
const ownerId = typeof network.owner === 'string'
|
||||||
|
? network.owner
|
||||||
|
: network.owner._id;
|
||||||
|
return ownerId !== user.id;
|
||||||
|
}) && (
|
||||||
|
<div>
|
||||||
|
<h2 className="text-xl font-semibold mb-4">Public Networks From Others</h2>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{networks
|
||||||
|
.filter(network => {
|
||||||
|
if (!user) return false;
|
||||||
|
const ownerId = typeof network.owner === 'string'
|
||||||
|
? network.owner
|
||||||
|
: network.owner._id;
|
||||||
|
return ownerId !== user.id;
|
||||||
|
})
|
||||||
|
.map((network) => (
|
||||||
|
<div key={network._id} className="bg-white rounded-lg shadow-md overflow-hidden border-l-4 border-green-500">
|
||||||
|
<div className="p-4">
|
||||||
|
<h2 className="text-xl font-bold mb-2">{network.name}</h2>
|
||||||
|
{network.description && (
|
||||||
|
<p className="text-gray-600 mb-4">{network.description}</p>
|
||||||
|
)}
|
||||||
|
<div className="flex items-center mb-4">
|
||||||
|
<span className="px-2 py-1 rounded-full text-xs bg-green-100 text-green-800">
|
||||||
|
Public
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-gray-500 ml-2">
|
||||||
|
Created: {new Date(network.createdAt).toLocaleDateString()}
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-gray-500 ml-2">
|
||||||
|
By: {typeof network.owner === 'string'
|
||||||
|
? 'Unknown'
|
||||||
|
: network.owner.username}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<button
|
||||||
|
className="w-full bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
|
||||||
|
onClick={() => navigate(`/networks/${network._id}`)}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
)}
|
||||||
</div>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -3,7 +3,7 @@ import Network from '../models/network.model';
|
|||||||
import { UserRequest } from '../types/express';
|
import { UserRequest } from '../types/express';
|
||||||
import { validationResult } from 'express-validator';
|
import { validationResult } from 'express-validator';
|
||||||
|
|
||||||
// Get all networks for current user
|
// Get all networks for current user and all public networks
|
||||||
export const getUserNetworks = async (req: UserRequest, res: Response): Promise<void> => {
|
export const getUserNetworks = async (req: UserRequest, res: Response): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
@ -11,7 +11,15 @@ export const getUserNetworks = async (req: UserRequest, res: Response): Promise<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const networks = await Network.find({ owner: req.user._id });
|
// Find networks that either:
|
||||||
|
// 1. Belong to the current user, OR
|
||||||
|
// 2. Are public networks (created by any user)
|
||||||
|
const networks = await Network.find({
|
||||||
|
$or: [
|
||||||
|
{ owner: req.user._id },
|
||||||
|
{ isPublic: true }
|
||||||
|
]
|
||||||
|
}).populate('owner', 'username _id'); // Populate owner field with username
|
||||||
|
|
||||||
res.json({ success: true, data: networks });
|
res.json({ success: true, data: networks });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -63,7 +71,7 @@ export const getNetwork = async (req: UserRequest, res: Response): Promise<void>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const network = await Network.findById(networkId);
|
const network = await Network.findById(networkId).populate('owner', 'username _id');
|
||||||
|
|
||||||
if (!network) {
|
if (!network) {
|
||||||
res.status(404).json({ message: 'Network not found' });
|
res.status(404).json({ message: 'Network not found' });
|
||||||
@ -71,7 +79,7 @@ export const getNetwork = async (req: UserRequest, res: Response): Promise<void>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if user is owner or network is public
|
// Check if user is owner or network is public
|
||||||
if (network.owner.toString() !== req.user._id.toString() && !network.isPublic) {
|
if (network.owner._id.toString() !== req.user._id.toString() && !network.isPublic) {
|
||||||
res.status(403).json({ message: 'You do not have permission to access this network' });
|
res.status(403).json({ message: 'You do not have permission to access this network' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user