tinacms 0.59.1 → 0.60.0
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/CHANGELOG.md +14 -0
- package/dist/client/index.d.ts +4 -2
- package/dist/index.es.js +104 -46
- package/dist/index.js +103 -45
- package/dist/style.css +1470 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# tinacms
|
|
2
2
|
|
|
3
|
+
## 0.60.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 75974d0a4: Updates the tina cloud client to do id_token & access_token refreshes when needed
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 88c209b45: Throw when Tina Cloud responds with non 200 code
|
|
12
|
+
- dcdf1ecf0: Updates `react-router` to `v6` for `TinaAdmin`
|
|
13
|
+
- 47d126029: Fix support of objects in a list for MDX templates
|
|
14
|
+
- Updated dependencies [bc4699d2b]
|
|
15
|
+
- @tinacms/toolkit@0.56.2
|
|
16
|
+
|
|
3
17
|
## 0.59.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/client/index.d.ts
CHANGED
|
@@ -11,9 +11,9 @@ See the License for the specific language governing permissions and
|
|
|
11
11
|
limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
import { TokenObject } from '../auth/authenticate';
|
|
14
|
+
import { BranchData, EventBus } from '@tinacms/toolkit';
|
|
14
15
|
import { DocumentNode, GraphQLSchema } from 'graphql';
|
|
15
16
|
import gql from 'graphql-tag';
|
|
16
|
-
import { EventBus, BranchData } from '@tinacms/toolkit';
|
|
17
17
|
export declare type TinaIOConfig = {
|
|
18
18
|
frontendUrlOverride?: string;
|
|
19
19
|
identityApiUrlOverride?: string;
|
|
@@ -23,7 +23,7 @@ interface ServerOptions {
|
|
|
23
23
|
clientId: string;
|
|
24
24
|
branch: string;
|
|
25
25
|
customContentApiUrl?: string;
|
|
26
|
-
getTokenFn?: () => TokenObject
|
|
26
|
+
getTokenFn?: () => Promise<TokenObject>;
|
|
27
27
|
tinaioConfig?: TinaIOConfig;
|
|
28
28
|
tokenStorage?: 'MEMORY' | 'LOCAL_STORAGE' | 'CUSTOM';
|
|
29
29
|
}
|
|
@@ -51,6 +51,8 @@ export declare class Client {
|
|
|
51
51
|
request<ReturnType>(query: ((gqlTag: typeof gql) => DocumentNode) | string, { variables }: {
|
|
52
52
|
variables: object;
|
|
53
53
|
}): Promise<ReturnType>;
|
|
54
|
+
parseJwt(token: any): any;
|
|
55
|
+
getRefreshedToken(tokens: string): Promise<TokenObject>;
|
|
54
56
|
isAuthorized(): Promise<boolean>;
|
|
55
57
|
isAuthenticated(): Promise<boolean>;
|
|
56
58
|
authenticate(): Promise<TokenObject>;
|
package/dist/index.es.js
CHANGED
|
@@ -29,17 +29,17 @@ var __objRest = (source, exclude) => {
|
|
|
29
29
|
}
|
|
30
30
|
return target;
|
|
31
31
|
};
|
|
32
|
+
import { EventBus, StyleReset, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, useCMS, useBranchData, FormMetaPlugin, Form, GlobalFormPlugin, FullscreenFormBuilder } from "@tinacms/toolkit";
|
|
33
|
+
export * from "@tinacms/toolkit";
|
|
32
34
|
import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType, getIntrospectionQuery, buildClientSchema, print } from "graphql";
|
|
33
35
|
import set from "lodash.set";
|
|
34
36
|
import gql$1 from "graphql-tag";
|
|
35
|
-
import { EventBus, StyleReset, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, useCMS, useBranchData, FormMetaPlugin, Form, GlobalFormPlugin, FullscreenFormBuilder } from "@tinacms/toolkit";
|
|
36
|
-
export * from "@tinacms/toolkit";
|
|
37
37
|
import React, { useState, useCallback, useEffect, Fragment } from "react";
|
|
38
38
|
import styled from "styled-components";
|
|
39
39
|
import * as yup from "yup";
|
|
40
40
|
import { setEditing, useEditState } from "@tinacms/sharedctx";
|
|
41
41
|
import { getIn, setIn } from "final-form";
|
|
42
|
-
import { NavLink, useLocation, useParams, Link,
|
|
42
|
+
import { NavLink, useLocation, useParams, Link, useNavigate, BrowserRouter, Routes, Route } from "react-router-dom";
|
|
43
43
|
import { Menu, Transition } from "@headlessui/react";
|
|
44
44
|
function popupWindow(url, title, window2, w, h) {
|
|
45
45
|
const y = window2.top.outerHeight / 2 + window2.top.screenY - h / 2;
|
|
@@ -424,10 +424,10 @@ mutation addPendingDocumentMutation(
|
|
|
424
424
|
this.clientId = options.clientId;
|
|
425
425
|
switch (tokenStorage) {
|
|
426
426
|
case "LOCAL_STORAGE":
|
|
427
|
-
this.getToken = function() {
|
|
427
|
+
this.getToken = async function() {
|
|
428
428
|
const tokens = localStorage.getItem(AUTH_TOKEN_KEY) || null;
|
|
429
429
|
if (tokens) {
|
|
430
|
-
return
|
|
430
|
+
return await this.getRefreshedToken(tokens);
|
|
431
431
|
} else {
|
|
432
432
|
return {
|
|
433
433
|
access_token: null,
|
|
@@ -441,9 +441,9 @@ mutation addPendingDocumentMutation(
|
|
|
441
441
|
};
|
|
442
442
|
break;
|
|
443
443
|
case "MEMORY":
|
|
444
|
-
this.getToken = () => {
|
|
444
|
+
this.getToken = async () => {
|
|
445
445
|
if (this.token) {
|
|
446
|
-
return
|
|
446
|
+
return await this.getRefreshedToken(this.token);
|
|
447
447
|
} else {
|
|
448
448
|
return {
|
|
449
449
|
access_token: null,
|
|
@@ -482,13 +482,16 @@ mutation addPendingDocumentMutation(
|
|
|
482
482
|
method: "POST",
|
|
483
483
|
headers: {
|
|
484
484
|
"Content-Type": "application/json",
|
|
485
|
-
Authorization: "Bearer " + this.getToken().id_token
|
|
485
|
+
Authorization: "Bearer " + (await this.getToken()).id_token
|
|
486
486
|
},
|
|
487
487
|
body: JSON.stringify({
|
|
488
488
|
query: typeof query === "function" ? print(query(gql$1)) : query,
|
|
489
489
|
variables
|
|
490
490
|
})
|
|
491
491
|
});
|
|
492
|
+
if (res.status !== 200) {
|
|
493
|
+
throw new Error(`Unable to complete request, ${res.statusText}`);
|
|
494
|
+
}
|
|
492
495
|
const json = await res.json();
|
|
493
496
|
if (json.errors) {
|
|
494
497
|
throw new Error(`Unable to fetch, errors:
|
|
@@ -496,6 +499,47 @@ mutation addPendingDocumentMutation(
|
|
|
496
499
|
}
|
|
497
500
|
return json.data;
|
|
498
501
|
}
|
|
502
|
+
parseJwt(token) {
|
|
503
|
+
const base64Url = token.split(".")[1];
|
|
504
|
+
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
505
|
+
const jsonPayload = decodeURIComponent(atob(base64).split("").map(function(c) {
|
|
506
|
+
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
507
|
+
}).join(""));
|
|
508
|
+
return JSON.parse(jsonPayload);
|
|
509
|
+
}
|
|
510
|
+
async getRefreshedToken(tokens) {
|
|
511
|
+
const { access_token, id_token, refresh_token } = JSON.parse(tokens);
|
|
512
|
+
const { exp, iss, client_id } = this.parseJwt(access_token);
|
|
513
|
+
if (Date.now() / 1e3 >= exp) {
|
|
514
|
+
const refreshResponse = await fetch(iss, {
|
|
515
|
+
method: "POST",
|
|
516
|
+
headers: {
|
|
517
|
+
"Content-Type": "application/x-amz-json-1.1",
|
|
518
|
+
"x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
|
|
519
|
+
},
|
|
520
|
+
body: JSON.stringify({
|
|
521
|
+
ClientId: client_id,
|
|
522
|
+
AuthFlow: "REFRESH_TOKEN_AUTH",
|
|
523
|
+
AuthParameters: {
|
|
524
|
+
REFRESH_TOKEN: refresh_token,
|
|
525
|
+
DEVICE_KEY: null
|
|
526
|
+
}
|
|
527
|
+
})
|
|
528
|
+
});
|
|
529
|
+
if (refreshResponse.status !== 200) {
|
|
530
|
+
throw new Error("Unable to refresh auth tokens");
|
|
531
|
+
}
|
|
532
|
+
const responseJson = await refreshResponse.json();
|
|
533
|
+
const newToken = {
|
|
534
|
+
access_token: responseJson.AuthenticationResult.AccessToken,
|
|
535
|
+
id_token: responseJson.AuthenticationResult.IdToken,
|
|
536
|
+
refresh_token
|
|
537
|
+
};
|
|
538
|
+
this.setToken(newToken);
|
|
539
|
+
return Promise.resolve(newToken);
|
|
540
|
+
}
|
|
541
|
+
return Promise.resolve({ access_token, id_token, refresh_token });
|
|
542
|
+
}
|
|
499
543
|
async isAuthorized() {
|
|
500
544
|
return this.isAuthenticated();
|
|
501
545
|
}
|
|
@@ -511,7 +555,7 @@ mutation addPendingDocumentMutation(
|
|
|
511
555
|
const headers = (init == null ? void 0 : init.headers) || {};
|
|
512
556
|
return await fetch(input, __spreadProps(__spreadValues({}, init), {
|
|
513
557
|
headers: new Headers(__spreadValues({
|
|
514
|
-
Authorization: "Bearer " + this.getToken().id_token
|
|
558
|
+
Authorization: "Bearer " + (await this.getToken()).id_token
|
|
515
559
|
}, headers))
|
|
516
560
|
}));
|
|
517
561
|
}
|
|
@@ -995,25 +1039,30 @@ function useGraphqlForms({
|
|
|
995
1039
|
setPendingReset(queryName);
|
|
996
1040
|
},
|
|
997
1041
|
onSubmit: async (payload2) => {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
onSubmit
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
});
|
|
1007
|
-
} else {
|
|
1008
|
-
try {
|
|
1009
|
-
await cms.api.tina.request(mutationString, {
|
|
1042
|
+
try {
|
|
1043
|
+
const params = transformDocumentIntoMutationRequestPayload(payload2, result.form.mutationInfo);
|
|
1044
|
+
const variables2 = { params };
|
|
1045
|
+
const mutationString = result.form.mutationInfo.string;
|
|
1046
|
+
if (onSubmit) {
|
|
1047
|
+
onSubmit({
|
|
1048
|
+
queryString: mutationString,
|
|
1049
|
+
mutationString,
|
|
1010
1050
|
variables: variables2
|
|
1011
1051
|
});
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1052
|
+
} else {
|
|
1053
|
+
try {
|
|
1054
|
+
await cms.api.tina.request(mutationString, {
|
|
1055
|
+
variables: variables2
|
|
1056
|
+
});
|
|
1057
|
+
cms.alerts.success("Document saved!");
|
|
1058
|
+
} catch (e) {
|
|
1059
|
+
cms.alerts.error("There was a problem saving your document");
|
|
1060
|
+
console.error(e);
|
|
1061
|
+
}
|
|
1016
1062
|
}
|
|
1063
|
+
} catch (e) {
|
|
1064
|
+
console.error(e);
|
|
1065
|
+
cms.alerts.error("There was a problem saving your document");
|
|
1017
1066
|
}
|
|
1018
1067
|
}
|
|
1019
1068
|
};
|
|
@@ -1125,6 +1174,9 @@ const transformParams = (data) => {
|
|
|
1125
1174
|
return { [_template]: nested };
|
|
1126
1175
|
} catch (e) {
|
|
1127
1176
|
if (e.message === "Failed to assertShape - _template is a required field") {
|
|
1177
|
+
if (!data) {
|
|
1178
|
+
return [];
|
|
1179
|
+
}
|
|
1128
1180
|
const accum = {};
|
|
1129
1181
|
Object.entries(data).map(([keyName, value]) => {
|
|
1130
1182
|
accum[keyName] = transformParams(value);
|
|
@@ -1687,8 +1739,9 @@ const Sidebar = ({ cms }) => {
|
|
|
1687
1739
|
return /* @__PURE__ */ React.createElement("li", {
|
|
1688
1740
|
key: `${collection.name}-link`
|
|
1689
1741
|
}, /* @__PURE__ */ React.createElement(NavLink, {
|
|
1690
|
-
className:
|
|
1691
|
-
|
|
1742
|
+
className: ({ isActive }) => {
|
|
1743
|
+
return `text-lg tracking-wide ${isActive ? "text-blue-600" : ""} hover:text-blue-600 flex items-center opacity-90 hover:opacity-100`;
|
|
1744
|
+
},
|
|
1692
1745
|
to: `/admin/collections/${collection.name}`
|
|
1693
1746
|
}, /* @__PURE__ */ React.createElement(ImFilesEmpty, {
|
|
1694
1747
|
className: "mr-2 h-6 opacity-80 w-auto"
|
|
@@ -2017,7 +2070,7 @@ const createDocument = async (cms, collection, template, mutationInfo, values) =
|
|
|
2017
2070
|
};
|
|
2018
2071
|
const CollectionCreatePage = () => {
|
|
2019
2072
|
const { collectionName, templateName } = useParams();
|
|
2020
|
-
const
|
|
2073
|
+
const navigate = useNavigate();
|
|
2021
2074
|
return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => /* @__PURE__ */ React.createElement(GetDocumentFields, {
|
|
2022
2075
|
cms,
|
|
2023
2076
|
collectionName,
|
|
@@ -2038,7 +2091,7 @@ const CollectionCreatePage = () => {
|
|
|
2038
2091
|
],
|
|
2039
2092
|
onSubmit: async (values) => {
|
|
2040
2093
|
await createDocument(cms, collection, template, mutationInfo, values);
|
|
2041
|
-
|
|
2094
|
+
navigate(`/admin/collections/${collection.name}`);
|
|
2042
2095
|
}
|
|
2043
2096
|
});
|
|
2044
2097
|
const formLabel = template ? `${collection.label} - Create New ${template.label}` : `${collection.label} - Create New`;
|
|
@@ -2105,7 +2158,7 @@ const updateDocument = async (cms, relativePath, collection, mutationInfo, value
|
|
|
2105
2158
|
};
|
|
2106
2159
|
const CollectionUpdatePage = () => {
|
|
2107
2160
|
const { collectionName, filename } = useParams();
|
|
2108
|
-
const
|
|
2161
|
+
const navigate = useNavigate();
|
|
2109
2162
|
return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => /* @__PURE__ */ React.createElement(GetDocumentFields, {
|
|
2110
2163
|
cms,
|
|
2111
2164
|
collectionName
|
|
@@ -2123,7 +2176,7 @@ const CollectionUpdatePage = () => {
|
|
|
2123
2176
|
initialValues: document2.values,
|
|
2124
2177
|
onSubmit: async (values) => {
|
|
2125
2178
|
await updateDocument(cms, relativePath, collection, mutationInfo, values);
|
|
2126
|
-
|
|
2179
|
+
navigate(`/collections/${collection.name}`);
|
|
2127
2180
|
}
|
|
2128
2181
|
});
|
|
2129
2182
|
return /* @__PURE__ */ React.createElement("div", {
|
|
@@ -2154,10 +2207,10 @@ const useEmbedTailwind = () => {
|
|
|
2154
2207
|
const TinaAdmin = () => {
|
|
2155
2208
|
useEmbedTailwind();
|
|
2156
2209
|
const isSSR = typeof window === "undefined";
|
|
2210
|
+
const { edit } = useEditState();
|
|
2157
2211
|
if (isSSR) {
|
|
2158
2212
|
return null;
|
|
2159
2213
|
}
|
|
2160
|
-
const { edit } = useEditState();
|
|
2161
2214
|
if (!edit) {
|
|
2162
2215
|
return /* @__PURE__ */ React.createElement(Layout, null, /* @__PURE__ */ React.createElement(LoginPage, null));
|
|
2163
2216
|
}
|
|
@@ -2170,22 +2223,27 @@ const TinaAdmin = () => {
|
|
|
2170
2223
|
cms
|
|
2171
2224
|
}), /* @__PURE__ */ React.createElement("div", {
|
|
2172
2225
|
className: "flex-1"
|
|
2173
|
-
}, /* @__PURE__ */ React.createElement(
|
|
2174
|
-
path:
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
}
|
|
2180
|
-
path:
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2226
|
+
}, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
|
|
2227
|
+
path: "/admin/collections/:collectionName/new",
|
|
2228
|
+
element: /* @__PURE__ */ React.createElement(CollectionCreatePage, null)
|
|
2229
|
+
}), /* @__PURE__ */ React.createElement(Route, {
|
|
2230
|
+
path: "/admin/collections/:collectionName/:templateName/new",
|
|
2231
|
+
element: /* @__PURE__ */ React.createElement(CollectionCreatePage, null)
|
|
2232
|
+
}), /* @__PURE__ */ React.createElement(Route, {
|
|
2233
|
+
path: "/admin/collections/:collectionName/:filename",
|
|
2234
|
+
element: /* @__PURE__ */ React.createElement(CollectionUpdatePage, null)
|
|
2235
|
+
}), /* @__PURE__ */ React.createElement(Route, {
|
|
2236
|
+
path: "/admin/collections/:collectionName",
|
|
2237
|
+
element: /* @__PURE__ */ React.createElement(CollectionListPage, null)
|
|
2238
|
+
}), /* @__PURE__ */ React.createElement(Route, {
|
|
2239
|
+
path: "/admin",
|
|
2240
|
+
element: /* @__PURE__ */ React.createElement(DashboardPage, null)
|
|
2241
|
+
}))))));
|
|
2184
2242
|
} else {
|
|
2185
|
-
return /* @__PURE__ */ React.createElement(Layout, null, /* @__PURE__ */ React.createElement(BrowserRouter, null, /* @__PURE__ */ React.createElement(
|
|
2186
|
-
path:
|
|
2243
|
+
return /* @__PURE__ */ React.createElement(Layout, null, /* @__PURE__ */ React.createElement(BrowserRouter, null, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
|
|
2244
|
+
path: "/admin/logout"
|
|
2187
2245
|
}, /* @__PURE__ */ React.createElement(LogoutPage, null)), /* @__PURE__ */ React.createElement(Route, {
|
|
2188
|
-
path:
|
|
2246
|
+
path: "/admin"
|
|
2189
2247
|
}, () => {
|
|
2190
2248
|
window.location.href = "/";
|
|
2191
2249
|
}))));
|
package/dist/index.js
CHANGED
|
@@ -30,8 +30,8 @@ var __objRest = (source, exclude) => {
|
|
|
30
30
|
return target;
|
|
31
31
|
};
|
|
32
32
|
(function(global, factory) {
|
|
33
|
-
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("graphql"), require("lodash.set"), require("graphql-tag"), require("
|
|
34
|
-
})(this, function(exports2, graphql, set, gql$1,
|
|
33
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@tinacms/toolkit"), require("graphql"), require("lodash.set"), require("graphql-tag"), require("react"), require("styled-components"), require("yup"), require("@tinacms/sharedctx"), require("final-form"), require("react-router-dom"), require("@headlessui/react")) : typeof define === "function" && define.amd ? define(["exports", "@tinacms/toolkit", "graphql", "lodash.set", "graphql-tag", "react", "styled-components", "yup", "@tinacms/sharedctx", "final-form", "react-router-dom", "@headlessui/react"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.tinacms = {}, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP));
|
|
34
|
+
})(this, function(exports2, toolkit, graphql, set, gql$1, React, styled, yup, sharedctx, finalForm, reactRouterDom, react) {
|
|
35
35
|
"use strict";
|
|
36
36
|
function _interopDefaultLegacy(e) {
|
|
37
37
|
return e && typeof e === "object" && "default" in e ? e : { "default": e };
|
|
@@ -444,10 +444,10 @@ mutation addPendingDocumentMutation(
|
|
|
444
444
|
this.clientId = options.clientId;
|
|
445
445
|
switch (tokenStorage) {
|
|
446
446
|
case "LOCAL_STORAGE":
|
|
447
|
-
this.getToken = function() {
|
|
447
|
+
this.getToken = async function() {
|
|
448
448
|
const tokens = localStorage.getItem(AUTH_TOKEN_KEY) || null;
|
|
449
449
|
if (tokens) {
|
|
450
|
-
return
|
|
450
|
+
return await this.getRefreshedToken(tokens);
|
|
451
451
|
} else {
|
|
452
452
|
return {
|
|
453
453
|
access_token: null,
|
|
@@ -461,9 +461,9 @@ mutation addPendingDocumentMutation(
|
|
|
461
461
|
};
|
|
462
462
|
break;
|
|
463
463
|
case "MEMORY":
|
|
464
|
-
this.getToken = () => {
|
|
464
|
+
this.getToken = async () => {
|
|
465
465
|
if (this.token) {
|
|
466
|
-
return
|
|
466
|
+
return await this.getRefreshedToken(this.token);
|
|
467
467
|
} else {
|
|
468
468
|
return {
|
|
469
469
|
access_token: null,
|
|
@@ -502,13 +502,16 @@ mutation addPendingDocumentMutation(
|
|
|
502
502
|
method: "POST",
|
|
503
503
|
headers: {
|
|
504
504
|
"Content-Type": "application/json",
|
|
505
|
-
Authorization: "Bearer " + this.getToken().id_token
|
|
505
|
+
Authorization: "Bearer " + (await this.getToken()).id_token
|
|
506
506
|
},
|
|
507
507
|
body: JSON.stringify({
|
|
508
508
|
query: typeof query === "function" ? graphql.print(query(gql__default["default"])) : query,
|
|
509
509
|
variables
|
|
510
510
|
})
|
|
511
511
|
});
|
|
512
|
+
if (res.status !== 200) {
|
|
513
|
+
throw new Error(`Unable to complete request, ${res.statusText}`);
|
|
514
|
+
}
|
|
512
515
|
const json = await res.json();
|
|
513
516
|
if (json.errors) {
|
|
514
517
|
throw new Error(`Unable to fetch, errors:
|
|
@@ -516,6 +519,47 @@ mutation addPendingDocumentMutation(
|
|
|
516
519
|
}
|
|
517
520
|
return json.data;
|
|
518
521
|
}
|
|
522
|
+
parseJwt(token) {
|
|
523
|
+
const base64Url = token.split(".")[1];
|
|
524
|
+
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
525
|
+
const jsonPayload = decodeURIComponent(atob(base64).split("").map(function(c) {
|
|
526
|
+
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
527
|
+
}).join(""));
|
|
528
|
+
return JSON.parse(jsonPayload);
|
|
529
|
+
}
|
|
530
|
+
async getRefreshedToken(tokens) {
|
|
531
|
+
const { access_token, id_token, refresh_token } = JSON.parse(tokens);
|
|
532
|
+
const { exp, iss, client_id } = this.parseJwt(access_token);
|
|
533
|
+
if (Date.now() / 1e3 >= exp) {
|
|
534
|
+
const refreshResponse = await fetch(iss, {
|
|
535
|
+
method: "POST",
|
|
536
|
+
headers: {
|
|
537
|
+
"Content-Type": "application/x-amz-json-1.1",
|
|
538
|
+
"x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
|
|
539
|
+
},
|
|
540
|
+
body: JSON.stringify({
|
|
541
|
+
ClientId: client_id,
|
|
542
|
+
AuthFlow: "REFRESH_TOKEN_AUTH",
|
|
543
|
+
AuthParameters: {
|
|
544
|
+
REFRESH_TOKEN: refresh_token,
|
|
545
|
+
DEVICE_KEY: null
|
|
546
|
+
}
|
|
547
|
+
})
|
|
548
|
+
});
|
|
549
|
+
if (refreshResponse.status !== 200) {
|
|
550
|
+
throw new Error("Unable to refresh auth tokens");
|
|
551
|
+
}
|
|
552
|
+
const responseJson = await refreshResponse.json();
|
|
553
|
+
const newToken = {
|
|
554
|
+
access_token: responseJson.AuthenticationResult.AccessToken,
|
|
555
|
+
id_token: responseJson.AuthenticationResult.IdToken,
|
|
556
|
+
refresh_token
|
|
557
|
+
};
|
|
558
|
+
this.setToken(newToken);
|
|
559
|
+
return Promise.resolve(newToken);
|
|
560
|
+
}
|
|
561
|
+
return Promise.resolve({ access_token, id_token, refresh_token });
|
|
562
|
+
}
|
|
519
563
|
async isAuthorized() {
|
|
520
564
|
return this.isAuthenticated();
|
|
521
565
|
}
|
|
@@ -531,7 +575,7 @@ mutation addPendingDocumentMutation(
|
|
|
531
575
|
const headers = (init == null ? void 0 : init.headers) || {};
|
|
532
576
|
return await fetch(input, __spreadProps(__spreadValues({}, init), {
|
|
533
577
|
headers: new Headers(__spreadValues({
|
|
534
|
-
Authorization: "Bearer " + this.getToken().id_token
|
|
578
|
+
Authorization: "Bearer " + (await this.getToken()).id_token
|
|
535
579
|
}, headers))
|
|
536
580
|
}));
|
|
537
581
|
}
|
|
@@ -1015,25 +1059,30 @@ mutation addPendingDocumentMutation(
|
|
|
1015
1059
|
setPendingReset(queryName);
|
|
1016
1060
|
},
|
|
1017
1061
|
onSubmit: async (payload2) => {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
onSubmit
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
});
|
|
1027
|
-
} else {
|
|
1028
|
-
try {
|
|
1029
|
-
await cms.api.tina.request(mutationString, {
|
|
1062
|
+
try {
|
|
1063
|
+
const params = transformDocumentIntoMutationRequestPayload(payload2, result.form.mutationInfo);
|
|
1064
|
+
const variables2 = { params };
|
|
1065
|
+
const mutationString = result.form.mutationInfo.string;
|
|
1066
|
+
if (onSubmit) {
|
|
1067
|
+
onSubmit({
|
|
1068
|
+
queryString: mutationString,
|
|
1069
|
+
mutationString,
|
|
1030
1070
|
variables: variables2
|
|
1031
1071
|
});
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1072
|
+
} else {
|
|
1073
|
+
try {
|
|
1074
|
+
await cms.api.tina.request(mutationString, {
|
|
1075
|
+
variables: variables2
|
|
1076
|
+
});
|
|
1077
|
+
cms.alerts.success("Document saved!");
|
|
1078
|
+
} catch (e) {
|
|
1079
|
+
cms.alerts.error("There was a problem saving your document");
|
|
1080
|
+
console.error(e);
|
|
1081
|
+
}
|
|
1036
1082
|
}
|
|
1083
|
+
} catch (e) {
|
|
1084
|
+
console.error(e);
|
|
1085
|
+
cms.alerts.error("There was a problem saving your document");
|
|
1037
1086
|
}
|
|
1038
1087
|
}
|
|
1039
1088
|
};
|
|
@@ -1145,6 +1194,9 @@ mutation addPendingDocumentMutation(
|
|
|
1145
1194
|
return { [_template]: nested };
|
|
1146
1195
|
} catch (e) {
|
|
1147
1196
|
if (e.message === "Failed to assertShape - _template is a required field") {
|
|
1197
|
+
if (!data) {
|
|
1198
|
+
return [];
|
|
1199
|
+
}
|
|
1148
1200
|
const accum = {};
|
|
1149
1201
|
Object.entries(data).map(([keyName, value]) => {
|
|
1150
1202
|
accum[keyName] = transformParams(value);
|
|
@@ -1707,8 +1759,9 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
1707
1759
|
return /* @__PURE__ */ React__default["default"].createElement("li", {
|
|
1708
1760
|
key: `${collection.name}-link`
|
|
1709
1761
|
}, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.NavLink, {
|
|
1710
|
-
className:
|
|
1711
|
-
|
|
1762
|
+
className: ({ isActive }) => {
|
|
1763
|
+
return `text-lg tracking-wide ${isActive ? "text-blue-600" : ""} hover:text-blue-600 flex items-center opacity-90 hover:opacity-100`;
|
|
1764
|
+
},
|
|
1712
1765
|
to: `/admin/collections/${collection.name}`
|
|
1713
1766
|
}, /* @__PURE__ */ React__default["default"].createElement(ImFilesEmpty, {
|
|
1714
1767
|
className: "mr-2 h-6 opacity-80 w-auto"
|
|
@@ -2037,7 +2090,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
2037
2090
|
};
|
|
2038
2091
|
const CollectionCreatePage = () => {
|
|
2039
2092
|
const { collectionName, templateName } = reactRouterDom.useParams();
|
|
2040
|
-
const
|
|
2093
|
+
const navigate = reactRouterDom.useNavigate();
|
|
2041
2094
|
return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => /* @__PURE__ */ React__default["default"].createElement(GetDocumentFields, {
|
|
2042
2095
|
cms,
|
|
2043
2096
|
collectionName,
|
|
@@ -2058,7 +2111,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
2058
2111
|
],
|
|
2059
2112
|
onSubmit: async (values) => {
|
|
2060
2113
|
await createDocument(cms, collection, template, mutationInfo, values);
|
|
2061
|
-
|
|
2114
|
+
navigate(`/admin/collections/${collection.name}`);
|
|
2062
2115
|
}
|
|
2063
2116
|
});
|
|
2064
2117
|
const formLabel = template ? `${collection.label} - Create New ${template.label}` : `${collection.label} - Create New`;
|
|
@@ -2125,7 +2178,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
2125
2178
|
};
|
|
2126
2179
|
const CollectionUpdatePage = () => {
|
|
2127
2180
|
const { collectionName, filename } = reactRouterDom.useParams();
|
|
2128
|
-
const
|
|
2181
|
+
const navigate = reactRouterDom.useNavigate();
|
|
2129
2182
|
return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => /* @__PURE__ */ React__default["default"].createElement(GetDocumentFields, {
|
|
2130
2183
|
cms,
|
|
2131
2184
|
collectionName
|
|
@@ -2143,7 +2196,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
2143
2196
|
initialValues: document2.values,
|
|
2144
2197
|
onSubmit: async (values) => {
|
|
2145
2198
|
await updateDocument(cms, relativePath, collection, mutationInfo, values);
|
|
2146
|
-
|
|
2199
|
+
navigate(`/collections/${collection.name}`);
|
|
2147
2200
|
}
|
|
2148
2201
|
});
|
|
2149
2202
|
return /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
@@ -2174,10 +2227,10 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
2174
2227
|
const TinaAdmin = () => {
|
|
2175
2228
|
useEmbedTailwind();
|
|
2176
2229
|
const isSSR = typeof window === "undefined";
|
|
2230
|
+
const { edit } = sharedctx.useEditState();
|
|
2177
2231
|
if (isSSR) {
|
|
2178
2232
|
return null;
|
|
2179
2233
|
}
|
|
2180
|
-
const { edit } = sharedctx.useEditState();
|
|
2181
2234
|
if (!edit) {
|
|
2182
2235
|
return /* @__PURE__ */ React__default["default"].createElement(Layout, null, /* @__PURE__ */ React__default["default"].createElement(LoginPage, null));
|
|
2183
2236
|
}
|
|
@@ -2190,22 +2243,27 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
2190
2243
|
cms
|
|
2191
2244
|
}), /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
2192
2245
|
className: "flex-1"
|
|
2193
|
-
}, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.
|
|
2194
|
-
path:
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
}
|
|
2200
|
-
path:
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2246
|
+
}, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Routes, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
2247
|
+
path: "/admin/collections/:collectionName/new",
|
|
2248
|
+
element: /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null)
|
|
2249
|
+
}), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
2250
|
+
path: "/admin/collections/:collectionName/:templateName/new",
|
|
2251
|
+
element: /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null)
|
|
2252
|
+
}), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
2253
|
+
path: "/admin/collections/:collectionName/:filename",
|
|
2254
|
+
element: /* @__PURE__ */ React__default["default"].createElement(CollectionUpdatePage, null)
|
|
2255
|
+
}), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
2256
|
+
path: "/admin/collections/:collectionName",
|
|
2257
|
+
element: /* @__PURE__ */ React__default["default"].createElement(CollectionListPage, null)
|
|
2258
|
+
}), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
2259
|
+
path: "/admin",
|
|
2260
|
+
element: /* @__PURE__ */ React__default["default"].createElement(DashboardPage, null)
|
|
2261
|
+
}))))));
|
|
2204
2262
|
} else {
|
|
2205
|
-
return /* @__PURE__ */ React__default["default"].createElement(Layout, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.BrowserRouter, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.
|
|
2206
|
-
path:
|
|
2263
|
+
return /* @__PURE__ */ React__default["default"].createElement(Layout, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.BrowserRouter, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Routes, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
2264
|
+
path: "/admin/logout"
|
|
2207
2265
|
}, /* @__PURE__ */ React__default["default"].createElement(LogoutPage, null)), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
|
|
2208
|
-
path:
|
|
2266
|
+
path: "/admin"
|
|
2209
2267
|
}, () => {
|
|
2210
2268
|
window.location.href = "/";
|
|
2211
2269
|
}))));
|