tinacms 0.68.14 → 0.68.15
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 +1 -1
- package/dist/admin/components/GetCollection.d.ts +4 -2
- package/dist/index.es.js +135 -20
- package/dist/index.js +134 -19
- package/dist/style.css +11 -2
- package/package.json +2 -2
package/dist/admin/api.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare class TinaAdminApi {
|
|
|
25
25
|
collection: string;
|
|
26
26
|
relativePath: string;
|
|
27
27
|
}): Promise<void>;
|
|
28
|
-
fetchCollection(collectionName: string, includeDocuments: boolean, after?: string): Promise<Collection>;
|
|
28
|
+
fetchCollection(collectionName: string, includeDocuments: boolean, after?: string, sortKey?: string, order?: 'asc' | 'desc'): Promise<Collection>;
|
|
29
29
|
fetchDocument(collectionName: string, relativePath: string): Promise<{
|
|
30
30
|
document: DocumentForm;
|
|
31
31
|
}>;
|
|
@@ -12,17 +12,19 @@ limitations under the License.
|
|
|
12
12
|
*/
|
|
13
13
|
import type { TinaCMS } from '@tinacms/toolkit';
|
|
14
14
|
import type { Collection } from '../types';
|
|
15
|
-
export declare const useGetCollection: (cms: TinaCMS, collectionName: string, includeDocuments?: boolean, after?: string) => {
|
|
15
|
+
export declare const useGetCollection: (cms: TinaCMS, collectionName: string, includeDocuments?: boolean, after?: string, sortKey?: string) => {
|
|
16
16
|
collection: Collection;
|
|
17
17
|
loading: boolean;
|
|
18
18
|
error: Error;
|
|
19
19
|
reFetchCollection: () => void;
|
|
20
|
+
collectionExtra: import("@tinacms/schema-tools").TinaCloudCollection<true>;
|
|
20
21
|
};
|
|
21
|
-
declare const GetCollection: ({ cms, collectionName, includeDocuments, startCursor, children, }: {
|
|
22
|
+
declare const GetCollection: ({ cms, collectionName, includeDocuments, startCursor, sortKey, children, }: {
|
|
22
23
|
cms: TinaCMS;
|
|
23
24
|
collectionName: string;
|
|
24
25
|
includeDocuments?: boolean;
|
|
25
26
|
startCursor?: string;
|
|
27
|
+
sortKey?: string;
|
|
26
28
|
children: any;
|
|
27
29
|
}) => JSX.Element;
|
|
28
30
|
export default GetCollection;
|
package/dist/index.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCMS, Form, GlobalFormPlugin, EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, TinaMediaStore, DummyMediaStore, Nav, LocalWarning, OverflowMenu, CursorPaginator, PopupModal, FormStatus, FormBuilder } from "@tinacms/toolkit";
|
|
1
|
+
import { useCMS, Form, GlobalFormPlugin, EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, TinaMediaStore, DummyMediaStore, Nav, LocalWarning, Select, OverflowMenu, CursorPaginator, PopupModal, FormStatus, FormBuilder } from "@tinacms/toolkit";
|
|
2
2
|
export * from "@tinacms/toolkit";
|
|
3
3
|
import * as G from "graphql";
|
|
4
4
|
import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType as isScalarType$1, getIntrospectionQuery, buildClientSchema, print, parse } from "graphql";
|
|
@@ -2483,10 +2483,10 @@ class TinaAdminApi {
|
|
|
2483
2483
|
}
|
|
2484
2484
|
}`, { variables: { collection, relativePath } });
|
|
2485
2485
|
}
|
|
2486
|
-
async fetchCollection(collectionName, includeDocuments, after) {
|
|
2486
|
+
async fetchCollection(collectionName, includeDocuments, after, sortKey, order) {
|
|
2487
2487
|
if (includeDocuments === true) {
|
|
2488
|
-
const sort = this.schema.getIsTitleFieldName(collectionName);
|
|
2489
|
-
const response = await this.api.request(`#graphql
|
|
2488
|
+
const sort = sortKey || this.schema.getIsTitleFieldName(collectionName);
|
|
2489
|
+
const response = order === "asc" ? await this.api.request(`#graphql
|
|
2490
2490
|
query($collection: String!, $includeDocuments: Boolean!, $sort: String, $limit: Float, $after: String){
|
|
2491
2491
|
collection(collection: $collection){
|
|
2492
2492
|
name
|
|
@@ -2527,6 +2527,47 @@ class TinaAdminApi {
|
|
|
2527
2527
|
limit: 10,
|
|
2528
2528
|
after
|
|
2529
2529
|
}
|
|
2530
|
+
}) : await this.api.request(`#graphql
|
|
2531
|
+
query($collection: String!, $includeDocuments: Boolean!, $sort: String, $limit: Float, $after: String){
|
|
2532
|
+
collection(collection: $collection){
|
|
2533
|
+
name
|
|
2534
|
+
label
|
|
2535
|
+
format
|
|
2536
|
+
templates
|
|
2537
|
+
documents(sort: $sort, before: $after, last: $limit) @include(if: $includeDocuments) {
|
|
2538
|
+
totalCount
|
|
2539
|
+
pageInfo {
|
|
2540
|
+
hasPreviousPage
|
|
2541
|
+
hasNextPage
|
|
2542
|
+
startCursor
|
|
2543
|
+
endCursor
|
|
2544
|
+
}
|
|
2545
|
+
edges {
|
|
2546
|
+
node {
|
|
2547
|
+
... on Document {
|
|
2548
|
+
_sys {
|
|
2549
|
+
title
|
|
2550
|
+
template
|
|
2551
|
+
breadcrumbs
|
|
2552
|
+
path
|
|
2553
|
+
basename
|
|
2554
|
+
relativePath
|
|
2555
|
+
filename
|
|
2556
|
+
extension
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
}`, {
|
|
2564
|
+
variables: {
|
|
2565
|
+
collection: collectionName,
|
|
2566
|
+
includeDocuments,
|
|
2567
|
+
sort,
|
|
2568
|
+
limit: 10,
|
|
2569
|
+
after
|
|
2570
|
+
}
|
|
2530
2571
|
});
|
|
2531
2572
|
return response.collection;
|
|
2532
2573
|
} else {
|
|
@@ -3280,6 +3321,9 @@ var styles = /* @__PURE__ */ (() => `.tina-tailwind {
|
|
|
3280
3321
|
.tina-tailwind .gap-4 {
|
|
3281
3322
|
gap: 16px;
|
|
3282
3323
|
}
|
|
3324
|
+
.tina-tailwind .gap-2 {
|
|
3325
|
+
gap: 8px;
|
|
3326
|
+
}
|
|
3283
3327
|
.tina-tailwind .gap-3 {
|
|
3284
3328
|
gap: 12px;
|
|
3285
3329
|
}
|
|
@@ -3298,6 +3342,9 @@ var styles = /* @__PURE__ */ (() => `.tina-tailwind {
|
|
|
3298
3342
|
.tina-tailwind .overflow-y-auto {
|
|
3299
3343
|
overflow-y: auto;
|
|
3300
3344
|
}
|
|
3345
|
+
.tina-tailwind .whitespace-normal {
|
|
3346
|
+
white-space: normal;
|
|
3347
|
+
}
|
|
3301
3348
|
.tina-tailwind .whitespace-nowrap {
|
|
3302
3349
|
white-space: nowrap;
|
|
3303
3350
|
}
|
|
@@ -3419,8 +3466,8 @@ var styles = /* @__PURE__ */ (() => `.tina-tailwind {
|
|
|
3419
3466
|
.tina-tailwind .pb-4 {
|
|
3420
3467
|
padding-bottom: 16px;
|
|
3421
3468
|
}
|
|
3422
|
-
.tina-tailwind .pt-
|
|
3423
|
-
padding-top:
|
|
3469
|
+
.tina-tailwind .pt-16 {
|
|
3470
|
+
padding-top: 64px;
|
|
3424
3471
|
}
|
|
3425
3472
|
.tina-tailwind .pt-3 {
|
|
3426
3473
|
padding-top: 12px;
|
|
@@ -3464,6 +3511,9 @@ var styles = /* @__PURE__ */ (() => `.tina-tailwind {
|
|
|
3464
3511
|
.tina-tailwind .font-medium {
|
|
3465
3512
|
font-weight: 500;
|
|
3466
3513
|
}
|
|
3514
|
+
.tina-tailwind .font-semibold {
|
|
3515
|
+
font-weight: 600;
|
|
3516
|
+
}
|
|
3467
3517
|
.tina-tailwind .uppercase {
|
|
3468
3518
|
text-transform: uppercase;
|
|
3469
3519
|
}
|
|
@@ -4558,7 +4608,7 @@ const PageHeader = ({
|
|
|
4558
4608
|
isLocalMode,
|
|
4559
4609
|
children
|
|
4560
4610
|
}) => /* @__PURE__ */ React.createElement(React.Fragment, null, isLocalMode && /* @__PURE__ */ React.createElement(LocalWarning, null), /* @__PURE__ */ React.createElement("div", {
|
|
4561
|
-
className: "bg-white pb-4 pt-
|
|
4611
|
+
className: "bg-white pb-4 pt-16 border-b border-gray-200 px-12"
|
|
4562
4612
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
4563
4613
|
className: "w-full mx-auto max-w-screen-xl"
|
|
4564
4614
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
@@ -4685,8 +4735,10 @@ const LoadingPage = () => /* @__PURE__ */ React.createElement(React.Fragment, nu
|
|
|
4685
4735
|
fontWeight: "normal"
|
|
4686
4736
|
}
|
|
4687
4737
|
}, "Please wait, Tina is loading data..."))));
|
|
4688
|
-
const useGetCollection = (cms, collectionName, includeDocuments = true, after = "") => {
|
|
4738
|
+
const useGetCollection = (cms, collectionName, includeDocuments = true, after = "", sortKey) => {
|
|
4689
4739
|
const api = new TinaAdminApi(cms);
|
|
4740
|
+
const schema = cms.api.tina.schema;
|
|
4741
|
+
const collectionExtra = schema.getCollection(collectionName);
|
|
4690
4742
|
const [collection, setCollection] = useState(void 0);
|
|
4691
4743
|
const [loading, setLoading] = useState(true);
|
|
4692
4744
|
const [error, setError] = useState(void 0);
|
|
@@ -4694,8 +4746,10 @@ const useGetCollection = (cms, collectionName, includeDocuments = true, after =
|
|
|
4694
4746
|
useEffect(() => {
|
|
4695
4747
|
const fetchCollection = async () => {
|
|
4696
4748
|
if (await api.isAuthenticated()) {
|
|
4749
|
+
const { name, order } = JSON.parse(sortKey || "{}");
|
|
4750
|
+
const validSortKey = collectionExtra.fields.map((x) => x.name).includes(name) ? name : void 0;
|
|
4697
4751
|
try {
|
|
4698
|
-
const collection2 = await api.fetchCollection(collectionName, includeDocuments, after);
|
|
4752
|
+
const collection2 = await api.fetchCollection(collectionName, includeDocuments, after, validSortKey, order);
|
|
4699
4753
|
setCollection(collection2);
|
|
4700
4754
|
} catch (error2) {
|
|
4701
4755
|
cms.alerts.error(`[${error2.name}] GetCollection failed: ${error2.message}`, 30 * 1e3);
|
|
@@ -4708,26 +4762,29 @@ const useGetCollection = (cms, collectionName, includeDocuments = true, after =
|
|
|
4708
4762
|
};
|
|
4709
4763
|
setLoading(true);
|
|
4710
4764
|
fetchCollection();
|
|
4711
|
-
}, [cms, collectionName, resetState, after]);
|
|
4765
|
+
}, [cms, collectionName, resetState, after, sortKey]);
|
|
4712
4766
|
const reFetchCollection = () => setResetSate((x) => x + 1);
|
|
4713
|
-
return { collection, loading, error, reFetchCollection };
|
|
4767
|
+
return { collection, loading, error, reFetchCollection, collectionExtra };
|
|
4714
4768
|
};
|
|
4715
4769
|
const GetCollection = ({
|
|
4716
4770
|
cms,
|
|
4717
4771
|
collectionName,
|
|
4718
4772
|
includeDocuments = true,
|
|
4719
4773
|
startCursor,
|
|
4774
|
+
sortKey,
|
|
4720
4775
|
children
|
|
4721
4776
|
}) => {
|
|
4722
|
-
const { collection, loading, error, reFetchCollection } = useGetCollection(cms, collectionName, includeDocuments, startCursor || "");
|
|
4777
|
+
const { collection, loading, error, reFetchCollection, collectionExtra } = useGetCollection(cms, collectionName, includeDocuments, startCursor || "", sortKey) || {};
|
|
4723
4778
|
if (error) {
|
|
4724
4779
|
return null;
|
|
4725
4780
|
}
|
|
4726
4781
|
if (loading) {
|
|
4727
4782
|
return /* @__PURE__ */ React.createElement(LoadingPage, null);
|
|
4728
4783
|
}
|
|
4729
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collection, loading, reFetchCollection));
|
|
4784
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collection, loading, reFetchCollection, collectionExtra));
|
|
4730
4785
|
};
|
|
4786
|
+
const LOCAL_STORAGE_KEY = "tinacms.admin.collection.list.page";
|
|
4787
|
+
const isSSR = typeof window === "undefined";
|
|
4731
4788
|
const TemplateMenu = ({ templates }) => {
|
|
4732
4789
|
return /* @__PURE__ */ React.createElement(Menu, {
|
|
4733
4790
|
as: "div",
|
|
@@ -4776,8 +4833,17 @@ const CollectionListPage = () => {
|
|
|
4776
4833
|
});
|
|
4777
4834
|
const [endCursor, setEndCursor] = useState("");
|
|
4778
4835
|
const [prevCursors, setPrevCursors] = useState([]);
|
|
4836
|
+
const [sortKey, setSortKey] = useState(isSSR ? "" : window.localStorage.getItem(`${LOCAL_STORAGE_KEY}.${collectionName}`) || JSON.stringify({
|
|
4837
|
+
order: "asc",
|
|
4838
|
+
name: ""
|
|
4839
|
+
}));
|
|
4840
|
+
const [sortOrder, setSortOrder] = useState("asc");
|
|
4779
4841
|
const loc = useLocation();
|
|
4780
4842
|
useEffect(() => {
|
|
4843
|
+
setSortKey(window.localStorage.getItem(`${LOCAL_STORAGE_KEY}.${collectionName}`) || JSON.stringify({
|
|
4844
|
+
order: "asc",
|
|
4845
|
+
name: ""
|
|
4846
|
+
}));
|
|
4781
4847
|
setEndCursor("");
|
|
4782
4848
|
setPrevCursors([]);
|
|
4783
4849
|
}, [loc]);
|
|
@@ -4786,13 +4852,15 @@ const CollectionListPage = () => {
|
|
|
4786
4852
|
cms,
|
|
4787
4853
|
collectionName,
|
|
4788
4854
|
includeDocuments: true,
|
|
4789
|
-
startCursor: endCursor
|
|
4790
|
-
|
|
4855
|
+
startCursor: endCursor,
|
|
4856
|
+
sortKey
|
|
4857
|
+
}, (collection, _loading, reFetchCollection, collectionExtra) => {
|
|
4791
4858
|
var _a, _b;
|
|
4792
4859
|
const totalCount = collection.documents.totalCount;
|
|
4793
4860
|
const documents = collection.documents.edges;
|
|
4794
4861
|
const admin = cms.api.admin;
|
|
4795
4862
|
const pageInfo = collection.documents.pageInfo;
|
|
4863
|
+
const fields = collectionExtra.fields.filter((x) => ["string", "number", "datetime"].includes(x.type));
|
|
4796
4864
|
return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(React.Fragment, null, open && /* @__PURE__ */ React.createElement(DeleteModal, {
|
|
4797
4865
|
filename: vars.relativePath,
|
|
4798
4866
|
deleteFunc: async () => {
|
|
@@ -4809,9 +4877,56 @@ const CollectionListPage = () => {
|
|
|
4809
4877
|
close: () => setOpen(false)
|
|
4810
4878
|
}), /* @__PURE__ */ React.createElement(PageHeader, {
|
|
4811
4879
|
isLocalMode: (_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode
|
|
4812
|
-
}, /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("
|
|
4880
|
+
}, /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
4881
|
+
className: "flex flex-col gap-4"
|
|
4882
|
+
}, /* @__PURE__ */ React.createElement("h3", {
|
|
4813
4883
|
className: "font-sans text-2xl text-gray-700"
|
|
4814
|
-
}, collection.label ? collection.label : collection.name),
|
|
4884
|
+
}, collection.label ? collection.label : collection.name), fields.length > 0 && /* @__PURE__ */ React.createElement("div", {
|
|
4885
|
+
className: "flex gap-2 items-center"
|
|
4886
|
+
}, /* @__PURE__ */ React.createElement("label", {
|
|
4887
|
+
htmlFor: "sort",
|
|
4888
|
+
className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
|
|
4889
|
+
}, "Sort by"), /* @__PURE__ */ React.createElement(Select, {
|
|
4890
|
+
name: "sort",
|
|
4891
|
+
options: [
|
|
4892
|
+
{
|
|
4893
|
+
label: "Default",
|
|
4894
|
+
value: JSON.stringify({
|
|
4895
|
+
order: "asc",
|
|
4896
|
+
name: ""
|
|
4897
|
+
})
|
|
4898
|
+
},
|
|
4899
|
+
...fields.map((x) => [
|
|
4900
|
+
{
|
|
4901
|
+
label: x.label + " (Ascending)",
|
|
4902
|
+
value: JSON.stringify({
|
|
4903
|
+
name: x.name,
|
|
4904
|
+
order: "asc"
|
|
4905
|
+
})
|
|
4906
|
+
},
|
|
4907
|
+
{
|
|
4908
|
+
label: x.label + " (Descending)",
|
|
4909
|
+
value: JSON.stringify({
|
|
4910
|
+
name: x.name,
|
|
4911
|
+
order: "desc"
|
|
4912
|
+
})
|
|
4913
|
+
}
|
|
4914
|
+
]).flat()
|
|
4915
|
+
],
|
|
4916
|
+
input: {
|
|
4917
|
+
id: "sort",
|
|
4918
|
+
name: "sort",
|
|
4919
|
+
value: sortKey,
|
|
4920
|
+
onChange: (e) => {
|
|
4921
|
+
const val = JSON.parse(e.target.value);
|
|
4922
|
+
setEndCursor("");
|
|
4923
|
+
setPrevCursors([]);
|
|
4924
|
+
window == null ? void 0 : window.localStorage.setItem(`${LOCAL_STORAGE_KEY}.${collectionName}`, e.target.value);
|
|
4925
|
+
setSortKey(e.target.value);
|
|
4926
|
+
setSortOrder(val.order);
|
|
4927
|
+
}
|
|
4928
|
+
}
|
|
4929
|
+
}))), !collection.templates && /* @__PURE__ */ React.createElement(Link, {
|
|
4815
4930
|
to: `new`,
|
|
4816
4931
|
className: "icon-parent inline-flex items-center font-medium focus:outline-none focus:ring-2 focus:shadow-outline text-center rounded-full justify-center transition-all duration-150 ease-out shadow text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-500 text-sm h-10 px-6"
|
|
4817
4932
|
}, "Create New", " ", /* @__PURE__ */ React.createElement(BiPlus, {
|
|
@@ -4899,7 +5014,7 @@ const CollectionListPage = () => {
|
|
|
4899
5014
|
className: "pt-3"
|
|
4900
5015
|
}, /* @__PURE__ */ React.createElement(CursorPaginator, {
|
|
4901
5016
|
variant: "white",
|
|
4902
|
-
hasNext: pageInfo == null ? void 0 : pageInfo.hasNextPage,
|
|
5017
|
+
hasNext: sortOrder === "asc" ? pageInfo == null ? void 0 : pageInfo.hasNextPage : pageInfo.hasPreviousPage,
|
|
4903
5018
|
navigateNext: () => {
|
|
4904
5019
|
const newState = [...prevCursors, endCursor];
|
|
4905
5020
|
setPrevCursors(newState);
|
|
@@ -5237,9 +5352,9 @@ const Redirect = () => {
|
|
|
5237
5352
|
return null;
|
|
5238
5353
|
};
|
|
5239
5354
|
const TinaAdmin = () => {
|
|
5240
|
-
const
|
|
5355
|
+
const isSSR2 = typeof window === "undefined";
|
|
5241
5356
|
const { edit } = useEditState();
|
|
5242
|
-
if (
|
|
5357
|
+
if (isSSR2) {
|
|
5243
5358
|
return null;
|
|
5244
5359
|
}
|
|
5245
5360
|
if (!edit) {
|
package/dist/index.js
CHANGED
|
@@ -2501,10 +2501,10 @@ mutation addPendingDocumentMutation(
|
|
|
2501
2501
|
}
|
|
2502
2502
|
}`, { variables: { collection, relativePath } });
|
|
2503
2503
|
}
|
|
2504
|
-
async fetchCollection(collectionName, includeDocuments, after) {
|
|
2504
|
+
async fetchCollection(collectionName, includeDocuments, after, sortKey, order) {
|
|
2505
2505
|
if (includeDocuments === true) {
|
|
2506
|
-
const sort = this.schema.getIsTitleFieldName(collectionName);
|
|
2507
|
-
const response = await this.api.request(`#graphql
|
|
2506
|
+
const sort = sortKey || this.schema.getIsTitleFieldName(collectionName);
|
|
2507
|
+
const response = order === "asc" ? await this.api.request(`#graphql
|
|
2508
2508
|
query($collection: String!, $includeDocuments: Boolean!, $sort: String, $limit: Float, $after: String){
|
|
2509
2509
|
collection(collection: $collection){
|
|
2510
2510
|
name
|
|
@@ -2537,6 +2537,47 @@ mutation addPendingDocumentMutation(
|
|
|
2537
2537
|
}
|
|
2538
2538
|
}
|
|
2539
2539
|
}
|
|
2540
|
+
}`, {
|
|
2541
|
+
variables: {
|
|
2542
|
+
collection: collectionName,
|
|
2543
|
+
includeDocuments,
|
|
2544
|
+
sort,
|
|
2545
|
+
limit: 10,
|
|
2546
|
+
after
|
|
2547
|
+
}
|
|
2548
|
+
}) : await this.api.request(`#graphql
|
|
2549
|
+
query($collection: String!, $includeDocuments: Boolean!, $sort: String, $limit: Float, $after: String){
|
|
2550
|
+
collection(collection: $collection){
|
|
2551
|
+
name
|
|
2552
|
+
label
|
|
2553
|
+
format
|
|
2554
|
+
templates
|
|
2555
|
+
documents(sort: $sort, before: $after, last: $limit) @include(if: $includeDocuments) {
|
|
2556
|
+
totalCount
|
|
2557
|
+
pageInfo {
|
|
2558
|
+
hasPreviousPage
|
|
2559
|
+
hasNextPage
|
|
2560
|
+
startCursor
|
|
2561
|
+
endCursor
|
|
2562
|
+
}
|
|
2563
|
+
edges {
|
|
2564
|
+
node {
|
|
2565
|
+
... on Document {
|
|
2566
|
+
_sys {
|
|
2567
|
+
title
|
|
2568
|
+
template
|
|
2569
|
+
breadcrumbs
|
|
2570
|
+
path
|
|
2571
|
+
basename
|
|
2572
|
+
relativePath
|
|
2573
|
+
filename
|
|
2574
|
+
extension
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2540
2581
|
}`, {
|
|
2541
2582
|
variables: {
|
|
2542
2583
|
collection: collectionName,
|
|
@@ -3298,6 +3339,9 @@ mutation addPendingDocumentMutation(
|
|
|
3298
3339
|
.tina-tailwind .gap-4 {
|
|
3299
3340
|
gap: 16px;
|
|
3300
3341
|
}
|
|
3342
|
+
.tina-tailwind .gap-2 {
|
|
3343
|
+
gap: 8px;
|
|
3344
|
+
}
|
|
3301
3345
|
.tina-tailwind .gap-3 {
|
|
3302
3346
|
gap: 12px;
|
|
3303
3347
|
}
|
|
@@ -3316,6 +3360,9 @@ mutation addPendingDocumentMutation(
|
|
|
3316
3360
|
.tina-tailwind .overflow-y-auto {
|
|
3317
3361
|
overflow-y: auto;
|
|
3318
3362
|
}
|
|
3363
|
+
.tina-tailwind .whitespace-normal {
|
|
3364
|
+
white-space: normal;
|
|
3365
|
+
}
|
|
3319
3366
|
.tina-tailwind .whitespace-nowrap {
|
|
3320
3367
|
white-space: nowrap;
|
|
3321
3368
|
}
|
|
@@ -3437,8 +3484,8 @@ mutation addPendingDocumentMutation(
|
|
|
3437
3484
|
.tina-tailwind .pb-4 {
|
|
3438
3485
|
padding-bottom: 16px;
|
|
3439
3486
|
}
|
|
3440
|
-
.tina-tailwind .pt-
|
|
3441
|
-
padding-top:
|
|
3487
|
+
.tina-tailwind .pt-16 {
|
|
3488
|
+
padding-top: 64px;
|
|
3442
3489
|
}
|
|
3443
3490
|
.tina-tailwind .pt-3 {
|
|
3444
3491
|
padding-top: 12px;
|
|
@@ -3482,6 +3529,9 @@ mutation addPendingDocumentMutation(
|
|
|
3482
3529
|
.tina-tailwind .font-medium {
|
|
3483
3530
|
font-weight: 500;
|
|
3484
3531
|
}
|
|
3532
|
+
.tina-tailwind .font-semibold {
|
|
3533
|
+
font-weight: 600;
|
|
3534
|
+
}
|
|
3485
3535
|
.tina-tailwind .uppercase {
|
|
3486
3536
|
text-transform: uppercase;
|
|
3487
3537
|
}
|
|
@@ -4576,7 +4626,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4576
4626
|
isLocalMode,
|
|
4577
4627
|
children
|
|
4578
4628
|
}) => /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, isLocalMode && /* @__PURE__ */ React__default["default"].createElement(toolkit.LocalWarning, null), /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
4579
|
-
className: "bg-white pb-4 pt-
|
|
4629
|
+
className: "bg-white pb-4 pt-16 border-b border-gray-200 px-12"
|
|
4580
4630
|
}, /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
4581
4631
|
className: "w-full mx-auto max-w-screen-xl"
|
|
4582
4632
|
}, /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
@@ -4703,8 +4753,10 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4703
4753
|
fontWeight: "normal"
|
|
4704
4754
|
}
|
|
4705
4755
|
}, "Please wait, Tina is loading data..."))));
|
|
4706
|
-
const useGetCollection = (cms, collectionName, includeDocuments = true, after = "") => {
|
|
4756
|
+
const useGetCollection = (cms, collectionName, includeDocuments = true, after = "", sortKey) => {
|
|
4707
4757
|
const api = new TinaAdminApi(cms);
|
|
4758
|
+
const schema = cms.api.tina.schema;
|
|
4759
|
+
const collectionExtra = schema.getCollection(collectionName);
|
|
4708
4760
|
const [collection, setCollection] = React.useState(void 0);
|
|
4709
4761
|
const [loading, setLoading] = React.useState(true);
|
|
4710
4762
|
const [error, setError] = React.useState(void 0);
|
|
@@ -4712,8 +4764,10 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4712
4764
|
React.useEffect(() => {
|
|
4713
4765
|
const fetchCollection = async () => {
|
|
4714
4766
|
if (await api.isAuthenticated()) {
|
|
4767
|
+
const { name, order } = JSON.parse(sortKey || "{}");
|
|
4768
|
+
const validSortKey = collectionExtra.fields.map((x) => x.name).includes(name) ? name : void 0;
|
|
4715
4769
|
try {
|
|
4716
|
-
const collection2 = await api.fetchCollection(collectionName, includeDocuments, after);
|
|
4770
|
+
const collection2 = await api.fetchCollection(collectionName, includeDocuments, after, validSortKey, order);
|
|
4717
4771
|
setCollection(collection2);
|
|
4718
4772
|
} catch (error2) {
|
|
4719
4773
|
cms.alerts.error(`[${error2.name}] GetCollection failed: ${error2.message}`, 30 * 1e3);
|
|
@@ -4726,26 +4780,29 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4726
4780
|
};
|
|
4727
4781
|
setLoading(true);
|
|
4728
4782
|
fetchCollection();
|
|
4729
|
-
}, [cms, collectionName, resetState, after]);
|
|
4783
|
+
}, [cms, collectionName, resetState, after, sortKey]);
|
|
4730
4784
|
const reFetchCollection = () => setResetSate((x) => x + 1);
|
|
4731
|
-
return { collection, loading, error, reFetchCollection };
|
|
4785
|
+
return { collection, loading, error, reFetchCollection, collectionExtra };
|
|
4732
4786
|
};
|
|
4733
4787
|
const GetCollection = ({
|
|
4734
4788
|
cms,
|
|
4735
4789
|
collectionName,
|
|
4736
4790
|
includeDocuments = true,
|
|
4737
4791
|
startCursor,
|
|
4792
|
+
sortKey,
|
|
4738
4793
|
children
|
|
4739
4794
|
}) => {
|
|
4740
|
-
const { collection, loading, error, reFetchCollection } = useGetCollection(cms, collectionName, includeDocuments, startCursor || "");
|
|
4795
|
+
const { collection, loading, error, reFetchCollection, collectionExtra } = useGetCollection(cms, collectionName, includeDocuments, startCursor || "", sortKey) || {};
|
|
4741
4796
|
if (error) {
|
|
4742
4797
|
return null;
|
|
4743
4798
|
}
|
|
4744
4799
|
if (loading) {
|
|
4745
4800
|
return /* @__PURE__ */ React__default["default"].createElement(LoadingPage, null);
|
|
4746
4801
|
}
|
|
4747
|
-
return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(collection, loading, reFetchCollection));
|
|
4802
|
+
return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(collection, loading, reFetchCollection, collectionExtra));
|
|
4748
4803
|
};
|
|
4804
|
+
const LOCAL_STORAGE_KEY = "tinacms.admin.collection.list.page";
|
|
4805
|
+
const isSSR = typeof window === "undefined";
|
|
4749
4806
|
const TemplateMenu = ({ templates }) => {
|
|
4750
4807
|
return /* @__PURE__ */ React__default["default"].createElement(react.Menu, {
|
|
4751
4808
|
as: "div",
|
|
@@ -4794,8 +4851,17 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4794
4851
|
});
|
|
4795
4852
|
const [endCursor, setEndCursor] = React.useState("");
|
|
4796
4853
|
const [prevCursors, setPrevCursors] = React.useState([]);
|
|
4854
|
+
const [sortKey, setSortKey] = React.useState(isSSR ? "" : window.localStorage.getItem(`${LOCAL_STORAGE_KEY}.${collectionName}`) || JSON.stringify({
|
|
4855
|
+
order: "asc",
|
|
4856
|
+
name: ""
|
|
4857
|
+
}));
|
|
4858
|
+
const [sortOrder, setSortOrder] = React.useState("asc");
|
|
4797
4859
|
const loc = reactRouterDom.useLocation();
|
|
4798
4860
|
React.useEffect(() => {
|
|
4861
|
+
setSortKey(window.localStorage.getItem(`${LOCAL_STORAGE_KEY}.${collectionName}`) || JSON.stringify({
|
|
4862
|
+
order: "asc",
|
|
4863
|
+
name: ""
|
|
4864
|
+
}));
|
|
4799
4865
|
setEndCursor("");
|
|
4800
4866
|
setPrevCursors([]);
|
|
4801
4867
|
}, [loc]);
|
|
@@ -4804,13 +4870,15 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4804
4870
|
cms,
|
|
4805
4871
|
collectionName,
|
|
4806
4872
|
includeDocuments: true,
|
|
4807
|
-
startCursor: endCursor
|
|
4808
|
-
|
|
4873
|
+
startCursor: endCursor,
|
|
4874
|
+
sortKey
|
|
4875
|
+
}, (collection, _loading, reFetchCollection, collectionExtra) => {
|
|
4809
4876
|
var _a, _b;
|
|
4810
4877
|
const totalCount = collection.documents.totalCount;
|
|
4811
4878
|
const documents = collection.documents.edges;
|
|
4812
4879
|
const admin = cms.api.admin;
|
|
4813
4880
|
const pageInfo = collection.documents.pageInfo;
|
|
4881
|
+
const fields = collectionExtra.fields.filter((x) => ["string", "number", "datetime"].includes(x.type));
|
|
4814
4882
|
return /* @__PURE__ */ React__default["default"].createElement(PageWrapper, null, /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, open && /* @__PURE__ */ React__default["default"].createElement(DeleteModal, {
|
|
4815
4883
|
filename: vars.relativePath,
|
|
4816
4884
|
deleteFunc: async () => {
|
|
@@ -4827,9 +4895,56 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4827
4895
|
close: () => setOpen(false)
|
|
4828
4896
|
}), /* @__PURE__ */ React__default["default"].createElement(PageHeader, {
|
|
4829
4897
|
isLocalMode: (_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode
|
|
4830
|
-
}, /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("
|
|
4898
|
+
}, /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
4899
|
+
className: "flex flex-col gap-4"
|
|
4900
|
+
}, /* @__PURE__ */ React__default["default"].createElement("h3", {
|
|
4831
4901
|
className: "font-sans text-2xl text-gray-700"
|
|
4832
|
-
}, collection.label ? collection.label : collection.name),
|
|
4902
|
+
}, collection.label ? collection.label : collection.name), fields.length > 0 && /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
4903
|
+
className: "flex gap-2 items-center"
|
|
4904
|
+
}, /* @__PURE__ */ React__default["default"].createElement("label", {
|
|
4905
|
+
htmlFor: "sort",
|
|
4906
|
+
className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
|
|
4907
|
+
}, "Sort by"), /* @__PURE__ */ React__default["default"].createElement(toolkit.Select, {
|
|
4908
|
+
name: "sort",
|
|
4909
|
+
options: [
|
|
4910
|
+
{
|
|
4911
|
+
label: "Default",
|
|
4912
|
+
value: JSON.stringify({
|
|
4913
|
+
order: "asc",
|
|
4914
|
+
name: ""
|
|
4915
|
+
})
|
|
4916
|
+
},
|
|
4917
|
+
...fields.map((x) => [
|
|
4918
|
+
{
|
|
4919
|
+
label: x.label + " (Ascending)",
|
|
4920
|
+
value: JSON.stringify({
|
|
4921
|
+
name: x.name,
|
|
4922
|
+
order: "asc"
|
|
4923
|
+
})
|
|
4924
|
+
},
|
|
4925
|
+
{
|
|
4926
|
+
label: x.label + " (Descending)",
|
|
4927
|
+
value: JSON.stringify({
|
|
4928
|
+
name: x.name,
|
|
4929
|
+
order: "desc"
|
|
4930
|
+
})
|
|
4931
|
+
}
|
|
4932
|
+
]).flat()
|
|
4933
|
+
],
|
|
4934
|
+
input: {
|
|
4935
|
+
id: "sort",
|
|
4936
|
+
name: "sort",
|
|
4937
|
+
value: sortKey,
|
|
4938
|
+
onChange: (e) => {
|
|
4939
|
+
const val = JSON.parse(e.target.value);
|
|
4940
|
+
setEndCursor("");
|
|
4941
|
+
setPrevCursors([]);
|
|
4942
|
+
window == null ? void 0 : window.localStorage.setItem(`${LOCAL_STORAGE_KEY}.${collectionName}`, e.target.value);
|
|
4943
|
+
setSortKey(e.target.value);
|
|
4944
|
+
setSortOrder(val.order);
|
|
4945
|
+
}
|
|
4946
|
+
}
|
|
4947
|
+
}))), !collection.templates && /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Link, {
|
|
4833
4948
|
to: `new`,
|
|
4834
4949
|
className: "icon-parent inline-flex items-center font-medium focus:outline-none focus:ring-2 focus:shadow-outline text-center rounded-full justify-center transition-all duration-150 ease-out shadow text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-500 text-sm h-10 px-6"
|
|
4835
4950
|
}, "Create New", " ", /* @__PURE__ */ React__default["default"].createElement(BiPlus, {
|
|
@@ -4917,7 +5032,7 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4917
5032
|
className: "pt-3"
|
|
4918
5033
|
}, /* @__PURE__ */ React__default["default"].createElement(toolkit.CursorPaginator, {
|
|
4919
5034
|
variant: "white",
|
|
4920
|
-
hasNext: pageInfo == null ? void 0 : pageInfo.hasNextPage,
|
|
5035
|
+
hasNext: sortOrder === "asc" ? pageInfo == null ? void 0 : pageInfo.hasNextPage : pageInfo.hasPreviousPage,
|
|
4921
5036
|
navigateNext: () => {
|
|
4922
5037
|
const newState = [...prevCursors, endCursor];
|
|
4923
5038
|
setPrevCursors(newState);
|
|
@@ -5255,9 +5370,9 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
5255
5370
|
return null;
|
|
5256
5371
|
};
|
|
5257
5372
|
const TinaAdmin = () => {
|
|
5258
|
-
const
|
|
5373
|
+
const isSSR2 = typeof window === "undefined";
|
|
5259
5374
|
const { edit } = sharedctx.useEditState();
|
|
5260
|
-
if (
|
|
5375
|
+
if (isSSR2) {
|
|
5261
5376
|
return null;
|
|
5262
5377
|
}
|
|
5263
5378
|
if (!edit) {
|
package/dist/style.css
CHANGED
|
@@ -544,6 +544,9 @@
|
|
|
544
544
|
.tina-tailwind .gap-4 {
|
|
545
545
|
gap: 16px;
|
|
546
546
|
}
|
|
547
|
+
.tina-tailwind .gap-2 {
|
|
548
|
+
gap: 8px;
|
|
549
|
+
}
|
|
547
550
|
.tina-tailwind .gap-3 {
|
|
548
551
|
gap: 12px;
|
|
549
552
|
}
|
|
@@ -562,6 +565,9 @@
|
|
|
562
565
|
.tina-tailwind .overflow-y-auto {
|
|
563
566
|
overflow-y: auto;
|
|
564
567
|
}
|
|
568
|
+
.tina-tailwind .whitespace-normal {
|
|
569
|
+
white-space: normal;
|
|
570
|
+
}
|
|
565
571
|
.tina-tailwind .whitespace-nowrap {
|
|
566
572
|
white-space: nowrap;
|
|
567
573
|
}
|
|
@@ -683,8 +689,8 @@
|
|
|
683
689
|
.tina-tailwind .pb-4 {
|
|
684
690
|
padding-bottom: 16px;
|
|
685
691
|
}
|
|
686
|
-
.tina-tailwind .pt-
|
|
687
|
-
padding-top:
|
|
692
|
+
.tina-tailwind .pt-16 {
|
|
693
|
+
padding-top: 64px;
|
|
688
694
|
}
|
|
689
695
|
.tina-tailwind .pt-3 {
|
|
690
696
|
padding-top: 12px;
|
|
@@ -728,6 +734,9 @@
|
|
|
728
734
|
.tina-tailwind .font-medium {
|
|
729
735
|
font-weight: 500;
|
|
730
736
|
}
|
|
737
|
+
.tina-tailwind .font-semibold {
|
|
738
|
+
font-weight: 600;
|
|
739
|
+
}
|
|
731
740
|
.tina-tailwind .uppercase {
|
|
732
741
|
text-transform: uppercase;
|
|
733
742
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinacms",
|
|
3
|
-
"version": "0.68.
|
|
3
|
+
"version": "0.68.15",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "./dist/index.es.js",
|
|
6
6
|
"exports": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@react-hook/window-size": "^3.0.7",
|
|
46
46
|
"@tinacms/schema-tools": "0.0.9",
|
|
47
47
|
"@tinacms/sharedctx": "0.1.2",
|
|
48
|
-
"@tinacms/toolkit": "0.56.
|
|
48
|
+
"@tinacms/toolkit": "0.56.37",
|
|
49
49
|
"crypto-js": "^4.0.0",
|
|
50
50
|
"fetch-ponyfill": "^7.1.0",
|
|
51
51
|
"final-form": "4.20.1",
|