Add Meta Mask to app store (#2650)
* Adds available apps * Adds App Model * WIP * Create meta mask app folder * Add description and images * Remove credential from installed apps page * Updates seeder script * Seeder fixes * lowercase categories * Upgrades prisma * WIP * WIP * Hopefully fixes circular deps * Type fixes * Fixes seeder * Adds migration to connect Credentials to Apps * Updates app store callbacks * Updates google credentials * Uses dirName from DB * Type fixes * Update reschedule.ts * Seeder fixes * Fixes categories listing * Update index.ts * Update schema.prisma * Updates dependencies * Renames giphy app * Uses dynamic imports for app metadata * Fixes credentials error * Uses dynamic import for api handlers * Dynamic import fixes * Allows for simple folder names in app store * Remove video adaptor * Squashes app migrations * seeder fixes * Renames to metamask * Updates metamask metadata * Fixes dyamic imports * Remove comments * Create migration.sql Co-authored-by: zomars <zomars@me.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com>
This commit is contained in:
		
							parent
							
								
									6a27fb2959
								
							
						
					
					
						commit
						7f463830bd
					
				
					 18 changed files with 190 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -532,15 +532,10 @@ const loggedInViewerRouter = createProtectedRouter()
 | 
			
		|||
      });
 | 
			
		||||
 | 
			
		||||
      if (web3Credential) {
 | 
			
		||||
        return ctx.prisma.credential.update({
 | 
			
		||||
        return ctx.prisma.credential.delete({
 | 
			
		||||
          where: {
 | 
			
		||||
            id: web3Credential.id,
 | 
			
		||||
          },
 | 
			
		||||
          data: {
 | 
			
		||||
            key: {
 | 
			
		||||
              isWeb3Active: !(web3Credential.key as JSONObject).isWeb3Active,
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        return ctx.prisma.credential.create({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ export const apiHandlers = {
 | 
			
		|||
  wipemycalother: import("./wipemycalother/api"),
 | 
			
		||||
  jitsivideo: import("./jitsivideo/api"),
 | 
			
		||||
  huddle01video: import("./huddle01video/api"),
 | 
			
		||||
  metamask: import("./metamask/api"),
 | 
			
		||||
  giphy: import("./giphy/api"),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ export const InstallAppButtonMap = {
 | 
			
		|||
  wipemycalother: dynamic(() => import("./wipemycalother/components/InstallAppButton")),
 | 
			
		||||
  jitsivideo: dynamic(() => import("./jitsivideo/components/InstallAppButton")),
 | 
			
		||||
  huddle01video: dynamic(() => import("./huddle01video/components/InstallAppButton")),
 | 
			
		||||
  metamask: dynamic(() => import("./metamask/components/InstallAppButton")),
 | 
			
		||||
  giphy: dynamic(() => import("./giphy/components/InstallAppButton")),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import * as googlevideo from "./googlevideo";
 | 
			
		|||
import * as hubspotothercalendar from "./hubspotothercalendar";
 | 
			
		||||
import * as huddle01video from "./huddle01video";
 | 
			
		||||
import * as jitsivideo from "./jitsivideo";
 | 
			
		||||
import * as metamask from "./metamask";
 | 
			
		||||
import * as office365calendar from "./office365calendar";
 | 
			
		||||
import * as office365video from "./office365video";
 | 
			
		||||
import * as slackmessaging from "./slackmessaging";
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +34,7 @@ const appStore = {
 | 
			
		|||
  tandemvideo,
 | 
			
		||||
  zoomvideo,
 | 
			
		||||
  wipemycalother,
 | 
			
		||||
  metamask,
 | 
			
		||||
  giphy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import { metadata as googlevideo } from "./googlevideo/_metadata";
 | 
			
		|||
import { metadata as hubspotothercalendar } from "./hubspotothercalendar/_metadata";
 | 
			
		||||
import { metadata as huddle01video } from "./huddle01video/_metadata";
 | 
			
		||||
import { metadata as jitsivideo } from "./jitsivideo/_metadata";
 | 
			
		||||
import { metadata as metamask } from "./metamask/_metadata";
 | 
			
		||||
import { metadata as office365calendar } from "./office365calendar/_metadata";
 | 
			
		||||
import { metadata as office365video } from "./office365video/_metadata";
 | 
			
		||||
import { metadata as slackmessaging } from "./slackmessaging/_metadata";
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +32,7 @@ export const appStoreMetadata = {
 | 
			
		|||
  tandemvideo,
 | 
			
		||||
  zoomvideo,
 | 
			
		||||
  wipemycalother,
 | 
			
		||||
  metamask,
 | 
			
		||||
  giphy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								packages/app-store/metamask/README.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								packages/app-store/metamask/README.mdx
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
---
 | 
			
		||||
items:
 | 
			
		||||
  - /api/app-store/metamask/example1.png
 | 
			
		||||
  - /api/app-store/metamask/example2.png
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<Slider items={items} />
 | 
			
		||||
 | 
			
		||||
Only book and allow bookings from people who share the same tokens, DAOs, or NFTs.
 | 
			
		||||
 | 
			
		||||
Send a group scheduling link that only members of a DAO or token-based community can join.
 | 
			
		||||
 | 
			
		||||
Share your booking link and be sure to only receive bookings from owners of your chosen tokens or coins.
 | 
			
		||||
 | 
			
		||||
Provide office hours for other DAO members or outsiders who want to learn more from you.
 | 
			
		||||
 | 
			
		||||
[Click here to learn more](https://cal.com/web3)
 | 
			
		||||
							
								
								
									
										26
									
								
								packages/app-store/metamask/_metadata.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								packages/app-store/metamask/_metadata.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
import type { App } from "@calcom/types/App";
 | 
			
		||||
 | 
			
		||||
import _package from "./package.json";
 | 
			
		||||
 | 
			
		||||
export const metadata = {
 | 
			
		||||
  name: "MetaMask",
 | 
			
		||||
  description: _package.description,
 | 
			
		||||
  installed: true,
 | 
			
		||||
  category: "web3",
 | 
			
		||||
  // If using static next public folder, can then be referenced from the base URL (/).
 | 
			
		||||
  imageSrc: "/api/app-store/metamask/icon.svg",
 | 
			
		||||
  logo: "/api/app-store/metamask/icon.svg",
 | 
			
		||||
  publisher: "Cal.com",
 | 
			
		||||
  rating: 5,
 | 
			
		||||
  reviews: 69,
 | 
			
		||||
  slug: "metamask",
 | 
			
		||||
  title: "Meta Mask",
 | 
			
		||||
  trending: true,
 | 
			
		||||
  type: "metamask_web3",
 | 
			
		||||
  url: "https://cal.com/",
 | 
			
		||||
  variant: "other",
 | 
			
		||||
  verified: true,
 | 
			
		||||
  email: "help@cal.com",
 | 
			
		||||
} as App;
 | 
			
		||||
 | 
			
		||||
export default metadata;
 | 
			
		||||
							
								
								
									
										39
									
								
								packages/app-store/metamask/api/add.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								packages/app-store/metamask/api/add.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
import type { NextApiRequest, NextApiResponse } from "next";
 | 
			
		||||
 | 
			
		||||
import prisma from "@calcom/prisma";
 | 
			
		||||
 | 
			
		||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
 | 
			
		||||
  if (!req.session?.user?.id) {
 | 
			
		||||
    return res.status(401).json({ message: "You must be logged in to do this" });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const appType = "metamask_web3";
 | 
			
		||||
  try {
 | 
			
		||||
    const alreadyInstalled = await prisma.credential.findFirst({
 | 
			
		||||
      where: {
 | 
			
		||||
        type: appType,
 | 
			
		||||
        userId: req.session.user.id,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
    if (alreadyInstalled) {
 | 
			
		||||
      throw new Error("Already installed");
 | 
			
		||||
    }
 | 
			
		||||
    const installation = await prisma.credential.create({
 | 
			
		||||
      data: {
 | 
			
		||||
        type: appType,
 | 
			
		||||
        key: { isWeb3Active: true },
 | 
			
		||||
        userId: req.session.user.id,
 | 
			
		||||
        appId: "metamask",
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
    if (!installation) {
 | 
			
		||||
      throw new Error("Unable to create user credential for metamask");
 | 
			
		||||
    }
 | 
			
		||||
  } catch (error: unknown) {
 | 
			
		||||
    if (error instanceof Error) {
 | 
			
		||||
      return res.status(500).json({ message: error.message });
 | 
			
		||||
    }
 | 
			
		||||
    return res.status(500);
 | 
			
		||||
  }
 | 
			
		||||
  return res.redirect("/apps/installed");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								packages/app-store/metamask/api/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								packages/app-store/metamask/api/index.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
export { default as add } from "./add";
 | 
			
		||||
							
								
								
									
										18
									
								
								packages/app-store/metamask/components/InstallAppButton.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								packages/app-store/metamask/components/InstallAppButton.tsx
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
import useAddAppMutation from "../../_utils/useAddAppMutation";
 | 
			
		||||
import { InstallAppButtonProps } from "../../types";
 | 
			
		||||
 | 
			
		||||
export default function InstallAppButton(props: InstallAppButtonProps) {
 | 
			
		||||
  // @ts-ignore TODO: deprecate App types in favor of DB slugs
 | 
			
		||||
  const mutation = useAddAppMutation("metamask");
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      {props.render({
 | 
			
		||||
        onClick() {
 | 
			
		||||
          mutation.mutate("");
 | 
			
		||||
        },
 | 
			
		||||
        loading: mutation.isLoading,
 | 
			
		||||
      })}
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								packages/app-store/metamask/components/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								packages/app-store/metamask/components/index.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
export { default as InstallAppButton } from "./InstallAppButton";
 | 
			
		||||
							
								
								
									
										2
									
								
								packages/app-store/metamask/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								packages/app-store/metamask/index.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
export * as api from "./api";
 | 
			
		||||
export { metadata } from "./_metadata";
 | 
			
		||||
							
								
								
									
										14
									
								
								packages/app-store/metamask/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								packages/app-store/metamask/package.json
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
{
 | 
			
		||||
  "$schema": "https://json.schemastore.org/package.json",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "name": "@calcom/metamask",
 | 
			
		||||
  "version": "0.0.0",
 | 
			
		||||
  "main": "./index.ts",
 | 
			
		||||
  "description": "Only book and allow bookings from people who share the same tokens, DAOs, or NFTs.",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@calcom/prisma": "*"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@calcom/types": "*"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								packages/app-store/metamask/static/example1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/app-store/metamask/static/example1.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 88 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								packages/app-store/metamask/static/example2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/app-store/metamask/static/example2.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 515 KiB  | 
							
								
								
									
										61
									
								
								packages/app-store/metamask/static/icon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								packages/app-store/metamask/static/icon.svg
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 | 
			
		||||
<svg version="1.1" id="Layer_1" xmlns:ev="http://www.w3.org/2001/xml-events"
 | 
			
		||||
	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 318.6 318.6"
 | 
			
		||||
	 style="enable-background:new 0 0 318.6 318.6;" xml:space="preserve">
 | 
			
		||||
<style type="text/css">
 | 
			
		||||
	.st0{fill:#E2761B;stroke:#E2761B;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st1{fill:#E4761B;stroke:#E4761B;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st2{fill:#D7C1B3;stroke:#D7C1B3;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st3{fill:#233447;stroke:#233447;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st4{fill:#CD6116;stroke:#CD6116;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st5{fill:#E4751F;stroke:#E4751F;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st6{fill:#F6851B;stroke:#F6851B;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st7{fill:#C0AD9E;stroke:#C0AD9E;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st8{fill:#161616;stroke:#161616;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
	.st9{fill:#763D16;stroke:#763D16;stroke-linecap:round;stroke-linejoin:round;}
 | 
			
		||||
</style>
 | 
			
		||||
<polygon class="st0" points="274.1,35.5 174.6,109.4 193,65.8 "/>
 | 
			
		||||
<g>
 | 
			
		||||
	<polygon class="st1" points="44.4,35.5 143.1,110.1 125.6,65.8 	"/>
 | 
			
		||||
	<polygon class="st1" points="238.3,206.8 211.8,247.4 268.5,263 284.8,207.7 	"/>
 | 
			
		||||
	<polygon class="st1" points="33.9,207.7 50.1,263 106.8,247.4 80.3,206.8 	"/>
 | 
			
		||||
	<polygon class="st1" points="103.6,138.2 87.8,162.1 144.1,164.6 142.1,104.1 	"/>
 | 
			
		||||
	<polygon class="st1" points="214.9,138.2 175.9,103.4 174.6,164.6 230.8,162.1 	"/>
 | 
			
		||||
	<polygon class="st1" points="106.8,247.4 140.6,230.9 111.4,208.1 	"/>
 | 
			
		||||
	<polygon class="st1" points="177.9,230.9 211.8,247.4 207.1,208.1 	"/>
 | 
			
		||||
</g>
 | 
			
		||||
<g>
 | 
			
		||||
	<polygon class="st2" points="211.8,247.4 177.9,230.9 180.6,253 180.3,262.3 	"/>
 | 
			
		||||
	<polygon class="st2" points="106.8,247.4 138.3,262.3 138.1,253 140.6,230.9 	"/>
 | 
			
		||||
</g>
 | 
			
		||||
<polygon class="st3" points="138.8,193.5 110.6,185.2 130.5,176.1 "/>
 | 
			
		||||
<polygon class="st3" points="179.7,193.5 188,176.1 208,185.2 "/>
 | 
			
		||||
<g>
 | 
			
		||||
	<polygon class="st4" points="106.8,247.4 111.6,206.8 80.3,207.7 	"/>
 | 
			
		||||
	<polygon class="st4" points="207,206.8 211.8,247.4 238.3,207.7 	"/>
 | 
			
		||||
	<polygon class="st4" points="230.8,162.1 174.6,164.6 179.8,193.5 188.1,176.1 208.1,185.2 	"/>
 | 
			
		||||
	<polygon class="st4" points="110.6,185.2 130.6,176.1 138.8,193.5 144.1,164.6 87.8,162.1 	"/>
 | 
			
		||||
</g>
 | 
			
		||||
<g>
 | 
			
		||||
	<polygon class="st5" points="87.8,162.1 111.4,208.1 110.6,185.2 	"/>
 | 
			
		||||
	<polygon class="st5" points="208.1,185.2 207.1,208.1 230.8,162.1 	"/>
 | 
			
		||||
	<polygon class="st5" points="144.1,164.6 138.8,193.5 145.4,227.6 146.9,182.7 	"/>
 | 
			
		||||
	<polygon class="st5" points="174.6,164.6 171.9,182.6 173.1,227.6 179.8,193.5 	"/>
 | 
			
		||||
</g>
 | 
			
		||||
<polygon class="st6" points="179.8,193.5 173.1,227.6 177.9,230.9 207.1,208.1 208.1,185.2 "/>
 | 
			
		||||
<polygon class="st6" points="110.6,185.2 111.4,208.1 140.6,230.9 145.4,227.6 138.8,193.5 "/>
 | 
			
		||||
<polygon class="st7" points="180.3,262.3 180.6,253 178.1,250.8 140.4,250.8 138.1,253 138.3,262.3 106.8,247.4 117.8,256.4 
 | 
			
		||||
	140.1,271.9 178.4,271.9 200.8,256.4 211.8,247.4 "/>
 | 
			
		||||
<polygon class="st8" points="177.9,230.9 173.1,227.6 145.4,227.6 140.6,230.9 138.1,253 140.4,250.8 178.1,250.8 180.6,253 "/>
 | 
			
		||||
<g>
 | 
			
		||||
	<polygon class="st9" points="278.3,114.2 286.8,73.4 274.1,35.5 177.9,106.9 214.9,138.2 267.2,153.5 278.8,140 273.8,136.4 
 | 
			
		||||
		281.8,129.1 275.6,124.3 283.6,118.2 	"/>
 | 
			
		||||
	<polygon class="st9" points="31.8,73.4 40.3,114.2 34.9,118.2 42.9,124.3 36.8,129.1 44.8,136.4 39.8,140 51.3,153.5 103.6,138.2 
 | 
			
		||||
		140.6,106.9 44.4,35.5 	"/>
 | 
			
		||||
</g>
 | 
			
		||||
<polygon class="st6" points="267.2,153.5 214.9,138.2 230.8,162.1 207.1,208.1 238.3,207.7 284.8,207.7 "/>
 | 
			
		||||
<polygon class="st6" points="103.6,138.2 51.3,153.5 33.9,207.7 80.3,207.7 111.4,208.1 87.8,162.1 "/>
 | 
			
		||||
<polygon class="st6" points="174.6,164.6 177.9,106.9 193.1,65.8 125.6,65.8 140.6,106.9 144.1,164.6 145.3,182.8 145.4,227.6 
 | 
			
		||||
	173.1,227.6 173.3,182.8 "/>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 3.9 KiB  | 
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
-- Connects each saved Credential to their respective App
 | 
			
		||||
UPDATE "Credential" SET "appId" = 'metamask' WHERE "type" = 'metamask_web3';
 | 
			
		||||
UPDATE "Credential" SET "appId" = 'giphy' WHERE "type" = 'giphy_other';
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +77,7 @@ async function main() {
 | 
			
		|||
  }
 | 
			
		||||
  // Web3 apps
 | 
			
		||||
  await createApp("huddle01", "huddle01video", ["web3", "video"]);
 | 
			
		||||
  await createApp("metamask", "metamask", ["web3"]);
 | 
			
		||||
  // Messaging apps
 | 
			
		||||
  if (process.env.SLACK_CLIENT_ID && process.env.SLACK_CLIENT_SECRET && process.env.SLACK_SIGNING_SECRET) {
 | 
			
		||||
    await createApp("slack", "slackmessaging", ["messaging"], {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue