public networks now display correctly

This commit is contained in:
philipredstone 2025-04-15 14:32:54 +02:00
parent 524dc010d0
commit c078610c4d
3 changed files with 129 additions and 37 deletions

View File

@ -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;

View File

@ -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>
); );

View File

@ -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;
} }