Skip to content

Commit

Permalink
Merge pull request #344 from sinamics/org_admin
Browse files Browse the repository at this point in the history
Enhance Organization Management: Admin Addition, UI Updates.
sinamics authored Mar 14, 2024
2 parents 7d146ee + 38e5e34 commit b59420e
Showing 13 changed files with 492 additions and 127 deletions.
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ const OrganizationInviteModal = ({ organizationId }: Iprops) => {
const { refetch: refecthOrgUsers } = api.org.getOrgUsers.useQuery({
organizationId,
});
const { data: allUsers } = api.admin.getUsers.useQuery({ isAdmin: false });
const { data: allUsers } = api.org.getPlatformUsers.useQuery({ organizationId });

const { mutate: addUser } = api.org.addUser.useMutation();

@@ -74,8 +74,9 @@ const OrganizationInviteModal = ({ organizationId }: Iprops) => {
onChange={(e) => dropDownHandler(e)}
className="select select-sm select-bordered select-ghost max-w-xs"
>
<option>READ_ONLY</option>
<option>ADMIN</option>
<option>USER</option>
<option>READ_ONLY</option>
</select>
</div>
</div>
2 changes: 1 addition & 1 deletion src/components/elements/dropdownlist.tsx
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ const ScrollableDropdown = ({
width: containerRef.current ? containerRef.current.offsetWidth : "auto",
}}
>
{filteredItems.map((item) => (
{filteredItems?.map((item) => (
<li
key={item[idField]}
tabIndex={0}
100 changes: 53 additions & 47 deletions src/components/layouts/chatAside.tsx
Original file line number Diff line number Diff line change
@@ -64,6 +64,7 @@ const ChatAside = () => {
const [inputMsg, setInputMsg] = useState({ chatMessage: "" });
const query = useRouter().query;
const orgId = query.orgid as string;
const networkId = query.id as string;
const messageEndRef = useRef(null);

const { mutate: markMessagesAsRead } = api.org.markMessagesAsRead.useMutation();
@@ -145,57 +146,62 @@ const ChatAside = () => {
},
);
};

// add showChatBtn = true if networkId is not null
const showChatBtn = networkId !== undefined;

return (
<>
{/* Chat Toggle Button */}
<button
className={`w-14 z-10 fixed right-2 top-20 transition-all duration-150 ${
openChats.includes(orgId) ? "mr-72" : "w-0"
}`}
aria-label="Toggle chat"
onClick={() => toggleChat(orgId)}
>
<div className="flex items-center relative">
{/* Replace with an actual chat icon */}
{openChats.includes(orgId) ? (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8.25 4.5l7.5 7.5-7.5 7.5"
/>
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 19.5L8.25 12l7.5-7.5"
/>
</svg>
)}
<div className="relative">
<span className="text-xs">{t("chatSidebar.toggleChatLabel")}</span>
{hasNewMessages[orgId] ? (
<span className="absolute bg-red-400 w-2 h-2 rounded-lg -left-1 top-1 glow" />
) : null}
{showChatBtn ? (
<button
className={`w-14 z-10 fixed right-2 top-20 transition-all duration-150 ${
openChats.includes(orgId) ? "mr-72" : "w-0"
}`}
aria-label="Toggle chat"
onClick={() => toggleChat(orgId)}
>
<div className="flex items-center relative">
{openChats.includes(orgId) ? (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8.25 4.5l7.5 7.5-7.5 7.5"
/>
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 19.5L8.25 12l7.5-7.5"
/>
</svg>
)}
<div className="relative">
<span className="text-xs">{t("chatSidebar.toggleChatLabel")}</span>
{hasNewMessages[orgId] ? (
<span className="absolute bg-red-400 w-2 h-2 rounded-lg -left-1 top-1 glow" />
) : null}
</div>
</div>
</div>
</button>
</button>
) : null}
{/* Chat Aside Panel */}
<aside
className={`fixed h-full right-0 bg-base-200 shadow-md transition-all duration-150 ${
2 changes: 1 addition & 1 deletion src/components/layouts/logFooter.tsx
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ export const LogsFooter = ({ sidebarOpen, asideOpen }) => {
<>
<button
className={`fixed z-10 flex items-center justify-center flex-col text-6xl ${
asideOpen ? "right-[calc(50%+1rem)]" : "right-[calc(42%+1rem)]"
asideOpen ? "right-[calc(16%+1rem)]" : "right-[calc(1%+1rem)]"
} ${
logsOpen ? "bottom-[calc(350px/2+2.5rem)]" : "bottom-[0px]"
} rounded-full p-2 shadow-md transition-all duration-150`}
77 changes: 42 additions & 35 deletions src/components/layouts/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -172,58 +172,65 @@ const Sidebar = (): JSX.Element => {
{t("organization")}
</span>
</li>
{me?.memberOfOrgs.map((org) => (
<li key={org.orgName} className="my-px">
<Link
shallow
href={`/organization/${org.id}`}
className={`flex h-10 flex-row items-center rounded-lg px-3
{me?.memberOfOrgs.map((org) => {
const truncatedOrgName =
org.orgName.length > 15
? `${org.orgName.slice(0, 15)}...`
: org.orgName;

return (
<li key={org.orgName} className="my-px">
<Link
shallow
href={`/organization/${org.id}`}
className={`flex h-10 flex-row items-center rounded-lg px-3
${
router.query.orgid?.includes(org.id)
? "bg-gray-100 text-gray-700"
: "hover:bg-slate-700"
}`}
>
<span className="flex items-center justify-center text-lg text-gray-400">
{/* https://heroicons.com/ */}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21"
/>
</svg>
</span>
<span className="ml-3">{org.orgName}</span>
<div className="relative">
{hasNewMessages[org.id] ? (
// <span className="absolute bg-red-400 w-2 h-2 rounded-lg left-1 -top-2 glow" />
>
<span className="flex items-center justify-center text-lg text-gray-400">
{/* https://heroicons.com/ */}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-4 h-4 text-red-500 ml-2"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8.625 12a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0H8.25m4.125 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0H12m4.125 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0h-.375M21 12c0 4.556-4.03 8.25-9 8.25a9.764 9.764 0 01-2.555-.337A5.972 5.972 0 015.41 20.97a5.969 5.969 0 01-.474-.065 4.48 4.48 0 00.978-2.025c.09-.457-.133-.901-.467-1.226C3.93 16.178 3 14.189 3 12c0-4.556 4.03-8.25 9-8.25s9 3.694 9 8.25z"
d="M3.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21"
/>
</svg>
) : null}
</div>
</Link>
</li>
))}
</span>
<span className="ml-3">{truncatedOrgName}</span>
<div className="relative">
{hasNewMessages[org.id] ? (
// <span className="absolute bg-red-400 w-2 h-2 rounded-lg left-1 -top-2 glow" />
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-4 h-4 text-red-500 ml-2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8.625 12a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0H8.25m4.125 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0H12m4.125 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm0 0h-.375M21 12c0 4.556-4.03 8.25-9 8.25a9.764 9.764 0 01-2.555-.337A5.972 5.972 0 015.41 20.97a5.969 5.969 0 01-.474-.065 4.48 4.48 0 00.978-2.025c.09-.457-.133-.901-.467-1.226C3.93 16.178 3 14.189 3 12c0-4.556 4.03-8.25 9-8.25s9 3.694 9 8.25z"
/>
</svg>
) : null}
</div>
</Link>
</li>
);
})}
</>
) : null}
{session?.user?.role === "ADMIN" ? (
13 changes: 12 additions & 1 deletion src/components/networkByIdPage/table/memberHeaderColumns.tsx
Original file line number Diff line number Diff line change
@@ -249,6 +249,7 @@ export const MemberHeaderColumns = ({ nwid, central = false, organizationId }: I
sortUndefined: -1,
sortingFn: sortingPhysicalIpAddress,
cell: ({ getValue, row: { original } }) => {
const isOffline = original?.conStatus === ConnectionStatus.Offline;
if (central) {
const centralPhysicalAddress: string = original?.physicalAddress;
if (!centralPhysicalAddress || typeof centralPhysicalAddress !== "string")
@@ -268,7 +269,17 @@ export const MemberHeaderColumns = ({ nwid, central = false, organizationId }: I
</span>
);

return physicalAddress.split("/")[0];
return (
<div>
{isOffline ? (
<span className="text-sm text-gray-400/50">
{physicalAddress.split("/")[0]}
</span>
) : (
<span>{physicalAddress.split("/")[0]}</span>
)}
</div>
);
},
},
),
24 changes: 22 additions & 2 deletions src/components/organization/editOrgModal.tsx
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import toast from "react-hot-toast";
import { useModalStore } from "~/utils/store";
import { useTranslations } from "next-intl";
import Input from "../elements/input";
import { ErrorData } from "~/types/errorHandling";

interface Iprops {
organizationId: string;
@@ -15,10 +16,29 @@ const EditOrganizationModal = ({ organizationId }: Iprops) => {
const [input, setInput] = useState({ orgDescription: "", orgName: "" });
const { closeModal } = useModalStore((state) => state);
const { refetch: refecthAllOrg } = api.org.getAllOrg.useQuery();
const { data: orgData } = api.org.getOrgById.useQuery({
const { data: orgData, refetch: refecthOrgById } = api.org.getOrgById.useQuery({
organizationId,
});
const { mutate: updateOrg } = api.org.updateMeta.useMutation();
const { mutate: updateOrg } = api.org.updateMeta.useMutation({
onSuccess: () => {
toast.success("Organization updated successfully");
refecthAllOrg();
refecthOrgById();
closeModal();
},
onError: (error) => {
if ((error.data as ErrorData)?.zodError) {
const fieldErrors = (error.data as ErrorData)?.zodError.fieldErrors;
for (const field in fieldErrors) {
toast.error(`${fieldErrors[field].join(", ")}`);
}
} else if (error.message) {
toast.error(error.message);
} else {
toast.error("An unknown error occurred");
}
},
});
useEffect(() => {
if (orgData) {
setInput({
Loading

0 comments on commit b59420e

Please sign in to comment.