tinacms 1.5.7 → 1.5.9
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/dist/admin/api.d.ts +10 -7
- package/dist/admin/components/GetCollection.d.ts +15 -3
- package/dist/admin/types.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.es.js +472 -208
- package/dist/index.js +472 -206
- package/dist/internalClient/index.d.ts +34 -1
- package/dist/style.css +3 -0
- package/package.json +4 -3
package/dist/index.es.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, TinaMediaStore, DummyMediaStore, useCMS, Nav, BranchBanner, LocalWarning, BillingWarning, Select,
|
|
2
|
+
import { EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, TinaMediaStore, DummyMediaStore, useCMS, Nav, BranchBanner, LocalWarning, BillingWarning, Select, Message, OverflowMenu, CursorPaginator, Input, PopupModal, BaseTextField, Form, wrapFieldsWithMeta, FormStatus, FormBuilder } from "@tinacms/toolkit";
|
|
3
3
|
export * from "@tinacms/toolkit";
|
|
4
4
|
export { MdxFieldPluginExtendible } from "@tinacms/toolkit";
|
|
5
5
|
import { getIntrospectionQuery, buildClientSchema, print, parse, buildSchema } from "graphql";
|
|
@@ -39,6 +39,152 @@ const authenticate = (clientId, frontendUrl) => {
|
|
|
39
39
|
authTab = popupWindow(`${frontendUrl}/signin?clientId=${clientId}&origin=${origin}`, "_blank", window, 1e3, 700);
|
|
40
40
|
});
|
|
41
41
|
};
|
|
42
|
+
class StringBuilder {
|
|
43
|
+
constructor(limit) {
|
|
44
|
+
this.length = 0;
|
|
45
|
+
this.buffer = [];
|
|
46
|
+
this.limit = limit;
|
|
47
|
+
}
|
|
48
|
+
append(str) {
|
|
49
|
+
if (this.length + str.length > this.limit) {
|
|
50
|
+
return true;
|
|
51
|
+
} else {
|
|
52
|
+
this.buffer.push(str);
|
|
53
|
+
this.length += str.length;
|
|
54
|
+
if (this.length > this.limit) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
toString() {
|
|
61
|
+
return this.buffer.join(" ");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const extractText = (data, acc, indexableNodeTypes) => {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
if (data) {
|
|
67
|
+
if (indexableNodeTypes.indexOf(data.type) !== -1 && (data.text || data.value)) {
|
|
68
|
+
const tokens = tokenizeString(data.text || data.value);
|
|
69
|
+
for (const token of tokens) {
|
|
70
|
+
if (acc.append(token)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
(_b = (_a = data.children) == null ? void 0 : _a.forEach) == null ? void 0 : _b.call(_a, (child) => extractText(child, acc, indexableNodeTypes));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const relativePath = (path, collection) => {
|
|
79
|
+
return path.replace(/\\/g, "/").replace(collection.path, "").replace(/^\/|\/$/g, "");
|
|
80
|
+
};
|
|
81
|
+
const tokenizeString = (str) => {
|
|
82
|
+
return str.split(/[\s\.,]+/).map((s) => s.toLowerCase()).filter((s) => s);
|
|
83
|
+
};
|
|
84
|
+
const processTextFieldValue = (value, maxLen) => {
|
|
85
|
+
const tokens = tokenizeString(value);
|
|
86
|
+
const builder = new StringBuilder(maxLen);
|
|
87
|
+
for (const part of tokens) {
|
|
88
|
+
if (builder.append(part)) {
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return builder.toString();
|
|
93
|
+
};
|
|
94
|
+
const processDocumentForIndexing = (data, path, collection, textIndexLength, field) => {
|
|
95
|
+
if (!field) {
|
|
96
|
+
const relPath = relativePath(path, collection);
|
|
97
|
+
data["_id"] = `${collection.name}:${relPath}`;
|
|
98
|
+
data["_relativePath"] = relPath;
|
|
99
|
+
}
|
|
100
|
+
for (const f of collection.fields || (field == null ? void 0 : field.fields) || []) {
|
|
101
|
+
if (!f.searchable) {
|
|
102
|
+
delete data[f.name];
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const isList = f.list;
|
|
106
|
+
if (data[f.name]) {
|
|
107
|
+
if (f.type === "object") {
|
|
108
|
+
if (isList) {
|
|
109
|
+
data[f.name] = data[f.name].map((obj) => processDocumentForIndexing(obj, path, collection, textIndexLength, f));
|
|
110
|
+
} else {
|
|
111
|
+
data[f.name] = processDocumentForIndexing(data[f.name], path, collection, textIndexLength, f);
|
|
112
|
+
}
|
|
113
|
+
} else if (f.type === "string") {
|
|
114
|
+
const fieldTextIndexLength = f.maxSearchIndexFieldLength || textIndexLength;
|
|
115
|
+
if (isList) {
|
|
116
|
+
data[f.name] = data[f.name].map((value) => processTextFieldValue(value, fieldTextIndexLength));
|
|
117
|
+
} else {
|
|
118
|
+
data[f.name] = processTextFieldValue(data[f.name], fieldTextIndexLength);
|
|
119
|
+
}
|
|
120
|
+
} else if (f.type === "rich-text") {
|
|
121
|
+
const fieldTextIndexLength = f.maxSearchIndexFieldLength || textIndexLength;
|
|
122
|
+
if (isList) {
|
|
123
|
+
data[f.name] = data[f.name].map((value) => {
|
|
124
|
+
const acc = new StringBuilder(fieldTextIndexLength);
|
|
125
|
+
extractText(value, acc, ["text", "code_block", "html"]);
|
|
126
|
+
return acc.toString();
|
|
127
|
+
});
|
|
128
|
+
} else {
|
|
129
|
+
const acc = new StringBuilder(fieldTextIndexLength);
|
|
130
|
+
extractText(data[f.name], acc, ["text", "code_block", "html"]);
|
|
131
|
+
data[f.name] = acc.toString();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return data;
|
|
137
|
+
};
|
|
138
|
+
const queryToSearchIndexQuery = (query) => {
|
|
139
|
+
let q;
|
|
140
|
+
const parts = query.split(" ");
|
|
141
|
+
if (parts.length === 1) {
|
|
142
|
+
q = { AND: [parts[0]] };
|
|
143
|
+
} else {
|
|
144
|
+
q = { AND: parts.filter((part) => part.toLowerCase() !== "and") };
|
|
145
|
+
}
|
|
146
|
+
return q;
|
|
147
|
+
};
|
|
148
|
+
const optionsToSearchIndexOptions = (options) => {
|
|
149
|
+
const opt = {};
|
|
150
|
+
if (options == null ? void 0 : options.limit) {
|
|
151
|
+
opt["PAGE"] = {
|
|
152
|
+
SIZE: options.limit,
|
|
153
|
+
NUMBER: (options == null ? void 0 : options.cursor) ? parseInt(options.cursor) : 0
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return opt;
|
|
157
|
+
};
|
|
158
|
+
const parseSearchIndexResponse = (data, options) => {
|
|
159
|
+
const results = data["RESULT"];
|
|
160
|
+
const total = data["RESULT_LENGTH"];
|
|
161
|
+
if ((options == null ? void 0 : options.cursor) && (options == null ? void 0 : options.limit)) {
|
|
162
|
+
const prevCursor = options.cursor === "0" ? null : (parseInt(options.cursor) - 1).toString();
|
|
163
|
+
const nextCursor = total <= (parseInt(options.cursor) + 1) * options.limit ? null : (parseInt(options.cursor) + 1).toString();
|
|
164
|
+
return {
|
|
165
|
+
results,
|
|
166
|
+
total,
|
|
167
|
+
prevCursor,
|
|
168
|
+
nextCursor
|
|
169
|
+
};
|
|
170
|
+
} else if (!(options == null ? void 0 : options.cursor) && (options == null ? void 0 : options.limit)) {
|
|
171
|
+
const prevCursor = null;
|
|
172
|
+
const nextCursor = total <= options.limit ? null : "1";
|
|
173
|
+
return {
|
|
174
|
+
results,
|
|
175
|
+
total,
|
|
176
|
+
prevCursor,
|
|
177
|
+
nextCursor
|
|
178
|
+
};
|
|
179
|
+
} else {
|
|
180
|
+
return {
|
|
181
|
+
results,
|
|
182
|
+
total,
|
|
183
|
+
prevCursor: null,
|
|
184
|
+
nextCursor: null
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
};
|
|
42
188
|
const captureBranchName = /^refs\/heads\/(.*)/;
|
|
43
189
|
const parseRefForBranchName = (ref) => {
|
|
44
190
|
const matches = ref.match(captureBranchName);
|
|
@@ -217,6 +363,9 @@ mutation addPendingDocumentMutation(
|
|
|
217
363
|
this.contentApiBase = ((_d = this.options.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://content.tinajs.io`;
|
|
218
364
|
this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/${this.tinaGraphQLVersion}/content/${this.options.clientId}/github/${encodedBranch}`;
|
|
219
365
|
}
|
|
366
|
+
getBranch() {
|
|
367
|
+
return this.branch;
|
|
368
|
+
}
|
|
220
369
|
async request(query, { variables }) {
|
|
221
370
|
const token = await this.getToken();
|
|
222
371
|
const headers = {
|
|
@@ -502,6 +651,62 @@ class LocalClient extends Client {
|
|
|
502
651
|
return localStorage.getItem(LOCAL_CLIENT_KEY) === "true";
|
|
503
652
|
}
|
|
504
653
|
}
|
|
654
|
+
class TinaCMSSearchClient {
|
|
655
|
+
constructor(client) {
|
|
656
|
+
this.client = client;
|
|
657
|
+
}
|
|
658
|
+
async query(query, options) {
|
|
659
|
+
const q = queryToSearchIndexQuery(query);
|
|
660
|
+
const opt = optionsToSearchIndexOptions(options);
|
|
661
|
+
const optionsParam = opt["PAGE"] ? `&options=${JSON.stringify(opt)}` : "";
|
|
662
|
+
const res = await this.client.fetchWithToken(`${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}?q=${JSON.stringify(q)}${optionsParam}`);
|
|
663
|
+
return parseSearchIndexResponse(await res.json(), options);
|
|
664
|
+
}
|
|
665
|
+
async del(ids) {
|
|
666
|
+
const res = await this.client.fetchWithToken(`${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}?ids=${ids.join(",")}`, {
|
|
667
|
+
method: "DELETE"
|
|
668
|
+
});
|
|
669
|
+
if (res.status !== 200) {
|
|
670
|
+
throw new Error("Failed to update search index");
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
async put(docs) {
|
|
674
|
+
const res = await this.client.fetchWithToken(`${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}`, {
|
|
675
|
+
method: "POST",
|
|
676
|
+
body: JSON.stringify({ docs }),
|
|
677
|
+
headers: {
|
|
678
|
+
"Content-Type": "application/json"
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
if (res.status !== 200) {
|
|
682
|
+
throw new Error("Failed to update search index");
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
supportsClientSideIndexing() {
|
|
686
|
+
return true;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
class LocalSearchClient {
|
|
690
|
+
constructor(client) {
|
|
691
|
+
this.client = client;
|
|
692
|
+
}
|
|
693
|
+
async query(query, options) {
|
|
694
|
+
const q = queryToSearchIndexQuery(query);
|
|
695
|
+
const opt = optionsToSearchIndexOptions(options);
|
|
696
|
+
const optionsParam = opt["PAGE"] ? `&options=${JSON.stringify(opt)}` : "";
|
|
697
|
+
const res = await this.client.fetchWithToken(`http://localhost:4001/searchIndex?q=${JSON.stringify(q)}${optionsParam}`);
|
|
698
|
+
return parseSearchIndexResponse(await res.json(), options);
|
|
699
|
+
}
|
|
700
|
+
del(ids) {
|
|
701
|
+
return Promise.resolve(void 0);
|
|
702
|
+
}
|
|
703
|
+
put(docs) {
|
|
704
|
+
return Promise.resolve(void 0);
|
|
705
|
+
}
|
|
706
|
+
supportsClientSideIndexing() {
|
|
707
|
+
return false;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
505
710
|
function ModalBuilder(modalProps) {
|
|
506
711
|
return /* @__PURE__ */ React.createElement(Modal, null, /* @__PURE__ */ React.createElement(ModalPopup, null, /* @__PURE__ */ React.createElement(ModalHeader, null, modalProps.title), /* @__PURE__ */ React.createElement(ModalBody, {
|
|
507
712
|
padded: true
|
|
@@ -586,8 +791,14 @@ function safeAssertShape(value, yupSchema) {
|
|
|
586
791
|
}
|
|
587
792
|
class TinaAdminApi {
|
|
588
793
|
constructor(cms) {
|
|
794
|
+
var _a, _b, _c, _d;
|
|
795
|
+
this.maxSearchIndexFieldLength = 100;
|
|
589
796
|
this.api = cms.api.tina;
|
|
590
797
|
this.schema = cms.api.tina.schema;
|
|
798
|
+
if (cms.api.search && ((_a = cms.api.search) == null ? void 0 : _a.supportsClientSideIndexing())) {
|
|
799
|
+
this.searchClient = cms.api.searchClient;
|
|
800
|
+
this.maxSearchIndexFieldLength = ((_d = (_c = (_b = this.schema.config) == null ? void 0 : _b.config) == null ? void 0 : _c.search) == null ? void 0 : _d.maxSearchIndexFieldLength) || 100;
|
|
801
|
+
}
|
|
591
802
|
}
|
|
592
803
|
async isAuthenticated() {
|
|
593
804
|
return await this.api.isAuthenticated();
|
|
@@ -606,25 +817,33 @@ class TinaAdminApi {
|
|
|
606
817
|
fetchCollections() {
|
|
607
818
|
return this.schema.getCollections();
|
|
608
819
|
}
|
|
609
|
-
async renameDocument({ collection, relativePath, newRelativePath }) {
|
|
820
|
+
async renameDocument({ collection, relativePath: relativePath2, newRelativePath }) {
|
|
610
821
|
await this.api.request(`#graphql
|
|
611
822
|
mutation RenameDocument($collection: String!, $relativePath: String! $newRelativePath: String!) {
|
|
612
823
|
updateDocument(collection: $collection, relativePath: $relativePath, params: {relativePath: $newRelativePath}){
|
|
613
824
|
__typename
|
|
614
825
|
}
|
|
615
826
|
}
|
|
616
|
-
`, { variables: { collection, relativePath, newRelativePath } });
|
|
827
|
+
`, { variables: { collection, relativePath: relativePath2, newRelativePath } });
|
|
828
|
+
if (this.searchClient) {
|
|
829
|
+
const { document: doc } = await this.fetchDocument(collection.name, newRelativePath);
|
|
830
|
+
const processed = processDocumentForIndexing(doc["_values"], `${collection.path}/${newRelativePath}`, collection, this.maxSearchIndexFieldLength);
|
|
831
|
+
await this.searchClient.put([processed]);
|
|
832
|
+
await this.searchClient.del([`${collection.name}:${relativePath2}`]);
|
|
833
|
+
}
|
|
617
834
|
}
|
|
618
835
|
async deleteDocument({
|
|
619
836
|
collection,
|
|
620
|
-
relativePath
|
|
837
|
+
relativePath: relativePath2
|
|
621
838
|
}) {
|
|
839
|
+
var _a;
|
|
622
840
|
await this.api.request(`#graphql
|
|
623
841
|
mutation DeleteDocument($collection: String!, $relativePath: String! ){
|
|
624
842
|
deleteDocument(collection: $collection, relativePath: $relativePath){
|
|
625
843
|
__typename
|
|
626
844
|
}
|
|
627
|
-
}`, { variables: { collection, relativePath } });
|
|
845
|
+
}`, { variables: { collection, relativePath: relativePath2 } });
|
|
846
|
+
await ((_a = this.searchClient) == null ? void 0 : _a.del([`${collection}:${relativePath2}`]));
|
|
628
847
|
}
|
|
629
848
|
async fetchCollection(collectionName, includeDocuments, folder = "", after, sortKey, order, filterArgs) {
|
|
630
849
|
let filter = null;
|
|
@@ -770,18 +989,43 @@ class TinaAdminApi {
|
|
|
770
989
|
}
|
|
771
990
|
}
|
|
772
991
|
}
|
|
773
|
-
async fetchDocument(collectionName,
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
992
|
+
async fetchDocument(collectionName, relativePath2, values = true) {
|
|
993
|
+
let query;
|
|
994
|
+
if (values) {
|
|
995
|
+
query = `#graphql
|
|
996
|
+
query($collection: String!, $relativePath: String!) {
|
|
997
|
+
document(collection:$collection, relativePath:$relativePath) {
|
|
998
|
+
... on Document {
|
|
999
|
+
_values
|
|
1000
|
+
}
|
|
779
1001
|
}
|
|
780
|
-
}
|
|
781
|
-
|
|
1002
|
+
}`;
|
|
1003
|
+
} else {
|
|
1004
|
+
query = `#graphql
|
|
1005
|
+
query($collection: String!, $relativePath: String!) {
|
|
1006
|
+
document(collection:$collection, relativePath:$relativePath) {
|
|
1007
|
+
__typename
|
|
1008
|
+
... on Document {
|
|
1009
|
+
_sys {
|
|
1010
|
+
title
|
|
1011
|
+
template
|
|
1012
|
+
breadcrumbs
|
|
1013
|
+
path
|
|
1014
|
+
basename
|
|
1015
|
+
relativePath
|
|
1016
|
+
filename
|
|
1017
|
+
extension
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}`;
|
|
1022
|
+
}
|
|
1023
|
+
const response = await this.api.request(query, {
|
|
1024
|
+
variables: { collection: collectionName, relativePath: relativePath2 }
|
|
1025
|
+
});
|
|
782
1026
|
return response;
|
|
783
1027
|
}
|
|
784
|
-
async createDocument(
|
|
1028
|
+
async createDocument(collection, relativePath2, params) {
|
|
785
1029
|
const response = await this.api.request(`#graphql
|
|
786
1030
|
mutation($collection: String!, $relativePath: String!, $params: DocumentMutation!) {
|
|
787
1031
|
createDocument(
|
|
@@ -791,14 +1035,19 @@ class TinaAdminApi {
|
|
|
791
1035
|
){__typename}
|
|
792
1036
|
}`, {
|
|
793
1037
|
variables: {
|
|
794
|
-
collection:
|
|
795
|
-
relativePath,
|
|
1038
|
+
collection: collection.name,
|
|
1039
|
+
relativePath: relativePath2,
|
|
796
1040
|
params
|
|
797
1041
|
}
|
|
798
1042
|
});
|
|
1043
|
+
if (this.searchClient) {
|
|
1044
|
+
const { document: doc } = await this.fetchDocument(collection.name, relativePath2);
|
|
1045
|
+
const processed = processDocumentForIndexing(doc["_values"], `${collection.path}/${relativePath2}`, collection, this.maxSearchIndexFieldLength);
|
|
1046
|
+
await this.searchClient.put([processed]);
|
|
1047
|
+
}
|
|
799
1048
|
return response;
|
|
800
1049
|
}
|
|
801
|
-
async updateDocument(
|
|
1050
|
+
async updateDocument(collection, relativePath2, params) {
|
|
802
1051
|
const response = await this.api.request(`#graphql
|
|
803
1052
|
mutation($collection: String!, $relativePath: String!, $params: DocumentUpdateMutation!) {
|
|
804
1053
|
updateDocument(
|
|
@@ -808,11 +1057,16 @@ class TinaAdminApi {
|
|
|
808
1057
|
){__typename}
|
|
809
1058
|
}`, {
|
|
810
1059
|
variables: {
|
|
811
|
-
collection:
|
|
812
|
-
relativePath,
|
|
1060
|
+
collection: collection.name,
|
|
1061
|
+
relativePath: relativePath2,
|
|
813
1062
|
params
|
|
814
1063
|
}
|
|
815
1064
|
});
|
|
1065
|
+
if (this.searchClient) {
|
|
1066
|
+
const { document: doc } = await this.fetchDocument(collection.name, relativePath2);
|
|
1067
|
+
const processed = processDocumentForIndexing(doc["_values"], `${collection.path}/${relativePath2}`, collection, this.maxSearchIndexFieldLength);
|
|
1068
|
+
await this.searchClient.put([processed]);
|
|
1069
|
+
}
|
|
816
1070
|
return response;
|
|
817
1071
|
}
|
|
818
1072
|
}
|
|
@@ -898,6 +1152,23 @@ const TinaCloudProvider = (props) => {
|
|
|
898
1152
|
} else {
|
|
899
1153
|
cms.api.tina.setBranch(currentBranch);
|
|
900
1154
|
}
|
|
1155
|
+
useEffect(() => {
|
|
1156
|
+
var _a, _b, _c, _d;
|
|
1157
|
+
let searchClient;
|
|
1158
|
+
if (props.isLocalClient) {
|
|
1159
|
+
searchClient = new LocalSearchClient(cms.api.tina);
|
|
1160
|
+
} else {
|
|
1161
|
+
const hasTinaSearch = Boolean((_b = (_a = props.schema.config) == null ? void 0 : _a.search) == null ? void 0 : _b.tina);
|
|
1162
|
+
if (hasTinaSearch) {
|
|
1163
|
+
searchClient = new TinaCMSSearchClient(cms.api.tina);
|
|
1164
|
+
} else {
|
|
1165
|
+
searchClient = (_d = (_c = props.schema.config) == null ? void 0 : _c.search) == null ? void 0 : _d.searchClient;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
if (searchClient) {
|
|
1169
|
+
cms.registerApi("search", searchClient);
|
|
1170
|
+
}
|
|
1171
|
+
}, [props]);
|
|
901
1172
|
if (!cms.api.admin) {
|
|
902
1173
|
cms.registerApi("admin", new TinaAdminApi(cms));
|
|
903
1174
|
}
|
|
@@ -1464,6 +1735,9 @@ var styles = `.tina-tailwind {
|
|
|
1464
1735
|
.tina-tailwind .w-full {
|
|
1465
1736
|
width: 100%;
|
|
1466
1737
|
}
|
|
1738
|
+
.tina-tailwind .min-w-\\[200px\\] {
|
|
1739
|
+
min-width: 200px;
|
|
1740
|
+
}
|
|
1467
1741
|
.tina-tailwind .max-w-0 {
|
|
1468
1742
|
max-width: 0rem;
|
|
1469
1743
|
}
|
|
@@ -2131,16 +2405,16 @@ class ContentCreatorPlugin {
|
|
|
2131
2405
|
this.onChange = options.onChange;
|
|
2132
2406
|
this.initialValues = options.initialValues;
|
|
2133
2407
|
}
|
|
2134
|
-
async onSubmit({ collection, template, relativePath }, cms) {
|
|
2408
|
+
async onSubmit({ collection, template, relativePath: relativePath2 }, cms) {
|
|
2135
2409
|
try {
|
|
2136
2410
|
const selectedCollection = this.collections.find((collectionItem) => collectionItem.slug === collection);
|
|
2137
2411
|
const collectionFormat = selectedCollection.format;
|
|
2138
2412
|
const extensionLength = -1 * (collectionFormat.length + 1);
|
|
2139
|
-
let relativePathWithExt =
|
|
2140
|
-
if (
|
|
2141
|
-
relativePathWithExt = `${
|
|
2413
|
+
let relativePathWithExt = relativePath2;
|
|
2414
|
+
if (relativePath2.slice(extensionLength).toLocaleLowerCase() === `.${collectionFormat}`) {
|
|
2415
|
+
relativePathWithExt = `${relativePath2.slice(0, -3)}.${collectionFormat}`;
|
|
2142
2416
|
} else {
|
|
2143
|
-
relativePathWithExt = `${
|
|
2417
|
+
relativePathWithExt = `${relativePath2}.${collectionFormat}`;
|
|
2144
2418
|
}
|
|
2145
2419
|
const payload = {
|
|
2146
2420
|
relativePath: relativePathWithExt,
|
|
@@ -3158,6 +3432,75 @@ const useGetCollection = (cms, collectionName, includeDocuments = true, folder,
|
|
|
3158
3432
|
const reFetchCollection = () => setResetSate((x) => x + 1);
|
|
3159
3433
|
return { collection, loading, error, reFetchCollection, collectionExtra };
|
|
3160
3434
|
};
|
|
3435
|
+
const useSearchCollection = (cms, collectionName, includeDocuments = true, folder, after = "", search) => {
|
|
3436
|
+
const api = new TinaAdminApi(cms);
|
|
3437
|
+
const schema = cms.api.tina.schema;
|
|
3438
|
+
const collectionExtra = schema.getCollection(collectionName);
|
|
3439
|
+
const [collection, setCollection] = useState(void 0);
|
|
3440
|
+
const [loading, setLoading] = useState(true);
|
|
3441
|
+
const [error, setError] = useState(void 0);
|
|
3442
|
+
const [resetState, setResetSate] = useState(0);
|
|
3443
|
+
useEffect(() => {
|
|
3444
|
+
let cancelled = false;
|
|
3445
|
+
const searchCollection = async () => {
|
|
3446
|
+
if (await api.isAuthenticated() && !folder.loading && !cancelled) {
|
|
3447
|
+
try {
|
|
3448
|
+
const response = await cms.api.search.query(`${search} AND _collection:${collectionName}`, {
|
|
3449
|
+
limit: 15,
|
|
3450
|
+
cursor: after
|
|
3451
|
+
});
|
|
3452
|
+
const docs = await Promise.allSettled(response.results.map((result) => {
|
|
3453
|
+
const [collection2, relativePath2] = result._id.split(":");
|
|
3454
|
+
return api.fetchDocument(collection2, relativePath2, false);
|
|
3455
|
+
}));
|
|
3456
|
+
const edges = docs.filter((p) => {
|
|
3457
|
+
var _a;
|
|
3458
|
+
return p.status === "fulfilled" && !!((_a = p.value) == null ? void 0 : _a.document);
|
|
3459
|
+
}).map((result) => ({ node: result.value.document }));
|
|
3460
|
+
const c = await api.fetchCollection(collectionName, false, "");
|
|
3461
|
+
setCollection({
|
|
3462
|
+
format: collection.format,
|
|
3463
|
+
label: collection.label,
|
|
3464
|
+
name: collectionName,
|
|
3465
|
+
templates: collection.templates,
|
|
3466
|
+
documents: {
|
|
3467
|
+
pageInfo: {
|
|
3468
|
+
hasNextPage: !!response.nextCursor,
|
|
3469
|
+
hasPreviousPage: !!response.prevCursor,
|
|
3470
|
+
startCursor: "",
|
|
3471
|
+
endCursor: response.nextCursor || ""
|
|
3472
|
+
},
|
|
3473
|
+
edges
|
|
3474
|
+
}
|
|
3475
|
+
});
|
|
3476
|
+
} catch (error2) {
|
|
3477
|
+
cms.alerts.error(`[${error2.name}] GetCollection failed: ${error2.message}`);
|
|
3478
|
+
console.error(error2);
|
|
3479
|
+
setCollection(void 0);
|
|
3480
|
+
setError(error2);
|
|
3481
|
+
}
|
|
3482
|
+
setLoading(false);
|
|
3483
|
+
}
|
|
3484
|
+
};
|
|
3485
|
+
if (cancelled)
|
|
3486
|
+
return;
|
|
3487
|
+
setLoading(true);
|
|
3488
|
+
searchCollection();
|
|
3489
|
+
return () => {
|
|
3490
|
+
cancelled = true;
|
|
3491
|
+
};
|
|
3492
|
+
}, [
|
|
3493
|
+
cms,
|
|
3494
|
+
collectionName,
|
|
3495
|
+
folder.loading,
|
|
3496
|
+
folder.fullyQualifiedName,
|
|
3497
|
+
resetState,
|
|
3498
|
+
after,
|
|
3499
|
+
search
|
|
3500
|
+
]);
|
|
3501
|
+
const reFetchCollection = () => setResetSate((x) => x + 1);
|
|
3502
|
+
return { collection, loading, error, reFetchCollection, collectionExtra };
|
|
3503
|
+
};
|
|
3161
3504
|
const GetCollection = ({
|
|
3162
3505
|
cms,
|
|
3163
3506
|
collectionName,
|
|
@@ -3166,10 +3509,11 @@ const GetCollection = ({
|
|
|
3166
3509
|
startCursor,
|
|
3167
3510
|
sortKey,
|
|
3168
3511
|
children,
|
|
3169
|
-
filterArgs
|
|
3512
|
+
filterArgs,
|
|
3513
|
+
search
|
|
3170
3514
|
}) => {
|
|
3171
3515
|
const navigate = useNavigate();
|
|
3172
|
-
const { collection, loading, error, reFetchCollection, collectionExtra } = useGetCollection(cms, collectionName, includeDocuments, folder, startCursor || "", sortKey, filterArgs) || {};
|
|
3516
|
+
const { collection, loading, error, reFetchCollection, collectionExtra } = search ? useSearchCollection(cms, collectionName, includeDocuments, folder, startCursor || "", search) : useGetCollection(cms, collectionName, includeDocuments, folder, startCursor || "", sortKey, filterArgs) || {};
|
|
3173
3517
|
useEffect(() => {
|
|
3174
3518
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
3175
3519
|
if (loading)
|
|
@@ -3177,9 +3521,10 @@ const GetCollection = ({
|
|
|
3177
3521
|
const collectionDefinition = cms.api.tina.schema.getCollection(collection.name);
|
|
3178
3522
|
const allowCreate = (_c = (_b = (_a = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _a.allowedActions) == null ? void 0 : _b.create) != null ? _c : true;
|
|
3179
3523
|
const allowDelete = (_f = (_e = (_d = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _d.allowedActions) == null ? void 0 : _e.delete) != null ? _f : true;
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3524
|
+
const collectionResponse = collection;
|
|
3525
|
+
if (!allowCreate && !allowDelete && ((_h = (_g = collectionResponse.documents) == null ? void 0 : _g.edges) == null ? void 0 : _h.length) === 1 && ((_k = (_j = (_i = collectionResponse.documents) == null ? void 0 : _i.edges[0]) == null ? void 0 : _j.node) == null ? void 0 : _k.__typename) !== "Folder") {
|
|
3526
|
+
const doc = collectionResponse.documents.edges[0].node;
|
|
3527
|
+
handleNavigate(navigate, cms, collectionResponse, collectionDefinition, doc);
|
|
3183
3528
|
}
|
|
3184
3529
|
}, [(collection == null ? void 0 : collection.name) || "", loading]);
|
|
3185
3530
|
if (error) {
|
|
@@ -3308,13 +3653,14 @@ const CollectionListPage = () => {
|
|
|
3308
3653
|
after: "",
|
|
3309
3654
|
booleanEquals: null
|
|
3310
3655
|
});
|
|
3311
|
-
const [activeSearch, setActiveSearch] = React.useState(false);
|
|
3312
3656
|
const [endCursor, setEndCursor] = useState("");
|
|
3313
3657
|
const [prevCursors, setPrevCursors] = useState([]);
|
|
3314
3658
|
const [sortKey, setSortKey] = useState(isSSR ? "" : window.localStorage.getItem(`${LOCAL_STORAGE_KEY}.${collectionName}`) || JSON.stringify({
|
|
3315
3659
|
order: "asc",
|
|
3316
3660
|
name: ""
|
|
3317
3661
|
}));
|
|
3662
|
+
const [search, setSearch] = useState("");
|
|
3663
|
+
const [searchInput, setSearchInput] = useState("");
|
|
3318
3664
|
const { order = "asc", name: sortName } = JSON.parse(sortKey || "{}");
|
|
3319
3665
|
const [sortOrder, setSortOrder] = useState(order);
|
|
3320
3666
|
const loc = useLocation();
|
|
@@ -3359,25 +3705,20 @@ const CollectionListPage = () => {
|
|
|
3359
3705
|
before: "",
|
|
3360
3706
|
after: "",
|
|
3361
3707
|
booleanEquals: null
|
|
3362
|
-
}
|
|
3708
|
+
},
|
|
3709
|
+
search
|
|
3363
3710
|
}, (collection, _loading, reFetchCollection, collectionExtra) => {
|
|
3364
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
3711
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
3365
3712
|
collection.documents.totalCount;
|
|
3366
3713
|
const documents = collection.documents.edges;
|
|
3367
3714
|
const admin = cms.api.admin;
|
|
3368
3715
|
const pageInfo = collection.documents.pageInfo;
|
|
3369
3716
|
const fields = (_a = collectionExtra.fields) == null ? void 0 : _a.filter((x) => ["string", "number", "datetime", "boolean"].includes(x.type));
|
|
3370
3717
|
const sortField = fields == null ? void 0 : fields.find((field) => field.name === sortName);
|
|
3371
|
-
const
|
|
3372
|
-
return ["string", "datetime", "boolean"].includes(x.type) && !x.list;
|
|
3373
|
-
});
|
|
3374
|
-
const filterField = filterFields == null ? void 0 : filterFields.find((x) => x.name === vars.filterField);
|
|
3375
|
-
const showStartsWith = (filterField == null ? void 0 : filterField.type) === "string" && !filterField.list;
|
|
3376
|
-
const showDateFilter = (filterField == null ? void 0 : filterField.type) === "datetime";
|
|
3377
|
-
const showBooleanToggle = (filterField == null ? void 0 : filterField.type) === "boolean" && !filterField.list;
|
|
3718
|
+
const searchEnabled = !!((_d = (_c = (_b = cms.api.tina.schema) == null ? void 0 : _b.config) == null ? void 0 : _c.config) == null ? void 0 : _d.search);
|
|
3378
3719
|
const collectionDefinition = cms.api.tina.schema.getCollection(collection.name);
|
|
3379
|
-
const allowCreate = (
|
|
3380
|
-
const allowDelete = (
|
|
3720
|
+
const allowCreate = (_g = (_f = (_e = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _e.allowedActions) == null ? void 0 : _f.create) != null ? _g : true;
|
|
3721
|
+
const allowDelete = (_j = (_i = (_h = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _h.allowedActions) == null ? void 0 : _i.delete) != null ? _j : true;
|
|
3381
3722
|
const folderView = folder.fullyQualifiedName !== "";
|
|
3382
3723
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, deleteModalOpen && /* @__PURE__ */ React.createElement(DeleteModal, {
|
|
3383
3724
|
filename: vars.relativePath,
|
|
@@ -3419,7 +3760,7 @@ const CollectionListPage = () => {
|
|
|
3419
3760
|
},
|
|
3420
3761
|
close: () => setRenameModalOpen(false)
|
|
3421
3762
|
}), /* @__PURE__ */ React.createElement(PageHeader, {
|
|
3422
|
-
isLocalMode: (
|
|
3763
|
+
isLocalMode: (_l = (_k = cms == null ? void 0 : cms.api) == null ? void 0 : _k.tina) == null ? void 0 : _l.isLocalMode
|
|
3423
3764
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
3424
3765
|
className: "w-full grid grid-flow-col items-end gap-4"
|
|
3425
3766
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
@@ -3427,8 +3768,8 @@ const CollectionListPage = () => {
|
|
|
3427
3768
|
}, /* @__PURE__ */ React.createElement("h3", {
|
|
3428
3769
|
className: "font-sans text-2xl text-gray-700"
|
|
3429
3770
|
}, collection.label ? collection.label : collection.name), /* @__PURE__ */ React.createElement("div", {
|
|
3430
|
-
className: "flex gap-4 items-
|
|
3431
|
-
}, (fields == null ? void 0 : fields.length) > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
3771
|
+
className: "flex gap-4 items-start flex-wrap"
|
|
3772
|
+
}, (fields == null ? void 0 : fields.length) > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, !search && /* @__PURE__ */ React.createElement("div", {
|
|
3432
3773
|
className: "flex flex-col gap-2 items-start"
|
|
3433
3774
|
}, /* @__PURE__ */ React.createElement("label", {
|
|
3434
3775
|
htmlFor: "sort",
|
|
@@ -3473,152 +3814,22 @@ const CollectionListPage = () => {
|
|
|
3473
3814
|
setSortOrder(val.order);
|
|
3474
3815
|
}
|
|
3475
3816
|
}
|
|
3476
|
-
})), /* @__PURE__ */ React.createElement("form", {
|
|
3477
|
-
className: "flex flex-wrap gap-4 items-end"
|
|
3478
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
3479
|
-
className: "flex flex-shrink-0 flex-col gap-2 items-start"
|
|
3480
|
-
}, /* @__PURE__ */ React.createElement("label", {
|
|
3481
|
-
htmlFor: "filter",
|
|
3482
|
-
className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
|
|
3483
|
-
}, "Filter by"), /* @__PURE__ */ React.createElement(Select, {
|
|
3484
|
-
name: "filter",
|
|
3485
|
-
options: [
|
|
3486
|
-
{
|
|
3487
|
-
label: "None",
|
|
3488
|
-
value: ""
|
|
3489
|
-
},
|
|
3490
|
-
...filterFields.map((x) => ({
|
|
3491
|
-
label: typeof x.label === "string" && x.label || x.name,
|
|
3492
|
-
value: x.name
|
|
3493
|
-
}))
|
|
3494
|
-
],
|
|
3495
|
-
input: {
|
|
3496
|
-
id: "filter",
|
|
3497
|
-
name: "filter",
|
|
3498
|
-
value: vars.filterField,
|
|
3499
|
-
onChange: (e) => {
|
|
3500
|
-
const val = e.target.value;
|
|
3501
|
-
setEndCursor("");
|
|
3502
|
-
setPrevCursors([]);
|
|
3503
|
-
setVars((old) => ({
|
|
3504
|
-
...old,
|
|
3505
|
-
filterField: val
|
|
3506
|
-
}));
|
|
3507
|
-
if (!val) {
|
|
3508
|
-
reFetchCollection();
|
|
3509
|
-
}
|
|
3510
|
-
}
|
|
3511
|
-
}
|
|
3512
|
-
})), showStartsWith && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
3513
|
-
className: "flex flex-shrink-0 flex-col gap-2 items-start"
|
|
3514
|
-
}, /* @__PURE__ */ React.createElement("label", {
|
|
3515
|
-
htmlFor: "startsWith",
|
|
3516
|
-
className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
|
|
3517
|
-
}, "Starts with"), /* @__PURE__ */ React.createElement(Input, {
|
|
3518
|
-
name: "startsWith",
|
|
3519
|
-
id: "startsWith",
|
|
3520
|
-
value: vars.startsWith,
|
|
3521
|
-
onChange: (e) => {
|
|
3522
|
-
const val = e.target.value;
|
|
3523
|
-
setVars((old) => ({
|
|
3524
|
-
...old,
|
|
3525
|
-
startsWith: val,
|
|
3526
|
-
after: "",
|
|
3527
|
-
before: "",
|
|
3528
|
-
booleanEquals: null
|
|
3529
|
-
}));
|
|
3530
|
-
}
|
|
3531
|
-
}))), showDateFilter && /* @__PURE__ */ React.createElement("div", {
|
|
3532
|
-
className: "flex flex-shrink-0 gap-4"
|
|
3533
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
3534
|
-
className: "flex flex-col gap-2 items-start"
|
|
3535
|
-
}, /* @__PURE__ */ React.createElement("label", {
|
|
3536
|
-
htmlFor: "dateAfter",
|
|
3537
|
-
className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
|
|
3538
|
-
}, "After"), /* @__PURE__ */ React.createElement(ReactDateTimeWithStyles, {
|
|
3539
|
-
inputProps: {
|
|
3540
|
-
className: textFieldClasses
|
|
3541
|
-
},
|
|
3542
|
-
value: vars.after,
|
|
3543
|
-
onChange: (e) => {
|
|
3544
|
-
setVars((old) => ({
|
|
3545
|
-
...old,
|
|
3546
|
-
after: typeof e.format === "function" ? e.format() : "",
|
|
3547
|
-
booleanEquals: null,
|
|
3548
|
-
startsWith: ""
|
|
3549
|
-
}));
|
|
3550
|
-
}
|
|
3551
3817
|
})), /* @__PURE__ */ React.createElement("div", {
|
|
3552
|
-
className: "flex flex-col gap-2 items-start"
|
|
3553
|
-
}, /* @__PURE__ */ React.createElement(
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
value: vars.before,
|
|
3561
|
-
onChange: (e) => {
|
|
3562
|
-
setVars((old) => ({
|
|
3563
|
-
...old,
|
|
3564
|
-
before: typeof e.format === "function" ? e.format() : "",
|
|
3565
|
-
booleanEquals: null,
|
|
3566
|
-
startsWith: ""
|
|
3567
|
-
}));
|
|
3568
|
-
}
|
|
3569
|
-
}))), showBooleanToggle && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
3570
|
-
className: "flex flex-col gap-2 items-start"
|
|
3571
|
-
}, /* @__PURE__ */ React.createElement("label", {
|
|
3572
|
-
htmlFor: "toggle",
|
|
3818
|
+
className: "flex flex-1 flex-col gap-2 items-start w-full"
|
|
3819
|
+
}, searchEnabled ? /* @__PURE__ */ React.createElement(SearchInput, {
|
|
3820
|
+
loading: _loading,
|
|
3821
|
+
search,
|
|
3822
|
+
setSearch,
|
|
3823
|
+
searchInput,
|
|
3824
|
+
setSearchInput
|
|
3825
|
+
}) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("label", {
|
|
3573
3826
|
className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
|
|
3574
|
-
},
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
setVars((old) => ({
|
|
3581
|
-
...old,
|
|
3582
|
-
booleanEquals: !old.booleanEquals,
|
|
3583
|
-
after: "",
|
|
3584
|
-
before: "",
|
|
3585
|
-
startsWith: ""
|
|
3586
|
-
}));
|
|
3587
|
-
}
|
|
3588
|
-
},
|
|
3589
|
-
name: "toggle"
|
|
3590
|
-
}))), (showStartsWith || showDateFilter || showBooleanToggle) && /* @__PURE__ */ React.createElement("div", {
|
|
3591
|
-
className: "flex gap-3"
|
|
3592
|
-
}, /* @__PURE__ */ React.createElement(Button, {
|
|
3593
|
-
onClick: () => {
|
|
3594
|
-
setActiveSearch(true);
|
|
3595
|
-
setEndCursor("");
|
|
3596
|
-
setPrevCursors([]);
|
|
3597
|
-
reFetchCollection();
|
|
3598
|
-
},
|
|
3599
|
-
variant: "primary",
|
|
3600
|
-
type: "submit"
|
|
3601
|
-
}, "Search", " ", /* @__PURE__ */ React.createElement(BiSearch, {
|
|
3602
|
-
className: "w-5 h-full ml-1.5 opacity-70"
|
|
3603
|
-
})), (vars.startsWith || vars.after || vars.before || vars.booleanEquals) && /* @__PURE__ */ React.createElement(Button, {
|
|
3604
|
-
onClick: () => {
|
|
3605
|
-
setActiveSearch(false);
|
|
3606
|
-
setVars((old) => ({
|
|
3607
|
-
...old,
|
|
3608
|
-
filterField: "",
|
|
3609
|
-
startsWith: "",
|
|
3610
|
-
after: "",
|
|
3611
|
-
before: "",
|
|
3612
|
-
booleanEquals: null
|
|
3613
|
-
}));
|
|
3614
|
-
setEndCursor("");
|
|
3615
|
-
setPrevCursors([]);
|
|
3616
|
-
reFetchCollection();
|
|
3617
|
-
},
|
|
3618
|
-
variant: "white"
|
|
3619
|
-
}, "Clear", " ", /* @__PURE__ */ React.createElement(BiX, {
|
|
3620
|
-
className: "w-5 h-full ml-1 opacity-70"
|
|
3621
|
-
}))))))), /* @__PURE__ */ React.createElement("div", {
|
|
3827
|
+
}, "Search"), /* @__PURE__ */ React.createElement(Message, {
|
|
3828
|
+
link: "https://tina.io/docs/reference/search/overview",
|
|
3829
|
+
linkLabel: "Read The Docs",
|
|
3830
|
+
type: "info",
|
|
3831
|
+
size: "small"
|
|
3832
|
+
}, "Search not configured.")))))), /* @__PURE__ */ React.createElement("div", {
|
|
3622
3833
|
className: "flex self-end justify-self-end"
|
|
3623
3834
|
}, !collection.templates && allowCreate && /* @__PURE__ */ React.createElement(Link, {
|
|
3624
3835
|
to: `/${folder.fullyQualifiedName ? [
|
|
@@ -3643,7 +3854,7 @@ const CollectionListPage = () => {
|
|
|
3643
3854
|
className: "table-auto shadow bg-white border-b border-gray-200 w-full max-w-full rounded-lg"
|
|
3644
3855
|
}, /* @__PURE__ */ React.createElement("tbody", {
|
|
3645
3856
|
className: "divide-y divide-gray-150"
|
|
3646
|
-
},
|
|
3857
|
+
}, folder.name && !search && /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("td", {
|
|
3647
3858
|
colSpan: 5
|
|
3648
3859
|
}, /* @__PURE__ */ React.createElement(Breadcrumb, {
|
|
3649
3860
|
folder,
|
|
@@ -3834,6 +4045,59 @@ const CollectionListPage = () => {
|
|
|
3834
4045
|
}));
|
|
3835
4046
|
});
|
|
3836
4047
|
};
|
|
4048
|
+
const SearchInput = ({
|
|
4049
|
+
loading,
|
|
4050
|
+
search,
|
|
4051
|
+
setSearch,
|
|
4052
|
+
searchInput,
|
|
4053
|
+
setSearchInput
|
|
4054
|
+
}) => {
|
|
4055
|
+
const [searchLoaded, setSearchLoaded] = useState(false);
|
|
4056
|
+
useEffect(() => {
|
|
4057
|
+
if (loading) {
|
|
4058
|
+
setSearchLoaded(false);
|
|
4059
|
+
} else {
|
|
4060
|
+
setSearchLoaded(true);
|
|
4061
|
+
}
|
|
4062
|
+
}, [loading]);
|
|
4063
|
+
return /* @__PURE__ */ React.createElement("form", {
|
|
4064
|
+
className: "flex flex-1 flex-col gap-2 items-start w-full"
|
|
4065
|
+
}, /* @__PURE__ */ React.createElement("label", {
|
|
4066
|
+
htmlFor: "search",
|
|
4067
|
+
className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
|
|
4068
|
+
}, "Search"), /* @__PURE__ */ React.createElement("div", {
|
|
4069
|
+
className: "flex flex-wrap items-center gap-3"
|
|
4070
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
4071
|
+
className: "flex-1 min-w-[200px]"
|
|
4072
|
+
}, /* @__PURE__ */ React.createElement(Input, {
|
|
4073
|
+
type: "text",
|
|
4074
|
+
name: "search",
|
|
4075
|
+
placeholder: "Search",
|
|
4076
|
+
value: searchInput,
|
|
4077
|
+
onChange: (e) => {
|
|
4078
|
+
setSearchInput(e.target.value);
|
|
4079
|
+
}
|
|
4080
|
+
})), /* @__PURE__ */ React.createElement("div", {
|
|
4081
|
+
className: "flex gap-3"
|
|
4082
|
+
}, /* @__PURE__ */ React.createElement(Button, {
|
|
4083
|
+
onClick: () => {
|
|
4084
|
+
setSearch(searchInput);
|
|
4085
|
+
setSearchLoaded(false);
|
|
4086
|
+
},
|
|
4087
|
+
variant: "primary",
|
|
4088
|
+
type: "submit"
|
|
4089
|
+
}, "Search ", /* @__PURE__ */ React.createElement(BiSearch, {
|
|
4090
|
+
className: "w-5 h-full ml-1.5 opacity-70"
|
|
4091
|
+
})), search && searchLoaded && /* @__PURE__ */ React.createElement(Button, {
|
|
4092
|
+
onClick: () => {
|
|
4093
|
+
setSearch("");
|
|
4094
|
+
setSearchInput("");
|
|
4095
|
+
},
|
|
4096
|
+
variant: "white"
|
|
4097
|
+
}, "Clear ", /* @__PURE__ */ React.createElement(BiX, {
|
|
4098
|
+
className: "w-5 h-full ml-1 opacity-70"
|
|
4099
|
+
})))));
|
|
4100
|
+
};
|
|
3837
4101
|
const Breadcrumb = ({ folder, navigate, collectionName }) => {
|
|
3838
4102
|
const folderArray = folder.name.split("/");
|
|
3839
4103
|
return /* @__PURE__ */ React.createElement("div", {
|
|
@@ -3944,14 +4208,14 @@ function FaUnlock(props) {
|
|
|
3944
4208
|
const createDocument = async (cms, collection, template, mutationInfo, folder, values) => {
|
|
3945
4209
|
const api = new TinaAdminApi(cms);
|
|
3946
4210
|
const { filename, ...leftover } = values;
|
|
3947
|
-
const
|
|
4211
|
+
const relativePath2 = `${folder ? `${folder}/` : ""}${filename}.${collection.format}`;
|
|
3948
4212
|
const params = api.schema.transformPayload(collection.name, {
|
|
3949
4213
|
_collection: collection.name,
|
|
3950
4214
|
...template && { _template: template.name },
|
|
3951
4215
|
...leftover
|
|
3952
4216
|
});
|
|
3953
4217
|
if (await api.isAuthenticated()) {
|
|
3954
|
-
await api.createDocument(collection
|
|
4218
|
+
await api.createDocument(collection, relativePath2, params);
|
|
3955
4219
|
} else {
|
|
3956
4220
|
const authMessage = `CreateDocument failed: User is no longer authenticated; please login and try again.`;
|
|
3957
4221
|
cms.alerts.error(authMessage);
|
|
@@ -4146,7 +4410,7 @@ const RenderForm$1 = ({
|
|
|
4146
4410
|
onPristineChange: setFormIsPristine
|
|
4147
4411
|
})));
|
|
4148
4412
|
};
|
|
4149
|
-
const useGetDocument = (cms, collectionName,
|
|
4413
|
+
const useGetDocument = (cms, collectionName, relativePath2) => {
|
|
4150
4414
|
const api = new TinaAdminApi(cms);
|
|
4151
4415
|
const [document, setDocument] = useState(void 0);
|
|
4152
4416
|
const [loading, setLoading] = useState(true);
|
|
@@ -4155,7 +4419,7 @@ const useGetDocument = (cms, collectionName, relativePath) => {
|
|
|
4155
4419
|
const fetchDocument = async () => {
|
|
4156
4420
|
if (api.isAuthenticated()) {
|
|
4157
4421
|
try {
|
|
4158
|
-
const response = await api.fetchDocument(collectionName,
|
|
4422
|
+
const response = await api.fetchDocument(collectionName, relativePath2);
|
|
4159
4423
|
setDocument(response.document);
|
|
4160
4424
|
} catch (error2) {
|
|
4161
4425
|
cms.alerts.error(`[${error2.name}] GetDocument failed: ${error2.message}`);
|
|
@@ -4168,16 +4432,16 @@ const useGetDocument = (cms, collectionName, relativePath) => {
|
|
|
4168
4432
|
};
|
|
4169
4433
|
setLoading(true);
|
|
4170
4434
|
fetchDocument();
|
|
4171
|
-
}, [cms, collectionName,
|
|
4435
|
+
}, [cms, collectionName, relativePath2]);
|
|
4172
4436
|
return { document, loading, error };
|
|
4173
4437
|
};
|
|
4174
4438
|
const GetDocument = ({
|
|
4175
4439
|
cms,
|
|
4176
4440
|
collectionName,
|
|
4177
|
-
relativePath,
|
|
4441
|
+
relativePath: relativePath2,
|
|
4178
4442
|
children
|
|
4179
4443
|
}) => {
|
|
4180
|
-
const { document, loading, error } = useGetDocument(cms, collectionName,
|
|
4444
|
+
const { document, loading, error } = useGetDocument(cms, collectionName, relativePath2);
|
|
4181
4445
|
if (error) {
|
|
4182
4446
|
return /* @__PURE__ */ React.createElement(FullscreenError, null);
|
|
4183
4447
|
}
|
|
@@ -4196,7 +4460,7 @@ const CollectionDuplicatePage = () => {
|
|
|
4196
4460
|
folder,
|
|
4197
4461
|
includeDocuments: false
|
|
4198
4462
|
}, (collection) => {
|
|
4199
|
-
const
|
|
4463
|
+
const relativePath2 = `${filename.startsWith("~/") ? filename.substring(2) : filename}.${collection.format}`;
|
|
4200
4464
|
const mutationInfo = {
|
|
4201
4465
|
includeCollection: true,
|
|
4202
4466
|
includeTemplate: !!collection.templates
|
|
@@ -4204,7 +4468,7 @@ const CollectionDuplicatePage = () => {
|
|
|
4204
4468
|
return /* @__PURE__ */ React.createElement(GetDocument, {
|
|
4205
4469
|
cms,
|
|
4206
4470
|
collectionName: collection.name,
|
|
4207
|
-
relativePath
|
|
4471
|
+
relativePath: relativePath2
|
|
4208
4472
|
}, (document) => {
|
|
4209
4473
|
var _a;
|
|
4210
4474
|
return /* @__PURE__ */ React.createElement(RenderForm$1, {
|
|
@@ -4218,11 +4482,11 @@ const CollectionDuplicatePage = () => {
|
|
|
4218
4482
|
});
|
|
4219
4483
|
}));
|
|
4220
4484
|
};
|
|
4221
|
-
const updateDocument = async (cms,
|
|
4485
|
+
const updateDocument = async (cms, relativePath2, collection, mutationInfo, values) => {
|
|
4222
4486
|
const api = new TinaAdminApi(cms);
|
|
4223
4487
|
const params = api.schema.transformPayload(collection.name, values);
|
|
4224
4488
|
if (await api.isAuthenticated()) {
|
|
4225
|
-
await api.updateDocument(collection
|
|
4489
|
+
await api.updateDocument(collection, relativePath2, params);
|
|
4226
4490
|
} else {
|
|
4227
4491
|
const authMessage = `UpdateDocument failed: User is no longer authenticated; please login and try again.`;
|
|
4228
4492
|
cms.alerts.error(authMessage);
|
|
@@ -4241,7 +4505,7 @@ const CollectionUpdatePage = () => {
|
|
|
4241
4505
|
folder,
|
|
4242
4506
|
includeDocuments: false
|
|
4243
4507
|
}, (collection) => {
|
|
4244
|
-
const
|
|
4508
|
+
const relativePath2 = `${resolvedFile}.${collection.format}`;
|
|
4245
4509
|
const mutationInfo = {
|
|
4246
4510
|
includeCollection: true,
|
|
4247
4511
|
includeTemplate: !!collection.templates
|
|
@@ -4249,12 +4513,12 @@ const CollectionUpdatePage = () => {
|
|
|
4249
4513
|
return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(GetDocument, {
|
|
4250
4514
|
cms,
|
|
4251
4515
|
collectionName: collection.name,
|
|
4252
|
-
relativePath
|
|
4516
|
+
relativePath: relativePath2
|
|
4253
4517
|
}, (document) => /* @__PURE__ */ React.createElement(RenderForm, {
|
|
4254
4518
|
cms,
|
|
4255
4519
|
document,
|
|
4256
4520
|
filename: resolvedFile,
|
|
4257
|
-
relativePath,
|
|
4521
|
+
relativePath: relativePath2,
|
|
4258
4522
|
collection,
|
|
4259
4523
|
mutationInfo
|
|
4260
4524
|
})));
|
|
@@ -4264,14 +4528,14 @@ const RenderForm = ({
|
|
|
4264
4528
|
cms,
|
|
4265
4529
|
document,
|
|
4266
4530
|
filename,
|
|
4267
|
-
relativePath,
|
|
4531
|
+
relativePath: relativePath2,
|
|
4268
4532
|
collection,
|
|
4269
4533
|
mutationInfo
|
|
4270
4534
|
}) => {
|
|
4271
4535
|
var _a, _b;
|
|
4272
4536
|
const [formIsPristine, setFormIsPristine] = useState(true);
|
|
4273
4537
|
const schema = cms.api.tina.schema;
|
|
4274
|
-
const parentFolder2 =
|
|
4538
|
+
const parentFolder2 = relativePath2.split("/").slice(0, -1).join("/");
|
|
4275
4539
|
const schemaCollection = schema.getCollection(collection.name);
|
|
4276
4540
|
const template = schema.getTemplateForData({
|
|
4277
4541
|
collection: schemaCollection,
|
|
@@ -4291,7 +4555,7 @@ const RenderForm = ({
|
|
|
4291
4555
|
initialValues: document._values,
|
|
4292
4556
|
onSubmit: async (values) => {
|
|
4293
4557
|
try {
|
|
4294
|
-
await updateDocument(cms,
|
|
4558
|
+
await updateDocument(cms, relativePath2, collection, mutationInfo, values);
|
|
4295
4559
|
cms.alerts.success("Document updated!");
|
|
4296
4560
|
} catch (error) {
|
|
4297
4561
|
console.error(error);
|
|
@@ -4299,7 +4563,7 @@ const RenderForm = ({
|
|
|
4299
4563
|
}
|
|
4300
4564
|
}
|
|
4301
4565
|
});
|
|
4302
|
-
}, [cms, document,
|
|
4566
|
+
}, [cms, document, relativePath2, collection, mutationInfo]);
|
|
4303
4567
|
const navBreakpoint = 1e3;
|
|
4304
4568
|
const windowWidth = useWindowWidth();
|
|
4305
4569
|
const renderNavToggle = windowWidth < navBreakpoint + 1;
|
|
@@ -4604,4 +4868,4 @@ const defineStaticConfig = (config) => {
|
|
|
4604
4868
|
return config;
|
|
4605
4869
|
};
|
|
4606
4870
|
const defineConfig = defineStaticConfig;
|
|
4607
|
-
export { AuthWallInner, Client, DEFAULT_LOCAL_TINA_GQL_SERVER_URL, LocalClient, RouteMappingPlugin, TinaAdmin, TinaAdminApi, TinaCMSProvider2, TinaCloudAuthWall, TinaCloudProvider, assertShape, asyncPoll, createClient, TinaCMSProvider2 as default, defineConfig, defineLegacyConfig, defineSchema, defineStaticConfig, getStaticPropsForTina, gql, safeAssertShape, staticRequest, useDocumentCreatorPlugin, useTinaAuthRedirect };
|
|
4871
|
+
export { AuthWallInner, Client, DEFAULT_LOCAL_TINA_GQL_SERVER_URL, LocalClient, LocalSearchClient, RouteMappingPlugin, TinaAdmin, TinaAdminApi, TinaCMSProvider2, TinaCMSSearchClient, TinaCloudAuthWall, TinaCloudProvider, assertShape, asyncPoll, createClient, TinaCMSProvider2 as default, defineConfig, defineLegacyConfig, defineSchema, defineStaticConfig, getStaticPropsForTina, gql, safeAssertShape, staticRequest, useDocumentCreatorPlugin, useTinaAuthRedirect };
|