├── functions
├── README.md
├── new_invitation
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ ├── README.md
│ ├── pnpm-lock.yaml
│ └── .gitignore
├── add_user_to_team
│ ├── package.json
│ ├── README.md
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── index.ts
│ └── .gitignore
├── setup_workspace
│ ├── package.json
│ ├── README.md
│ ├── pnpm-lock.yaml
│ ├── .gitignore
│ └── src
│ │ └── index.ts
├── change_username_to_email
│ ├── package.json
│ ├── README.md
│ ├── src
│ │ └── index.ts
│ ├── pnpm-lock.yaml
│ └── .gitignore
├── setup_user_workspace
│ ├── package.json
│ ├── README.md
│ ├── pnpm-lock.yaml
│ ├── .gitignore
│ └── src
│ │ └── index.ts
├── push_notifications
│ ├── package.json
│ ├── README.md
│ ├── .gitignore
│ ├── pnpm-lock.yaml
│ └── src
│ │ └── index.ts
└── upload_user_profile
│ ├── package.json
│ ├── README.md
│ ├── .gitignore
│ └── src
│ └── index.ts
├── .prettierrc
├── .gitattributes
├── src
├── utility
│ ├── index.ts
│ └── appwriteClient.ts
├── components
│ ├── layout
│ │ ├── index.ts
│ │ ├── title
│ │ │ └── index.tsx
│ │ ├── layout
│ │ │ └── index.tsx
│ │ └── header
│ │ │ └── index.tsx
│ ├── offLayoutArea
│ │ └── index.tsx
│ ├── index.ts
│ ├── ChakraNextImage.tsx
│ ├── Bold.tsx
│ ├── ExtraBold.tsx
│ ├── ChatMessage.tsx
│ ├── QuickLink.tsx
│ ├── ColorInput.tsx
│ ├── FormItem.tsx
│ ├── InvitationError.tsx
│ ├── ProjectsCard.tsx
│ ├── InviteMember.tsx
│ ├── RemoveUser.tsx
│ ├── SideBarProject.tsx
│ ├── SideBar.tsx
│ ├── WorkspacesList.tsx
│ ├── NewMember.tsx
│ ├── NotificationList.tsx
│ ├── ProjectsList.tsx
│ └── NavBar.tsx
└── authProvider.ts
├── .npmrc
├── types
├── index.ts
└── Project.ts
├── public
├── favicon.ico
├── images
│ ├── logo.png
│ ├── empty.png
│ ├── notask.png
│ ├── accept_invite.png
│ ├── noinvitations.png
│ ├── nonotifications.png
│ ├── flags
│ │ ├── de.svg
│ │ └── en.svg
│ └── growth.svg
├── refine-collapsed.svg
└── locales
│ ├── en
│ └── common.json
│ └── de
│ └── common.json
├── next-i18next.config.js
├── styles
└── styles.sass
├── .eslintrc.json
├── animations
├── index.ts
├── unfade.ts
├── rise.ts
└── rise_reverse.ts
├── .gitignore
├── next-env.d.ts
├── pages
├── project
│ └── [id]
│ │ ├── roles.tsx
│ │ ├── chat.tsx
│ │ └── index.tsx
├── login.tsx
├── _document.tsx
├── notifications.tsx
├── accept_invite.tsx
├── accept_invitation.tsx
├── invitations.tsx
├── _app.tsx
├── dashboard.tsx
└── features.tsx
├── next.config.js
├── theme
└── chakra.ts
├── .github
└── FUNDING.yml
├── LICENSE
├── tsconfig.json
├── package.json
├── README.MD
└── appwrite.json
/functions/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 4
3 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js linguist-language=TypeScript
--------------------------------------------------------------------------------
/src/utility/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./appwriteClient";
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | legacy-peer-deps=true
2 | strict-peer-dependencies=false
3 |
--------------------------------------------------------------------------------
/types/index.ts:
--------------------------------------------------------------------------------
1 | import { default as Project } from "./Project";
2 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyeboard/takoyaki/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyeboard/takoyaki/HEAD/public/images/logo.png
--------------------------------------------------------------------------------
/public/images/empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyeboard/takoyaki/HEAD/public/images/empty.png
--------------------------------------------------------------------------------
/public/images/notask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyeboard/takoyaki/HEAD/public/images/notask.png
--------------------------------------------------------------------------------
/public/images/accept_invite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyeboard/takoyaki/HEAD/public/images/accept_invite.png
--------------------------------------------------------------------------------
/public/images/noinvitations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyeboard/takoyaki/HEAD/public/images/noinvitations.png
--------------------------------------------------------------------------------
/public/images/nonotifications.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyeboard/takoyaki/HEAD/public/images/nonotifications.png
--------------------------------------------------------------------------------
/next-i18next.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | i18n: {
3 | defaultLocale: "en",
4 | locales: ["en", "de"],
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/src/components/layout/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./header";
2 | export * from "./sider";
3 | export * from "./layout";
4 | export * from "./title";
5 |
--------------------------------------------------------------------------------
/styles/styles.sass:
--------------------------------------------------------------------------------
1 | *::-webkit-scrollbar
2 | display: none
3 |
4 | *
5 | box-sizing: border-box
6 | transition: all ease-in-out 100ms
7 |
--------------------------------------------------------------------------------
/types/Project.ts:
--------------------------------------------------------------------------------
1 | export default interface Project {
2 | title: string;
3 | description: string;
4 | color: string;
5 | completed: number;
6 | }
7 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["next/core-web-vitals", "prettier"],
3 | "plugins": ["prettier"],
4 | "rules": {
5 | "prettier/prettier": "warn"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/animations/index.ts:
--------------------------------------------------------------------------------
1 | export { default as rise } from "./rise";
2 | export { default as rise_reverse } from "./rise_reverse";
3 | export { default as unfade } from "./unfade";
4 |
--------------------------------------------------------------------------------
/src/components/offLayoutArea/index.tsx:
--------------------------------------------------------------------------------
1 | import { RefineKbar } from "@pankod/refine-kbar";
2 |
3 | export const OffLayoutArea: React.FC = () => {
4 | return ;
5 | };
6 |
--------------------------------------------------------------------------------
/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export { default as ChakraNextImage } from "./ChakraNextImage";
2 | export { default as Bold } from "./Bold";
3 | export { default as ExtraBold } from "./ExtraBold";
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # npm
2 | node_modules
3 | # next.js build files
4 | .next
5 | # environment variables
6 | .env
7 | .env.*
8 | !.env.example
9 | # Build
10 | functions/**/*.js
11 | .vercel
12 |
--------------------------------------------------------------------------------
/animations/unfade.ts:
--------------------------------------------------------------------------------
1 | import { keyframes } from "@pankod/refine-chakra-ui";
2 |
3 | export default keyframes`
4 | 0% {
5 | opacity: 0;
6 | }
7 | 100% {
8 | opacity: 1;
9 | }
10 | `;
11 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/public/images/flags/de.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/ChakraNextImage.tsx:
--------------------------------------------------------------------------------
1 | import { chakra } from "@pankod/refine-chakra-ui";
2 | import Image from "next/image";
3 |
4 | export default chakra(Image, {
5 | shouldForwardProp: (prop) =>
6 | ["width", "height", "src", "alt"].includes(prop),
7 | });
8 |
--------------------------------------------------------------------------------
/animations/rise.ts:
--------------------------------------------------------------------------------
1 | import { keyframes } from "@pankod/refine-chakra-ui";
2 |
3 | export default keyframes`
4 | 0% {
5 | opacity: 0;
6 | transform: translateY(55px);
7 | }
8 | 100% {
9 | opacity: 1;
10 | transform: translateY(0px);
11 | }
12 | `;
13 |
--------------------------------------------------------------------------------
/pages/project/[id]/roles.tsx:
--------------------------------------------------------------------------------
1 | import SideBarProject from "@components/SideBarProject";
2 | import { Flex } from "@pankod/refine-chakra-ui";
3 |
4 | const Roles = () => {
5 | return (
6 |
7 |
8 |
9 | );
10 | };
11 |
12 | export default Roles;
13 |
--------------------------------------------------------------------------------
/animations/rise_reverse.ts:
--------------------------------------------------------------------------------
1 | import { keyframes } from "@pankod/refine-chakra-ui";
2 |
3 | export default keyframes`
4 | 0% {
5 | opacity: 0;
6 | transform: translateY(-55px);
7 | height: 0vh;
8 | }
9 | 100% {
10 | opacity: 1;
11 | transform: translateY(0px);
12 | height: 100vh;
13 | }
14 | `;
15 |
--------------------------------------------------------------------------------
/functions/new_invitation/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appwrite-function",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "node-appwrite": "^8.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/functions/add_user_to_team/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appwrite-function",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "node-appwrite": "^8.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/functions/setup_workspace/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appwrite-function",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "node-appwrite": "^8.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/layout/title/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useRouterContext, TitleProps } from "@pankod/refine-core";
3 | import { Link as ChakraLink } from "@pankod/refine-chakra-ui";
4 |
5 | export const Title: React.FC = ({ collapsed }) => {
6 | const { Link } = useRouterContext();
7 |
8 | return ;
9 | };
10 |
--------------------------------------------------------------------------------
/functions/change_username_to_email/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appwrite-function",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "node-appwrite": "^8.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/functions/setup_user_workspace/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appwrite-function",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "node-appwrite": "^8.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/pages/login.tsx:
--------------------------------------------------------------------------------
1 | import { useRouter } from "next/router";
2 | import { useEffect } from "react";
3 | import { account } from "src/utility";
4 |
5 | const Login = () => {
6 | useEffect(() => {
7 | account.createOAuth2Session(
8 | "google",
9 | `${location.origin}/dashboard`,
10 | location.origin
11 | );
12 | }, []);
13 | };
14 |
15 | export default Login;
16 |
--------------------------------------------------------------------------------
/src/components/Bold.tsx:
--------------------------------------------------------------------------------
1 | import { Nunito } from "@next/font/google";
2 | import { chakra, Text, TextProps } from "@pankod/refine-chakra-ui";
3 |
4 | const font = Nunito({ subsets: ["latin"], weight: "700" });
5 |
6 | const Bold: React.FC = ({ children, ...props }) => {
7 | return (
8 |
9 | {children}
10 |
11 | );
12 | };
13 |
14 | export default Bold;
15 |
--------------------------------------------------------------------------------
/src/components/ExtraBold.tsx:
--------------------------------------------------------------------------------
1 | import { Nunito } from "@next/font/google";
2 | import { Text, TextProps } from "@pankod/refine-chakra-ui";
3 |
4 | const font = Nunito({ subsets: ["latin"], weight: "800" });
5 |
6 | const ExtraBold: React.FC = ({ children, ...props }) => {
7 | return (
8 |
9 | {children}
10 |
11 | );
12 | };
13 |
14 | export default ExtraBold;
15 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | const { i18n } = require("./next-i18next.config");
2 |
3 | module.exports = {
4 | i18n,
5 | experimental: {
6 | newNextLinkBehavior: true,
7 | },
8 | images: {
9 | remotePatterns: [
10 | {
11 | protocol: "https",
12 | hostname: "avatars.githubusercontent.com",
13 | port: "",
14 | pathname: "/**",
15 | },
16 | ],
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/functions/push_notifications/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appwrite-function",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "moment": "^2.29.4",
14 | "node-appwrite": "^8.0.0"
15 | },
16 | "devDependencies": {
17 | "@types/moment": "^2.13.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Html, Head, Main, NextScript } from "next/document";
2 | import { refineTheme, ColorModeScript } from "@pankod/refine-chakra-ui";
3 |
4 | export default function Document() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/functions/upload_user_profile/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appwrite-function",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "googleapis": "^110.0.0",
14 | "needle": "^3.2.0",
15 | "node-appwrite": "^8.0.0"
16 | },
17 | "devDependencies": {
18 | "@types/needle": "^3.2.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/utility/appwriteClient.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Account,
3 | Appwrite,
4 | Databases,
5 | Storage,
6 | Teams,
7 | } from "@pankod/refine-appwrite";
8 |
9 | const APPWRITE_URL = "https://appwrite.kyeboard.me/v1";
10 | const APPWRITE_PROJECT = "63df174eb4161f4803ca";
11 |
12 | const appwriteClient = new Appwrite();
13 |
14 | appwriteClient.setEndpoint(APPWRITE_URL).setProject(APPWRITE_PROJECT);
15 | const account = new Account(appwriteClient);
16 | const storage = new Storage(appwriteClient);
17 | const database = new Databases(appwriteClient);
18 | const teams = new Teams(appwriteClient);
19 |
20 | export { appwriteClient, account, storage, teams, database };
21 |
--------------------------------------------------------------------------------
/theme/chakra.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from "@pankod/refine-chakra-ui";
2 |
3 | const theme = extendTheme({
4 | styles: {
5 | global: {
6 | body: {
7 | bg: "#E7E7F2",
8 | color: "#2E3440",
9 | },
10 | },
11 | },
12 | initialColorMode: "light",
13 | useSystemColorMode: false,
14 | breakpoints: {
15 | // Nav Bar breakpoints
16 | nav_sm: "",
17 |
18 | // SideBar breakpoints
19 | sidebar_md: "1000px",
20 |
21 | sm: "800px",
22 | },
23 | components: {
24 | Button: {
25 | defaultProps: {
26 | _hover: { bg: "#2E3440" },
27 | },
28 | },
29 | },
30 | });
31 |
32 | export default theme;
33 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [kyeboard]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/public/images/flags/en.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/authProvider.ts:
--------------------------------------------------------------------------------
1 | import { AuthProvider } from "@pankod/refine-core";
2 |
3 | import { account } from "./utility";
4 |
5 | export const authProvider: AuthProvider = {
6 | login: async ({ email, password }) => {
7 | try {
8 | await account.createEmailSession(email, password);
9 | return Promise.resolve();
10 | } catch (e) {
11 | return Promise.reject();
12 | }
13 | },
14 | logout: async () => {
15 | await account.deleteSession("current");
16 |
17 | return "/";
18 | },
19 | checkError: () => Promise.resolve(),
20 | checkAuth: async () => {
21 | const session = await account.get();
22 |
23 | if (session) {
24 | return Promise.resolve();
25 | }
26 |
27 | return Promise.reject();
28 | },
29 | getPermissions: () => Promise.resolve(),
30 | getUserIdentity: async () => {
31 | const user = await account.get();
32 |
33 | if (user) {
34 | return user;
35 | }
36 | },
37 | };
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 kyeboard
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/components/layout/layout/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { LayoutProps } from "@pankod/refine-core";
3 | import { Box, useColorModeValue } from "@pankod/refine-chakra-ui";
4 |
5 | import { Sider as DefaultSider } from "../sider";
6 | import { Header as DefaultHeader } from "../header";
7 |
8 | export const Layout: React.FC = ({
9 | Sider,
10 | Header,
11 | Footer,
12 | OffLayoutArea,
13 | children,
14 | }) => {
15 | const SiderToRender = Sider ?? DefaultSider;
16 | const HeaderToRender = Header ?? DefaultHeader;
17 |
18 | const bg = useColorModeValue("gray.100", "gray.900");
19 |
20 | return (
21 |
22 |
23 |
30 |
31 | {children}
32 | {Footer && }
33 |
34 | {OffLayoutArea && }
35 |
36 | );
37 | };
38 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "strict": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "noEmit": true,
14 | "esModuleInterop": true,
15 | "module": "esnext",
16 | "moduleResolution": "node",
17 | "resolveJsonModule": true,
18 | "isolatedModules": true,
19 | "jsx": "preserve",
20 | "baseUrl": ".",
21 | "paths": {
22 | "@components/*": [
23 | "src/components/*"
24 | ],
25 | "@components": [
26 | "src/components"
27 | ],
28 | "@contexts/*": [
29 | "src/contexts/*"
30 | ],
31 | "@contexts": [
32 | "src/contexts"
33 | ],
34 | "@styles/*": [
35 | "src/styles/*"
36 | ],
37 | "@styles": [
38 | "src/styles"
39 | ],
40 | "@public/*": [
41 | "public/*"
42 | ],
43 | "@public": [
44 | "public"
45 | ]
46 | },
47 | "incremental": true
48 | },
49 | "include": [
50 | "next-env.d.ts",
51 | "**/*.ts",
52 | "**/*.tsx"
53 | ],
54 | "exclude": [
55 | "node_modules"
56 | ]
57 | }
58 |
--------------------------------------------------------------------------------
/public/refine-collapsed.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/components/ChatMessage.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Flex } from "@pankod/refine-chakra-ui";
2 | import { rise } from "animations";
3 | import ChakraNextImage from "./ChakraNextImage";
4 |
5 | interface ChatMessageProps {
6 | animationDelay: number;
7 | imageSrc: string;
8 | children: React.ReactNode;
9 | }
10 |
11 | const ChatMessage: React.FC = ({
12 | animationDelay,
13 | imageSrc,
14 | children,
15 | }) => {
16 | return (
17 |
25 |
32 |
38 | {children}
39 |
40 |
41 | );
42 | };
43 |
44 | export default ChatMessage;
45 |
--------------------------------------------------------------------------------
/pages/project/[id]/chat.tsx:
--------------------------------------------------------------------------------
1 | import SideBarProject from "@components/SideBarProject";
2 | import { Models } from "@pankod/refine-appwrite";
3 | import { Box, Flex } from "@pankod/refine-chakra-ui";
4 | import TeamChat from "@components/TeamChat";
5 | import { AnimatePresence, motion } from "framer-motion";
6 | import Head from "next/head";
7 |
8 | interface Message extends Models.Document {
9 | message: string;
10 | timestamp: string;
11 | author: string;
12 | }
13 |
14 | const Chat = () => {
15 | const animatedElement = motion(Flex);
16 |
17 | return (
18 |
23 |
24 |
25 | Team chat - planetary
26 |
27 |
35 |
36 |
37 |
38 |
39 |
40 | );
41 | };
42 |
43 | export default Chat;
44 |
--------------------------------------------------------------------------------
/src/components/QuickLink.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, keyframes, Text } from "@pankod/refine-chakra-ui";
2 | import Link from "next/link";
3 |
4 | interface QuickLinkProps {
5 | title: string;
6 | href: string;
7 | icon: React.ReactNode;
8 | delay: number;
9 | current?: boolean;
10 | }
11 |
12 | const rise = keyframes`
13 | 0% {
14 | opacity: 0;
15 | transform: translateY(55px);
16 | }
17 | 100% {
18 | opacity: 1;
19 | transform: translateY(0px);
20 | }
21 | `;
22 |
23 | export const QuickLink: React.FC = ({
24 | title,
25 | href,
26 | icon,
27 | current,
28 | delay,
29 | }) => {
30 | return (
31 |
32 |
46 | {icon}
47 |
48 | {title}
49 |
50 |
51 |
52 | );
53 | };
54 |
--------------------------------------------------------------------------------
/src/components/ColorInput.tsx:
--------------------------------------------------------------------------------
1 | import { Flex } from "@pankod/refine-chakra-ui";
2 |
3 | interface ColorSelectionProps {
4 | onChange: (new_value: string) => void;
5 | value: string;
6 | }
7 |
8 | interface Color {
9 | display: string;
10 | value: string;
11 | }
12 |
13 | const colors: Array = [
14 | {
15 | display: "rgb(243, 139, 168)",
16 | value: "rgba(243, 139, 168, 0.3)",
17 | },
18 | {
19 | display: "rgb(137, 180, 250)",
20 | value: "rgba(137, 180, 250, 0.3)",
21 | },
22 | {
23 | display: "rgb(166, 227, 161)",
24 | value: "rgba(166, 227, 161, 0.3)",
25 | },
26 | {
27 | display: "rgb(203, 166, 247)",
28 | value: "rgba(203, 166, 247, 0.3)",
29 | },
30 | {
31 | display: "rgb(245, 194, 231)",
32 | value: "rgba(245, 194, 231, 0.3)",
33 | },
34 | {
35 | display: "rgb(242, 205, 205)",
36 | value: "rgba(242, 205, 205, 0.3)",
37 | },
38 | ];
39 |
40 | const ColorSelection: React.FC = ({ onChange, value }) => {
41 | return (
42 |
43 | {colors.map((color) => (
44 | onChange(color.value)}
52 | border={
53 | value === color.value ? "2px solid #2E3440" : "none"
54 | }
55 | />
56 | ))}
57 |
58 | );
59 | };
60 |
61 | export default ColorSelection;
62 |
--------------------------------------------------------------------------------
/functions/new_invitation/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Client, Databases, Models, Teams } from "node-appwrite";
2 |
3 | interface Request {
4 | headers: {
5 | [key: string]: string;
6 | };
7 | payload: {
8 | [key: string]: string;
9 | };
10 | variables: {
11 | [key: string]: string;
12 | };
13 | }
14 |
15 | interface Response {
16 | send: (text: string, status?: number) => void;
17 | json: (obj: any, status?: number) => void;
18 | }
19 |
20 | const new_invitation = async function (req: Request, res: Response) {
21 | const client = new Client();
22 |
23 | // You can remove services you don't use
24 | const databases = new Databases(client);
25 | const teams = new Teams(client);
26 |
27 | if (
28 | !req.variables["APPWRITE_FUNCTION_ENDPOINT"] ||
29 | !req.variables["APPWRITE_FUNCTION_API_KEY"]
30 | ) {
31 | console.warn(
32 | "Environment variables are not set. Function cannot use Appwrite SDK."
33 | );
34 | } else {
35 | client
36 | .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"])
37 | .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"])
38 | .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"])
39 | .setSelfSigned(true);
40 | }
41 |
42 | const data: Models.Membership = JSON.parse(
43 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
44 | );
45 |
46 | for (const membership of (await teams.listMemberships(data.teamId))
47 | .memberships) {
48 | if (membership.userName == data.userName && membership.confirm) return;
49 | }
50 |
51 | await databases.createDocument(data.userName, "invitations", data.teamId, {
52 | name: data.teamName,
53 | accept_url: `https://planetary.kyeboard.me/accept_invitation?teamId=${data.teamId}`,
54 | });
55 |
56 | res.json({
57 | success: true,
58 | message: "New invitation sent",
59 | });
60 | };
61 |
62 | export default new_invitation;
63 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "planetary",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "cross-env NODE_OPTIONS=--max_old_space_size=4096 refine dev",
7 | "build": "refine build",
8 | "start": "refine start",
9 | "lint": "eslint '**/*.{js,jsx,ts,tsx}'",
10 | "lint:fix": "eslint '**/*.{js,jsx,ts,tsx}' --fix",
11 | "lint:setup": "next lint",
12 | "refine": "refine"
13 | },
14 | "dependencies": {
15 | "@next/font": "^13.1.6",
16 | "@pankod/refine-appwrite": "^5.1.0",
17 | "@pankod/refine-chakra-ui": "^1.0.0",
18 | "@pankod/refine-cli": "^1.13.0",
19 | "@pankod/refine-core": "^3.90.4",
20 | "@pankod/refine-inferencer": "^2.0.2",
21 | "@pankod/refine-kbar": "^0.8.0",
22 | "@pankod/refine-nextjs-router": "^4.1.0",
23 | "@pankod/refine-react-hook-form": "^3.27.1",
24 | "@pankod/refine-react-table": "^4.7.2",
25 | "@tabler/icons": "^1.39.1",
26 | "appwrite": "^10.2.0",
27 | "feather-icons": "^4.29.0",
28 | "framer-motion": "^9.0.2",
29 | "googleapis": "^110.0.0",
30 | "lodash": "^4.17.21",
31 | "moment": "^2.29.4",
32 | "needle": "^3.2.0",
33 | "next": "^13.0.6",
34 | "next-compose-plugins": "^2.2.1",
35 | "next-i18next": "^8.9.0",
36 | "node-appwrite": "^8.2.0",
37 | "react": "^18.2.0",
38 | "react-dom": "^18.2.0",
39 | "react-feather": "^2.0.10",
40 | "sass": "^1.58.0",
41 | "validatorjs": "^3.22.1"
42 | },
43 | "devDependencies": {
44 | "@types/feather-icons": "^4.29.1",
45 | "@types/lodash": "^4.14.191",
46 | "@types/needle": "^3.2.0",
47 | "@types/node": "^14.14.13",
48 | "@types/react": "^18.0.15",
49 | "@types/react-dom": "^18.0.6",
50 | "@types/validatorjs": "^3.15.0",
51 | "@typescript-eslint/parser": "^4.9.1",
52 | "cross-env": "^7.0.3",
53 | "eslint": "8.33.0",
54 | "eslint-config-next": "13.1.6",
55 | "eslint-config-prettier": "^8.6.0",
56 | "eslint-plugin-prettier": "^4.2.1",
57 | "typescript": "^4.7.4"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/functions/new_invitation/README.md:
--------------------------------------------------------------------------------
1 | # new_invitation
2 |
3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file.
4 |
5 | ## 🤖 Documentation
6 |
7 | Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are.
8 |
9 |
10 |
11 | _Example input:_
12 |
13 | This function expects no input
14 |
15 |
16 |
17 | _Example output:_
18 |
19 |
20 |
21 | ```json
22 | {
23 | "areDevelopersAwesome": true
24 | }
25 | ```
26 |
27 | ## 📝 Environment Variables
28 |
29 | List of environment variables used by this cloud function:
30 |
31 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project
32 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key
33 |
34 |
35 | ## 🚀 Deployment
36 |
37 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience.
38 |
39 | ### Using CLI
40 |
41 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`.
42 |
43 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy.
44 |
45 | ### Manual using tar.gz
46 |
47 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated.
48 |
--------------------------------------------------------------------------------
/functions/setup_workspace/README.md:
--------------------------------------------------------------------------------
1 | # setup_workspace
2 |
3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file.
4 |
5 | ## 🤖 Documentation
6 |
7 | Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are.
8 |
9 |
10 |
11 | _Example input:_
12 |
13 | This function expects no input
14 |
15 |
16 |
17 | _Example output:_
18 |
19 |
20 |
21 | ```json
22 | {
23 | "areDevelopersAwesome": true
24 | }
25 | ```
26 |
27 | ## 📝 Environment Variables
28 |
29 | List of environment variables used by this cloud function:
30 |
31 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project
32 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key
33 |
34 |
35 | ## 🚀 Deployment
36 |
37 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience.
38 |
39 | ### Using CLI
40 |
41 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`.
42 |
43 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy.
44 |
45 | ### Manual using tar.gz
46 |
47 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated.
48 |
--------------------------------------------------------------------------------
/functions/add_user_to_team/README.md:
--------------------------------------------------------------------------------
1 | # add_user_to_team
2 |
3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file.
4 |
5 | ## 🤖 Documentation
6 |
7 | Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are.
8 |
9 |
10 |
11 | _Example input:_
12 |
13 | This function expects no input
14 |
15 |
16 |
17 | _Example output:_
18 |
19 |
20 |
21 | ```json
22 | {
23 | "areDevelopersAwesome": true
24 | }
25 | ```
26 |
27 | ## 📝 Environment Variables
28 |
29 | List of environment variables used by this cloud function:
30 |
31 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project
32 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key
33 |
34 |
35 | ## 🚀 Deployment
36 |
37 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience.
38 |
39 | ### Using CLI
40 |
41 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`.
42 |
43 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy.
44 |
45 | ### Manual using tar.gz
46 |
47 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated.
48 |
--------------------------------------------------------------------------------
/functions/push_notifications/README.md:
--------------------------------------------------------------------------------
1 | # push_notifications
2 |
3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file.
4 |
5 | ## 🤖 Documentation
6 |
7 | Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are.
8 |
9 |
10 |
11 | _Example input:_
12 |
13 | This function expects no input
14 |
15 |
16 |
17 | _Example output:_
18 |
19 |
20 |
21 | ```json
22 | {
23 | "areDevelopersAwesome": true
24 | }
25 | ```
26 |
27 | ## 📝 Environment Variables
28 |
29 | List of environment variables used by this cloud function:
30 |
31 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project
32 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key
33 |
34 |
35 | ## 🚀 Deployment
36 |
37 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience.
38 |
39 | ### Using CLI
40 |
41 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`.
42 |
43 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy.
44 |
45 | ### Manual using tar.gz
46 |
47 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated.
48 |
--------------------------------------------------------------------------------
/functions/setup_user_workspace/README.md:
--------------------------------------------------------------------------------
1 | # setup_user_workspace
2 |
3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file.
4 |
5 | ## 🤖 Documentation
6 |
7 | Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are.
8 |
9 |
10 |
11 | _Example input:_
12 |
13 | This function expects no input
14 |
15 |
16 |
17 | _Example output:_
18 |
19 |
20 |
21 | ```json
22 | {
23 | "areDevelopersAwesome": true
24 | }
25 | ```
26 |
27 | ## 📝 Environment Variables
28 |
29 | List of environment variables used by this cloud function:
30 |
31 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project
32 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key
33 |
34 |
35 | ## 🚀 Deployment
36 |
37 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience.
38 |
39 | ### Using CLI
40 |
41 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`.
42 |
43 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy.
44 |
45 | ### Manual using tar.gz
46 |
47 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated.
48 |
--------------------------------------------------------------------------------
/functions/upload_user_profile/README.md:
--------------------------------------------------------------------------------
1 | # upload_user_profile
2 |
3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file.
4 |
5 | ## 🤖 Documentation
6 |
7 | Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are.
8 |
9 |
10 |
11 | _Example input:_
12 |
13 | This function expects no input
14 |
15 |
16 |
17 | _Example output:_
18 |
19 |
20 |
21 | ```json
22 | {
23 | "areDevelopersAwesome": true
24 | }
25 | ```
26 |
27 | ## 📝 Environment Variables
28 |
29 | List of environment variables used by this cloud function:
30 |
31 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project
32 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key
33 |
34 |
35 | ## 🚀 Deployment
36 |
37 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience.
38 |
39 | ### Using CLI
40 |
41 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`.
42 |
43 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy.
44 |
45 | ### Manual using tar.gz
46 |
47 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated.
48 |
--------------------------------------------------------------------------------
/functions/change_username_to_email/README.md:
--------------------------------------------------------------------------------
1 | # change_username_to_email
2 |
3 | Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file.
4 |
5 | ## 🤖 Documentation
6 |
7 | Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are.
8 |
9 |
10 |
11 | _Example input:_
12 |
13 | This function expects no input
14 |
15 |
16 |
17 | _Example output:_
18 |
19 |
20 |
21 | ```json
22 | {
23 | "areDevelopersAwesome": true
24 | }
25 | ```
26 |
27 | ## 📝 Environment Variables
28 |
29 | List of environment variables used by this cloud function:
30 |
31 | - **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project
32 | - **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key
33 |
34 |
35 | ## 🚀 Deployment
36 |
37 | There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience.
38 |
39 | ### Using CLI
40 |
41 | Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`.
42 |
43 | Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy.
44 |
45 | ### Manual using tar.gz
46 |
47 | Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated.
48 |
--------------------------------------------------------------------------------
/src/components/FormItem.tsx:
--------------------------------------------------------------------------------
1 | import { Nunito } from "@next/font/google";
2 | import {
3 | FormControl,
4 | FormControlProps,
5 | FormErrorMessage,
6 | FormHelperText,
7 | FormLabel,
8 | Input,
9 | Textarea,
10 | } from "@pankod/refine-chakra-ui";
11 |
12 | const font = Nunito({ subsets: ["latin"], weight: "700" });
13 |
14 | interface FormItemProps extends FormControlProps {
15 | value: string | number;
16 | set_value: any;
17 | check: (data: any) => boolean;
18 | error_message: string;
19 | title: string;
20 | is_textarea?: boolean;
21 | placeholder: string;
22 | type: string;
23 | helper_message: string;
24 | }
25 |
26 | const FormItem: React.FC = ({
27 | value,
28 | title,
29 | placeholder,
30 | set_value,
31 | check,
32 | is_textarea,
33 | type,
34 | error_message,
35 | helper_message,
36 | ...props
37 | }) => {
38 | const validity = check(value);
39 |
40 | return (
41 |
42 | {title}
43 | {is_textarea ? (
44 |
72 | );
73 | };
74 |
75 | FormItem.defaultProps = {
76 | is_textarea: false,
77 | };
78 |
79 | export default FormItem;
80 |
--------------------------------------------------------------------------------
/src/components/InvitationError.tsx:
--------------------------------------------------------------------------------
1 | import { Button, Flex } from "@pankod/refine-chakra-ui";
2 | import { rise } from "animations";
3 | import { useRouter } from "next/router";
4 | import { ComponentType } from "react";
5 | import Bold from "./Bold";
6 |
7 | interface InvitationErrorProps {
8 | error: string;
9 | container: ComponentType;
10 | animatedelement: ComponentType;
11 | }
12 |
13 | const InvitationError: React.FC = ({
14 | error,
15 | container: Container,
16 | animatedelement: AnimatedElement,
17 | }) => {
18 | const router = useRouter();
19 |
20 | return (
21 |
37 |
48 | {error}
49 |
63 |
64 |
65 | );
66 | };
67 |
68 | export default InvitationError;
69 |
--------------------------------------------------------------------------------
/pages/notifications.tsx:
--------------------------------------------------------------------------------
1 | import ExtraBold from "@components/ExtraBold";
2 | import SideBar from "@components/SideBar";
3 | import { Box, Flex } from "@pankod/refine-chakra-ui";
4 | import { useState } from "react";
5 | import { Menu } from "react-feather";
6 | import { rise } from "animations";
7 | import NotificationList from "@components/NotificationList";
8 | import { AnimatePresence, motion } from "framer-motion";
9 | import Head from "next/head";
10 |
11 | const Notifications = () => {
12 | const AnimatedElement = motion(Flex);
13 | const Container = motion(Flex);
14 | const [expand, set_expand] = useState(false);
15 |
16 | return (
17 |
22 |
23 | Your notifications - planetary
24 |
25 | set_expand(false)}
29 | />
30 |
36 |
43 | set_expand(true)}
46 | >
47 |
48 |
49 |
50 | Notifications
51 |
52 |
53 |
54 |
58 |
59 |
60 |
61 | );
62 | };
63 |
64 | export default Notifications;
65 |
--------------------------------------------------------------------------------
/pages/accept_invite.tsx:
--------------------------------------------------------------------------------
1 | import Bold from "@components/Bold";
2 | import InvitationError from "@components/InvitationError";
3 | import SideBar from "@components/SideBar";
4 | import { Flex, Image, Spinner, Text } from "@pankod/refine-chakra-ui";
5 | import { AnimatePresence, motion } from "framer-motion";
6 | import { useRouter } from "next/router";
7 | import { useEffect, useState } from "react";
8 | import { teams } from "src/utility";
9 |
10 | const AcceptInvite = () => {
11 | const router = useRouter();
12 | const [error, set_error] = useState("");
13 |
14 | useEffect(() => {
15 | if (!router.isReady) return;
16 |
17 | const accept_invite = async () => {
18 | try {
19 | await teams.updateMembershipStatus(
20 | router.query.teamId as string,
21 | router.query.membershipId as string,
22 | router.query.userId as string,
23 | router.query.secret as string
24 | );
25 | } catch (err: any) {
26 | set_error(err.message);
27 | }
28 | };
29 |
30 | accept_invite();
31 | }, [router]);
32 |
33 | const Container = motion(Flex);
34 | const AnimatedElement = motion(Flex);
35 |
36 | return (
37 |
38 |
39 | {error && (
40 |
45 | )}
46 |
47 | {}} />
48 |
56 |
61 |
62 |
63 | Accepting the invitation...
64 |
65 |
66 |
67 | );
68 | };
69 |
70 | export default AcceptInvite;
71 |
--------------------------------------------------------------------------------
/functions/change_username_to_email/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Account, Client, Users } from "node-appwrite";
2 |
3 | interface Request {
4 | headers: {
5 | [key: string]: string;
6 | };
7 | payload: {
8 | [key: string]: string;
9 | };
10 | variables: {
11 | [key: string]: string;
12 | };
13 | }
14 |
15 | interface Response {
16 | send: (text: string, status?: number) => void;
17 | json: (obj: any, status?: number) => void;
18 | }
19 |
20 | interface EventData {
21 | userId: string;
22 | }
23 |
24 | const change_username_to_email = async function (req: Request, res: Response) {
25 | const client = new Client();
26 |
27 | // You can remove services you don't use
28 | const account = new Users(client);
29 |
30 | if (
31 | !req.variables["APPWRITE_FUNCTION_ENDPOINT"] ||
32 | !req.variables["APPWRITE_FUNCTION_API_KEY"]
33 | ) {
34 | console.warn(
35 | "Environment variables are not set. Function cannot use Appwrite SDK."
36 | );
37 | } else {
38 | client
39 | .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"])
40 | .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"])
41 | .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"])
42 | .setSelfSigned(true);
43 | }
44 |
45 | const data: EventData = JSON.parse(
46 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
47 | );
48 |
49 | const user = await account.get(data.userId);
50 |
51 | // Extract the first part of the email with regex (for example: if the email is 0xsapphir3@gmail.com, I want only 0xsapphir3)
52 | const username = (user.email.match(/^[^@]*/) as RegExpMatchArray)[0];
53 |
54 | // Get the user
55 | const current_username = user.name;
56 |
57 | // // Check if the current_username is correct by testing it against the regex which checks if it only contains alphanumeric, hyphen, non-leading underscore, period
58 | if (!current_username.match(/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/)) {
59 | // The name is invalid (contains special characters)
60 | await account.updateName(data.userId, username);
61 |
62 | res.json({
63 | success: true,
64 | message: "Username not valid, resetting to " + username,
65 | });
66 | } else {
67 | res.json({
68 | success: true,
69 | message: "Skipping as the username is already valid",
70 | });
71 | }
72 | };
73 |
74 | export default change_username_to_email;
75 |
--------------------------------------------------------------------------------
/pages/accept_invitation.tsx:
--------------------------------------------------------------------------------
1 | import InvitationError from "@components/InvitationError";
2 | import SideBar from "@components/SideBar";
3 | import { Flex, Image, Spinner, Text } from "@pankod/refine-chakra-ui";
4 | import { AnimatePresence, motion } from "framer-motion";
5 | import { useRouter } from "next/router";
6 | import { useEffect, useState } from "react";
7 | import { account, database } from "src/utility";
8 |
9 | const AcceptInvitation = () => {
10 | const router = useRouter();
11 | const [error, set_error] = useState("");
12 |
13 | useEffect(() => {
14 | if (!router.isReady) return;
15 |
16 | const accept_invite = async () => {
17 | const current_user = await account.get();
18 |
19 | // Check if it exists
20 | try {
21 | await database.updateDocument(
22 | current_user.name,
23 | "invitations",
24 | router.query.teamId as string,
25 | {
26 | status: true,
27 | }
28 | );
29 |
30 | await new Promise(r => setTimeout(r, 1000));
31 |
32 | router.push("/dashboard");
33 | } catch (err) {
34 | set_error("Invalid invitation!");
35 | }
36 | };
37 |
38 | accept_invite();
39 | }, [router]);
40 |
41 | const AnimatedElement = motion(Flex);
42 | const AnimatedContainer = motion(Flex);
43 |
44 | return (
45 |
46 | {}} />
47 |
48 | {error && (
49 |
54 | )}
55 |
56 |
64 |
69 |
70 |
71 | Accepting the invite...
72 |
73 |
74 |
75 | );
76 | };
77 |
78 | export default AcceptInvitation;
79 |
--------------------------------------------------------------------------------
/functions/new_invitation/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | node-appwrite: ^8.0.0
5 |
6 | dependencies:
7 | node-appwrite: 8.2.0
8 |
9 | packages:
10 |
11 | /asynckit/0.4.0:
12 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
13 | dev: false
14 |
15 | /axios/1.3.3:
16 | resolution: {integrity: sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==}
17 | dependencies:
18 | follow-redirects: 1.15.2
19 | form-data: 4.0.0
20 | proxy-from-env: 1.1.0
21 | transitivePeerDependencies:
22 | - debug
23 | dev: false
24 |
25 | /combined-stream/1.0.8:
26 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
27 | engines: {node: '>= 0.8'}
28 | dependencies:
29 | delayed-stream: 1.0.0
30 | dev: false
31 |
32 | /delayed-stream/1.0.0:
33 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
34 | engines: {node: '>=0.4.0'}
35 | dev: false
36 |
37 | /follow-redirects/1.15.2:
38 | resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
39 | engines: {node: '>=4.0'}
40 | peerDependencies:
41 | debug: '*'
42 | peerDependenciesMeta:
43 | debug:
44 | optional: true
45 | dev: false
46 |
47 | /form-data/4.0.0:
48 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
49 | engines: {node: '>= 6'}
50 | dependencies:
51 | asynckit: 0.4.0
52 | combined-stream: 1.0.8
53 | mime-types: 2.1.35
54 | dev: false
55 |
56 | /mime-db/1.52.0:
57 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
58 | engines: {node: '>= 0.6'}
59 | dev: false
60 |
61 | /mime-types/2.1.35:
62 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
63 | engines: {node: '>= 0.6'}
64 | dependencies:
65 | mime-db: 1.52.0
66 | dev: false
67 |
68 | /node-appwrite/8.2.0:
69 | resolution: {integrity: sha512-SFSTxHewwtbjkiF93OJEqOZC1x3mnvz1G/rKg9BNz4CG5PI9xP/pKqsKHYDdwUOfOB2Su90jI7fKglIPFd+o8A==}
70 | dependencies:
71 | axios: 1.3.3
72 | form-data: 4.0.0
73 | transitivePeerDependencies:
74 | - debug
75 | dev: false
76 |
77 | /proxy-from-env/1.1.0:
78 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
79 | dev: false
80 |
--------------------------------------------------------------------------------
/functions/setup_workspace/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | node-appwrite: ^8.0.0
5 |
6 | dependencies:
7 | node-appwrite: 8.2.0
8 |
9 | packages:
10 |
11 | /asynckit/0.4.0:
12 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
13 | dev: false
14 |
15 | /axios/1.3.2:
16 | resolution: {integrity: sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==}
17 | dependencies:
18 | follow-redirects: 1.15.2
19 | form-data: 4.0.0
20 | proxy-from-env: 1.1.0
21 | transitivePeerDependencies:
22 | - debug
23 | dev: false
24 |
25 | /combined-stream/1.0.8:
26 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
27 | engines: {node: '>= 0.8'}
28 | dependencies:
29 | delayed-stream: 1.0.0
30 | dev: false
31 |
32 | /delayed-stream/1.0.0:
33 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
34 | engines: {node: '>=0.4.0'}
35 | dev: false
36 |
37 | /follow-redirects/1.15.2:
38 | resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
39 | engines: {node: '>=4.0'}
40 | peerDependencies:
41 | debug: '*'
42 | peerDependenciesMeta:
43 | debug:
44 | optional: true
45 | dev: false
46 |
47 | /form-data/4.0.0:
48 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
49 | engines: {node: '>= 6'}
50 | dependencies:
51 | asynckit: 0.4.0
52 | combined-stream: 1.0.8
53 | mime-types: 2.1.35
54 | dev: false
55 |
56 | /mime-db/1.52.0:
57 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
58 | engines: {node: '>= 0.6'}
59 | dev: false
60 |
61 | /mime-types/2.1.35:
62 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
63 | engines: {node: '>= 0.6'}
64 | dependencies:
65 | mime-db: 1.52.0
66 | dev: false
67 |
68 | /node-appwrite/8.2.0:
69 | resolution: {integrity: sha512-SFSTxHewwtbjkiF93OJEqOZC1x3mnvz1G/rKg9BNz4CG5PI9xP/pKqsKHYDdwUOfOB2Su90jI7fKglIPFd+o8A==}
70 | dependencies:
71 | axios: 1.3.2
72 | form-data: 4.0.0
73 | transitivePeerDependencies:
74 | - debug
75 | dev: false
76 |
77 | /proxy-from-env/1.1.0:
78 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
79 | dev: false
80 |
--------------------------------------------------------------------------------
/functions/add_user_to_team/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | node-appwrite: ^8.0.0
5 |
6 | dependencies:
7 | node-appwrite: 8.2.0
8 |
9 | packages:
10 |
11 | /asynckit/0.4.0:
12 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
13 | dev: false
14 |
15 | /axios/1.3.3:
16 | resolution: {integrity: sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==}
17 | dependencies:
18 | follow-redirects: 1.15.2
19 | form-data: 4.0.0
20 | proxy-from-env: 1.1.0
21 | transitivePeerDependencies:
22 | - debug
23 | dev: false
24 |
25 | /combined-stream/1.0.8:
26 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
27 | engines: {node: '>= 0.8'}
28 | dependencies:
29 | delayed-stream: 1.0.0
30 | dev: false
31 |
32 | /delayed-stream/1.0.0:
33 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
34 | engines: {node: '>=0.4.0'}
35 | dev: false
36 |
37 | /follow-redirects/1.15.2:
38 | resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
39 | engines: {node: '>=4.0'}
40 | peerDependencies:
41 | debug: '*'
42 | peerDependenciesMeta:
43 | debug:
44 | optional: true
45 | dev: false
46 |
47 | /form-data/4.0.0:
48 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
49 | engines: {node: '>= 6'}
50 | dependencies:
51 | asynckit: 0.4.0
52 | combined-stream: 1.0.8
53 | mime-types: 2.1.35
54 | dev: false
55 |
56 | /mime-db/1.52.0:
57 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
58 | engines: {node: '>= 0.6'}
59 | dev: false
60 |
61 | /mime-types/2.1.35:
62 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
63 | engines: {node: '>= 0.6'}
64 | dependencies:
65 | mime-db: 1.52.0
66 | dev: false
67 |
68 | /node-appwrite/8.2.0:
69 | resolution: {integrity: sha512-SFSTxHewwtbjkiF93OJEqOZC1x3mnvz1G/rKg9BNz4CG5PI9xP/pKqsKHYDdwUOfOB2Su90jI7fKglIPFd+o8A==}
70 | dependencies:
71 | axios: 1.3.3
72 | form-data: 4.0.0
73 | transitivePeerDependencies:
74 | - debug
75 | dev: false
76 |
77 | /proxy-from-env/1.1.0:
78 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
79 | dev: false
80 |
--------------------------------------------------------------------------------
/functions/setup_user_workspace/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | node-appwrite: ^8.0.0
5 |
6 | dependencies:
7 | node-appwrite: 8.2.0
8 |
9 | packages:
10 |
11 | /asynckit/0.4.0:
12 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
13 | dev: false
14 |
15 | /axios/1.3.3:
16 | resolution: {integrity: sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==}
17 | dependencies:
18 | follow-redirects: 1.15.2
19 | form-data: 4.0.0
20 | proxy-from-env: 1.1.0
21 | transitivePeerDependencies:
22 | - debug
23 | dev: false
24 |
25 | /combined-stream/1.0.8:
26 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
27 | engines: {node: '>= 0.8'}
28 | dependencies:
29 | delayed-stream: 1.0.0
30 | dev: false
31 |
32 | /delayed-stream/1.0.0:
33 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
34 | engines: {node: '>=0.4.0'}
35 | dev: false
36 |
37 | /follow-redirects/1.15.2:
38 | resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
39 | engines: {node: '>=4.0'}
40 | peerDependencies:
41 | debug: '*'
42 | peerDependenciesMeta:
43 | debug:
44 | optional: true
45 | dev: false
46 |
47 | /form-data/4.0.0:
48 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
49 | engines: {node: '>= 6'}
50 | dependencies:
51 | asynckit: 0.4.0
52 | combined-stream: 1.0.8
53 | mime-types: 2.1.35
54 | dev: false
55 |
56 | /mime-db/1.52.0:
57 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
58 | engines: {node: '>= 0.6'}
59 | dev: false
60 |
61 | /mime-types/2.1.35:
62 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
63 | engines: {node: '>= 0.6'}
64 | dependencies:
65 | mime-db: 1.52.0
66 | dev: false
67 |
68 | /node-appwrite/8.2.0:
69 | resolution: {integrity: sha512-SFSTxHewwtbjkiF93OJEqOZC1x3mnvz1G/rKg9BNz4CG5PI9xP/pKqsKHYDdwUOfOB2Su90jI7fKglIPFd+o8A==}
70 | dependencies:
71 | axios: 1.3.3
72 | form-data: 4.0.0
73 | transitivePeerDependencies:
74 | - debug
75 | dev: false
76 |
77 | /proxy-from-env/1.1.0:
78 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
79 | dev: false
80 |
--------------------------------------------------------------------------------
/functions/change_username_to_email/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | node-appwrite: ^8.0.0
5 |
6 | dependencies:
7 | node-appwrite: 8.2.0
8 |
9 | packages:
10 |
11 | /asynckit/0.4.0:
12 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
13 | dev: false
14 |
15 | /axios/1.3.2:
16 | resolution: {integrity: sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==}
17 | dependencies:
18 | follow-redirects: 1.15.2
19 | form-data: 4.0.0
20 | proxy-from-env: 1.1.0
21 | transitivePeerDependencies:
22 | - debug
23 | dev: false
24 |
25 | /combined-stream/1.0.8:
26 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
27 | engines: {node: '>= 0.8'}
28 | dependencies:
29 | delayed-stream: 1.0.0
30 | dev: false
31 |
32 | /delayed-stream/1.0.0:
33 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
34 | engines: {node: '>=0.4.0'}
35 | dev: false
36 |
37 | /follow-redirects/1.15.2:
38 | resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
39 | engines: {node: '>=4.0'}
40 | peerDependencies:
41 | debug: '*'
42 | peerDependenciesMeta:
43 | debug:
44 | optional: true
45 | dev: false
46 |
47 | /form-data/4.0.0:
48 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
49 | engines: {node: '>= 6'}
50 | dependencies:
51 | asynckit: 0.4.0
52 | combined-stream: 1.0.8
53 | mime-types: 2.1.35
54 | dev: false
55 |
56 | /mime-db/1.52.0:
57 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
58 | engines: {node: '>= 0.6'}
59 | dev: false
60 |
61 | /mime-types/2.1.35:
62 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
63 | engines: {node: '>= 0.6'}
64 | dependencies:
65 | mime-db: 1.52.0
66 | dev: false
67 |
68 | /node-appwrite/8.2.0:
69 | resolution: {integrity: sha512-SFSTxHewwtbjkiF93OJEqOZC1x3mnvz1G/rKg9BNz4CG5PI9xP/pKqsKHYDdwUOfOB2Su90jI7fKglIPFd+o8A==}
70 | dependencies:
71 | axios: 1.3.2
72 | form-data: 4.0.0
73 | transitivePeerDependencies:
74 | - debug
75 | dev: false
76 |
77 | /proxy-from-env/1.1.0:
78 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
79 | dev: false
80 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # [Planetary](https://planetary.kyeboard.me)
4 |
5 | Get ready to slay your to-do list like a dragon-slaying knight with this app. It's like a personal assistant without the coffee addiction and annoying small talk. Say 'goodbye' to procrastination and 'hello' to getting sh*t done. Don't be a potato on the couch, be a productive potato with this app.
6 |
7 | ## Participants
8 | I worked solo on this project and killed it, but I'm pretty sure I also killed a few brain cells in the process.
9 |
10 | - GitHub: https://www.github.com/kyeboard
11 | - Twitter: [https://www.twitter.com/kyeboard_](https://www.twitter.com/kyeboard_)
12 |
13 | ## Prerequisites
14 | In order to setup and run this project locally, you must have:
15 |
16 | - [Docker](https://www.docker.com/)
17 | - [Appwrite](https://www.appwrite.io/)
18 | - Brain (IYKYK)
19 |
20 | ## Setup Appwrite
21 | Before starting the development server, you must have your Appwrite project setup.
22 |
23 | - Create a new Appwrite project with any name but with the id of planetary.
24 | - In the Auth tab, go to Settings and setup Google OAuth provider with your google client credentials.
25 | - In the Databases section, create a new database with the id of `teams`.
26 | - In that database, create a database with the id of `teams` as well.
27 | - Next, you need to setup your collection with attributes
28 | - Create a new string attribute with the name of `title`, `string` type and `required`.
29 | - Create a new string attribute with the name of `description`, `string` type and `required`.
30 | - Create a new string attribute with the name of `color`, `string` type and `required`.
31 | - Create a new boolean attribute with the name of `completed`, `integer` type and `not required`.
32 | - Create six functions (all with NodeJs environment ) and deploy all the folder in the `functions/` folder to each of the functions. It doesnt really matter if the id is same or different, but if you want to ease your deployment, then you can use the id from the `appwrite.json` and run `appwrite deploy functions` to quickly deploy all your functions (Make sure to build them before deploying, it is written in typescript).
33 |
34 | Boom! You are done, all the best with the next steps ;)
35 |
36 | ## Install project
37 | To run this awesome website locally, first:
38 |
39 | - Clone the github repo
40 | ```
41 | git clone https://www.github.com/kyeboard/planetary.git
42 | ```
43 |
44 | - Change the directory to the folder
45 | ```
46 | cd planetary
47 | ```
48 |
49 | - Install required dependencies
50 | ```
51 | pnpm install
52 | ```
53 |
54 | - Start the website
55 | ```
56 | pnpm start
57 | ```
58 |
59 |
60 |
61 | Built with ♥, [RefineJS](https://refine.dev/) and [Appwrite](https://www.appwrite.io)
62 |
--------------------------------------------------------------------------------
/functions/add_user_to_team/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Account, Client, Databases, Teams, Users } from "node-appwrite";
2 |
3 | interface Request {
4 | headers: {
5 | [key: string]: string;
6 | };
7 | payload: {
8 | [key: string]: string;
9 | };
10 | variables: {
11 | [key: string]: string;
12 | };
13 | }
14 |
15 | interface Response {
16 | send: (text: string, status?: number) => void;
17 | json: (obj: any, status?: number) => void;
18 | }
19 |
20 | interface EventData {
21 | $id: string;
22 | $collectionId: string;
23 | $databaseId: string;
24 | }
25 |
26 | const add_user_to_team = async function (req: Request, res: Response) {
27 | const client = new Client();
28 |
29 | // You can remove services you don't use
30 | const account = new Users(client);
31 | const teams = new Teams(client);
32 | const databases = new Databases(client);
33 |
34 | if (
35 | !req.variables["APPWRITE_FUNCTION_ENDPOINT"] ||
36 | !req.variables["APPWRITE_FUNCTION_API_KEY"]
37 | ) {
38 | console.warn(
39 | "Environment variables are not set. Function cannot use Appwrite SDK."
40 | );
41 | } else {
42 | client
43 | .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"])
44 | .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"])
45 | .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"])
46 | .setSelfSigned(true);
47 | }
48 |
49 | const data: EventData = JSON.parse(
50 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
51 | );
52 |
53 | try {
54 | let invited_user;
55 | const invitation: any = await databases.getDocument(
56 | data.$databaseId,
57 | "invitations",
58 | data.$id
59 | );
60 |
61 | for (const membership of (await teams.listMemberships(data.$id))
62 | .memberships) {
63 | if (membership.userName == data.$databaseId) {
64 | invited_user = membership;
65 |
66 | // Remove user
67 | teams.deleteMembership(data.$id, membership.$id);
68 | }
69 | }
70 |
71 | if (typeof invited_user == "undefined") {
72 | return;
73 | }
74 |
75 | if (invitation.status == true) {
76 | await teams.createMembership(
77 | data.$id,
78 | invited_user.userEmail,
79 | [],
80 | "https://planetary.kyeboard.me/dashboard"
81 | );
82 |
83 | await databases.deleteDocument(
84 | data.$databaseId,
85 | data.$collectionId,
86 | data.$id
87 | );
88 | }
89 |
90 | res.json({ success: true, message: "Done" });
91 | } catch (err) {
92 | res.json(err);
93 | }
94 | };
95 |
96 | export default add_user_to_team;
97 |
--------------------------------------------------------------------------------
/src/components/layout/header/index.tsx:
--------------------------------------------------------------------------------
1 | import { useRouter } from "next/router";
2 | import { useGetIdentity, useGetLocale } from "@pankod/refine-core";
3 | import NextRouter from "@pankod/refine-nextjs-router";
4 | import {
5 | Box,
6 | IconButton,
7 | HStack,
8 | Text,
9 | Avatar,
10 | Icon,
11 | Menu,
12 | MenuButton,
13 | MenuItem,
14 | MenuList,
15 | useColorMode,
16 | } from "@pankod/refine-chakra-ui";
17 | import { IconMoon, IconSun, IconLanguage } from "@tabler/icons";
18 |
19 | export const Header: React.FC = () => {
20 | const { data: user } = useGetIdentity();
21 | const showUserInfo = user && (user.name || user.avatar);
22 |
23 | const { colorMode, toggleColorMode } = useColorMode();
24 |
25 | const locale = useGetLocale();
26 | const currentLocale = locale();
27 |
28 | const { locales } = useRouter();
29 |
30 | return (
31 |
40 | {showUserInfo && (
41 |
42 |
43 | {user?.name}
44 |
45 |
46 |
47 | )}
48 |
76 |
81 |
86 |
87 |
88 | );
89 | };
90 |
--------------------------------------------------------------------------------
/src/components/ProjectsCard.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Flex, Text } from "@pankod/refine-chakra-ui";
2 | import { useOne } from "@pankod/refine-core";
3 | import { rise } from "animations";
4 | import { useRouter } from "next/router";
5 | import { ComponentType, Suspense } from "react";
6 | import Project from "types/Project";
7 | import ExtraBold from "./ExtraBold";
8 |
9 | interface ProjectCardProps {
10 | id: string;
11 | name: string;
12 | animatedelement: ComponentType;
13 | }
14 |
15 | const ProjectCard: React.FC = ({
16 | id,
17 | name,
18 | animatedelement: AnimatedElement,
19 | }) => {
20 | const { data, isLoading } = useOne({
21 | resource: "teams",
22 | id,
23 | dataProviderName: "teams",
24 | });
25 | const router = useRouter();
26 |
27 | if (!isLoading) {
28 | return (
29 |
30 | router.push(`/project/${id}`)}
34 | borderRadius="3xl"
35 | bg={data?.data.color}
36 | maxWidth="450px"
37 | width="full"
38 | opacity={0}
39 | height="full"
40 | initial={{
41 | opacity: 0,
42 | transform: "translateY(30px)",
43 | }}
44 | animate={{
45 | opacity: 1,
46 | transform: "translateY(0px)",
47 | }}
48 | exit={{ opacity: 0, transform: "translateY(30px)" }}
49 | transition={{ duration: "0.3" }}
50 | >
51 | {name}
52 |
53 | {data?.data.description}
54 |
55 |
56 | {data?.data.completed + "%"}
57 |
58 |
59 |
65 |
73 |
74 |
75 |
76 | );
77 | }
78 |
79 | return <>>;
80 | };
81 |
82 | export default ProjectCard;
83 |
--------------------------------------------------------------------------------
/src/components/InviteMember.tsx:
--------------------------------------------------------------------------------
1 | import { Nunito } from "@next/font/google";
2 | import { Box, Button, Flex, Input, Text } from "@pankod/refine-chakra-ui";
3 | import { useState } from "react";
4 | import { Check, Mail, Plus } from "react-feather";
5 |
6 | const font = Nunito({ subsets: ["latin"], weight: "700" });
7 |
8 | const InviteMember = () => {
9 | const [members, set_members] = useState>([
10 | "me.kyeboard@gmail.com",
11 | ]);
12 | const [new_member, set_new_member] = useState("");
13 | const [sending, toggle_sending] = useState(false);
14 |
15 | const add_member = () => {
16 | members.push(new_member);
17 |
18 | set_new_member("");
19 | };
20 |
21 | return (
22 |
33 |
41 |
46 | Invite member
47 |
48 |
49 | set_new_member(e.target.value)}
55 | />
56 |
65 |
66 |
67 | {members.map((e) => {
68 | return (
69 |
77 |
78 | {e}
79 |
80 | );
81 | })}
82 |
83 |
84 |
85 | );
86 | };
87 |
88 | export default InviteMember;
89 |
--------------------------------------------------------------------------------
/functions/new_invitation/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/node
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node
4 |
5 | ### Node ###
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 | .pnpm-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # Snowpack dependency directory (https://snowpack.dev/)
51 | web_modules/
52 |
53 | # TypeScript cache
54 | *.tsbuildinfo
55 |
56 | # Optional npm cache directory
57 | .npm
58 |
59 | # Optional eslint cache
60 | .eslintcache
61 |
62 | # Optional stylelint cache
63 | .stylelintcache
64 |
65 | # Microbundle cache
66 | .rpt2_cache/
67 | .rts2_cache_cjs/
68 | .rts2_cache_es/
69 | .rts2_cache_umd/
70 |
71 | # Optional REPL history
72 | .node_repl_history
73 |
74 | # Output of 'npm pack'
75 | *.tgz
76 |
77 | # Yarn Integrity file
78 | .yarn-integrity
79 |
80 | # dotenv environment variable files
81 | .env
82 | .env.development.local
83 | .env.test.local
84 | .env.production.local
85 | .env.local
86 |
87 | # parcel-bundler cache (https://parceljs.org/)
88 | .cache
89 | .parcel-cache
90 |
91 | # Next.js build output
92 | .next
93 | out
94 |
95 | # Nuxt.js build / generate output
96 | .nuxt
97 | dist
98 |
99 | # Gatsby files
100 | .cache/
101 | # Comment in the public line in if your project uses Gatsby and not Next.js
102 | # https://nextjs.org/blog/next-9-1#public-directory-support
103 | # public
104 |
105 | # vuepress build output
106 | .vuepress/dist
107 |
108 | # vuepress v2.x temp and cache directory
109 | .temp
110 |
111 | # Docusaurus cache and generated files
112 | .docusaurus
113 |
114 | # Serverless directories
115 | .serverless/
116 |
117 | # FuseBox cache
118 | .fusebox/
119 |
120 | # DynamoDB Local files
121 | .dynamodb/
122 |
123 | # TernJS port file
124 | .tern-port
125 |
126 | # Stores VSCode versions used for testing VSCode extensions
127 | .vscode-test
128 |
129 | # yarn v2
130 | .yarn/cache
131 | .yarn/unplugged
132 | .yarn/build-state.yml
133 | .yarn/install-state.gz
134 | .pnp.*
135 |
136 | ### Node Patch ###
137 | # Serverless Webpack directories
138 | .webpack/
139 |
140 | # Optional stylelint cache
141 |
142 | # SvelteKit build / generate output
143 | .svelte-kit
144 |
145 | # End of https://www.toptal.com/developers/gitignore/api/node
146 |
147 | # OS
148 | ## Mac
149 | .DS_Store
150 |
--------------------------------------------------------------------------------
/functions/setup_workspace/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/node
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node
4 |
5 | ### Node ###
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 | .pnpm-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # Snowpack dependency directory (https://snowpack.dev/)
51 | web_modules/
52 |
53 | # TypeScript cache
54 | *.tsbuildinfo
55 |
56 | # Optional npm cache directory
57 | .npm
58 |
59 | # Optional eslint cache
60 | .eslintcache
61 |
62 | # Optional stylelint cache
63 | .stylelintcache
64 |
65 | # Microbundle cache
66 | .rpt2_cache/
67 | .rts2_cache_cjs/
68 | .rts2_cache_es/
69 | .rts2_cache_umd/
70 |
71 | # Optional REPL history
72 | .node_repl_history
73 |
74 | # Output of 'npm pack'
75 | *.tgz
76 |
77 | # Yarn Integrity file
78 | .yarn-integrity
79 |
80 | # dotenv environment variable files
81 | .env
82 | .env.development.local
83 | .env.test.local
84 | .env.production.local
85 | .env.local
86 |
87 | # parcel-bundler cache (https://parceljs.org/)
88 | .cache
89 | .parcel-cache
90 |
91 | # Next.js build output
92 | .next
93 | out
94 |
95 | # Nuxt.js build / generate output
96 | .nuxt
97 | dist
98 |
99 | # Gatsby files
100 | .cache/
101 | # Comment in the public line in if your project uses Gatsby and not Next.js
102 | # https://nextjs.org/blog/next-9-1#public-directory-support
103 | # public
104 |
105 | # vuepress build output
106 | .vuepress/dist
107 |
108 | # vuepress v2.x temp and cache directory
109 | .temp
110 |
111 | # Docusaurus cache and generated files
112 | .docusaurus
113 |
114 | # Serverless directories
115 | .serverless/
116 |
117 | # FuseBox cache
118 | .fusebox/
119 |
120 | # DynamoDB Local files
121 | .dynamodb/
122 |
123 | # TernJS port file
124 | .tern-port
125 |
126 | # Stores VSCode versions used for testing VSCode extensions
127 | .vscode-test
128 |
129 | # yarn v2
130 | .yarn/cache
131 | .yarn/unplugged
132 | .yarn/build-state.yml
133 | .yarn/install-state.gz
134 | .pnp.*
135 |
136 | ### Node Patch ###
137 | # Serverless Webpack directories
138 | .webpack/
139 |
140 | # Optional stylelint cache
141 |
142 | # SvelteKit build / generate output
143 | .svelte-kit
144 |
145 | # End of https://www.toptal.com/developers/gitignore/api/node
146 |
147 | # OS
148 | ## Mac
149 | .DS_Store
150 |
--------------------------------------------------------------------------------
/functions/add_user_to_team/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/node
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node
4 |
5 | ### Node ###
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 | .pnpm-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # Snowpack dependency directory (https://snowpack.dev/)
51 | web_modules/
52 |
53 | # TypeScript cache
54 | *.tsbuildinfo
55 |
56 | # Optional npm cache directory
57 | .npm
58 |
59 | # Optional eslint cache
60 | .eslintcache
61 |
62 | # Optional stylelint cache
63 | .stylelintcache
64 |
65 | # Microbundle cache
66 | .rpt2_cache/
67 | .rts2_cache_cjs/
68 | .rts2_cache_es/
69 | .rts2_cache_umd/
70 |
71 | # Optional REPL history
72 | .node_repl_history
73 |
74 | # Output of 'npm pack'
75 | *.tgz
76 |
77 | # Yarn Integrity file
78 | .yarn-integrity
79 |
80 | # dotenv environment variable files
81 | .env
82 | .env.development.local
83 | .env.test.local
84 | .env.production.local
85 | .env.local
86 |
87 | # parcel-bundler cache (https://parceljs.org/)
88 | .cache
89 | .parcel-cache
90 |
91 | # Next.js build output
92 | .next
93 | out
94 |
95 | # Nuxt.js build / generate output
96 | .nuxt
97 | dist
98 |
99 | # Gatsby files
100 | .cache/
101 | # Comment in the public line in if your project uses Gatsby and not Next.js
102 | # https://nextjs.org/blog/next-9-1#public-directory-support
103 | # public
104 |
105 | # vuepress build output
106 | .vuepress/dist
107 |
108 | # vuepress v2.x temp and cache directory
109 | .temp
110 |
111 | # Docusaurus cache and generated files
112 | .docusaurus
113 |
114 | # Serverless directories
115 | .serverless/
116 |
117 | # FuseBox cache
118 | .fusebox/
119 |
120 | # DynamoDB Local files
121 | .dynamodb/
122 |
123 | # TernJS port file
124 | .tern-port
125 |
126 | # Stores VSCode versions used for testing VSCode extensions
127 | .vscode-test
128 |
129 | # yarn v2
130 | .yarn/cache
131 | .yarn/unplugged
132 | .yarn/build-state.yml
133 | .yarn/install-state.gz
134 | .pnp.*
135 |
136 | ### Node Patch ###
137 | # Serverless Webpack directories
138 | .webpack/
139 |
140 | # Optional stylelint cache
141 |
142 | # SvelteKit build / generate output
143 | .svelte-kit
144 |
145 | # End of https://www.toptal.com/developers/gitignore/api/node
146 |
147 | # OS
148 | ## Mac
149 | .DS_Store
150 |
--------------------------------------------------------------------------------
/functions/push_notifications/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/node
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node
4 |
5 | ### Node ###
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 | .pnpm-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # Snowpack dependency directory (https://snowpack.dev/)
51 | web_modules/
52 |
53 | # TypeScript cache
54 | *.tsbuildinfo
55 |
56 | # Optional npm cache directory
57 | .npm
58 |
59 | # Optional eslint cache
60 | .eslintcache
61 |
62 | # Optional stylelint cache
63 | .stylelintcache
64 |
65 | # Microbundle cache
66 | .rpt2_cache/
67 | .rts2_cache_cjs/
68 | .rts2_cache_es/
69 | .rts2_cache_umd/
70 |
71 | # Optional REPL history
72 | .node_repl_history
73 |
74 | # Output of 'npm pack'
75 | *.tgz
76 |
77 | # Yarn Integrity file
78 | .yarn-integrity
79 |
80 | # dotenv environment variable files
81 | .env
82 | .env.development.local
83 | .env.test.local
84 | .env.production.local
85 | .env.local
86 |
87 | # parcel-bundler cache (https://parceljs.org/)
88 | .cache
89 | .parcel-cache
90 |
91 | # Next.js build output
92 | .next
93 | out
94 |
95 | # Nuxt.js build / generate output
96 | .nuxt
97 | dist
98 |
99 | # Gatsby files
100 | .cache/
101 | # Comment in the public line in if your project uses Gatsby and not Next.js
102 | # https://nextjs.org/blog/next-9-1#public-directory-support
103 | # public
104 |
105 | # vuepress build output
106 | .vuepress/dist
107 |
108 | # vuepress v2.x temp and cache directory
109 | .temp
110 |
111 | # Docusaurus cache and generated files
112 | .docusaurus
113 |
114 | # Serverless directories
115 | .serverless/
116 |
117 | # FuseBox cache
118 | .fusebox/
119 |
120 | # DynamoDB Local files
121 | .dynamodb/
122 |
123 | # TernJS port file
124 | .tern-port
125 |
126 | # Stores VSCode versions used for testing VSCode extensions
127 | .vscode-test
128 |
129 | # yarn v2
130 | .yarn/cache
131 | .yarn/unplugged
132 | .yarn/build-state.yml
133 | .yarn/install-state.gz
134 | .pnp.*
135 |
136 | ### Node Patch ###
137 | # Serverless Webpack directories
138 | .webpack/
139 |
140 | # Optional stylelint cache
141 |
142 | # SvelteKit build / generate output
143 | .svelte-kit
144 |
145 | # End of https://www.toptal.com/developers/gitignore/api/node
146 |
147 | # OS
148 | ## Mac
149 | .DS_Store
150 |
--------------------------------------------------------------------------------
/functions/setup_user_workspace/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/node
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node
4 |
5 | ### Node ###
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 | .pnpm-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # Snowpack dependency directory (https://snowpack.dev/)
51 | web_modules/
52 |
53 | # TypeScript cache
54 | *.tsbuildinfo
55 |
56 | # Optional npm cache directory
57 | .npm
58 |
59 | # Optional eslint cache
60 | .eslintcache
61 |
62 | # Optional stylelint cache
63 | .stylelintcache
64 |
65 | # Microbundle cache
66 | .rpt2_cache/
67 | .rts2_cache_cjs/
68 | .rts2_cache_es/
69 | .rts2_cache_umd/
70 |
71 | # Optional REPL history
72 | .node_repl_history
73 |
74 | # Output of 'npm pack'
75 | *.tgz
76 |
77 | # Yarn Integrity file
78 | .yarn-integrity
79 |
80 | # dotenv environment variable files
81 | .env
82 | .env.development.local
83 | .env.test.local
84 | .env.production.local
85 | .env.local
86 |
87 | # parcel-bundler cache (https://parceljs.org/)
88 | .cache
89 | .parcel-cache
90 |
91 | # Next.js build output
92 | .next
93 | out
94 |
95 | # Nuxt.js build / generate output
96 | .nuxt
97 | dist
98 |
99 | # Gatsby files
100 | .cache/
101 | # Comment in the public line in if your project uses Gatsby and not Next.js
102 | # https://nextjs.org/blog/next-9-1#public-directory-support
103 | # public
104 |
105 | # vuepress build output
106 | .vuepress/dist
107 |
108 | # vuepress v2.x temp and cache directory
109 | .temp
110 |
111 | # Docusaurus cache and generated files
112 | .docusaurus
113 |
114 | # Serverless directories
115 | .serverless/
116 |
117 | # FuseBox cache
118 | .fusebox/
119 |
120 | # DynamoDB Local files
121 | .dynamodb/
122 |
123 | # TernJS port file
124 | .tern-port
125 |
126 | # Stores VSCode versions used for testing VSCode extensions
127 | .vscode-test
128 |
129 | # yarn v2
130 | .yarn/cache
131 | .yarn/unplugged
132 | .yarn/build-state.yml
133 | .yarn/install-state.gz
134 | .pnp.*
135 |
136 | ### Node Patch ###
137 | # Serverless Webpack directories
138 | .webpack/
139 |
140 | # Optional stylelint cache
141 |
142 | # SvelteKit build / generate output
143 | .svelte-kit
144 |
145 | # End of https://www.toptal.com/developers/gitignore/api/node
146 |
147 | # OS
148 | ## Mac
149 | .DS_Store
150 |
--------------------------------------------------------------------------------
/functions/upload_user_profile/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/node
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node
4 |
5 | ### Node ###
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 | .pnpm-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # Snowpack dependency directory (https://snowpack.dev/)
51 | web_modules/
52 |
53 | # TypeScript cache
54 | *.tsbuildinfo
55 |
56 | # Optional npm cache directory
57 | .npm
58 |
59 | # Optional eslint cache
60 | .eslintcache
61 |
62 | # Optional stylelint cache
63 | .stylelintcache
64 |
65 | # Microbundle cache
66 | .rpt2_cache/
67 | .rts2_cache_cjs/
68 | .rts2_cache_es/
69 | .rts2_cache_umd/
70 |
71 | # Optional REPL history
72 | .node_repl_history
73 |
74 | # Output of 'npm pack'
75 | *.tgz
76 |
77 | # Yarn Integrity file
78 | .yarn-integrity
79 |
80 | # dotenv environment variable files
81 | .env
82 | .env.development.local
83 | .env.test.local
84 | .env.production.local
85 | .env.local
86 |
87 | # parcel-bundler cache (https://parceljs.org/)
88 | .cache
89 | .parcel-cache
90 |
91 | # Next.js build output
92 | .next
93 | out
94 |
95 | # Nuxt.js build / generate output
96 | .nuxt
97 | dist
98 |
99 | # Gatsby files
100 | .cache/
101 | # Comment in the public line in if your project uses Gatsby and not Next.js
102 | # https://nextjs.org/blog/next-9-1#public-directory-support
103 | # public
104 |
105 | # vuepress build output
106 | .vuepress/dist
107 |
108 | # vuepress v2.x temp and cache directory
109 | .temp
110 |
111 | # Docusaurus cache and generated files
112 | .docusaurus
113 |
114 | # Serverless directories
115 | .serverless/
116 |
117 | # FuseBox cache
118 | .fusebox/
119 |
120 | # DynamoDB Local files
121 | .dynamodb/
122 |
123 | # TernJS port file
124 | .tern-port
125 |
126 | # Stores VSCode versions used for testing VSCode extensions
127 | .vscode-test
128 |
129 | # yarn v2
130 | .yarn/cache
131 | .yarn/unplugged
132 | .yarn/build-state.yml
133 | .yarn/install-state.gz
134 | .pnp.*
135 |
136 | ### Node Patch ###
137 | # Serverless Webpack directories
138 | .webpack/
139 |
140 | # Optional stylelint cache
141 |
142 | # SvelteKit build / generate output
143 | .svelte-kit
144 |
145 | # End of https://www.toptal.com/developers/gitignore/api/node
146 |
147 | # OS
148 | ## Mac
149 | .DS_Store
150 |
--------------------------------------------------------------------------------
/functions/change_username_to_email/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/node
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node
4 |
5 | ### Node ###
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 | .pnpm-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # Snowpack dependency directory (https://snowpack.dev/)
51 | web_modules/
52 |
53 | # TypeScript cache
54 | *.tsbuildinfo
55 |
56 | # Optional npm cache directory
57 | .npm
58 |
59 | # Optional eslint cache
60 | .eslintcache
61 |
62 | # Optional stylelint cache
63 | .stylelintcache
64 |
65 | # Microbundle cache
66 | .rpt2_cache/
67 | .rts2_cache_cjs/
68 | .rts2_cache_es/
69 | .rts2_cache_umd/
70 |
71 | # Optional REPL history
72 | .node_repl_history
73 |
74 | # Output of 'npm pack'
75 | *.tgz
76 |
77 | # Yarn Integrity file
78 | .yarn-integrity
79 |
80 | # dotenv environment variable files
81 | .env
82 | .env.development.local
83 | .env.test.local
84 | .env.production.local
85 | .env.local
86 |
87 | # parcel-bundler cache (https://parceljs.org/)
88 | .cache
89 | .parcel-cache
90 |
91 | # Next.js build output
92 | .next
93 | out
94 |
95 | # Nuxt.js build / generate output
96 | .nuxt
97 | dist
98 |
99 | # Gatsby files
100 | .cache/
101 | # Comment in the public line in if your project uses Gatsby and not Next.js
102 | # https://nextjs.org/blog/next-9-1#public-directory-support
103 | # public
104 |
105 | # vuepress build output
106 | .vuepress/dist
107 |
108 | # vuepress v2.x temp and cache directory
109 | .temp
110 |
111 | # Docusaurus cache and generated files
112 | .docusaurus
113 |
114 | # Serverless directories
115 | .serverless/
116 |
117 | # FuseBox cache
118 | .fusebox/
119 |
120 | # DynamoDB Local files
121 | .dynamodb/
122 |
123 | # TernJS port file
124 | .tern-port
125 |
126 | # Stores VSCode versions used for testing VSCode extensions
127 | .vscode-test
128 |
129 | # yarn v2
130 | .yarn/cache
131 | .yarn/unplugged
132 | .yarn/build-state.yml
133 | .yarn/install-state.gz
134 | .pnp.*
135 |
136 | ### Node Patch ###
137 | # Serverless Webpack directories
138 | .webpack/
139 |
140 | # Optional stylelint cache
141 |
142 | # SvelteKit build / generate output
143 | .svelte-kit
144 |
145 | # End of https://www.toptal.com/developers/gitignore/api/node
146 |
147 | # OS
148 | ## Mac
149 | .DS_Store
150 |
--------------------------------------------------------------------------------
/pages/invitations.tsx:
--------------------------------------------------------------------------------
1 | import ExtraBold from "@components/ExtraBold";
2 | import SideBar from "@components/SideBar";
3 | import { Models } from "@pankod/refine-appwrite";
4 | import { Box, Flex, Input } from "@pankod/refine-chakra-ui";
5 | import { useState } from "react";
6 | import { Menu } from "react-feather";
7 | import { rise } from "animations";
8 | import InvitationsList from "@components/InvitationsList";
9 | import { motion } from "framer-motion";
10 | import Head from "next/head";
11 | import { useGetIdentity, useList } from "@pankod/refine-core";
12 |
13 | interface Invitation extends Models.Document {
14 | name: string;
15 | accept_url: string;
16 | }
17 |
18 | const Invitations = () => {
19 | const animatedelement = motion(Flex);
20 | const [expand, set_expand] = useState(false);
21 | // Get current user
22 | const { data: identity, isLoading: identityLoading } =
23 | useGetIdentity>();
24 |
25 | // Get the invitations
26 | const { data, isLoading, refetch } = useList({
27 | resource: `invitations-${identity?.name}`,
28 | });
29 |
30 | return (
31 |
32 | {
35 | set_expand(false);
36 | }}
37 | expand={expand}
38 | />
39 |
40 | Your invitations - planetary
41 |
42 |
48 |
54 | set_expand(true)}
57 | >
58 |
59 |
60 |
61 | Invitations
62 |
63 |
64 |
74 |
82 |
83 |
84 | );
85 | };
86 |
87 | export default Invitations;
88 |
--------------------------------------------------------------------------------
/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { AppProps } from "next/app";
3 | import "../styles/styles.sass";
4 | import { Refine } from "@pankod/refine-core";
5 | import {
6 | notificationProvider,
7 | ChakraProvider,
8 | ReadyPage,
9 | ErrorComponent,
10 | Box,
11 | Flex,
12 | } from "@pankod/refine-chakra-ui";
13 | import routerProvider from "@pankod/refine-nextjs-router";
14 | import { dataProvider, liveProvider } from "@pankod/refine-appwrite";
15 | import { appWithTranslation, useTranslation } from "next-i18next";
16 | import { RefineKbarProvider } from "@pankod/refine-kbar";
17 | import { authProvider } from "src/authProvider";
18 | import NavBar from "@components/NavBar";
19 | import { appwriteClient } from "src/utility";
20 | import { Title, Sider, Layout, Header } from "@components/layout";
21 | import { OffLayoutArea } from "@components/offLayoutArea";
22 | import theme from "theme/chakra";
23 | import { customDataProvider } from "providers/appwrite";
24 | import { Nunito } from "@next/font/google";
25 | import { motion } from "framer-motion";
26 | import { appwriteTeamProvider } from "providers/appwriteTeam";
27 |
28 | const nunito = Nunito({ subsets: ["latin"], weight: "600" });
29 |
30 | function MyApp({ Component, pageProps }: AppProps): JSX.Element {
31 | const { t, i18n } = useTranslation();
32 | const AnimatedElement = motion(Flex);
33 |
34 | const i18nProvider = {
35 | translate: (key: string, params: object) => t(key, params),
36 | changeLocale: (lang: string) => i18n.changeLanguage(lang),
37 | getLocale: () => i18n.language,
38 | };
39 |
40 | return (
41 |
42 |
43 | }
60 | Title={Title}
61 | Sider={Sider}
62 | Layout={Layout}
63 | Header={Header}
64 | i18nProvider={i18nProvider}
65 | OffLayoutArea={OffLayoutArea}
66 | resources={[{ name: "projects" }]}
67 | >
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | );
76 | }
77 |
78 | export default appWithTranslation(MyApp);
79 |
--------------------------------------------------------------------------------
/functions/push_notifications/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | '@types/moment': ^2.13.0
5 | moment: ^2.29.4
6 | node-appwrite: ^8.0.0
7 |
8 | dependencies:
9 | moment: 2.29.4
10 | node-appwrite: 8.2.0
11 |
12 | devDependencies:
13 | '@types/moment': 2.13.0
14 |
15 | packages:
16 |
17 | /@types/moment/2.13.0:
18 | resolution: {integrity: sha512-DyuyYGpV6r+4Z1bUznLi/Y7HpGn4iQ4IVcGn8zrr1P4KotKLdH0sbK1TFR6RGyX6B+G8u83wCzL+bpawKU/hdQ==}
19 | deprecated: This is a stub types definition for Moment (https://github.com/moment/moment). Moment provides its own type definitions, so you don't need @types/moment installed!
20 | dependencies:
21 | moment: 2.29.4
22 | dev: true
23 |
24 | /asynckit/0.4.0:
25 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
26 | dev: false
27 |
28 | /axios/1.3.3:
29 | resolution: {integrity: sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==}
30 | dependencies:
31 | follow-redirects: 1.15.2
32 | form-data: 4.0.0
33 | proxy-from-env: 1.1.0
34 | transitivePeerDependencies:
35 | - debug
36 | dev: false
37 |
38 | /combined-stream/1.0.8:
39 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
40 | engines: {node: '>= 0.8'}
41 | dependencies:
42 | delayed-stream: 1.0.0
43 | dev: false
44 |
45 | /delayed-stream/1.0.0:
46 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
47 | engines: {node: '>=0.4.0'}
48 | dev: false
49 |
50 | /follow-redirects/1.15.2:
51 | resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
52 | engines: {node: '>=4.0'}
53 | peerDependencies:
54 | debug: '*'
55 | peerDependenciesMeta:
56 | debug:
57 | optional: true
58 | dev: false
59 |
60 | /form-data/4.0.0:
61 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
62 | engines: {node: '>= 6'}
63 | dependencies:
64 | asynckit: 0.4.0
65 | combined-stream: 1.0.8
66 | mime-types: 2.1.35
67 | dev: false
68 |
69 | /mime-db/1.52.0:
70 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
71 | engines: {node: '>= 0.6'}
72 | dev: false
73 |
74 | /mime-types/2.1.35:
75 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
76 | engines: {node: '>= 0.6'}
77 | dependencies:
78 | mime-db: 1.52.0
79 | dev: false
80 |
81 | /moment/2.29.4:
82 | resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==}
83 |
84 | /node-appwrite/8.2.0:
85 | resolution: {integrity: sha512-SFSTxHewwtbjkiF93OJEqOZC1x3mnvz1G/rKg9BNz4CG5PI9xP/pKqsKHYDdwUOfOB2Su90jI7fKglIPFd+o8A==}
86 | dependencies:
87 | axios: 1.3.3
88 | form-data: 4.0.0
89 | transitivePeerDependencies:
90 | - debug
91 | dev: false
92 |
93 | /proxy-from-env/1.1.0:
94 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
95 | dev: false
96 |
--------------------------------------------------------------------------------
/appwrite.json:
--------------------------------------------------------------------------------
1 | {
2 | "projectId": "63df174eb4161f4803ca",
3 | "projectName": "planetary",
4 | "functions": [
5 | {
6 | "$id": "63e31e32e7d2ca74ee8d",
7 | "name": "change_username_to_email",
8 | "runtime": "node-16.0",
9 | "path": "functions/change_username_to_email",
10 | "entrypoint": "src/index.js",
11 | "ignore": ["node_modules", ".npm"],
12 | "execute": [],
13 | "events": [],
14 | "schedule": "",
15 | "timeout": 15
16 | },
17 | {
18 | "$id": "63e32b6bdc2a464f3059",
19 | "name": "upload_user_profile",
20 | "runtime": "node-16.0",
21 | "path": "functions/upload_user_profile",
22 | "entrypoint": "src/index.js",
23 | "ignore": ["node_modules", ".npm"],
24 | "execute": [],
25 | "events": [],
26 | "schedule": "",
27 | "timeout": 15
28 | },
29 | {
30 | "$id": "63e4ddf38ac89fc4a010",
31 | "name": "setup_workspace",
32 | "runtime": "node-16.0",
33 | "path": "functions/setup_workspace",
34 | "entrypoint": "src/index.js",
35 | "ignore": ["node_modules", ".npm"],
36 | "execute": [],
37 | "events": ["teams.*.create"],
38 | "schedule": "",
39 | "timeout": 15
40 | },
41 | {
42 | "$id": "63eda39f6455ca9e4342",
43 | "name": "setup_user_workspace",
44 | "runtime": "node-16.0",
45 | "path": "functions/setup_user_workspace",
46 | "entrypoint": "src/index.js",
47 | "ignore": ["node_modules", ".npm"],
48 | "execute": [],
49 | "events": ["users.*.sessions.*.create"],
50 | "schedule": "",
51 | "timeout": 15
52 | },
53 | {
54 | "$id": "63eef40e7c0cb5283968",
55 | "name": "push_notifications",
56 | "runtime": "node-16.0",
57 | "path": "functions/push_notifications",
58 | "entrypoint": "src/index.js",
59 | "ignore": ["node_modules", ".npm"],
60 | "execute": [
61 | "teams.*.memberships.*.create",
62 | "databases.*.collections.todos.documents.*.create",
63 | "databases.*.collections.events.documents.*.create"
64 | ],
65 | "events": [],
66 | "schedule": "",
67 | "timeout": 15
68 | },
69 | {
70 | "$id": "63ef0749140ad5e4d6aa",
71 | "name": "new_invitation",
72 | "runtime": "node-16.0",
73 | "path": "functions/new_invitation",
74 | "entrypoint": "src/index.js",
75 | "ignore": ["node_modules", ".npm"],
76 | "execute": [],
77 | "events": ["teams.*.memberships.*.create"],
78 | "schedule": "",
79 | "timeout": 15
80 | },
81 | {
82 | "$id": "63f1a7b8741c48e8e37d",
83 | "name": "add_user_to_team",
84 | "runtime": "node-16.0",
85 | "path": "functions/add_user_to_team",
86 | "entrypoint": "src/index.js",
87 | "ignore": ["node_modules", ".npm"],
88 | "execute": [],
89 | "events": [
90 | "databases.*.collections.invitations.documents.*.update"
91 | ],
92 | "schedule": "",
93 | "timeout": 15
94 | }
95 | ]
96 | }
97 |
--------------------------------------------------------------------------------
/public/images/growth.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/RemoveUser.tsx:
--------------------------------------------------------------------------------
1 | import { Button, Flex, Spinner, Text } from "@pankod/refine-chakra-ui";
2 | import { rise } from "animations";
3 | import { useRouter } from "next/router";
4 | import { ComponentType, useState } from "react";
5 | import { teams } from "src/utility";
6 | import Bold from "./Bold";
7 |
8 | interface RemoveUserProps {
9 | container: ComponentType;
10 | animatedelement: ComponentType;
11 | destroy_self: () => void;
12 | username: string;
13 | membership_id: string;
14 | }
15 |
16 | const RemoveUser: React.FC = ({
17 | container: Container,
18 | animatedelement: AnimatedElement,
19 | destroy_self,
20 | username,
21 | membership_id,
22 | }) => {
23 | const [loading, set_loading] = useState(false);
24 | const router = useRouter();
25 |
26 | const remove_member = async () => {
27 | set_loading(true);
28 |
29 | const membership = await teams.deleteMembership(
30 | router.query.id as string,
31 | membership_id
32 | );
33 |
34 | destroy_self();
35 | };
36 |
37 | return (
38 |
54 |
65 |
66 | Are you sure you want to remove {username}?
67 |
68 |
69 |
82 |
95 |
96 |
97 |
98 | );
99 | };
100 |
101 | export default RemoveUser;
102 |
--------------------------------------------------------------------------------
/src/components/SideBarProject.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, Image, Text, Box } from "@pankod/refine-chakra-ui";
2 | import { useGetIdentity } from "@pankod/refine-core";
3 | import { useRouter } from "next/router";
4 | import { useEffect } from "react";
5 | import {
6 | Settings,
7 | Folder,
8 | MessageSquare,
9 | Users,
10 | Video,
11 | Key,
12 | X,
13 | } from "react-feather";
14 | import { account } from "src/utility";
15 | import { QuickLink } from "./QuickLink";
16 |
17 | interface SideBarProps {
18 | current: string;
19 | expand?: boolean;
20 | destroy_self?: () => void;
21 | }
22 |
23 | const SideBarProject: React.FC = ({
24 | current,
25 | expand,
26 | destroy_self,
27 | }) => {
28 | const { data: user, isError } = useGetIdentity();
29 | const router = useRouter();
30 |
31 | useEffect(() => {
32 | if (isError) {
33 | router.push("/");
34 | }
35 | }, [isError]);
36 |
37 | return (
38 |
52 |
59 |
60 |
61 |
62 |
63 |
64 | }
69 | current={current === "todos"}
70 | />
71 | }
76 | current={current === "chat"}
77 | />
78 | }
83 | current={current === "members"}
84 | />
85 |
86 |
92 |
93 | Purple Light
94 |
95 | me@kyeboard.me
96 |
97 |
98 |
99 |
100 |
101 | );
102 | };
103 |
104 | SideBarProject.defaultProps = {
105 | expand: false,
106 | destroy_self: () => {},
107 | };
108 |
109 | export default SideBarProject;
110 |
--------------------------------------------------------------------------------
/functions/upload_user_profile/src/index.ts:
--------------------------------------------------------------------------------
1 | // Import dependencies
2 | import { google } from "googleapis";
3 | import { Client, InputFile, Storage, Users } from "node-appwrite";
4 | import { Readable } from "stream";
5 | import needle from "needle";
6 |
7 | // Types
8 | interface Request {
9 | headers: {
10 | [key: string]: string;
11 | };
12 | payload: {
13 | [key: string]: string;
14 | };
15 | variables: {
16 | [key: string]: string;
17 | };
18 | }
19 |
20 | interface EventData {
21 | providerAccessToken: string;
22 | userId: string;
23 | }
24 |
25 | interface Response {
26 | send: (text: string, status?: number) => void;
27 | json: (obj: any, status?: number) => void;
28 | }
29 |
30 | // Create a function that takes in an image url and a file name. Download the image and save it to the storage bucket.
31 | const uploadImage = async (
32 | url: string,
33 | id: string,
34 | fileName: string,
35 | storage: Storage
36 | ) => {
37 | // Download the image
38 | const image_res = await needle("get", url);
39 |
40 | // Create a new instance of file
41 | const file = new (InputFile as any)(
42 | Readable.from(image_res.body),
43 | fileName,
44 | Buffer.byteLength(image_res.body)
45 | );
46 |
47 | await storage.createFile("63dfd4b2bf3364da5f0c", id, file);
48 | };
49 |
50 | const upload_user_profile = async function (req: Request, res: Response) {
51 | const client = new Client();
52 |
53 | // You can remove services you don't use
54 | const storage = new Storage(client);
55 | const users = new Users(client);
56 |
57 | if (
58 | !req.variables["APPWRITE_FUNCTION_ENDPOINT"] ||
59 | !req.variables["APPWRITE_FUNCTION_API_KEY"]
60 | ) {
61 | console.warn(
62 | "Environment variables are not set. Function cannot use Appwrite SDK."
63 | );
64 | } else {
65 | client
66 | .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"])
67 | .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"])
68 | .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"]);
69 | }
70 |
71 | try {
72 | const data: EventData = JSON.parse(
73 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
74 | );
75 |
76 | const user = await users.get(data.userId);
77 |
78 | // Fetch the google info of the user with the `providerAccessToken` in data and call the upload image, passing the picture url
79 | const oauth2Client = new google.auth.OAuth2();
80 | oauth2Client.setCredentials({ access_token: data.providerAccessToken });
81 |
82 | const oauth2 = google.oauth2({
83 | auth: oauth2Client,
84 | version: "v2",
85 | });
86 |
87 | const google_res = await oauth2.userinfo.get({});
88 |
89 | await uploadImage(
90 | google_res.data.picture ?? "",
91 | user.name,
92 | "profile.jpeg",
93 | storage
94 | );
95 |
96 | res.json({ success: true, message: "Successfully uploaded the pfp" });
97 | } catch (e) {
98 | res.json({ success: false, message: e });
99 | }
100 | };
101 |
102 | export default upload_user_profile;
103 |
104 | // Uncomment to test
105 | // upload_user_profile(
106 | // {
107 | // headers: {},
108 | // payload: {},
109 | // variables: {
110 | // APPWRITE_FUNCTION_ENDPOINT: "",
111 | // APPWRITE_FUNCTION_PROJECT_ID: "",
112 | // APPWRITE_FUNCTION_API_KEY: ""
113 | // APPWRITE_FUNCTION_EVENT_DATA: JSON.stringify({
114 | // providerAccessToken: "",
115 | // userId: "",
116 | // }),
117 | // },
118 | // },
119 | // {
120 | // json(obj, status) {
121 | // console.log(obj);
122 | // },
123 | // send(text, status) {
124 | // console.log(text);
125 | // },
126 | // }
127 | // );
128 |
--------------------------------------------------------------------------------
/public/locales/en/common.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": {
3 | "login": {
4 | "title": "Sign in to your account",
5 | "signin": "Sign in",
6 | "signup": "Sign up",
7 | "divider": "or",
8 | "fields": {
9 | "email": "Email",
10 | "password": "Password"
11 | },
12 | "errors": {
13 | "validEmail": "Invalid email address"
14 | },
15 | "buttons": {
16 | "submit": "Login",
17 | "forgotPassword": "Forgot password?",
18 | "noAccount": "Don’t have an account?",
19 | "rememberMe": "Remember me"
20 | }
21 | },
22 | "forgotPassword": {
23 | "title": "Forgot your password?",
24 | "fields": {
25 | "email": "Email"
26 | },
27 | "errors": {
28 | "validEmail": "Invalid email address"
29 | },
30 | "buttons": {
31 | "submit": "Send reset instructions"
32 | }
33 | },
34 | "register": {
35 | "title": "Sign up for your account",
36 | "fields": {
37 | "email": "Email",
38 | "password": "Password"
39 | },
40 | "errors": {
41 | "validEmail": "Invalid email address"
42 | },
43 | "buttons": {
44 | "submit": "Register",
45 | "haveAccount": "Have an account?"
46 | }
47 | },
48 | "updatePassword": {
49 | "title": "Update password",
50 | "fields": {
51 | "password": "New Password",
52 | "confirmPassword": "Confirm new password"
53 | },
54 | "errors": {
55 | "confirmPasswordNotMatch": "Passwords do not match"
56 | },
57 | "buttons": {
58 | "submit": "Update"
59 | }
60 | },
61 | "error": {
62 | "info": "You may have forgotten to add the {{action}} component to {{resource}} resource.",
63 | "404": "Sorry, the page you visited does not exist.",
64 | "resource404": "Are you sure you have created the {{resource}} resource.",
65 | "backHome": "Back Home"
66 | }
67 | },
68 | "actions": {
69 | "list": "List",
70 | "create": "Create",
71 | "edit": "Edit",
72 | "show": "Show"
73 | },
74 | "buttons": {
75 | "create": "Create",
76 | "save": "Save",
77 | "logout": "Logout",
78 | "delete": "Delete",
79 | "edit": "Edit",
80 | "cancel": "Cancel",
81 | "confirm": "Are you sure?",
82 | "filter": "Filter",
83 | "clear": "Clear",
84 | "refresh": "Refresh",
85 | "show": "Show",
86 | "undo": "Undo",
87 | "import": "Import",
88 | "clone": "Clone",
89 | "notAccessTitle": "You don't have permission to access"
90 | },
91 | "warnWhenUnsavedChanges": "Are you sure you want to leave? You have unsaved changes.",
92 | "notifications": {
93 | "success": "Successful",
94 | "error": "Error (status code: {{statusCode}})",
95 | "undoable": "You have {{seconds}} seconds to undo",
96 | "createSuccess": "Successfully created {{resource}}",
97 | "createError": "There was an error creating {{resource}} (status code: {{statusCode}})",
98 | "deleteSuccess": "Successfully deleted {{resource}}",
99 | "deleteError": "Error when deleting {{resource}} (status code: {{statusCode}})",
100 | "editSuccess": "Successfully edited {{resource}}",
101 | "editError": "Error when editing {{resource}} (status code: {{statusCode}})",
102 | "importProgress": "Importing: {{processed}}/{{total}}"
103 | },
104 | "loading": "Loading",
105 | "tags": {
106 | "clone": "Clone"
107 | },
108 | "dashboard": {
109 | "title": "Dashboard"
110 | },
111 | "posts": {
112 | "posts": "Posts",
113 | "fields": {
114 | "id": "Id",
115 | "title": "Title",
116 | "category": {
117 | "title": "Category",
118 | "filter": {
119 | "placeholder": "Select Category"
120 | }
121 | },
122 | "status": {
123 | "title": "Status",
124 | "published": "Published",
125 | "draft": "Draft",
126 | "rejected": "Rejected"
127 | },
128 | "content": "Content",
129 | "createdAt": "Created At"
130 | },
131 | "titles": {
132 | "create": "Create Post",
133 | "edit": "Edit Post",
134 | "list": "Posts",
135 | "show": "Show Post"
136 | }
137 | },
138 | "table": {
139 | "actions": "Actions"
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/pages/dashboard.tsx:
--------------------------------------------------------------------------------
1 | import SideBar from "@components/SideBar";
2 | import NewProject from "@components/NewProject";
3 | import { Box, Flex } from "@pankod/refine-chakra-ui";
4 | import { rise } from "animations";
5 | import { useState } from "react";
6 | import { AnimatePresence, motion } from "framer-motion";
7 | import ExtraBold from "@components/ExtraBold";
8 | import ProjectsList from "@components/ProjectsList";
9 | import Head from "next/head";
10 | import { Menu } from "react-feather";
11 |
12 | const DashBoard = () => {
13 | // Get today's date
14 | const date = new Date();
15 |
16 | // States of the application
17 | const [show_new, set_show_new] = useState(false);
18 | const [refresh, set_refresh] = useState(true);
19 | const [expand, set_expand] = useState(false);
20 |
21 | // Create an array full of month's name
22 | const month = [
23 | "January",
24 | "February",
25 | "March",
26 | "April",
27 | "May",
28 | "June",
29 | "July",
30 | "August",
31 | "September",
32 | "October",
33 | "November",
34 | "December",
35 | ];
36 |
37 | // Globally creating the framer-motion component so that they dont refresh on every state update (e.g. Input box change)
38 | const Container = motion(Flex);
39 | const AnimatedElement = motion(Flex);
40 | const ProjectCardAnimated = motion(Flex);
41 |
42 | // The awesome UI
43 | return (
44 |
49 |
50 | Your dashboard - planetary
51 |
52 | set_expand(false)}
56 | />
57 |
73 |
74 | {show_new && (
75 | set_refresh(true)}
78 | animatedelement={AnimatedElement}
79 | destroy_self={() => set_show_new(false)}
80 | />
81 | )}
82 |
83 |
84 |
91 | set_expand(true)}
94 | >
95 |
96 |
97 |
98 | Today, {date.getDate()} {month[date.getMonth()]}
99 |
100 |
101 |
102 |
103 |
109 |
110 |
111 |
112 | );
113 | };
114 |
115 | export default DashBoard;
116 |
--------------------------------------------------------------------------------
/public/locales/de/common.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": {
3 | "login": {
4 | "title": "Melden Sie sich bei Ihrem Konto an",
5 | "signin": "Einloggen",
6 | "signup": "Anmelden",
7 | "divider": "oder",
8 | "fields": {
9 | "email": "Email",
10 | "password": "Passwort"
11 | },
12 | "errors": {
13 | "validEmail": "Ungültige E-Mail-Adresse"
14 | },
15 | "buttons": {
16 | "submit": "Anmeldung",
17 | "forgotPassword": "Passwort vergessen?",
18 | "noAccount": "Sie haben kein Konto?",
19 | "rememberMe": "Erinnere dich an mich"
20 | }
21 | },
22 | "forgotPassword": {
23 | "title": "Haben Sie Ihr Passwort vergessen?",
24 | "fields": {
25 | "email": "Email"
26 | },
27 | "errors": {
28 | "validEmail": "Ungültige E-Mail-Adresse"
29 | },
30 | "buttons": {
31 | "submit": "Anweisungen zum Zurücksetzen senden"
32 | }
33 | },
34 | "register": {
35 | "title": "Registrieren Sie sich für Ihr Konto",
36 | "fields": {
37 | "email": "Email",
38 | "password": "Passwort"
39 | },
40 | "errors": {
41 | "validEmail": "Ungültige E-Mail-Adresse"
42 | },
43 | "buttons": {
44 | "submit": "Registrieren",
45 | "haveAccount": "Ein Konto haben?"
46 | }
47 | },
48 | "updatePassword": {
49 | "title": "Kennwort aktualisieren",
50 | "fields": {
51 | "password": "Neues Passwort",
52 | "confirmPassword": "Bestätige neues Passwort"
53 | },
54 | "errors": {
55 | "confirmPasswordNotMatch": "Passwörter stimmen nicht überein"
56 | },
57 | "buttons": {
58 | "submit": "Aktualisieren"
59 | }
60 | },
61 | "error": {
62 | "info": "Sie haben vergessen, {{action}} component zu {{resource}} hinzufügen.",
63 | "404": "Leider existiert diese Seite nicht.",
64 | "resource404": "Haben Sie die {{resource}} resource erstellt?",
65 | "backHome": "Zurück"
66 | }
67 | },
68 | "actions": {
69 | "list": "Aufführen",
70 | "create": "Erstellen",
71 | "edit": "Bearbeiten",
72 | "show": "Zeigen"
73 | },
74 | "buttons": {
75 | "create": "Erstellen",
76 | "save": "Speichern",
77 | "logout": "Abmelden",
78 | "delete": "Löschen",
79 | "edit": "Bearbeiten",
80 | "cancel": "Abbrechen",
81 | "confirm": "Sicher?",
82 | "filter": "Filter",
83 | "clear": "Löschen",
84 | "refresh": "Erneuern",
85 | "show": "Zeigen",
86 | "undo": "Undo",
87 | "import": "Importieren",
88 | "clone": "Klon",
89 | "notAccessTitle": "Sie haben keine zugriffsberechtigung"
90 | },
91 | "warnWhenUnsavedChanges": "Nicht gespeicherte Änderungen werden nicht übernommen.",
92 | "notifications": {
93 | "success": "Erfolg",
94 | "error": "Fehler (status code: {{statusCode}})",
95 | "undoable": "Sie haben {{seconds}} Sekunden Zeit für Undo.",
96 | "createSuccess": "{{resource}} erfolgreich erstellt.",
97 | "createError": "Fehler beim Erstellen {{resource}} (status code: {{statusCode}})",
98 | "deleteSuccess": "{{resource}} erfolgreich gelöscht.",
99 | "deleteError": "Fehler beim Löschen {{resource}} (status code: {{statusCode}})",
100 | "editSuccess": "{{resource}} erfolgreich bearbeitet.",
101 | "editError": "Fehler beim Bearbeiten {{resource}} (status code: {{statusCode}})",
102 | "importProgress": "{{processed}}/{{total}} importiert"
103 | },
104 | "loading": "Wird geladen",
105 | "tags": {
106 | "clone": "Klon"
107 | },
108 | "dashboard": {
109 | "title": "Dashboard"
110 | },
111 | "posts": {
112 | "posts": "Einträge",
113 | "fields": {
114 | "id": "Id",
115 | "title": "Titel",
116 | "category": {
117 | "title": "Kategorie",
118 | "filter": {
119 | "placeholder": "Auswählen Category"
120 | }
121 | },
122 | "status": {
123 | "title": "Status",
124 | "published": "Veröffentlicht",
125 | "draft": "Draft",
126 | "rejected": "Abgelehnt"
127 | },
128 | "content": "Inhalh",
129 | "createdAt": "Erstellt am"
130 | },
131 | "titles": {
132 | "create": "Erstellen",
133 | "edit": "Bearbeiten",
134 | "list": "Einträge",
135 | "show": "Eintrag zeigen"
136 | }
137 | },
138 | "table": {
139 | "actions": "Aktionen"
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/components/SideBar.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, Image, Text, Box, keyframes } from "@pankod/refine-chakra-ui";
2 | import { useGetIdentity } from "@pankod/refine-core";
3 | import { useRouter } from "next/router";
4 | import { useEffect } from "react";
5 | import { BarChart2, Bell, Inbox, X } from "react-feather";
6 | import { account, storage } from "src/utility";
7 | import { QuickLink } from "./QuickLink";
8 |
9 | interface SideBarProps {
10 | current: string;
11 | expand?: boolean;
12 | destroy_self: () => void;
13 | }
14 |
15 | const rise = keyframes`
16 | 0% {
17 | opacity: 0;
18 | transform: translateY(55px);
19 | }
20 | 100% {
21 | opacity: 1;
22 | transform: translateY(0px);
23 | }
24 | `;
25 |
26 | const SideBar: React.FC = ({ current, expand, destroy_self }) => {
27 | const { data: user, isError } = useGetIdentity();
28 | const router = useRouter();
29 |
30 | useEffect(() => {
31 | if (isError) {
32 | router.push("/");
33 | }
34 | }, [isError]);
35 |
36 | return (
37 |
51 |
58 |
59 |
60 |
61 |
62 |
63 | }
67 | delay={0}
68 | current={current === "dashboard"}
69 | />
70 | }
74 | delay={30}
75 | current={current === "notifications"}
76 | />
77 | }
82 | current={current === "invitations"}
83 | />
84 |
96 |
107 |
111 | {(user ?? { name: "" }).name}
112 |
113 | {(user ?? { email: "" }).email}
114 |
115 |
116 |
117 |
118 |
119 | );
120 | };
121 |
122 | SideBar.defaultProps = {
123 | expand: false,
124 | destroy_self: () => {},
125 | };
126 |
127 | export default SideBar;
128 |
--------------------------------------------------------------------------------
/pages/project/[id]/index.tsx:
--------------------------------------------------------------------------------
1 | import SideBarProject from "@components/SideBarProject";
2 | import { Box, Button, Flex, Input, Text } from "@pankod/refine-chakra-ui";
3 | import { useState } from "react";
4 | import { useRouter } from "next/router";
5 | import NewWorkspace from "@components/NewWorkspace";
6 | import { AnimatePresence, motion } from "framer-motion";
7 | import { rise } from "animations";
8 | import { Menu, Plus } from "react-feather";
9 | import ExtraBold from "@components/ExtraBold";
10 | import Head from "next/head";
11 | import WorkspacesList from "@components/WorkspacesList";
12 |
13 | const DashBoard: React.FC<{}> = () => {
14 | const [show_newproject, set_newproject] = useState(false);
15 | const [filter, set_filter] = useState("");
16 | const [reload, set_reload] = useState(false);
17 | const router = useRouter();
18 | const [expand, set_expand] = useState(false);
19 |
20 | const Container = motion(Flex);
21 | const AnimatedElement = motion(Flex);
22 |
23 | return (
24 |
25 |
26 | Your workspaces - planetary
27 |
28 |
29 | {show_newproject && (
30 | {
34 | set_newproject(false);
35 | set_reload(true);
36 | }}
37 | />
38 | )}
39 |
40 | set_expand(false)}
44 | />
45 |
56 |
62 | set_expand(true)}
65 | >
66 |
67 |
68 |
69 | Workspaces
70 |
71 |
72 |
73 | set_filter(e.target.value)}
77 | animation={`${rise} 300ms ease-in-out forwards`}
78 | opacity={0}
79 | style={{ animationDelay: "50ms" }}
80 | padding={6}
81 | placeholder="Search for your workspaces..."
82 | />
83 |
101 |
102 | set_reload(false)}
106 | />
107 |
108 |
109 | );
110 | };
111 |
112 | export default DashBoard;
113 |
--------------------------------------------------------------------------------
/functions/push_notifications/src/index.ts:
--------------------------------------------------------------------------------
1 | import moment from "moment";
2 | import { Databases, Client, Models } from "node-appwrite";
3 |
4 | interface Request {
5 | headers: {
6 | [key: string]: string;
7 | };
8 | payload: {
9 | [key: string]: string;
10 | };
11 | variables: {
12 | [key: string]: string;
13 | };
14 | }
15 |
16 | interface Response {
17 | send: (text: string, status?: number) => void;
18 | json: (obj: any, status?: number) => void;
19 | }
20 |
21 | interface TodoData extends Models.Document {
22 | title: string;
23 | due_date: string;
24 | priority: number;
25 | assignee: string[];
26 | category: string;
27 | }
28 |
29 | interface EventData extends Models.Document {
30 | title: string;
31 | description: string;
32 | location: string;
33 | start: number;
34 | end: string[];
35 | attendees: string;
36 | }
37 |
38 | const push_notifications = async function (req: Request, res: Response) {
39 | const client = new Client();
40 |
41 | // You can remove services you don't use
42 | const database = new Databases(client);
43 |
44 | if (
45 | !req.variables["APPWRITE_FUNCTION_ENDPOINT"] ||
46 | !req.variables["APPWRITE_FUNCTION_API_KEY"]
47 | ) {
48 | console.warn(
49 | "Environment variables are not set. Function cannot use Appwrite SDK."
50 | );
51 | } else {
52 | client
53 | .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"])
54 | .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"])
55 | .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"])
56 | .setSelfSigned(true);
57 | }
58 |
59 | const membership_event = /teams.*.memberships.*.create/;
60 | const new_todo_event = /databases.*.collections.todos.documents.*.create/;
61 | const new_event_event = /databases.*.collections.events.documents.*.create/;
62 |
63 | if (membership_event.test(req.variables["APPWRITE_FUNCTION_EVENT"])) {
64 | // A new membership has been created
65 | const event_data: Models.Membership = JSON.parse(
66 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
67 | );
68 |
69 | // Create a new notification for the user
70 | await database.createDocument(
71 | event_data.userName,
72 | "notifications",
73 | "unique()",
74 | {
75 | message: `You are invited to join ${event_data.teamName}! Check your inbox or go to invitations tab!`,
76 | icon: "mail",
77 | }
78 | );
79 |
80 | res.json({
81 | success: true,
82 | message: "Successfully pushed the message to the inbox!",
83 | });
84 | } else if (new_todo_event.test(req.variables["APPWRITE_FUNCTION_EVENT"])) {
85 | // A new membership has been created
86 | const event_data: TodoData = JSON.parse(
87 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
88 | );
89 |
90 | for (const assignee of event_data.assignee) {
91 | console.log("Sending push notification to: " + assignee);
92 |
93 | await database.createDocument(
94 | assignee,
95 | "notifications",
96 | "unique()",
97 | {
98 | message: `You have been assigned a task with the title of ${
99 | event_data.title
100 | } and the due date being ${moment(
101 | event_data.due_date
102 | ).format("MMMM Do YYYY")}.`,
103 | icon: "bookmark",
104 | }
105 | );
106 | }
107 |
108 | // Create a new notification for the user
109 |
110 | res.json({
111 | success: true,
112 | message: "Successfully pushed the message to the inbox!",
113 | });
114 | } else if (new_event_event.test(req.variables["APPWRITE_FUNCTION_EVENT"])) {
115 | // A new membership has been created
116 | const event_data: EventData = JSON.parse(
117 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
118 | );
119 |
120 | for (const assignee of event_data.attendees) {
121 | console.log("Sending push notification to: " + assignee);
122 |
123 | await database.createDocument(
124 | assignee,
125 | "notifications",
126 | "unique()",
127 | {
128 | message: `You have been asked to attend ${
129 | event_data.title
130 | } on ${moment(event_data.start).format("MMMM Do YYYY")}.`,
131 | icon: "video",
132 | }
133 | );
134 | }
135 | }
136 | };
137 |
138 | export default push_notifications;
139 |
--------------------------------------------------------------------------------
/src/components/WorkspacesList.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Flex, Image, Spinner, Text } from "@pankod/refine-chakra-ui";
2 | import { useList } from "@pankod/refine-core";
3 | import Link from "next/link";
4 | import feather from "feather-icons";
5 | import { useRouter } from "next/router";
6 | import ExtraBold from "./ExtraBold";
7 |
8 | const WorkspacesList: React.FC<{
9 | filter: string;
10 | reload: boolean;
11 | revert: () => void;
12 | }> = ({ filter, reload, revert }) => {
13 | // Get the router
14 | const router = useRouter();
15 |
16 | // Get all the workspaces
17 | const { data, isLoading, refetch } = useList({
18 | resource: `categories-${router.query.id}`,
19 | });
20 |
21 | if (reload) {
22 | refetch();
23 | revert(); // Set refres to false
24 | }
25 |
26 | // icon list
27 | const icons: { [key: string]: any } = new Object(feather.icons);
28 |
29 | return (
30 |
31 | {isLoading ? (
32 |
38 |
39 |
40 | ) : data?.data.length == 0 ? (
41 |
49 |
54 |
55 | Your to-dos are going to be more scrambled than an egg
56 | on a trampoline if you don't arrange them in
57 | workspaces.
58 |
59 |
60 | ) : (
61 |
62 |
63 | {data?.data.map((w) => {
64 | if (!w.title.includes(filter)) return;
65 |
66 | return (
67 |
74 |
77 |
86 |
98 |
102 | {w.title}
103 |
104 |
105 | {w.description}
106 |
107 |
108 |
109 |
110 | );
111 | })}
112 |
113 |
114 | )}
115 |
116 | );
117 | };
118 |
119 | export default WorkspacesList;
120 |
--------------------------------------------------------------------------------
/src/components/NewMember.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Button,
3 | Flex,
4 | FormControl,
5 | FormHelperText,
6 | Spinner,
7 | Text,
8 | } from "@pankod/refine-chakra-ui";
9 | import { rise } from "animations";
10 | import { useRouter } from "next/router";
11 | import { ComponentType, useState } from "react";
12 | import { teams } from "src/utility";
13 | import Bold from "./Bold";
14 | import ExtraBold from "./ExtraBold";
15 | import FormItem from "./FormItem";
16 |
17 | interface NewMemberProps {
18 | container: ComponentType;
19 | animatedelement: ComponentType;
20 | destroy_self: () => void;
21 | }
22 |
23 | const NewMember: React.FC = ({
24 | container: Container,
25 | animatedelement: AnimatedElement,
26 | destroy_self,
27 | }) => {
28 | const [email, set_email] = useState("");
29 | const [sumbitted, set_sumbitted] = useState(false);
30 | const [loading, set_loading] = useState(false);
31 | const router = useRouter();
32 |
33 | const invite_member = async () => {
34 | set_loading(true);
35 |
36 | await teams.createMembership(
37 | router.query.id as string,
38 | email,
39 | [],
40 | `${window.location.origin}/accept_invite`
41 | );
42 |
43 | destroy_self();
44 | };
45 |
46 | return (
47 |
63 |
74 |
80 | Invite a new member
81 |
82 |
131 |
132 |
133 | );
134 | };
135 |
136 | export default NewMember;
137 |
--------------------------------------------------------------------------------
/functions/setup_user_workspace/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Client, Databases, Users, Permission, Role } from "node-appwrite";
2 |
3 | interface Request {
4 | headers: {
5 | [key: string]: string;
6 | };
7 | payload: {
8 | [key: string]: string;
9 | };
10 | variables: {
11 | [key: string]: string;
12 | };
13 | }
14 |
15 | interface Response {
16 | send: (text: string, status?: number) => void;
17 | json: (obj: any, status?: number) => void;
18 | }
19 |
20 | interface EventData {
21 | userId: string;
22 | }
23 |
24 | const setup_user_workspace = async function (req: Request, res: Response) {
25 | const client = new Client();
26 |
27 | // You can remove services you don't use
28 | const database = new Databases(client);
29 | const users = new Users(client);
30 |
31 | if (
32 | !req.variables["APPWRITE_FUNCTION_ENDPOINT"] ||
33 | !req.variables["APPWRITE_FUNCTION_API_KEY"]
34 | ) {
35 | console.warn(
36 | "Environment variables are not set. Function cannot use Appwrite SDK."
37 | );
38 | } else {
39 | client
40 | .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"])
41 | .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"])
42 | .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"])
43 | .setSelfSigned(true);
44 | }
45 |
46 | const data: EventData = JSON.parse(
47 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
48 | );
49 |
50 | // Get the Appwrite user
51 | const user = await users.get(data.userId);
52 |
53 | // Create the database
54 | try {
55 | await database.create(user.name, user.name);
56 | } catch (err) {
57 | // Already database with that id is there, threfore meaning the user is already ready to go
58 | return res.json({
59 | success: true,
60 | message: "The user is already good to go",
61 | });
62 | }
63 |
64 | // Create collection for invitations
65 | await database.createCollection(user.$id, "invitations", "Invitations", [
66 | Permission.read(Role.user(user.$id)),
67 | Permission.update(Role.user(user.$id)),
68 | Permission.delete(Role.user(user.$id)),
69 | ]);
70 |
71 | // Create attributes for the invitation collection (name)
72 | await database.createStringAttribute(
73 | user.$id,
74 | "invitations",
75 | "name",
76 | 100,
77 | true
78 | );
79 |
80 | // Accept url
81 | await database.createUrlAttribute(
82 | user.$id,
83 | "invitations",
84 | "accept_url",
85 | true
86 | );
87 |
88 | await database.createBooleanAttribute(
89 | user.$id,
90 | "invitations",
91 | "accept_url",
92 | false,
93 | false
94 | );
95 |
96 |
97 | // Notifications collection
98 | // Create collection for invitations
99 | await database.createCollection(
100 | user.$id,
101 | "notifications",
102 | "Notifications",
103 | [
104 | Permission.read(Role.user(user.$id)),
105 | Permission.delete(Role.user(user.$id)),
106 | Permission.update(Role.user(user.$id)),
107 | ]
108 | );
109 |
110 | // Create attributes for the invitation collection (name)
111 | await database.createStringAttribute(
112 | user.$id,
113 | "notifications",
114 | "message",
115 | 1000,
116 | true
117 | );
118 |
119 | // Accept url
120 | await database.createStringAttribute(
121 | user.$id,
122 | "notifications",
123 | "icon",
124 | 20,
125 | true
126 | );
127 |
128 | // Success message
129 | res.json({
130 | success: true,
131 | message: "Successfully completed the user workspace setup",
132 | });
133 | };
134 |
135 | export default setup_user_workspace;
136 |
137 | // setup_user_workspace(
138 | // {
139 | // variables: {
140 | // APPWRITE_FUNCTION_ENDPOINT: "https://appwrite.kyeboard.me/v1",
141 | // APPWRITE_FUNCTION_PROJECT_ID: "63df174eb4161f4803ca",
142 | // APPWRITE_FUNCTION_API_KEY: "",
143 | // },
144 | // headers: {},
145 | // payload: {
146 | // $id: "63ed99ef9a0a96fffba9",
147 | // $createdAt: "2023-02-16T02:50:23.642+00:00",
148 | // userId: "63eb8f6cf07993a4a979",
149 | // expire: "2024-02-16 02:50:23.642",
150 | // provider: "google",
151 | // providerUid: "",
152 | // providerAccessToken: "",
153 | // providerAccessTokenExpiry: "2023-02-16T03:50:22.630+00:00",
154 | // providerRefreshToken: "",
155 | // ip: "",
156 | // osCode: "LIN",
157 | // osName: "GNU/Linux",
158 | // osVersion: "",
159 | // clientType: "browser",
160 | // clientCode: "CH",
161 | // clientName: "Chrome",
162 | // clientVersion: "110.0",
163 | // clientEngine: "Blink",
164 | // clientEngineVersion: "110.0.0.0",
165 | // deviceName: "desktop",
166 | // deviceBrand: "",
167 | // deviceModel: "",
168 | // countryCode: "in",
169 | // countryName: "India",
170 | // },
171 | // },
172 | // {
173 | // send: function (text, status) {
174 | // console.log(text);
175 | // },
176 | // json: function (text, status) {
177 | // console.log(text);
178 | // },
179 | // }
180 | // );
181 |
--------------------------------------------------------------------------------
/src/components/NotificationList.tsx:
--------------------------------------------------------------------------------
1 | import { Models } from "@pankod/refine-appwrite";
2 | import {
3 | Box,
4 | Flex,
5 | Image,
6 | Input,
7 | Spinner,
8 | Text,
9 | } from "@pankod/refine-chakra-ui";
10 | import feathericons from "feather-icons";
11 | import { ComponentType, useState } from "react";
12 | import { Check } from "react-feather";
13 | import { database } from "src/utility";
14 | import moment from "moment";
15 | import Bold from "./Bold";
16 | import { rise } from "animations";
17 | import { useGetIdentity, useList } from "@pankod/refine-core";
18 |
19 | interface NotificationListProps {
20 | container: ComponentType;
21 | animatedelement: ComponentType;
22 | }
23 |
24 | interface Notification extends Models.Document {
25 | icon: string;
26 | message: string;
27 | }
28 |
29 | const NotificationList: React.FC = ({
30 | container: Container,
31 | animatedelement: AnimatedElement,
32 | }) => {
33 | const { data: currentUser } =
34 | useGetIdentity>();
35 |
36 | const { data, isLoading, refetch } = useList({
37 | resource: `notifications-${currentUser?.name}`,
38 | });
39 | const [filter, set_filter] = useState("");
40 | const icons: { [key: string]: any } = new Object(feathericons.icons);
41 |
42 | const remove_notification = async (id: string) => {
43 | // Delete the document
44 | await database.deleteDocument(
45 | currentUser?.name ?? "",
46 | "notifications",
47 | id
48 | );
49 |
50 | // Refetch new documents
51 | refetch();
52 | };
53 |
54 | return (
55 |
56 | set_filter(e.target.value)}
62 | value={filter}
63 | padding={6}
64 | animation={`${rise} 500ms ease-in-out forwards`}
65 | opacity={0}
66 | marginBottom={5}
67 | style={{ animationDelay: "50ms" }}
68 | />
69 |
70 | {data?.data.map((n) => {
71 | if (!n.message.includes(filter)) return;
72 |
73 | return (
74 |
90 |
97 |
105 |
106 | {n.message}
107 |
117 | {moment(n.$createdAt).fromNow()}
118 |
119 | remove_notification(n.id)}
122 | padding={3}
123 | cursor="pointer"
124 | borderRadius="lg"
125 | >
126 |
127 |
128 |
129 | );
130 | })}
131 | {isLoading ? (
132 |
138 |
139 |
140 | ) : data?.data.length == 0 ? (
141 |
148 |
149 |
150 | Is this what inner peace feels like?
151 |
152 |
153 | ) : (
154 | <>>
155 | )}
156 |
157 | );
158 | };
159 |
160 | export default NotificationList;
161 |
--------------------------------------------------------------------------------
/src/components/ProjectsList.tsx:
--------------------------------------------------------------------------------
1 | // Import dependencies
2 | import { Models } from "@pankod/refine-appwrite";
3 | import {
4 | Box,
5 | Button,
6 | Flex,
7 | Image,
8 | Input,
9 | Spinner,
10 | Text,
11 | } from "@pankod/refine-chakra-ui";
12 | import { useList } from "@pankod/refine-core";
13 | import { rise } from "animations";
14 | import { AnimatePresence } from "framer-motion";
15 | import { ComponentType, useEffect, useState } from "react";
16 | import { Plus } from "react-feather";
17 | import { teams } from "src/utility";
18 | import Bold from "./Bold";
19 | import ProjectCard from "./ProjectsCard";
20 |
21 | // Props
22 | interface ProjectsListProps {
23 | refresh: boolean;
24 | set_refresh: (status: boolean) => void;
25 | animatedElement: ComponentType;
26 | set_show_new: (show: boolean) => void;
27 | }
28 |
29 | // The amazingly beautiful component
30 | const ProjectsList: React.FC = ({
31 | refresh,
32 | set_refresh,
33 | animatedElement: AnimatedElement,
34 | set_show_new,
35 | }) => {
36 | // States
37 | const { data, isLoading } = useList({
38 | dataProviderName: "team",
39 | resource: "",
40 | });
41 | const [filter, set_filter] = useState("");
42 |
43 | console.log(data);
44 |
45 | return (
46 |
47 |
55 | set_filter(e.target.value)}
62 | style={{ animationDelay: "160ms" }}
63 | animation={`${rise} 500ms ease-in-out forwards`}
64 | _placeholder={{ color: "gray.500" }}
65 | />
66 |
80 |
94 |
95 |
102 | Recent Projects
103 |
104 |
105 |
106 |
107 | {data?.data ? (
108 | data?.data.map((team) => {
109 | if (!team.name.includes(filter)) return;
110 |
111 | return (
112 | <>
113 |
119 | >
120 | );
121 | })
122 | ) : !isLoading && !refresh ? (
123 |
130 |
136 |
137 | When you realize there are no projects to work
138 | on and it's only Monday.
139 |
140 |
141 | ) : (
142 | <>>
143 | )}
144 |
145 | {isLoading ? (
146 |
152 |
153 |
154 | ) : (
155 | <>>
156 | )}
157 |
158 |
159 | );
160 | };
161 |
162 | export default ProjectsList;
163 |
--------------------------------------------------------------------------------
/functions/setup_workspace/src/index.ts:
--------------------------------------------------------------------------------
1 | // Import modules
2 | import { Client, Databases, Permission, Role, Teams } from "node-appwrite";
3 |
4 | // Request type
5 | interface Request {
6 | headers: {
7 | [key: string]: string;
8 | };
9 | payload: {
10 | [key: string]: string;
11 | };
12 | variables: {
13 | [key: string]: string;
14 | };
15 | }
16 |
17 | // Reponse type
18 | interface Response {
19 | send: (text: string, status?: number) => void;
20 | json: (obj: any, status?: number) => void;
21 | }
22 |
23 | // Event Data
24 | interface EventData {
25 | $id: string;
26 | name: string;
27 | }
28 |
29 | // Database structure
30 | const database_structure = {
31 | collections: [
32 | {
33 | name: "categories",
34 | rules: [
35 | {
36 | key: "title",
37 | required: true,
38 | array: false,
39 | },
40 | {
41 | key: "description",
42 | required: true,
43 | array: false,
44 | },
45 | {
46 | key: "completed",
47 | required: true,
48 | array: false,
49 | },
50 | {
51 | key: "icon",
52 | required: true,
53 | array: false,
54 | },
55 | {
56 | key: "color",
57 | required: true,
58 | array: false,
59 | },
60 | ],
61 | },
62 | {
63 | name: "todos",
64 | rules: [
65 | {
66 | key: "title",
67 | required: true,
68 | array: false,
69 | },
70 | {
71 | key: "due_date",
72 | required: true,
73 | array: false,
74 | },
75 | {
76 | key: "priority",
77 | required: true,
78 | array: false,
79 | },
80 | {
81 | key: "assignee",
82 | required: true,
83 | array: true,
84 | },
85 | {
86 | key: "category",
87 | required: true,
88 | array: false,
89 | },
90 | {
91 | key: "completed",
92 | required: false,
93 | array: false,
94 | },
95 | ],
96 | },
97 | {
98 | name: "chat",
99 | rules: [
100 | {
101 | key: "message",
102 | required: true,
103 | array: false,
104 | },
105 | {
106 | key: "timestamp",
107 | required: true,
108 | array: false,
109 | },
110 | {
111 | key: "author",
112 | required: true,
113 | array: false,
114 | },
115 | ],
116 | },
117 | ],
118 | };
119 |
120 | const setup_workspace = async function (req: Request, res: Response) {
121 | const client = new Client();
122 |
123 | const database = new Databases(client);
124 |
125 | if (
126 | !req.variables["APPWRITE_FUNCTION_ENDPOINT"] ||
127 | !req.variables["APPWRITE_FUNCTION_API_KEY"]
128 | ) {
129 | console.warn(
130 | "Environment variables are not set. Function cannot use Appwrite SDK."
131 | );
132 | } else {
133 | client
134 | .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"])
135 | .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"])
136 | .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"])
137 | .setSelfSigned(true);
138 | }
139 |
140 | const event_data: EventData = JSON.parse(
141 | req.variables["APPWRITE_FUNCTION_EVENT_DATA"]
142 | );
143 |
144 | // Setup the workspace according to the structure
145 | try {
146 | await database.create(event_data.$id, event_data.name);
147 |
148 | for (const collection of database_structure.collections) {
149 | await database.createCollection(
150 | event_data.$id,
151 | collection.name,
152 | collection.name,
153 | [
154 | Permission.read(Role.team(event_data.$id)),
155 | Permission.write(Role.team(event_data.$id)),
156 | Permission.update(Role.team(event_data.$id)),
157 | Permission.delete(Role.team(event_data.$id)),
158 | ]
159 | );
160 |
161 | for (const rules of collection.rules) {
162 | await database.createStringAttribute(
163 | event_data.$id,
164 | collection.name,
165 | rules.key,
166 | 100000,
167 | rules.required,
168 | "",
169 | rules.array
170 | );
171 | }
172 | }
173 |
174 | res.json({ message: "Workspace setup successfully" });
175 | } catch (e: any) {
176 | return res.json({
177 | error: e.message,
178 | });
179 | }
180 | };
181 |
182 | export default setup_workspace;
183 |
184 | // Uncomment to test
185 | // setup_workspace(
186 | // {
187 | // headers: {},
188 | // payload: {},
189 | // variables: {
190 | // APPWRITE_FUNCTION_ENDPOINT: "",
191 | // APPWRITE_FUNCTION_PROJECT_ID: "",
192 | // APPWRITE_FUNCTION_API_KEY: "",
193 | // APPWRITE_FUNCTION_EVENT_DATA: JSON.stringify({
194 | // $id: "",
195 | // name: "",
196 | // }),
197 | // },
198 | // },
199 | // {
200 | // json(obj, status) {
201 | // console.log(obj);
202 | // },
203 | // send(text, status) {
204 | // console.log(text);
205 | // },
206 | // }
207 | // );
208 |
--------------------------------------------------------------------------------
/pages/features.tsx:
--------------------------------------------------------------------------------
1 | import ExtraBold from "@components/ExtraBold";
2 | import { Box, Flex, Text } from "@pankod/refine-chakra-ui";
3 | import { rise } from "animations";
4 | import Head from "next/head";
5 | import { Eye, MessageSquare, Package, Users, Video } from "react-feather";
6 |
7 | const Features = () => {
8 | return (
9 |
16 |
17 | Awesome features - planetary
18 |
19 |
26 | Features
27 |
28 |
39 | Our app's features are like a personal assistant - but
40 | better, because they won't call in sick or drink all your
41 | coffee!
42 |
43 |
50 |
61 |
67 |
68 |
69 |
70 | Task Management
71 |
72 |
73 | When your team is managed with our app, you can finally
74 | focus on the important things in life, like browsing
75 | memes.
76 |
77 |
78 |
89 |
95 |
96 |
97 |
98 | Team chat
99 |
100 |
101 | Easily take a break and chill with your team mates with
102 | an inbuilt chat feature.
103 |
104 |
105 |
116 |
122 |
123 |
124 |
125 | Team management
126 |
127 |
128 | Easily invite other members to your project to collab,
129 | as well as remove them if they spam :P
130 |
131 |
132 |
143 |
149 |
150 |
151 |
152 | Beautiful UI
153 |
154 |
155 | Amazingly beautiful UI, it's like the Mona Lisa of
156 | task management apps - minus the creepy smile!
157 |
158 |
159 |
160 |
161 | );
162 | };
163 |
164 | export default Features;
165 |
--------------------------------------------------------------------------------
/src/components/NavBar.tsx:
--------------------------------------------------------------------------------
1 | import { Nunito } from "@next/font/google";
2 | import { Models } from "@pankod/refine-appwrite";
3 | import {
4 | Box,
5 | Button,
6 | Flex,
7 | Image,
8 | Spinner,
9 | Text,
10 | } from "@pankod/refine-chakra-ui";
11 | import { useAuthenticated } from "@pankod/refine-core";
12 | import { rise, rise_reverse } from "animations";
13 | import Link from "next/link";
14 | import { useRouter } from "next/router";
15 | import { ComponentType, useEffect, useState } from "react";
16 | import { Menu, X } from "react-feather";
17 | import { account, storage } from "src/utility";
18 |
19 | interface NavBarProps {
20 | user: boolean;
21 | animatedelement: ComponentType;
22 | }
23 |
24 | const nunito = Nunito({ subsets: ["latin"], weight: "800" });
25 |
26 | const NavBar: React.FC = ({
27 | user,
28 | animatedelement: AnimatedElement,
29 | }) => {
30 | const [open_dropdown, set_open_dropdown] = useState(false);
31 | const { isLoading, isError, refetch } = useAuthenticated();
32 | const [logging_out, set_logging_out] = useState(false);
33 | const router = useRouter();
34 |
35 | useEffect(() => {
36 | if (isError) {
37 | router.push("/");
38 | }
39 | }, [isError]);
40 |
41 | const toggle_auth = async () => {
42 | if (isError) {
43 | account.createOAuth2Session(
44 | "google",
45 | window.location.href + "dashboard"
46 | );
47 | } else {
48 | set_logging_out(true);
49 |
50 | await account.deleteSession("current");
51 |
52 | set_logging_out(false);
53 |
54 | router.push("/");
55 |
56 | refetch();
57 | }
58 | };
59 |
60 | return (
61 |
73 |
74 |
75 |
80 | Planetary
81 |
82 |
83 |
106 |
107 |
114 |
115 |
116 |
123 |
124 |
125 |
132 |
133 |
134 |
141 |
142 |
143 |
150 |
151 |
152 |
170 |
171 | {open_dropdown ? (
172 | set_open_dropdown(false)} />
173 | ) : (
174 |
177 |
178 | );
179 | };
180 |
181 | export default NavBar;
182 |
--------------------------------------------------------------------------------