@mongoosejs/studio 0.0.60 → 0.0.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,13 +11,14 @@ appendCSS(require('./navbar.css'));
11
11
  module.exports = app => app.component('navbar', {
12
12
  template: template,
13
13
  props: ['user', 'roles'],
14
- data: () => ({ nodeEnv: null, showFlyout: false }),
14
+ inject: ['state'],
15
+ data: () => ({ showFlyout: false }),
15
16
  computed: {
16
17
  routeName() {
17
18
  return this.$route.name;
18
19
  },
19
20
  warnEnv() {
20
- return this.nodeEnv === 'prod' || this.nodeEnv === 'production';
21
+ return this.state.nodeEnv === 'prod' || this.state.nodeEnv === 'production';
21
22
  },
22
23
  hasAPIKey() {
23
24
  return mothership.hasAPIKey;
@@ -26,10 +27,6 @@ module.exports = app => app.component('navbar', {
26
27
  return this.roles?.includes('owner') || this.roles?.includes('admin');
27
28
  }
28
29
  },
29
- async mounted() {
30
- const { nodeEnv } = await api.status();
31
- this.nodeEnv = nodeEnv;
32
- },
33
30
  methods: {
34
31
  async loginWithGithub() {
35
32
  const { url } = await mothership.githubLogin();
@@ -6,10 +6,13 @@
6
6
  <div class="text-lg mt-2 font-bold">
7
7
  Mongoose Studio
8
8
  </div>
9
- <div class="mt-2 text-gray-700">
9
+ <div v-if="loading" class="mt-2">
10
+ <img src="images/loader.gif" class="inline w-16 h-16">
11
+ </div>
12
+ <div class="mt-2 text-gray-700" v-if="!loading">
10
13
  {{workspaceName}}
11
14
  </div>
12
- <div class="mt-4">
15
+ <div class="mt-4" v-if="!loading">
13
16
  <async-button
14
17
  type="button"
15
18
  @click="loginWithGithub"
@@ -17,7 +20,7 @@
17
20
  Login With GitHub
18
21
  </async-button>
19
22
  </div>
20
- <div class="mt-4" v-if="error">
23
+ <div class="mt-4" v-if="state.authError">
21
24
  <div class="rounded-md bg-red-50 p-4">
22
25
  <div class="flex">
23
26
  <div class="shrink-0">
@@ -26,7 +29,7 @@
26
29
  </svg>
27
30
  </div>
28
31
  <div class="ml-3">
29
- <h3 class="text-sm font-medium text-red-800">{{error}}</h3>
32
+ <h3 class="text-sm font-medium text-red-800">{{state.authError}}</h3>
30
33
  </div>
31
34
  </div>
32
35
  </div>
@@ -6,25 +6,13 @@ const template = require('./splash.html');
6
6
  module.exports = app => app.component('splash', {
7
7
  template,
8
8
  inject: ['state'],
9
+ props: ['loading'],
9
10
  data: () => ({ error: null }),
10
11
  computed: {
11
12
  workspaceName() {
12
13
  return config__workspace.name;
13
14
  }
14
15
  },
15
- async mounted() {
16
- const href = window.location.href;
17
- if (href.match(/\?code=([a-zA-Z0-9]+)$/)) {
18
- const code = href.match(/\?code=([a-zA-Z0-9]+)$/)[1];
19
- const { accessToken, user, roles } = await mothership.github(code);
20
- if (roles == null) {
21
- this.error = 'You are not authorized to access this workspace';
22
- return;
23
- }
24
- this.state.user = user;
25
- window.localStorage.setItem('_mongooseStudioAccessToken', accessToken._id);
26
- }
27
- },
28
16
  methods: {
29
17
  async loginWithGithub() {
30
18
  const { url } = await mothership.githubLogin();
@@ -1,23 +1,75 @@
1
- <div class="mx-auto max-w-5xl py-6 px-2">
2
- <div class="text-xl font-bold">
3
- Current Members
4
- </div>
5
- <ul role="list" class="divide-y divide-gray-100">
6
- <li class="flex justify-between gap-x-6 py-5" v-for="user in users">
7
- <div class="flex min-w-0 gap-x-4">
8
- <img class="size-12 flex-none rounded-full bg-gray-50" :src="user.picture ?? 'images/logo.svg'" alt="">
9
- <div class="min-w-0 flex-auto">
10
- <p class="text-sm/6 font-semibold text-gray-900">{{user.name}}</p>
11
- <p class="mt-1 truncate text-xs/5 text-gray-500">{{user.email}}</p>
1
+ <div class="mx-auto max-w-5xl py-6 px-2 flex flex-col gap-8">
2
+ <div>
3
+ <div class="text-xl font-bold">
4
+ Subscription Details
5
+ </div>
6
+ <div v-if="workspace && workspace.subscriptionTier" class="mt-4 flex justify-between items-center">
7
+ <div>
8
+ <span class="font-bold">Tier:</span> {{workspace.subscriptionTier ?? 'No subscription'}}
9
+ </div>
10
+ <div>
11
+ <async-button
12
+ type="submit"
13
+ @click="getWorkspaceCustomerPortalLink"
14
+ class="inline-flex items-center justify-center rounded-md border border-transparent bg-ultramarine-600 py-1 px-2 text-sm font-medium text-white shadow-sm hover:bg-ultramarine-500 focus:outline-none focus:ring-2 focus:ring-forest-green-500 focus:ring-offset-2">
15
+ View in Stripe
16
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 ml-1">
17
+ <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
18
+ </svg>
19
+ </async-button>
20
+ </div>
21
+ </div>
22
+ <div v-if="workspace && !workspace.subscriptionTier" class="mt-4 flex justify-between items-center">
23
+ <div>
24
+ <span class="font-bold">No active subscription</span>
25
+ <div class="text-sm text-gray-700">
26
+ You won't be able to invite your team until you activate a subscription
12
27
  </div>
13
28
  </div>
14
- <div class="hidden shrink-0 sm:flex sm:flex-col sm:items-end">
15
- <p class="text-sm/6 text-gray-900 capitalize">{{getRolesForUser(user).join(', ')}}</p>
16
- <p class="mt-1 text-xs/5 text-gray-500">Last seen <time datetime="2023-01-23T13:23Z">3h ago</time></p>
29
+ <div>
30
+ <a
31
+ :href="paymentLink"
32
+ target="_blank"
33
+ class="inline-flex items-center justify-center rounded-md border border-transparent bg-ultramarine-600 py-1 px-2 text-sm font-medium text-white shadow-sm hover:bg-ultramarine-500 focus:outline-none focus:ring-2 focus:ring-ultramarine-500 focus:ring-offset-2">
34
+ Subscribe With Stripe
35
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 ml-1">
36
+ <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
37
+ </svg>
38
+ </a>
17
39
  </div>
18
- </li>
19
- </ul>
20
- <div class="mt-6">
40
+ </div>
41
+ </div>
42
+ <div>
43
+ <div class="text-xl font-bold">
44
+ Current Members
45
+ </div>
46
+ <ul role="list" class="divide-y divide-gray-100">
47
+ <li class="flex justify-between gap-x-6 py-5" v-for="user in users">
48
+ <div class="flex min-w-0 gap-x-4">
49
+ <img class="size-12 flex-none rounded-full bg-gray-50" :src="user.picture ?? 'images/logo.svg'" alt="">
50
+ <div class="min-w-0 flex-auto">
51
+ <p class="text-sm/6 font-semibold text-gray-900">
52
+ {{user.name}}
53
+ <span v-if="user.isFreeUser" class="inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20">Free</span>
54
+ </p>
55
+ <p class="mt-1 truncate text-xs/5 text-gray-500">{{user.email ?? 'No Email'}}</p>
56
+ </div>
57
+ </div>
58
+ <div class="hidden shrink-0 sm:flex sm:flex-col sm:items-end">
59
+ <p class="text-sm/6 text-gray-900 capitalize">{{getRolesForUser(user).join(', ')}}</p>
60
+ <div class="flex gap-3">
61
+ <p class="mt-1 text-xs/5 text-gray-500 cursor-pointer">
62
+ Edit
63
+ </p>
64
+ <p class="mt-1 text-xs/5 text-valencia-500 cursor-pointer" @click="showRemoveModal = user">
65
+ Remove
66
+ </p>
67
+ </div>
68
+ </div>
69
+ </li>
70
+ </ul>
71
+ </div>
72
+ <div>
21
73
  <div class="flex items-center justify-between">
22
74
  <div class="text-xl font-bold">
23
75
  Invitations
@@ -26,8 +78,12 @@
26
78
  <button
27
79
  type="button"
28
80
  @click="showNewInvitationModal = true"
29
- class="block rounded-md bg-ultramarine-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
81
+ :disabled="workspace && !workspace.subscriptionTier"
82
+ class="block rounded-md bg-ultramarine-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 disabled:bg-gray-500 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
30
83
  New Invitation
84
+ <svg class="inline w-4 h-4 ml-1" v-if="workspace && !workspace.subscriptionTier" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
85
+ <path fill-rule="evenodd" d="M12 1.5a5.25 5.25 0 00-5.25 5.25v3a3 3 0 00-3 3v6.75a3 3 0 003 3h10.5a3 3 0 003-3v-6.75a3 3 0 00-3-3v-3c0-2.9-2.35-5.25-5.25-5.25zm3.75 8.25v-3a3.75 3.75 0 10-7.5 0v3h7.5z" clip-rule="evenodd" />
86
+ </svg>
31
87
  </button>
32
88
  </div>
33
89
  </div>
@@ -83,4 +139,24 @@
83
139
  <new-invitation @close="showNewInvitationModal = false" @invitationCreated="invitations.push($event.invitation)"></new-invitation>
84
140
  </template>
85
141
  </modal>
142
+
143
+ <modal v-if="showRemoveModal">
144
+ <template v-slot:body>
145
+ <div class="modal-exit" @click="showRemoveModal = false">&times;</div>
146
+ <div>
147
+ Are you sure you want to remove user <span class="font-bold">{{showRemoveModal.githubUsername}}</span> from this workspace?
148
+ </div>
149
+ <div class="mt-6 grid grid-cols-2 gap-4">
150
+ <async-button
151
+ @click="removeFromWorkspace(showConfirmDeleteModal)"
152
+ class="border-0 mt-0 flex w-full items-center justify-center gap-3 rounded-md bg-valencia-500 hover:bg-valencia-400 px-3 py-1.5 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-orange-400">
153
+ <span class="text-sm font-semibold leading-6">Yes, Remove</span>
154
+ </async-button>
155
+
156
+ <span @click="showRemoveModal = null" class="cursor-pointer flex w-full items-center justify-center gap-3 rounded-md bg-slate-500 hover:bg-slate-400 px-3 py-1.5 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-400">
157
+ <span class="text-sm font-semibold leading-6">Cancel</span>
158
+ </span>
159
+ </div>
160
+ </template>
161
+ </modal>
86
162
  </div>
@@ -9,7 +9,8 @@ module.exports = app => app.component('team', {
9
9
  workspace: null,
10
10
  users: null,
11
11
  invitations: null,
12
- showNewInvitationModal: false
12
+ showNewInvitationModal: false,
13
+ showRemoveModal: null
13
14
  }),
14
15
  async mounted() {
15
16
  const { workspace, users, invitations } = await mothership.getWorkspaceTeam();
@@ -17,9 +18,24 @@ module.exports = app => app.component('team', {
17
18
  this.users = users;
18
19
  this.invitations = invitations;
19
20
  },
21
+ computed: {
22
+ paymentLink() {
23
+ return 'https://buy.stripe.com/test_eVaeYa2jC7565Lq7ss?client_reference_id=' + this.workspace?._id;
24
+ }
25
+ },
20
26
  methods: {
21
27
  getRolesForUser(user) {
22
28
  return this.workspace.members.find(member => member.userId === user._id)?.roles ?? [];
29
+ },
30
+ async removeFromWorkspace() {
31
+ const { workspace, users } = await mothership.removeFromWorkspace({ userId: this.showRemoveModal._id });
32
+ this.workspace = workspace;
33
+ this.users = users;
34
+ this.showRemoveModal = false;
35
+ },
36
+ async getWorkspaceCustomerPortalLink() {
37
+ const { url } = await mothership.getWorkspaceCustomerPortalLink();
38
+ window.open(url, '_self');
23
39
  }
24
40
  }
25
41
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongoosejs/studio",
3
- "version": "0.0.60",
3
+ "version": "0.0.62",
4
4
  "dependencies": {
5
5
  "archetype": "0.13.1",
6
6
  "csv-stringify": "6.3.0",