@mongoosejs/studio 0.0.68 → 0.0.70

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.
package/frontend/index.js CHANGED
@@ -33,7 +33,7 @@ module.exports = async function frontend(apiUrl, isLambda, options, workspace) {
33
33
  const config = {
34
34
  baseURL: apiUrl,
35
35
  isLambda,
36
- mothershipUrl: mothershipUrl ?? '',
36
+ mothershipUrl: apiKey ? mothershipUrl : null,
37
37
  workspace: workspaceData
38
38
  };
39
39
 
@@ -42,9 +42,8 @@ module.exports = async function frontend(apiUrl, isLambda, options, workspace) {
42
42
  fs.writeFileSync(configPath, `window.MONGOOSE_STUDIO_CONFIG = ${JSON.stringify(config, null, 2)};`);
43
43
  }
44
44
 
45
- const compiler = webpack(webpackConfig);
46
-
47
- if (options && options.watch) {
45
+ if (options && options.__watch) {
46
+ const compiler = webpack(webpackConfig);
48
47
  compiler.watch({}, (err) => {
49
48
  if (err) {
50
49
  process.nextTick(() => { throw new Error('Error compiling bundle: ' + err.stack); });
@@ -55,7 +54,8 @@ module.exports = async function frontend(apiUrl, isLambda, options, workspace) {
55
54
  const childProcess = exec('npm run tailwind:watch');
56
55
  childProcess.stdout.on('data', data => console.log('[TAILWIND]', data));
57
56
  childProcess.stderr.on('data', data => console.log('[TAILWIND]', data));
58
- } else {
57
+ } else if (options && options.__build) {
58
+ const compiler = webpack(webpackConfig);
59
59
  await new Promise((resolve, reject) => {
60
60
  compiler.run((err) => {
61
61
  if (err) {
@@ -16,7 +16,7 @@ const client = axios.create({
16
16
  baseURL: window.MONGOOSE_STUDIO_CONFIG.baseURL
17
17
  });
18
18
 
19
- console.log('API baseURL', window.MONGOOSE_STUDIO_CONFIG.baseURL);
19
+ console.log('API baseURL:', window.MONGOOSE_STUDIO_CONFIG.baseURL);
20
20
 
21
21
  window.apiClient = client;
22
22
  client.interceptors.request.use(req => {
@@ -1927,6 +1927,8 @@ const client = axios.create({
1927
1927
  baseURL: window.MONGOOSE_STUDIO_CONFIG.mothershipUrl
1928
1928
  });
1929
1929
 
1930
+ console.log('Mothership baseURL:', window.MONGOOSE_STUDIO_CONFIG.mothershipUrl);
1931
+
1930
1932
  client.hasAPIKey = !!window.MONGOOSE_STUDIO_CONFIG.mothershipUrl;
1931
1933
 
1932
1934
  client.interceptors.request.use(req => {
@@ -2184,6 +2186,8 @@ module.exports = app => app.component('team', {
2184
2186
  status: 'loading'
2185
2187
  }),
2186
2188
  async mounted() {
2189
+ window.pageState = this;
2190
+
2187
2191
  const { workspace, users, invitations } = await mothership.getWorkspaceTeam();
2188
2192
  this.workspace = workspace;
2189
2193
  this.users = users;
@@ -2192,7 +2196,8 @@ module.exports = app => app.component('team', {
2192
2196
  },
2193
2197
  computed: {
2194
2198
  paymentLink() {
2195
- return 'https://buy.stripe.com/test_eVaeYa2jC7565Lq7ss?client_reference_id=' + this.workspace?._id;
2199
+ return 'https://buy.stripe.com/3csaFg8XTdd0d6U7sy?client_reference_id=' + this.workspace?._id;
2200
+ // return 'https://buy.stripe.com/test_eVaeYa2jC7565Lq7ss?client_reference_id=' + this.workspace?._id;
2196
2201
  }
2197
2202
  },
2198
2203
  methods: {
@@ -2921,7 +2926,7 @@ module.exports = "<div class=\"py-2\">\n <div v-if=\"header\" class=\"border-b
2921
2926
  /***/ ((module) => {
2922
2927
 
2923
2928
  "use strict";
2924
- module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"status === 'loading'\" class=\"max-w-5xl mx-auto text-center\">\n <img src=\"images/loader.gif\" class=\"inline mt-10\">\n </div>\n <div v-if=\"dashboard && status === 'loaded'\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center w-full\">\n <h2 class=\"mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink\">{{title}}</h2>\n <div>\n <button\n v-if=\"!showEditor\"\n @click=\"showEditor = true\"\n type=\"button\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <img src=\"images/edit.svg\" class=\"inline h-[1em]\" /> Edit\n </button>\n </div>\n </div>\n <div v-if=\"!showEditor\" class=\"mt-4 mb-4\">\n <dashboard-result :result=\"result\"></dashboard-result>\n </div>\n <div v-if=\"showEditor\">\n <edit-dashboard\n :dashboardId=\"dashboard._id\"\n :code=\"code\"\n :currentDescription=\"description\"\n :currentTitle=\"title\"\n @close=\"showEditor=false;\"\n @update=\"updateCode\"></edit-dashboard>\n </div>\n <div v-if=\"errorMessage\" class=\"rounded-md bg-red-50 p-4 mt-4\">\n <div class=\"flex\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-red-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM8.28 7.22a.75.75 0 0 0-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 1 0 1.06 1.06L10 11.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L11.06 10l1.72-1.72a.75.75 0 0 0-1.06-1.06L10 8.94 8.28 7.22Z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3\">\n <h3 class=\"text-sm font-medium text-red-800\">{{errorMessage}}</h3>\n </div>\n </div>\n </div>\n\n </div>\n <div v-if=\"!dashboard && status === 'loaded'\">\n No dashboard with the given id could be found.\n </div>\n</div>\n";
2929
+ module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"status === 'loading'\" class=\"max-w-5xl mx-auto text-center\">\n <img src=\"images/loader.gif\" class=\"inline mt-10\">\n </div>\n <div v-if=\"dashboard && status === 'loaded'\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center w-full\" v-if=\"!showEditor\">\n <h2 class=\"mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink\">{{title}}</h2>\n <div>\n <button\n @click=\"showEditor = true\"\n type=\"button\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <img src=\"images/edit.svg\" class=\"inline h-[1em]\" /> Edit\n </button>\n </div>\n </div>\n <div v-if=\"!showEditor\" class=\"mt-4 mb-4\">\n <dashboard-result :result=\"result\"></dashboard-result>\n </div>\n <div v-if=\"showEditor\" class=\"mt-4\">\n <edit-dashboard\n :dashboardId=\"dashboard._id\"\n :code=\"code\"\n :currentDescription=\"description\"\n :currentTitle=\"title\"\n @close=\"showEditor=false;\"\n @update=\"updateCode\"></edit-dashboard>\n </div>\n <div v-if=\"errorMessage\" class=\"rounded-md bg-red-50 p-4 mt-4\">\n <div class=\"flex\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-red-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM8.28 7.22a.75.75 0 0 0-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 1 0 1.06 1.06L10 11.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L11.06 10l1.72-1.72a.75.75 0 0 0-1.06-1.06L10 8.94 8.28 7.22Z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3\">\n <h3 class=\"text-sm font-medium text-red-800\">{{errorMessage}}</h3>\n </div>\n </div>\n </div>\n\n </div>\n <div v-if=\"!dashboard && status === 'loaded'\">\n No dashboard with the given id could be found.\n </div>\n</div>\n";
2925
2930
 
2926
2931
  /***/ }),
2927
2932
 
@@ -2932,7 +2937,7 @@ module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"status === 'load
2932
2937
  /***/ ((module) => {
2933
2938
 
2934
2939
  "use strict";
2935
- module.exports = "<div class=\"p-4 bg-gray-100 rounded-lg shadow-lg\">\n <div v-show=\"status === 'loading'\" class=\"max-w-5xl mx-auto text-center\">\n <img src=\"images/loader.gif\" class=\"inline mt-10\">\n </div>\n <div v-show=\"status !== 'loading'\">\n <div>\n <input v-model=\"title\" class=\"w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" placeholder=\"Title\"/>\n </div>\n <div>\n <textarea v-model=\"description\" class=\"w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" rows=\"4\" placeholder=\"Description\">{{description}}</textarea>\n </div>\n <div>\n <textarea ref=\"codeEditor\" class=\"w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" rows=\"6\">{{code}}</textarea>\n </div>\n <div class=\"flex space-x-2\">\n <async-button @click=\"updateCode\" class=\"px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500\">Submit</async-button>\n <button @click=\"closeEditor\" class=\"px-4 py-2 bg-gray-500 text-white rounded-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-500\">Cancel</button>\n </div>\n </div>\n</div>";
2940
+ module.exports = "<div class=\"p-4 bg-gray-100 rounded-lg shadow-lg\">\n <div v-show=\"status === 'loading'\" class=\"max-w-5xl mx-auto text-center\">\n <img src=\"images/loader.gif\" class=\"inline mt-10\">\n </div>\n <div v-show=\"status !== 'loading'\" class=\"flex flex-col gap-4\">\n <div>\n <input v-model=\"title\" class=\"w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" placeholder=\"Title\"/>\n </div>\n <div>\n <textarea v-model=\"description\" class=\"w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" rows=\"4\" placeholder=\"Description\">{{description}}</textarea>\n </div>\n <div class=\"border border-gray-300 rounded-md\">\n <textarea ref=\"codeEditor\" class=\"w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" rows=\"6\">{{code}}</textarea>\n <textarea v-model=\"chatMessage\" class=\"w-full p-2\"></textarea>\n </div>\n <div class=\"flex space-x-2\">\n <async-button @click=\"updateCode\" class=\"px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500\">Submit</async-button>\n <button @click=\"closeEditor\" class=\"px-4 py-2 bg-gray-500 text-white rounded-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-500\">Cancel</button>\n </div>\n </div>\n</div>\n";
2936
2941
 
2937
2942
  /***/ }),
2938
2943
 
@@ -3372,7 +3377,7 @@ module.exports = "<div class=\"p-1\">\n <form class=\"space-y-4\">\n <div cl
3372
3377
  /***/ ((module) => {
3373
3378
 
3374
3379
  "use strict";
3375
- module.exports = "<div class=\"mx-auto max-w-5xl py-6 px-2 flex flex-col gap-8\">\n <div>\n <div class=\"text-xl font-bold\">\n Subscription Details\n </div>\n <div v-if=\"status === 'loading'\" class=\"mt-4\">\n <img src=\"images/loader.gif\" class=\"inline w-8 h-8\">\n </div>\n <div v-else-if=\"workspace && workspace.subscriptionTier\" class=\"mt-4 flex justify-between items-center\">\n <div>\n <span class=\"font-bold\">Tier:</span> {{workspace.subscriptionTier ?? 'No subscription'}}\n </div>\n <div>\n <async-button\n type=\"submit\"\n @click=\"getWorkspaceCustomerPortalLink\"\n 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\">\n View in Stripe\n <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\">\n <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\" />\n </svg>\n </async-button>\n </div>\n </div>\n <div v-else-if=\"workspace && !workspace.subscriptionTier\" class=\"mt-4 flex justify-between items-center\">\n <div>\n <span class=\"font-bold\">No active subscription</span>\n <div class=\"text-sm text-gray-700\">\n You won't be able to invite your team until you activate a subscription\n </div>\n </div>\n <div>\n <a\n :href=\"paymentLink\"\n target=\"_blank\"\n 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\">\n Subscribe With Stripe\n <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\">\n <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\" />\n </svg>\n </a>\n </div>\n </div>\n </div>\n <div>\n <div class=\"text-xl font-bold\">\n Current Members\n </div>\n <div v-if=\"status === 'loading'\" class=\"mt-4\">\n <img src=\"images/loader.gif\" class=\"inline w-8 h-8\">\n </div>\n <ul v-else role=\"list\" class=\"divide-y divide-gray-100\">\n <li class=\"flex justify-between gap-x-6 py-5\" v-for=\"user in users\">\n <div class=\"flex min-w-0 gap-x-4\">\n <img class=\"size-12 flex-none rounded-full bg-gray-50\" :src=\"user.picture ?? 'images/logo.svg'\" alt=\"\">\n <div class=\"min-w-0 flex-auto\">\n <p class=\"text-sm/6 font-semibold text-gray-900\">\n {{user.name}}\n <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>\n </p>\n <p class=\"mt-1 truncate text-xs/5 text-gray-500\">{{user.email ?? 'No Email'}}</p>\n </div>\n </div>\n <div class=\"hidden shrink-0 sm:flex sm:flex-col sm:items-end\">\n <p class=\"text-sm/6 text-gray-900 capitalize\">{{getRolesForUser(user).join(', ')}}</p>\n <div class=\"flex gap-3\">\n <p class=\"mt-1 text-xs/5 text-gray-500 cursor-pointer\">\n Edit\n </p>\n <p class=\"mt-1 text-xs/5 text-valencia-500 cursor-pointer\" @click=\"showRemoveModal = user\">\n Remove\n </p>\n </div>\n </div>\n </li>\n </ul>\n </div>\n <div>\n <div class=\"flex items-center justify-between\">\n <div class=\"text-xl font-bold\">\n Invitations\n </div>\n <div class=\"mt-4 sm:ml-16 sm:mt-0 sm:flex-none\">\n <button\n type=\"button\"\n @click=\"showNewInvitationModal = true\"\n :disabled=\"status === 'loading' || (workspace && !workspace.subscriptionTier)\"\n 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\">\n New Invitation\n <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\">\n <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\" />\n </svg>\n </button>\n </div>\n </div>\n <div v-if=\"status === 'loading'\" class=\"mt-4\">\n <img src=\"images/loader.gif\" class=\"inline w-8 h-8\">\n </div>\n <div v-else-if=\"invitations?.length > 0\" class=\"mt-8 flow-root\" v-if=\"invitations?.length > 0\">\n <div class=\"-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8\">\n <div class=\"inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8\">\n <table class=\"min-w-full divide-y divide-gray-300\">\n <thead>\n <tr>\n <th scope=\"col\" class=\"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0\">GitHub Username</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900\">Email</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900\">Status</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900\">Role</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200 bg-white\">\n <tr v-for=\"invitation in invitations\">\n <td class=\"whitespace-nowrap py-5 pl-4 pr-3 text-sm sm:pl-0\">\n {{invitation.githubUsername}}\n </td>\n <td class=\"whitespace-nowrap px-3 py-5 text-sm text-gray-500\">\n {{invitation.email}}\n </td>\n <td class=\"whitespace-nowrap px-3 py-5 text-sm text-gray-500\">\n <span class=\"inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-600/20\">\n Pending\n </span>\n </td>\n <td class=\"whitespace-nowrap px-3 py-5 text-sm text-gray-500\">\n {{invitation.roles.join(', ')}}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n <div v-else-if=\"invitations?.length === 0\" class=\"mt-4\">\n <div class=\"text-center\">\n <svg class=\"mx-auto size-12 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path vector-effect=\"non-scaling-stroke\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z\" />\n </svg>\n <h3 class=\"mt-2 text-sm font-semibold text-gray-900\">No invitations</h3>\n <p class=\"mt-1 text-sm text-gray-500\">You have no outstanding invitations</p>\n </div>\n </div>\n </div>\n\n <modal v-if=\"showNewInvitationModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"showNewInvitationModal = false\">&times;</div>\n <new-invitation @close=\"showNewInvitationModal = false\" @invitationCreated=\"invitations.push($event.invitation)\"></new-invitation>\n </template>\n </modal>\n\n <modal v-if=\"showRemoveModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"showRemoveModal = false\">&times;</div>\n <div>\n Are you sure you want to remove user <span class=\"font-bold\">{{showRemoveModal.githubUsername}}</span> from this workspace?\n </div>\n <div class=\"mt-6 grid grid-cols-2 gap-4\">\n <async-button\n @click=\"removeFromWorkspace(showConfirmDeleteModal)\"\n 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\">\n <span class=\"text-sm font-semibold leading-6\">Yes, Remove</span>\n </async-button>\n\n <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\">\n <span class=\"text-sm font-semibold leading-6\">Cancel</span>\n </span>\n </div>\n </template>\n </modal>\n</div>\n";
3380
+ module.exports = "<div class=\"mx-auto max-w-5xl py-6 px-2 flex flex-col gap-8\">\n <div>\n <div class=\"text-xl font-bold\">\n Subscription Details\n </div>\n <div v-if=\"status === 'loading'\" class=\"mt-4\">\n <img src=\"images/loader.gif\" class=\"inline w-8 h-8\">\n </div>\n <div v-else-if=\"workspace && workspace.subscriptionTier\" class=\"mt-4 flex justify-between items-center\">\n <div>\n <span class=\"font-bold\">Tier:</span> {{workspace.subscriptionTier ?? 'No subscription'}}\n </div>\n <div>\n <async-button\n type=\"submit\"\n @click=\"getWorkspaceCustomerPortalLink\"\n 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\">\n View in Stripe\n <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\">\n <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\" />\n </svg>\n </async-button>\n </div>\n </div>\n <div v-else-if=\"workspace && !workspace.subscriptionTier\" class=\"mt-4 flex justify-between items-center\">\n <div>\n <span class=\"font-bold\">No active subscription</span>\n <div class=\"text-sm text-gray-700\">\n You won't be able to invite your team until you activate a subscription\n </div>\n </div>\n <div>\n <a\n :href=\"paymentLink\"\n target=\"_blank\"\n 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\">\n Subscribe With Stripe\n <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\">\n <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\" />\n </svg>\n </a>\n </div>\n </div>\n </div>\n <div>\n <div class=\"text-xl font-bold\">\n Current Members\n </div>\n <div v-if=\"status === 'loading'\" class=\"mt-4\">\n <img src=\"images/loader.gif\" class=\"inline w-8 h-8\">\n </div>\n <ul v-else role=\"list\" class=\"divide-y divide-gray-100\">\n <li class=\"flex justify-between gap-x-6 py-5\" v-for=\"user in users\">\n <div class=\"flex min-w-0 gap-x-4\">\n <img class=\"size-12 flex-none rounded-full bg-gray-50\" :src=\"user.picture ?? 'images/logo.svg'\" alt=\"\">\n <div class=\"min-w-0 flex-auto\">\n <p class=\"text-sm/6 font-semibold text-gray-900\">\n {{user.name || user.githubUsername}}\n <span v-if=\"user.isFreeUser\" class=\"ml-1 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>\n </p>\n <p class=\"mt-1 truncate text-xs/5 text-gray-500\">{{user.email ?? 'No Email'}}</p>\n </div>\n </div>\n <div class=\"hidden shrink-0 sm:flex sm:flex-col sm:items-end\">\n <p class=\"text-sm/6 text-gray-900 capitalize\">{{getRolesForUser(user).join(', ')}}</p>\n <div class=\"flex gap-3\">\n <p class=\"mt-1 text-xs/5 text-gray-500 cursor-pointer\">\n Edit\n </p>\n <button\n class=\"mt-1 text-xs/5 text-valencia-500 cursor-pointer disabled:cursor-not-allowed disabled:text-gray-300\"\n :disabled=\"getRolesForUser(user).includes('owner')\"\n @click=\"showRemoveModal = user\">\n Remove\n </button>\n </div>\n </div>\n </li>\n </ul>\n </div>\n <div>\n <div class=\"flex items-center justify-between\">\n <div class=\"text-xl font-bold\">\n Invitations\n </div>\n <div class=\"mt-4 sm:ml-16 sm:mt-0 sm:flex-none\">\n <button\n type=\"button\"\n @click=\"showNewInvitationModal = true\"\n :disabled=\"status === 'loading' || (workspace && !workspace.subscriptionTier)\"\n 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\">\n New Invitation\n <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\">\n <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\" />\n </svg>\n </button>\n </div>\n </div>\n <div v-if=\"status === 'loading'\" class=\"mt-4\">\n <img src=\"images/loader.gif\" class=\"inline w-8 h-8\">\n </div>\n <div v-else-if=\"invitations?.length > 0\" class=\"mt-8 flow-root\" v-if=\"invitations?.length > 0\">\n <div class=\"-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8\">\n <div class=\"inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8\">\n <table class=\"min-w-full divide-y divide-gray-300\">\n <thead>\n <tr>\n <th scope=\"col\" class=\"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0\">GitHub Username</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900\">Email</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900\">Status</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900\">Role</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200 bg-white\">\n <tr v-for=\"invitation in invitations\">\n <td class=\"whitespace-nowrap py-5 pl-4 pr-3 text-sm sm:pl-0\">\n {{invitation.githubUsername}}\n </td>\n <td class=\"whitespace-nowrap px-3 py-5 text-sm text-gray-500\">\n {{invitation.email}}\n </td>\n <td class=\"whitespace-nowrap px-3 py-5 text-sm text-gray-500\">\n <span class=\"inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-600/20\">\n Pending\n </span>\n </td>\n <td class=\"whitespace-nowrap px-3 py-5 text-sm text-gray-500\">\n {{invitation.roles.join(', ')}}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n <div v-else-if=\"invitations?.length === 0\" class=\"mt-4\">\n <div class=\"text-center\">\n <svg class=\"mx-auto size-12 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path vector-effect=\"non-scaling-stroke\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z\" />\n </svg>\n <h3 class=\"mt-2 text-sm font-semibold text-gray-900\">No invitations</h3>\n <p class=\"mt-1 text-sm text-gray-500\">You have no outstanding invitations</p>\n </div>\n </div>\n </div>\n\n <modal v-if=\"showNewInvitationModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"showNewInvitationModal = false\">&times;</div>\n <new-invitation @close=\"showNewInvitationModal = false\" @invitationCreated=\"invitations.push($event.invitation)\"></new-invitation>\n </template>\n </modal>\n\n <modal v-if=\"showRemoveModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"showRemoveModal = false\">&times;</div>\n <div>\n Are you sure you want to remove user <span class=\"font-bold\">{{showRemoveModal.githubUsername}}</span> from this workspace?\n </div>\n <div class=\"mt-6 grid grid-cols-2 gap-4\">\n <async-button\n @click=\"removeFromWorkspace(showConfirmDeleteModal)\"\n 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\">\n <span class=\"text-sm font-semibold leading-6\">Yes, Remove</span>\n </async-button>\n\n <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\">\n <span class=\"text-sm font-semibold leading-6\">Cancel</span>\n </span>\n </div>\n </template>\n </modal>\n</div>\n";
3376
3381
 
3377
3382
  /***/ }),
3378
3383
 
@@ -11272,14 +11277,24 @@ app.component('app-component', {
11272
11277
  const href = window.location.href;
11273
11278
  if (href.match(/\?code=([a-zA-Z0-9]+)$/)) {
11274
11279
  const code = href.match(/\?code=([a-zA-Z0-9]+)$/)[1];
11275
- const { accessToken, user, roles } = await mothership.github(code);
11276
- if (roles == null) {
11277
- this.authError = 'You are not authorized to access this workspace';
11280
+ try {
11281
+ const { accessToken, user, roles } = await mothership.github(code);
11282
+ if (roles == null) {
11283
+ this.authError = 'You are not authorized to access this workspace';
11284
+ return;
11285
+ }
11286
+ this.user = user;
11287
+ this.roles = roles;
11288
+ window.localStorage.setItem('_mongooseStudioAccessToken', accessToken._id);
11289
+ } catch (err) {
11290
+ this.authError = 'An error occurred while logging in. Please try again.';
11291
+ this.status = 'loaded';
11278
11292
  return;
11293
+ } finally {
11294
+ setTimeout(() => {
11295
+ this.$router.replace(this.$router.currentRoute.value.path);
11296
+ }, 0);
11279
11297
  }
11280
- this.user = user;
11281
- this.roles = roles;
11282
- window.localStorage.setItem('_mongooseStudioAccessToken', accessToken._id);
11283
11298
 
11284
11299
  const { nodeEnv } = await api.status();
11285
11300
  this.nodeEnv = nodeEnv;
@@ -1899,6 +1899,11 @@ video {
1899
1899
  background-color: rgb(107 114 128 / var(--tw-bg-opacity));
1900
1900
  }
1901
1901
 
1902
+ .disabled\:text-gray-300:disabled {
1903
+ --tw-text-opacity: 1;
1904
+ color: rgb(209 213 219 / var(--tw-text-opacity));
1905
+ }
1906
+
1902
1907
  @media (min-width: 640px) {
1903
1908
  .sm\:-mx-6 {
1904
1909
  margin-left: -1.5rem;
@@ -5,7 +5,7 @@ const client = axios.create({
5
5
  baseURL: window.MONGOOSE_STUDIO_CONFIG.mothershipUrl
6
6
  });
7
7
 
8
- console.log('Mothership baseURL:', window.MONGOOSE_STUDIO_CONFIG.baseURL);
8
+ console.log('Mothership baseURL:', window.MONGOOSE_STUDIO_CONFIG.mothershipUrl);
9
9
 
10
10
  client.hasAPIKey = !!window.MONGOOSE_STUDIO_CONFIG.mothershipUrl;
11
11
 
@@ -67,9 +67,12 @@
67
67
  <p class="mt-1 text-xs/5 text-gray-500 cursor-pointer">
68
68
  Edit
69
69
  </p>
70
- <p class="mt-1 text-xs/5 text-valencia-500 cursor-pointer" @click="showRemoveModal = user">
70
+ <button
71
+ class="mt-1 text-xs/5 text-valencia-500 cursor-pointer disabled:cursor-not-allowed disabled:text-gray-300"
72
+ :disabled="getRolesForUser(user).includes('owner')"
73
+ @click="showRemoveModal = user">
71
74
  Remove
72
- </p>
75
+ </button>
73
76
  </div>
74
77
  </div>
75
78
  </li>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongoosejs/studio",
3
- "version": "0.0.68",
3
+ "version": "0.0.70",
4
4
  "dependencies": {
5
5
  "archetype": "0.13.1",
6
6
  "csv-stringify": "6.3.0",