-
-
);
const DetailRow = ({ label, value }: { label: string; value: string }) => (
-
+
);
-
export const FileDetails = ({ file }: { file: Models.Document }) => {
- return (
- <>
-
-
-
-
-
-
-
- >
- );
+ return (
+ <>
+
+
+
+
+
+
+
+ >
+ );
};
interface Props {
- file: Models.Document;
- onInputChange: React.Dispatch
>;
- onRemove: (email: string) => void;
+ file: Models.Document;
+ onInputChange: React.Dispatch>;
+ onRemove: (email: string) => void;
+ currentUserEmail: string;
+ setIsAdmin: React.Dispatch>;
}
-export const ShareInput = ({ file, onInputChange, onRemove }: Props) => {
- return (
- <>
-
+export const ShareInput = ({
+ file,
+ onInputChange,
+ onRemove,
+ currentUserEmail,
+ setIsAdmin,
+ }: Props) => {
+ // console.log(isAdmin);
+ const totalSharedUser = file.users.length + file.AdminUsers.length;
+ return (
+ <>
+
-
-
- Share file with other users
-
-
onInputChange(e.target.value.trim().split(","))}
- className="share-input-field"
- />
-
-
-
Shared with
-
- {file.users.length} users
-
-
+
+
+ Share file with other user
+
+
{
+ const inputEmails = e.target.value.trim().split(",");
+ onInputChange(inputEmails);
+ }}
+ className="share-input-field"
+ />
-
- {file.users.map((email: string) => (
- -
-
{email}
-
-
- ))}
-
-
-
- >
- );
+ {file.owner.email === currentUserEmail && (
+
+
setIsAdmin(checked)}
+ className={"data-[state=checked]:bg-red"}
+ />
+
+
+ Provide Admin Privileges
+
+
+ This includes allowing the user to rename, delete, and share
+ files, ensuring that shared users do not receive admin
+ privileges.
+
+
+
+ )}
+
+
+
+
Shared with
+
+ {totalSharedUser} users
+
+
+
+
+ {file.AdminUsers.map((email: string) => (
+ -
+
{email}
+ Admin
+
+ {currentUserEmail === file.owner.email && (
+
+ )}
+
+ ))}
+ {file.users.map((email: string) => (
+ -
+
{email}
+
+ {currentUserEmail === file.owner.email && ( // TODO: check if current user is in admin email array
+
+ )}
+
+ ))}
+
+
+
+ >
+ );
};
diff --git a/components/ui/switch.tsx b/components/ui/switch.tsx
new file mode 100644
index 0000000..5f4117f
--- /dev/null
+++ b/components/ui/switch.tsx
@@ -0,0 +1,29 @@
+"use client"
+
+import * as React from "react"
+import * as SwitchPrimitives from "@radix-ui/react-switch"
+
+import { cn } from "@/lib/utils"
+
+const Switch = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+))
+Switch.displayName = SwitchPrimitives.Root.displayName
+
+export { Switch }
diff --git a/lib/actions/file.actions.ts b/lib/actions/file.actions.ts
index 765030d..008e432 100644
--- a/lib/actions/file.actions.ts
+++ b/lib/actions/file.actions.ts
@@ -72,6 +72,7 @@ const createQueries = (
Query.or([
Query.equal("owner", [currentUser.$id]),
Query.contains("users", [currentUser.email]),
+ Query.contains("AdminUsers", [currentUser.email]),
]),
];
@@ -111,7 +112,7 @@ export const getFiles = async ({
queries,
);
- console.log({ files });
+ // console.log({ files });
return parseStringify(files);
} catch (error) {
handleError(error, "Failed to get files");
@@ -146,7 +147,8 @@ export const renameFile = async ({
export const updateFileUsers = async ({
fileId,
- emails,
+ userEmails,
+ adminEmails,
path,
}: UpdateFileUsersProps) => {
const { databases } = await createAdminClient();
@@ -157,7 +159,8 @@ export const updateFileUsers = async ({
appwriteConfig.filesCollectionId,
fileId,
{
- users: emails,
+ AdminUsers: adminEmails,
+ users: userEmails,
},
);
diff --git a/package-lock.json b/package-lock.json
index 16de3b2..2adeda3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
+ "@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-toast": "^1.2.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
@@ -1515,6 +1516,97 @@
}
}
},
+ "node_modules/@radix-ui/react-switch": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.2.tgz",
+ "integrity": "sha512-zGukiWHjEdBCRyXvKR6iXAQG6qXm2esuAD6kDOi9Cn+1X6ev3ASo4+CsYaD6Fov9r/AQFekqnD/7+V0Cs6/98g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
+ "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+ "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-primitive": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
+ "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-slot": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
+ "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-toast": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.2.tgz",
diff --git a/package.json b/package.json
index 71fc713..b6d90c7 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
+ "@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-toast": "^1.2.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
diff --git a/types/index.d.ts b/types/index.d.ts
index 55435ef..9f7eeaf 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -33,9 +33,11 @@ declare interface RenameFileProps {
}
declare interface UpdateFileUsersProps {
fileId: string;
- emails: string[];
+ userEmails: string[];
+ adminEmails: string[];
path: string;
}
+
declare interface DeleteFileProps {
fileId: string;
bucketFileId: string;