@mongoosejs/studio 0.0.60 → 0.0.61

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.
@@ -1794,8 +1794,25 @@ module.exports = app => app.component('models', {
1794
1794
  }).map(key => this.selectedPaths[key]);
1795
1795
  }
1796
1796
  },
1797
+ openFieldSelection() {
1798
+ if (this.$route.query?.fields) {
1799
+ this.selectedPaths.length = 0;
1800
+ console.log('there are fields in play', this.$route.query.fields)
1801
+ const fields = this.$route.query.fields.split(',');
1802
+ for (let i = 0; i < fields.length; i++) {
1803
+ this.selectedPaths.push({ path: fields[i] });
1804
+ }
1805
+ } else {
1806
+ this.selectedPaths = [{ path: '_id' }];
1807
+ }
1808
+ this.shouldShowFieldModal = true;
1809
+ },
1797
1810
  filterDocuments() {
1798
- this.filteredPaths = [...this.selectedPaths];
1811
+ if (this.selectedPaths.length > 0) {
1812
+ this.filteredPaths = [...this.selectedPaths];
1813
+ } else {
1814
+ this.filteredPaths.length = 0;
1815
+ }
1799
1816
  this.shouldShowFieldModal = false;
1800
1817
  const selectedParams = this.filteredPaths.map(x => x.path).join(',');
1801
1818
  this.query.fields = selectedParams;
@@ -1864,10 +1881,10 @@ module.exports = app => app.component('models', {
1864
1881
 
1865
1882
  const axios = __webpack_require__(/*! axios */ "./node_modules/axios/dist/browser/axios.cjs");
1866
1883
  const client = axios.create({
1867
- baseURL: 'http://localhost:8888/.netlify/functions'
1884
+ baseURL: 'https://mongoose-js.netlify.app/.netlify/functions'
1868
1885
  });
1869
1886
 
1870
- client.hasAPIKey = !!'http://localhost:8888/.netlify/functions';
1887
+ client.hasAPIKey = !!'https://mongoose-js.netlify.app/.netlify/functions';
1871
1888
 
1872
1889
  client.interceptors.request.use(req => {
1873
1890
  const accessToken = window.localStorage.getItem('_mongooseStudioAccessToken') || null;
@@ -1883,19 +1900,27 @@ exports.githubLogin = function githubLogin() {
1883
1900
  };
1884
1901
 
1885
1902
  exports.getWorkspaceTeam = function getWorkspaceTeam() {
1886
- return client.post('/getWorkspaceTeam', { workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]},{"userId":"67a91f3e5db099be8bd0f5c5","roles":["member"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-09T21:35:14.905Z","__v":1,"name":"Zevo DEV","subscriptionTier":"pro"}._id }).then(res => res.data);
1903
+ return client.post('/getWorkspaceTeam', { workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-17T21:53:20.548Z","__v":2,"name":"Zevo DEV","subscriptionTier":"pro","stripeCustomerId":"cus_RnCdSdRYLJQl4Z","stripeSubscriptionId":"sub_1QtcEgIIV4Jx8vgxY7z8cKeC"}._id }).then(res => res.data);
1887
1904
  };
1888
1905
 
1889
- exports.inviteToWorkspace = function inviteToWorkspace(params) {
1890
- return client.post('/inviteToWorkspace', { workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]},{"userId":"67a91f3e5db099be8bd0f5c5","roles":["member"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-09T21:35:14.905Z","__v":1,"name":"Zevo DEV","subscriptionTier":"pro"}._id, ...params }).then(res => res.data);
1906
+ exports.getWorkspaceCustomerPortalLink = function getWorkspaceCustomerPortalLink(params) {
1907
+ return client.post('/getWorkspaceCustomerPortalLink', { workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-17T21:53:20.548Z","__v":2,"name":"Zevo DEV","subscriptionTier":"pro","stripeCustomerId":"cus_RnCdSdRYLJQl4Z","stripeSubscriptionId":"sub_1QtcEgIIV4Jx8vgxY7z8cKeC"}._id, ...params }).then(res => res.data);
1891
1908
  };
1892
1909
 
1893
1910
  exports.github = function github(code) {
1894
- return client.post('/github', { code, workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]},{"userId":"67a91f3e5db099be8bd0f5c5","roles":["member"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-09T21:35:14.905Z","__v":1,"name":"Zevo DEV","subscriptionTier":"pro"}._id }).then(res => res.data);
1911
+ return client.post('/github', { code, workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-17T21:53:20.548Z","__v":2,"name":"Zevo DEV","subscriptionTier":"pro","stripeCustomerId":"cus_RnCdSdRYLJQl4Z","stripeSubscriptionId":"sub_1QtcEgIIV4Jx8vgxY7z8cKeC"}._id }).then(res => res.data);
1912
+ };
1913
+
1914
+ exports.inviteToWorkspace = function inviteToWorkspace(params) {
1915
+ return client.post('/inviteToWorkspace', { workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-17T21:53:20.548Z","__v":2,"name":"Zevo DEV","subscriptionTier":"pro","stripeCustomerId":"cus_RnCdSdRYLJQl4Z","stripeSubscriptionId":"sub_1QtcEgIIV4Jx8vgxY7z8cKeC"}._id, ...params }).then(res => res.data);
1895
1916
  };
1896
1917
 
1897
1918
  exports.me = function me() {
1898
- return client.post('/me', { workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]},{"userId":"67a91f3e5db099be8bd0f5c5","roles":["member"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-09T21:35:14.905Z","__v":1,"name":"Zevo DEV","subscriptionTier":"pro"}._id }).then(res => res.data);
1919
+ return client.post('/me', { workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-17T21:53:20.548Z","__v":2,"name":"Zevo DEV","subscriptionTier":"pro","stripeCustomerId":"cus_RnCdSdRYLJQl4Z","stripeSubscriptionId":"sub_1QtcEgIIV4Jx8vgxY7z8cKeC"}._id }).then(res => res.data);
1920
+ };
1921
+
1922
+ exports.removeFromWorkspace = function removeFromWorkspace(params) {
1923
+ return client.post('/removeFromWorkspace', { workspaceId: {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-17T21:53:20.548Z","__v":2,"name":"Zevo DEV","subscriptionTier":"pro","stripeCustomerId":"cus_RnCdSdRYLJQl4Z","stripeSubscriptionId":"sub_1QtcEgIIV4Jx8vgxY7z8cKeC"}._id, ...params }).then(res => res.data);
1899
1924
  };
1900
1925
 
1901
1926
  exports.hasAPIKey = client.hasAPIKey;
@@ -2042,7 +2067,7 @@ module.exports = app => app.component('splash', {
2042
2067
  data: () => ({ error: null }),
2043
2068
  computed: {
2044
2069
  workspaceName() {
2045
- return {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]},{"userId":"67a91f3e5db099be8bd0f5c5","roles":["member"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-09T21:35:14.905Z","__v":1,"name":"Zevo DEV","subscriptionTier":"pro"}.name;
2070
+ return {"_id":"67a5366c745bb0e6735950dc","ownerId":"679ba73e4cc3ddc28f6ef6af","baseUrl":"https://web.zevo.io","members":[{"userId":"679ba73e4cc3ddc28f6ef6af","roles":["owner"]}],"createdAt":"2025-02-06T22:23:40.903Z","updatedAt":"2025-02-17T21:53:20.548Z","__v":2,"name":"Zevo DEV","subscriptionTier":"pro","stripeCustomerId":"cus_RnCdSdRYLJQl4Z","stripeSubscriptionId":"sub_1QtcEgIIV4Jx8vgxY7z8cKeC"}.name;
2046
2071
  }
2047
2072
  },
2048
2073
  async mounted() {
@@ -2119,7 +2144,8 @@ module.exports = app => app.component('team', {
2119
2144
  workspace: null,
2120
2145
  users: null,
2121
2146
  invitations: null,
2122
- showNewInvitationModal: false
2147
+ showNewInvitationModal: false,
2148
+ showRemoveModal: null
2123
2149
  }),
2124
2150
  async mounted() {
2125
2151
  const { workspace, users, invitations } = await mothership.getWorkspaceTeam();
@@ -2127,9 +2153,32 @@ module.exports = app => app.component('team', {
2127
2153
  this.users = users;
2128
2154
  this.invitations = invitations;
2129
2155
  },
2156
+ computed: {
2157
+ paymentLink() {
2158
+ return 'https://buy.stripe.com/test_eVaeYa2jC7565Lq7ss?client_reference_id=' + this.workspace?._id;
2159
+ }
2160
+ },
2130
2161
  methods: {
2131
2162
  getRolesForUser(user) {
2132
2163
  return this.workspace.members.find(member => member.userId === user._id)?.roles ?? [];
2164
+ },
2165
+ async removeFromWorkspace() {
2166
+ const { workspace, users } = await mothership.removeFromWorkspace({ userId: this.showRemoveModal._id });
2167
+ this.workspace = workspace;
2168
+ this.users = users;
2169
+ this.showRemoveModal = false;
2170
+ },
2171
+ async getWorkspaceCustomerPortalLink() {
2172
+ const { url } = await mothership.getWorkspaceCustomerPortalLink();
2173
+ window.open(url, '_blank');
2174
+
2175
+ const interval = setInterval(async () => {
2176
+ const { workspace } = await mothership.getWorkspaceTeam();
2177
+ if (workspace.subscriptionTier) {
2178
+ this.workspace = workspace;
2179
+ clearInterval(interval);
2180
+ }
2181
+ }, 15000);
2133
2182
  }
2134
2183
  }
2135
2184
  });
@@ -3206,7 +3255,7 @@ module.exports = "<div class=\"list-subdocument tooltip\">\n <pre>\n <code r
3206
3255
  /***/ ((module) => {
3207
3256
 
3208
3257
  "use strict";
3209
- module.exports = "/** Vue modal */\n\n.modal-mask {\n position: fixed;\n z-index: 9998;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.5);\n display: table;\n transition: opacity 0.3s ease;\n}\n\n.modal-wrapper {\n display: table-cell;\n vertical-align: middle;\n}\n\n.modal-container {\n width: 600px;\n margin: 0px auto;\n padding: 20px 30px;\n padding-bottom: 40px;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);\n transition: all 0.3s ease;\n font-family: Helvetica, Arial, sans-serif;\n position: relative;\n}\n\n.modal-header {\n margin-top: 0;\n font-size: 18px;\n font-weight: bold;\n}\n\n.modal-header-success {\n color: #42b983;\n}\n\n.modal-header-error {\n color: #ff0000;\n}\n\n.modal-body {\n margin: 20px 0;\n max-height: calc(100vh - 40px - 60px - 10px);\n overflow: auto;\n}\n\n.modal__button--default {\n float: right;\n}\n\n/*\n * The following styles are auto-applied to elements with\n * transition=\"modal\" when their visibility is toggled\n * by Vue.js.\n *\n * You can easily play with the modal transition by editing\n * these styles.\n */\n\n.modal-enter {\n opacity: 0;\n}\n\n.modal-leave-active {\n opacity: 0;\n}\n\n.modal-enter .modal-container,\n.modal-leave-active .modal-container {\n -webkit-transform: scale(1.1);\n transform: scale(1.1);\n}\n\n.modal-container .modal-exit {\n position: absolute;\n right: 0.25em;\n top: 0.25em;\n cursor: pointer;\n font-size: 1.25em;\n height: 1.25em;\n width: 1.25em;\n border-radius: 100%;\n border: 1px solid #ddd;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-bottom: 0.25em;\n}\n";
3258
+ module.exports = "/** Vue modal */\n\n.modal-mask {\n position: fixed;\n z-index: 9998;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.5);\n display: table;\n transition: opacity 0.3s ease;\n}\n\n.modal-wrapper {\n display: table-cell;\n vertical-align: middle;\n}\n\n.modal-container {\n width: 600px;\n margin: 0px auto;\n padding: 20px 30px;\n padding-bottom: 40px;\n background-color: #fff;\n border-radius: 2px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);\n transition: all 0.3s ease;\n font-family: Helvetica, Arial, sans-serif;\n position: relative;\n}\n\n.modal-header {\n margin-top: 0;\n font-size: 18px;\n font-weight: bold;\n}\n\n.modal-header-success {\n color: #42b983;\n}\n\n.modal-header-error {\n color: #ff0000;\n}\n\n.modal-body {\n margin: 20px 0;\n max-height: calc(100vh - 40px - 60px - 10px);\n overflow: auto;\n}\n\n.modal__button--default {\n float: right;\n}\n\n/*\n * The following styles are auto-applied to elements with\n * transition=\"modal\" when their visibility is toggled\n * by Vue.js.\n *\n * You can easily play with the modal transition by editing\n * these styles.\n */\n\n.modal-enter {\n opacity: 0;\n}\n\n.modal-leave-active {\n opacity: 0;\n}\n\n.modal-enter .modal-container,\n.modal-leave-active .modal-container {\n -webkit-transform: scale(1.1);\n transform: scale(1.1);\n}\n\n.modal-container .modal-exit {\n position: absolute;\n right: 0.25em;\n top: 0.25em;\n cursor: pointer;\n font-size: 1.25em;\n height: 1.25em;\n width: 1.25em;\n border-radius: 100%;\n border: 1px solid #ddd;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-bottom: 0.25em;\n}\n\n.modal-container .modal-exit:hover {\n background-color: #f1f5ff;\n}\n";
3210
3259
 
3211
3260
  /***/ }),
3212
3261
 
@@ -3239,7 +3288,7 @@ module.exports = ".models {\n position: relative;\n display: flex;\n flex-dir
3239
3288
  /***/ ((module) => {
3240
3289
 
3241
3290
  "use strict";
3242
- module.exports = "<div class=\"models\">\n <div>\n <div class=\"flex grow flex-col gap-y-5 overflow-auto border-r border-gray-200 bg-white px-2 h-[calc(100vh-55px)] w-48\">\n <div class=\"flex font-bold font-xl mt-4 pl-2\">\n Models\n </div>\n <nav class=\"flex flex-1 flex-col\">\n <ul role=\"list\" class=\"flex flex-1 flex-col gap-y-7\">\n <li>\n <ul role=\"list\">\n <li v-for=\"model in models\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"block truncate rounded-md py-2 pr-2 pl-2 text-sm font-semibold text-gray-700\"\n :class=\"model === currentModel ? 'bg-ultramarine-100 font-bold' : 'hover:bg-ultramarine-100'\">\n {{model}}\n </router-link>\n </li>\n </ul>\n </li>\n </ul>\n </nav>\n </div>\n\n </div>\n <div class=\"documents\" ref=\"documentsList\">\n <div class=\"relative h-[42px]\">\n <div class=\"documents-menu\">\n <div class=\"flex flex-row items-center w-full gap-2\">\n <form @submit.prevent=\"search\" class=\"flex-grow m-0\">\n <input class=\"w-full rounded-md p-1 outline-gray-300 text-lg focus:ring-1 focus:ring-ultramarine-200 focus:ring-offset-0 focus:outline-none\" type=\"text\" placeholder=\"Filter or text\" v-model=\"searchText\" />\n </form>\n <div>\n <span v-if=\"status === 'loading'\">Loading ...</span>\n <span v-if=\"status === 'loaded'\">{{numDocuments === 1 ? numDocuments+ ' document' : numDocuments + ' documents'}}</span>\n </div>\n <button\n @click=\"shouldShowExportModal = true\"\n type=\"button\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 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\">\n Export\n </button>\n <button\n @click=\"shouldShowCreateModal = true;\"\n type=\"button\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 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\">\n Create\n </button>\n <button\n @click=\"shouldShowFieldModal = true\"\n type=\"button\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 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\">\n Fields\n </button>\n <span class=\"isolate inline-flex rounded-md shadow-sm\">\n <button\n @click=\"outputType = 'table'\"\n type=\"button\"\n class=\"relative inline-flex items-center rounded-none rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10\"\n :class=\"outputType === 'table' ? 'bg-gray-200' : 'bg-white'\">\n <img class=\"h-5 w-5\" src=\"images/table.svg\">\n </button>\n <button\n @click=\"outputType = 'json'\"\n type=\"button\"\n class=\"relative -ml-px inline-flex items-center rounded-none rounded-r-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10\"\n :class=\"outputType === 'json' ? 'bg-gray-200' : 'bg-white'\">\n <img class=\"h-5 w-5\" src=\"images/json.svg\">\n </button>\n </span>\n </div>\n </div>\n </div>\n <div class=\"documents-container relative\">\n <table v-if=\"outputType === 'table'\">\n <thead>\n <th v-for=\"path in filteredPaths\">\n {{path.path}}\n <span class=\"path-type\">\n ({{(path.instance || 'unknown')}})\n </span>\n <span class=\"sort-arrow\" @click=\"sortDocs(1, path.path)\">{{sortBy[path.path] == 1 ? 'X' : '↑'}}</span>\n <span class=\"sort-arrow\" @click=\"sortDocs(-1, path.path)\">{{sortBy[path.path] == -1 ? 'X' : '↓'}}</span>\n </th>\n </thead>\n <tbody>\n <tr v-for=\"document in documents\" @click=\"$router.push('/model/' + currentModel + '/document/' + document._id)\" :key=\"document._id\">\n <td v-for=\"schemaPath in filteredPaths\">\n <component\n :is=\"getComponentForPath(schemaPath)\"\n :value=\"getValueForPath(document, schemaPath.path)\"\n :allude=\"getReferenceModel(schemaPath)\">\n </component>\n </td>\n </tr>\n </tbody>\n </table>\n <div v-if=\"outputType === 'json'\">\n <div v-for=\"document in documents\" @click=\"$router.push('/model/' + currentModel + '/document/' + document._id)\" :key=\"document._id\">\n <list-json :value=\"filterDocument(document)\">\n </list-json>\n </div>\n </div>\n <div v-if=\"status === 'loading'\" class=\"loader\">\n <img src=\"images/loader.gif\">\n </div>\n </div>\n <modal v-if=\"shouldShowExportModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowExportModal = false\">&times;</div>\n <export-query-results\n :schemaPaths=\"schemaPaths\"\n :filter=\"filter\"\n :currentModel=\"currentModel\"\n @done=\"shouldShowExportModal = false\">\n </export-query-results>\n </template>\n </modal>\n <modal v-if=\"shouldShowFieldModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowFieldModal = false; selectedPaths = [...filteredPaths];\">&times;</div>\n <div v-for=\"(path, index) in schemaPaths\" :key=\"index\" style=\"margin-bottom: 0.5em\">\n <input type=\"checkbox\" :id=\"'path.path'+index\" @change=\"addOrRemove(path)\" :value=\"path.path\" :checked=\"isSelected(path.path)\" />\n <label :for=\"'path' + index\">{{path.path}}</label>\n </div>\n <div style=\"margin-top: 1em\">\n <button type=\"submit\" @click=\"filterDocuments()\" style=\"color: black;margin-right: 0.5em\">Filter Selection</button>\n <button type=\"submit\" @click=\"deselectAll()\" class=\"gray\" style=\"margin-right: 0.5em\">Deselect All</button>\n <button type=\"submit\" @click=\"resetDocuments()\" class=\"gray\">Cancel</button>\n\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowCreateModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCreateModal = false;\">&times;</div>\n <create-document :currentModel=\"currentModel\" :paths=\"schemaPaths\" @close=\"closeCreationModal\"></create-document>\n </template>\n </modal>\n </div>\n</div>\n";
3291
+ module.exports = "<div class=\"models\">\n <div>\n <div class=\"flex grow flex-col gap-y-5 overflow-auto border-r border-gray-200 bg-white px-2 h-[calc(100vh-55px)] w-48\">\n <div class=\"flex font-bold font-xl mt-4 pl-2\">\n Models\n </div>\n <nav class=\"flex flex-1 flex-col\">\n <ul role=\"list\" class=\"flex flex-1 flex-col gap-y-7\">\n <li>\n <ul role=\"list\">\n <li v-for=\"model in models\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"block truncate rounded-md py-2 pr-2 pl-2 text-sm font-semibold text-gray-700\"\n :class=\"model === currentModel ? 'bg-ultramarine-100 font-bold' : 'hover:bg-ultramarine-100'\">\n {{model}}\n </router-link>\n </li>\n </ul>\n </li>\n </ul>\n </nav>\n </div>\n\n </div>\n <div class=\"documents\" ref=\"documentsList\">\n <div class=\"relative h-[42px]\">\n <div class=\"documents-menu\">\n <div class=\"flex flex-row items-center w-full gap-2\">\n <form @submit.prevent=\"search\" class=\"flex-grow m-0\">\n <input class=\"w-full rounded-md p-1 border border-gray-300 outline-gray-300 text-lg focus:ring-1 focus:ring-ultramarine-200 focus:ring-offset-0 focus:outline-none\" type=\"text\" placeholder=\"Filter or text\" v-model=\"searchText\" />\n </form>\n <div>\n <span v-if=\"status === 'loading'\">Loading ...</span>\n <span v-if=\"status === 'loaded'\">{{numDocuments === 1 ? numDocuments+ ' document' : numDocuments + ' documents'}}</span>\n </div>\n <button\n @click=\"shouldShowExportModal = true\"\n type=\"button\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 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\">\n Export\n </button>\n <button\n @click=\"shouldShowCreateModal = true;\"\n type=\"button\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 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\">\n Create\n </button>\n <button\n @click=\"openFieldSelection\"\n type=\"button\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 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\">\n Fields\n </button>\n <span class=\"isolate inline-flex rounded-md shadow-sm\">\n <button\n @click=\"outputType = 'table'\"\n type=\"button\"\n class=\"relative inline-flex items-center rounded-none rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10\"\n :class=\"outputType === 'table' ? 'bg-gray-200' : 'bg-white'\">\n <img class=\"h-5 w-5\" src=\"images/table.svg\">\n </button>\n <button\n @click=\"outputType = 'json'\"\n type=\"button\"\n class=\"relative -ml-px inline-flex items-center rounded-none rounded-r-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10\"\n :class=\"outputType === 'json' ? 'bg-gray-200' : 'bg-white'\">\n <img class=\"h-5 w-5\" src=\"images/json.svg\">\n </button>\n </span>\n </div>\n </div>\n </div>\n <div class=\"documents-container relative\">\n <table v-if=\"outputType === 'table'\">\n <thead>\n <th v-for=\"path in filteredPaths\">\n {{path.path}}\n <span class=\"path-type\">\n ({{(path.instance || 'unknown')}})\n </span>\n <span class=\"sort-arrow\" @click=\"sortDocs(1, path.path)\">{{sortBy[path.path] == 1 ? 'X' : '↑'}}</span>\n <span class=\"sort-arrow\" @click=\"sortDocs(-1, path.path)\">{{sortBy[path.path] == -1 ? 'X' : '↓'}}</span>\n </th>\n </thead>\n <tbody>\n <tr v-for=\"document in documents\" @click=\"$router.push('/model/' + currentModel + '/document/' + document._id)\" :key=\"document._id\">\n <td v-for=\"schemaPath in filteredPaths\">\n <component\n :is=\"getComponentForPath(schemaPath)\"\n :value=\"getValueForPath(document, schemaPath.path)\"\n :allude=\"getReferenceModel(schemaPath)\">\n </component>\n </td>\n </tr>\n </tbody>\n </table>\n <div v-if=\"outputType === 'json'\">\n <div v-for=\"document in documents\" @click=\"$router.push('/model/' + currentModel + '/document/' + document._id)\" :key=\"document._id\">\n <list-json :value=\"filterDocument(document)\">\n </list-json>\n </div>\n </div>\n <div v-if=\"status === 'loading'\" class=\"loader\">\n <img src=\"images/loader.gif\">\n </div>\n </div>\n </div>\n\n <modal v-if=\"shouldShowExportModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowExportModal = false\">&times;</div>\n <export-query-results\n :schemaPaths=\"schemaPaths\"\n :filter=\"filter\"\n :currentModel=\"currentModel\"\n @done=\"shouldShowExportModal = false\">\n </export-query-results>\n </template>\n </modal>\n <modal v-if=\"shouldShowFieldModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowFieldModal = false; selectedPaths = [...filteredPaths];\">&times;</div>\n <div v-for=\"(path, index) in schemaPaths\" :key=\"index\" class=\"w-5 flex items-center\">\n <input class=\"mt-0 h-4 w-4 rounded border-gray-300 text-sky-600 focus:ring-sky-600 accent-sky-600\" type=\"checkbox\" :id=\"'path.path'+index\" @change=\"addOrRemove(path)\" :value=\"path.path\" :checked=\"isSelected(path.path)\" />\n <div class=\"ml-2 text-gray-700 grow shrink text-left\">\n <label :for=\"'path' + index\">{{path.path}}</label>\n </div>\n </div>\n <div class=\"mt-4 flex gap-2\">\n <button type=\"submit\" @click=\"filterDocuments()\" class=\"rounded-md bg-ultramarine-600 px-2.5 py-1.5 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-teal-600\">Filter Selection</button>\n <button type=\"submit\" @click=\"deselectAll()\" class=\"rounded-md bg-valencia-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-valencia-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600\">Deselect All</button>\n <button type=\"submit\" @click=\"resetDocuments()\" class=\"rounded-md bg-gray-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-gray-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600\" >Cancel</button>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowCreateModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCreateModal = false;\">&times;</div>\n <create-document :currentModel=\"currentModel\" :paths=\"schemaPaths\" @close=\"closeCreationModal\"></create-document>\n </template>\n </modal>\n</div>\n";
3243
3292
 
3244
3293
  /***/ }),
3245
3294
 
@@ -3261,7 +3310,7 @@ module.exports = ".navbar {\n width: 100%;\n background-color: #eee;\n}\n\n.ac
3261
3310
  /***/ ((module) => {
3262
3311
 
3263
3312
  "use strict";
3264
- module.exports = "<div class=\"navbar\">\n <div class=\"nav-left flex items-center gap-4 h-full\">\n <router-link to=\"/\">\n <img src=\"images/logo.svg\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <div v-if=\"!!nodeEnv\" class=\"inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900\" :class=\"warnEnv ? 'bg-red-300' : 'bg-yellow-300'\">\n {{nodeEnv}}\n </div>\n </div>\n <div class=\"nav-right h-full\">\n <div class=\"sm:ml-6 sm:flex sm:space-x-8 h-full\">\n <a\n href=\"#/\"\n class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium\"\n :class=\"routeName === 'root' ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Documents</a>\n <a\n href=\"#/dashboards\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"routeName === 'dashboards' ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Dashboards</a>\n\n <div class=\"h-full flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 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\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"h-full flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <div>\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n </div>\n\n <div v-if=\"showFlyout\" class=\"absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"user-menu-button\" tabindex=\"-1\">\n <router-link to=\"team\" v-if=\"canViewTeam\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n\n </div>\n </div>\n <div style=\"clear: both\"></div>\n</div>\n";
3313
+ module.exports = "<div class=\"navbar\">\n <div class=\"nav-left flex items-center gap-4 h-full\">\n <router-link to=\"/\">\n <img src=\"images/logo.svg\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <div v-if=\"!!nodeEnv\" class=\"inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900\" :class=\"warnEnv ? 'bg-red-300' : 'bg-yellow-300'\">\n {{nodeEnv}}\n </div>\n </div>\n <div class=\"nav-right h-full\">\n <div class=\"sm:ml-6 sm:flex sm:space-x-8 h-full\">\n <a\n href=\"#/\"\n class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium\"\n :class=\"routeName === 'root' ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Documents</a>\n <a\n href=\"#/dashboards\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"routeName === 'dashboards' ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Dashboards</a>\n\n <div class=\"h-full flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 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\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"h-full flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <div>\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n </div>\n\n <div v-if=\"showFlyout\" class=\"absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"user-menu-button\" tabindex=\"-1\">\n <router-link to=\"/team\" v-if=\"canViewTeam\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n\n </div>\n </div>\n <div style=\"clear: both\"></div>\n</div>\n";
3265
3314
 
3266
3315
  /***/ }),
3267
3316
 
@@ -3294,7 +3343,7 @@ module.exports = "<div class=\"p-1\">\n <form class=\"space-y-4\">\n <div cl
3294
3343
  /***/ ((module) => {
3295
3344
 
3296
3345
  "use strict";
3297
- module.exports = "<div class=\"mx-auto max-w-5xl py-6 px-2\">\n <div class=\"text-xl font-bold\">\n Current Members\n </div>\n <ul 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\">{{user.name}}</p>\n <p class=\"mt-1 truncate text-xs/5 text-gray-500\">{{user.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 <p class=\"mt-1 text-xs/5 text-gray-500\">Last seen <time datetime=\"2023-01-23T13:23Z\">3h ago</time></p>\n </div>\n </li>\n </ul>\n <div class=\"mt-6\">\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 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\">\n New Invitation\n </button>\n </div>\n </div>\n <div 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\n <div v-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</div>\n";
3346
+ 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=\"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-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 <ul 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=\"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 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\n <div v-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";
3298
3347
 
3299
3348
  /***/ }),
3300
3349
 
@@ -14,10 +14,6 @@ a {
14
14
  font-weight: bold !important;
15
15
  }
16
16
 
17
- input {
18
- outline: #666 solid 1px;
19
- }
20
-
21
17
  .tooltip {
22
18
  position: relative;
23
19
  display: inline-block;
@@ -686,6 +686,14 @@ video {
686
686
  margin-bottom: 1rem;
687
687
  }
688
688
 
689
+ .ml-1 {
690
+ margin-left: 0.25rem;
691
+ }
692
+
693
+ .ml-2 {
694
+ margin-left: 0.5rem;
695
+ }
696
+
689
697
  .ml-3 {
690
698
  margin-left: 0.75rem;
691
699
  }
@@ -702,6 +710,10 @@ video {
702
710
  margin-right: 0.5rem;
703
711
  }
704
712
 
713
+ .mt-0 {
714
+ margin-top: 0px;
715
+ }
716
+
705
717
  .mt-1 {
706
718
  margin-top: 0.25rem;
707
719
  }
@@ -777,6 +789,10 @@ video {
777
789
  height: 2rem;
778
790
  }
779
791
 
792
+ .h-4 {
793
+ height: 1rem;
794
+ }
795
+
780
796
  .h-48 {
781
797
  height: 12rem;
782
798
  }
@@ -813,6 +829,10 @@ video {
813
829
  max-height: 50vh;
814
830
  }
815
831
 
832
+ .w-4 {
833
+ width: 1rem;
834
+ }
835
+
816
836
  .w-48 {
817
837
  width: 12rem;
818
838
  }
@@ -833,10 +853,6 @@ video {
833
853
  width: 100%;
834
854
  }
835
855
 
836
- .w-72 {
837
- width: 18rem;
838
- }
839
-
840
856
  .min-w-0 {
841
857
  min-width: 0px;
842
858
  }
@@ -903,6 +919,10 @@ video {
903
919
  grid-template-columns: repeat(1, minmax(0, 1fr));
904
920
  }
905
921
 
922
+ .grid-cols-2 {
923
+ grid-template-columns: repeat(2, minmax(0, 1fr));
924
+ }
925
+
906
926
  .flex-row {
907
927
  flex-direction: row;
908
928
  }
@@ -935,10 +955,18 @@ video {
935
955
  gap: 0.5rem;
936
956
  }
937
957
 
958
+ .gap-3 {
959
+ gap: 0.75rem;
960
+ }
961
+
938
962
  .gap-4 {
939
963
  gap: 1rem;
940
964
  }
941
965
 
966
+ .gap-8 {
967
+ gap: 2rem;
968
+ }
969
+
942
970
  .gap-x-4 {
943
971
  -moz-column-gap: 1rem;
944
972
  column-gap: 1rem;
@@ -1016,10 +1044,6 @@ video {
1016
1044
  overflow-x: auto;
1017
1045
  }
1018
1046
 
1019
- .overflow-y-auto {
1020
- overflow-y: auto;
1021
- }
1022
-
1023
1047
  .truncate {
1024
1048
  overflow: hidden;
1025
1049
  text-overflow: ellipsis;
@@ -1143,11 +1167,21 @@ video {
1143
1167
  background-color: rgb(107 114 128 / var(--tw-bg-opacity));
1144
1168
  }
1145
1169
 
1170
+ .bg-gray-600 {
1171
+ --tw-bg-opacity: 1;
1172
+ background-color: rgb(75 85 99 / var(--tw-bg-opacity));
1173
+ }
1174
+
1146
1175
  .bg-gray-800 {
1147
1176
  --tw-bg-opacity: 1;
1148
1177
  background-color: rgb(31 41 55 / var(--tw-bg-opacity));
1149
1178
  }
1150
1179
 
1180
+ .bg-green-50 {
1181
+ --tw-bg-opacity: 1;
1182
+ background-color: rgb(240 253 244 / var(--tw-bg-opacity));
1183
+ }
1184
+
1151
1185
  .bg-green-600 {
1152
1186
  --tw-bg-opacity: 1;
1153
1187
  background-color: rgb(22 163 74 / var(--tw-bg-opacity));
@@ -1173,6 +1207,11 @@ video {
1173
1207
  background-color: rgb(241 245 249 / var(--tw-bg-opacity));
1174
1208
  }
1175
1209
 
1210
+ .bg-slate-500 {
1211
+ --tw-bg-opacity: 1;
1212
+ background-color: rgb(100 116 139 / var(--tw-bg-opacity));
1213
+ }
1214
+
1176
1215
  .bg-slate-600 {
1177
1216
  --tw-bg-opacity: 1;
1178
1217
  background-color: rgb(71 85 105 / var(--tw-bg-opacity));
@@ -1197,6 +1236,11 @@ video {
1197
1236
  background-color: rgb(24 35 255 / var(--tw-bg-opacity));
1198
1237
  }
1199
1238
 
1239
+ .bg-valencia-500 {
1240
+ --tw-bg-opacity: 1;
1241
+ background-color: rgb(220 73 73 / var(--tw-bg-opacity));
1242
+ }
1243
+
1200
1244
  .bg-valencia-600 {
1201
1245
  --tw-bg-opacity: 1;
1202
1246
  background-color: rgb(202 56 56 / var(--tw-bg-opacity));
@@ -1441,6 +1485,11 @@ video {
1441
1485
  color: rgb(17 24 39 / var(--tw-text-opacity));
1442
1486
  }
1443
1487
 
1488
+ .text-green-700 {
1489
+ --tw-text-opacity: 1;
1490
+ color: rgb(21 128 61 / var(--tw-text-opacity));
1491
+ }
1492
+
1444
1493
  .text-red-400 {
1445
1494
  --tw-text-opacity: 1;
1446
1495
  color: rgb(248 113 113 / var(--tw-text-opacity));
@@ -1456,6 +1505,11 @@ video {
1456
1505
  color: rgb(153 27 27 / var(--tw-text-opacity));
1457
1506
  }
1458
1507
 
1508
+ .text-sky-600 {
1509
+ --tw-text-opacity: 1;
1510
+ color: rgb(2 132 199 / var(--tw-text-opacity));
1511
+ }
1512
+
1459
1513
  .text-sky-800 {
1460
1514
  --tw-text-opacity: 1;
1461
1515
  color: rgb(7 89 133 / var(--tw-text-opacity));
@@ -1466,11 +1520,20 @@ video {
1466
1520
  color: rgb(0 168 165 / var(--tw-text-opacity));
1467
1521
  }
1468
1522
 
1523
+ .text-valencia-500 {
1524
+ --tw-text-opacity: 1;
1525
+ color: rgb(220 73 73 / var(--tw-text-opacity));
1526
+ }
1527
+
1469
1528
  .text-white {
1470
1529
  --tw-text-opacity: 1;
1471
1530
  color: rgb(255 255 255 / var(--tw-text-opacity));
1472
1531
  }
1473
1532
 
1533
+ .accent-sky-600 {
1534
+ accent-color: #0284c7;
1535
+ }
1536
+
1474
1537
  .shadow-lg {
1475
1538
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
1476
1539
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
@@ -1535,6 +1598,10 @@ video {
1535
1598
  --tw-ring-color: rgb(17 24 39 / 0.05);
1536
1599
  }
1537
1600
 
1601
+ .ring-green-600\/20 {
1602
+ --tw-ring-color: rgb(22 163 74 / 0.2);
1603
+ }
1604
+
1538
1605
  .filter {
1539
1606
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
1540
1607
  }
@@ -1597,6 +1664,11 @@ video {
1597
1664
  background-color: rgb(249 250 251 / var(--tw-bg-opacity));
1598
1665
  }
1599
1666
 
1667
+ .hover\:bg-gray-500:hover {
1668
+ --tw-bg-opacity: 1;
1669
+ background-color: rgb(107 114 128 / var(--tw-bg-opacity));
1670
+ }
1671
+
1600
1672
  .hover\:bg-gray-600:hover {
1601
1673
  --tw-bg-opacity: 1;
1602
1674
  background-color: rgb(75 85 99 / var(--tw-bg-opacity));
@@ -1612,6 +1684,11 @@ video {
1612
1684
  background-color: rgb(220 38 38 / var(--tw-bg-opacity));
1613
1685
  }
1614
1686
 
1687
+ .hover\:bg-slate-400:hover {
1688
+ --tw-bg-opacity: 1;
1689
+ background-color: rgb(148 163 184 / var(--tw-bg-opacity));
1690
+ }
1691
+
1615
1692
  .hover\:bg-slate-500:hover {
1616
1693
  --tw-bg-opacity: 1;
1617
1694
  background-color: rgb(100 116 139 / var(--tw-bg-opacity));
@@ -1637,6 +1714,11 @@ video {
1637
1714
  background-color: rgb(63 83 255 / var(--tw-bg-opacity));
1638
1715
  }
1639
1716
 
1717
+ .hover\:bg-valencia-400:hover {
1718
+ --tw-bg-opacity: 1;
1719
+ background-color: rgb(235 126 126 / var(--tw-bg-opacity));
1720
+ }
1721
+
1640
1722
  .hover\:bg-valencia-500:hover {
1641
1723
  --tw-bg-opacity: 1;
1642
1724
  background-color: rgb(220 73 73 / var(--tw-bg-opacity));
@@ -1681,25 +1763,21 @@ video {
1681
1763
  outline-color: #1823ff;
1682
1764
  }
1683
1765
 
1684
- .focus\:outline-ultramarine-50:focus {
1685
- outline-color: #f1f5ff;
1686
- }
1687
-
1688
1766
  .focus\:ring-0:focus {
1689
1767
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
1690
1768
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
1691
1769
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
1692
1770
  }
1693
1771
 
1694
- .focus\:ring-2:focus {
1772
+ .focus\:ring-1:focus {
1695
1773
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
1696
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
1774
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
1697
1775
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
1698
1776
  }
1699
1777
 
1700
- .focus\:ring-1:focus {
1778
+ .focus\:ring-2:focus {
1701
1779
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
1702
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
1780
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
1703
1781
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
1704
1782
  }
1705
1783
 
@@ -1728,29 +1806,34 @@ video {
1728
1806
  --tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity));
1729
1807
  }
1730
1808
 
1731
- .focus\:ring-white:focus {
1809
+ .focus\:ring-sky-600:focus {
1732
1810
  --tw-ring-opacity: 1;
1733
- --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity));
1811
+ --tw-ring-color: rgb(2 132 199 / var(--tw-ring-opacity));
1734
1812
  }
1735
1813
 
1736
- .focus\:ring-ultramarine-50:focus {
1814
+ .focus\:ring-ultramarine-200:focus {
1737
1815
  --tw-ring-opacity: 1;
1738
- --tw-ring-color: rgb(241 245 255 / var(--tw-ring-opacity));
1816
+ --tw-ring-color: rgb(206 218 255 / var(--tw-ring-opacity));
1739
1817
  }
1740
1818
 
1741
- .focus\:ring-ultramarine-200:focus {
1819
+ .focus\:ring-ultramarine-500:focus {
1742
1820
  --tw-ring-opacity: 1;
1743
- --tw-ring-color: rgb(206 218 255 / var(--tw-ring-opacity));
1821
+ --tw-ring-color: rgb(63 83 255 / var(--tw-ring-opacity));
1744
1822
  }
1745
1823
 
1746
- .focus\:ring-offset-2:focus {
1747
- --tw-ring-offset-width: 2px;
1824
+ .focus\:ring-white:focus {
1825
+ --tw-ring-opacity: 1;
1826
+ --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity));
1748
1827
  }
1749
1828
 
1750
1829
  .focus\:ring-offset-0:focus {
1751
1830
  --tw-ring-offset-width: 0px;
1752
1831
  }
1753
1832
 
1833
+ .focus\:ring-offset-2:focus {
1834
+ --tw-ring-offset-width: 2px;
1835
+ }
1836
+
1754
1837
  .focus\:ring-offset-gray-800:focus {
1755
1838
  --tw-ring-offset-color: #1f2937;
1756
1839
  }
@@ -1775,10 +1858,18 @@ video {
1775
1858
  outline-color: #16a34a;
1776
1859
  }
1777
1860
 
1861
+ .focus-visible\:outline-orange-400:focus-visible {
1862
+ outline-color: #fb923c;
1863
+ }
1864
+
1778
1865
  .focus-visible\:outline-red-600:focus-visible {
1779
1866
  outline-color: #dc2626;
1780
1867
  }
1781
1868
 
1869
+ .focus-visible\:outline-slate-400:focus-visible {
1870
+ outline-color: #94a3b8;
1871
+ }
1872
+
1782
1873
  .focus-visible\:outline-slate-600:focus-visible {
1783
1874
  outline-color: #475569;
1784
1875
  }
@@ -1791,6 +1882,15 @@ video {
1791
1882
  outline-color: #1823ff;
1792
1883
  }
1793
1884
 
1885
+ .disabled\:cursor-not-allowed:disabled {
1886
+ cursor: not-allowed;
1887
+ }
1888
+
1889
+ .disabled\:bg-gray-500:disabled {
1890
+ --tw-bg-opacity: 1;
1891
+ background-color: rgb(107 114 128 / var(--tw-bg-opacity));
1892
+ }
1893
+
1794
1894
  @media (min-width: 640px) {
1795
1895
  .sm\:-mx-6 {
1796
1896
  margin-left: -1.5rem;
@@ -92,3 +92,7 @@
92
92
  justify-content: center;
93
93
  padding-bottom: 0.25em;
94
94
  }
95
+
96
+ .modal-container .modal-exit:hover {
97
+ background-color: #f1f5ff;
98
+ }
@@ -28,7 +28,7 @@
28
28
  <div class="documents-menu">
29
29
  <div class="flex flex-row items-center w-full gap-2">
30
30
  <form @submit.prevent="search" class="flex-grow m-0">
31
- <input class="w-full rounded-md p-1 outline-gray-300 text-lg focus:ring-1 focus:ring-ultramarine-200 focus:ring-offset-0 focus:outline-none" type="text" placeholder="Filter or text" v-model="searchText" />
31
+ <input class="w-full rounded-md p-1 border border-gray-300 outline-gray-300 text-lg focus:ring-1 focus:ring-ultramarine-200 focus:ring-offset-0 focus:outline-none" type="text" placeholder="Filter or text" v-model="searchText" />
32
32
  </form>
33
33
  <div>
34
34
  <span v-if="status === 'loading'">Loading ...</span>
@@ -47,7 +47,7 @@
47
47
  Create
48
48
  </button>
49
49
  <button
50
- @click="shouldShowFieldModal = true"
50
+ @click="openFieldSelection"
51
51
  type="button"
52
52
  class="rounded bg-ultramarine-600 px-2 py-2 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">
53
53
  Fields
@@ -121,15 +121,16 @@
121
121
  <modal v-if="shouldShowFieldModal">
122
122
  <template v-slot:body>
123
123
  <div class="modal-exit" @click="shouldShowFieldModal = false; selectedPaths = [...filteredPaths];">&times;</div>
124
- <div v-for="(path, index) in schemaPaths" :key="index" style="margin-bottom: 0.5em">
125
- <input type="checkbox" :id="'path.path'+index" @change="addOrRemove(path)" :value="path.path" :checked="isSelected(path.path)" />
126
- <label :for="'path' + index">{{path.path}}</label>
124
+ <div v-for="(path, index) in schemaPaths" :key="index" class="w-5 flex items-center">
125
+ <input class="mt-0 h-4 w-4 rounded border-gray-300 text-sky-600 focus:ring-sky-600 accent-sky-600" type="checkbox" :id="'path.path'+index" @change="addOrRemove(path)" :value="path.path" :checked="isSelected(path.path)" />
126
+ <div class="ml-2 text-gray-700 grow shrink text-left">
127
+ <label :for="'path' + index">{{path.path}}</label>
128
+ </div>
127
129
  </div>
128
- <div style="margin-top: 1em">
129
- <button type="submit" @click="filterDocuments()" style="color: black;margin-right: 0.5em">Filter Selection</button>
130
- <button type="submit" @click="deselectAll()" class="gray" style="margin-right: 0.5em">Deselect All</button>
131
- <button type="submit" @click="resetDocuments()" class="gray">Cancel</button>
132
-
130
+ <div class="mt-4 flex gap-2">
131
+ <button type="submit" @click="filterDocuments()" class="rounded-md bg-ultramarine-600 px-2.5 py-1.5 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-teal-600">Filter Selection</button>
132
+ <button type="submit" @click="deselectAll()" class="rounded-md bg-valencia-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-valencia-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600">Deselect All</button>
133
+ <button type="submit" @click="resetDocuments()" class="rounded-md bg-gray-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-gray-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600" >Cancel</button>
133
134
  </div>
134
135
  </template>
135
136
  </modal>
@@ -211,8 +211,25 @@ module.exports = app => app.component('models', {
211
211
  }).map(key => this.selectedPaths[key]);
212
212
  }
213
213
  },
214
+ openFieldSelection() {
215
+ if (this.$route.query?.fields) {
216
+ this.selectedPaths.length = 0;
217
+ console.log('there are fields in play', this.$route.query.fields)
218
+ const fields = this.$route.query.fields.split(',');
219
+ for (let i = 0; i < fields.length; i++) {
220
+ this.selectedPaths.push({ path: fields[i] });
221
+ }
222
+ } else {
223
+ this.selectedPaths = [{ path: '_id' }];
224
+ }
225
+ this.shouldShowFieldModal = true;
226
+ },
214
227
  filterDocuments() {
215
- this.filteredPaths = [...this.selectedPaths];
228
+ if (this.selectedPaths.length > 0) {
229
+ this.filteredPaths = [...this.selectedPaths];
230
+ } else {
231
+ this.filteredPaths.length = 0;
232
+ }
216
233
  this.shouldShowFieldModal = false;
217
234
  const selectedParams = this.filteredPaths.map(x => x.path).join(',');
218
235
  this.query.fields = selectedParams;
@@ -24,16 +24,24 @@ exports.getWorkspaceTeam = function getWorkspaceTeam() {
24
24
  return client.post('/getWorkspaceTeam', { workspaceId: config__workspace._id }).then(res => res.data);
25
25
  };
26
26
 
27
- exports.inviteToWorkspace = function inviteToWorkspace(params) {
28
- return client.post('/inviteToWorkspace', { workspaceId: config__workspace._id, ...params }).then(res => res.data);
27
+ exports.getWorkspaceCustomerPortalLink = function getWorkspaceCustomerPortalLink(params) {
28
+ return client.post('/getWorkspaceCustomerPortalLink', { workspaceId: config__workspace._id, ...params }).then(res => res.data);
29
29
  };
30
30
 
31
31
  exports.github = function github(code) {
32
32
  return client.post('/github', { code, workspaceId: config__workspace._id }).then(res => res.data);
33
33
  };
34
34
 
35
+ exports.inviteToWorkspace = function inviteToWorkspace(params) {
36
+ return client.post('/inviteToWorkspace', { workspaceId: config__workspace._id, ...params }).then(res => res.data);
37
+ };
38
+
35
39
  exports.me = function me() {
36
40
  return client.post('/me', { workspaceId: config__workspace._id }).then(res => res.data);
37
41
  };
38
42
 
43
+ exports.removeFromWorkspace = function removeFromWorkspace(params) {
44
+ return client.post('/removeFromWorkspace', { workspaceId: config__workspace._id, ...params }).then(res => res.data);
45
+ };
46
+
39
47
  exports.hasAPIKey = client.hasAPIKey;
@@ -36,7 +36,7 @@
36
36
  </div>
37
37
 
38
38
  <div v-if="showFlyout" class="absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
39
- <router-link to="team" v-if="canViewTeam" @click="showFlyout = false" class="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200" role="menuitem" tabindex="-1" id="user-menu-item-2">Team</router-link>
39
+ <router-link to="/team" v-if="canViewTeam" @click="showFlyout = false" class="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200" role="menuitem" tabindex="-1" id="user-menu-item-2">Team</router-link>
40
40
  <span @click="logout" class="cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200" role="menuitem" tabindex="-1" id="user-menu-item-2">Sign out</span>
41
41
  </div>
42
42
  </div>
@@ -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.61",
4
4
  "dependencies": {
5
5
  "archetype": "0.13.1",
6
6
  "csv-stringify": "6.3.0",