@lodashventure/medusa-product-content 1.1.12 → 1.1.13
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/package.json +4 -5
- package/dist/admin/hooks/useProductContent.d.ts +0 -25
- package/dist/admin/hooks/useProductContent.js +0 -165
- package/dist/admin/lib/sdk.d.ts +0 -2
- package/dist/admin/lib/sdk.js +0 -15
- package/dist/admin/routes/product-content/page.d.ts +0 -8
- package/dist/admin/routes/product-content/page.js +0 -158
- package/dist/admin/utils/import-export.d.ts +0 -30
- package/dist/admin/utils/import-export.js +0 -384
- package/dist/admin/utils/locale.d.ts +0 -13
- package/dist/admin/utils/locale.js +0 -95
- package/dist/admin/utils/sanitize.d.ts +0 -29
- package/dist/admin/utils/sanitize.js +0 -188
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -6
- package/dist/modules/product-content/index.d.ts +0 -21
- package/dist/modules/product-content/index.js +0 -12
- package/dist/modules/product-content/models/product-content.d.ts +0 -7
- package/dist/modules/product-content/models/product-content.js +0 -18
- package/dist/modules/product-content/service.d.ts +0 -12
- package/dist/modules/product-content/service.js +0 -9
- package/dist/types/index.d.ts +0 -173
- package/dist/types/index.js +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lodashventure/medusa-product-content",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.13",
|
|
4
4
|
"description": "Medusa Admin plugin for enhanced product content management with rich text editor and i18n specifications",
|
|
5
5
|
"author": "Product Core Team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,10 +15,9 @@
|
|
|
15
15
|
"./package.json": "./package.json"
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"test": "jest"
|
|
18
|
+
"build": "medusa plugin:build",
|
|
19
|
+
"dev": "medusa plugin:develop",
|
|
20
|
+
"prepublishOnly": "medusa plugin:build"
|
|
22
21
|
},
|
|
23
22
|
"dependencies": {
|
|
24
23
|
"@tiptap/core": "^2.1.13",
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom hook for product content management
|
|
3
|
-
*/
|
|
4
|
-
import { ProductContentMetadata, LongDescription, LongDescriptionVersion, ProductSpecs } from "../../types";
|
|
5
|
-
export interface UseProductContentOptions {
|
|
6
|
-
productId: string;
|
|
7
|
-
maxVersions?: number;
|
|
8
|
-
autoSanitize?: boolean;
|
|
9
|
-
}
|
|
10
|
-
export interface UseProductContentReturn {
|
|
11
|
-
product: any;
|
|
12
|
-
isLoading: boolean;
|
|
13
|
-
error: Error | null;
|
|
14
|
-
metadata: ProductContentMetadata;
|
|
15
|
-
longDescription: LongDescription | null;
|
|
16
|
-
specs: ProductSpecs | null;
|
|
17
|
-
versions: LongDescriptionVersion[];
|
|
18
|
-
updateLongDescription: (html: string, richjson?: any, locale?: string) => Promise<void>;
|
|
19
|
-
updateSpecs: (specs: ProductSpecs) => Promise<void>;
|
|
20
|
-
createVersion: (description: LongDescription) => Promise<void>;
|
|
21
|
-
restoreVersion: (version: number) => Promise<void>;
|
|
22
|
-
deleteVersion: (version: number) => Promise<void>;
|
|
23
|
-
updateMetadata: (updates: Partial<ProductContentMetadata>) => Promise<void>;
|
|
24
|
-
}
|
|
25
|
-
export declare function useProductContent(options: UseProductContentOptions): UseProductContentReturn;
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Custom hook for product content management
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.useProductContent = useProductContent;
|
|
7
|
-
const react_1 = require("react");
|
|
8
|
-
const react_query_1 = require("@tanstack/react-query");
|
|
9
|
-
const sdk_1 = require("../lib/sdk");
|
|
10
|
-
const sanitize_1 = require("../utils/sanitize");
|
|
11
|
-
function useProductContent(options) {
|
|
12
|
-
const { productId, maxVersions = 10, autoSanitize = true } = options;
|
|
13
|
-
// Fetch product with expanded metadata
|
|
14
|
-
const { data: product, isLoading, error, } = (0, react_query_1.useQuery)({
|
|
15
|
-
queryKey: ["product", productId],
|
|
16
|
-
queryFn: async () => {
|
|
17
|
-
const response = await sdk_1.sdk.admin.product.retrieve(productId, {
|
|
18
|
-
fields: "*variants,*variants.prices,*variants.options,*options,*images,*collection,*categories,*metadata,*tags",
|
|
19
|
-
});
|
|
20
|
-
return response.product;
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
// Update mutation
|
|
24
|
-
const updateProduct = (0, react_query_1.useMutation)({
|
|
25
|
-
mutationFn: async (data) => {
|
|
26
|
-
return await sdk_1.sdk.admin.product.update(productId, data);
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
// Extract metadata
|
|
30
|
-
const metadata = (0, react_1.useMemo)(() => {
|
|
31
|
-
if (!product || !product.metadata)
|
|
32
|
-
return {};
|
|
33
|
-
return product.metadata;
|
|
34
|
-
}, [product]);
|
|
35
|
-
const longDescription = (0, react_1.useMemo)(() => {
|
|
36
|
-
return metadata.long_description || null;
|
|
37
|
-
}, [metadata.long_description]);
|
|
38
|
-
const specs = (0, react_1.useMemo)(() => {
|
|
39
|
-
return metadata.specs || null;
|
|
40
|
-
}, [metadata.specs]);
|
|
41
|
-
const versions = (0, react_1.useMemo)(() => {
|
|
42
|
-
return metadata.long_description_versions || [];
|
|
43
|
-
}, [metadata.long_description_versions]);
|
|
44
|
-
// Update long description
|
|
45
|
-
const updateLongDescription = (0, react_1.useCallback)(async (html, richjson, locale = "th-TH") => {
|
|
46
|
-
const sanitizedHtml = autoSanitize ? (0, sanitize_1.sanitizeHTML)(html) : html;
|
|
47
|
-
const newDescription = {
|
|
48
|
-
html: sanitizedHtml,
|
|
49
|
-
richjson,
|
|
50
|
-
locale,
|
|
51
|
-
updated_at: new Date().toISOString(),
|
|
52
|
-
updated_by: "current_user", // TODO: Get from auth context
|
|
53
|
-
};
|
|
54
|
-
// Create version if exists
|
|
55
|
-
let newVersions = [...versions];
|
|
56
|
-
if (longDescription) {
|
|
57
|
-
const version = {
|
|
58
|
-
...longDescription,
|
|
59
|
-
version: versions.length + 1,
|
|
60
|
-
created_at: longDescription.updated_at || new Date().toISOString(),
|
|
61
|
-
};
|
|
62
|
-
newVersions = [version, ...versions].slice(0, maxVersions);
|
|
63
|
-
}
|
|
64
|
-
await updateProduct.mutateAsync({
|
|
65
|
-
metadata: {
|
|
66
|
-
...metadata,
|
|
67
|
-
long_description: newDescription,
|
|
68
|
-
long_description_versions: newVersions,
|
|
69
|
-
content_last_updated: new Date().toISOString(),
|
|
70
|
-
content_updated_by: "current_user",
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
}, [
|
|
74
|
-
autoSanitize,
|
|
75
|
-
longDescription,
|
|
76
|
-
maxVersions,
|
|
77
|
-
metadata,
|
|
78
|
-
updateProduct,
|
|
79
|
-
versions,
|
|
80
|
-
]);
|
|
81
|
-
// Update specifications
|
|
82
|
-
const updateSpecs = (0, react_1.useCallback)(async (newSpecs) => {
|
|
83
|
-
await updateProduct.mutateAsync({
|
|
84
|
-
metadata: {
|
|
85
|
-
...metadata,
|
|
86
|
-
specs: newSpecs,
|
|
87
|
-
content_last_updated: new Date().toISOString(),
|
|
88
|
-
content_updated_by: "current_user",
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
}, [metadata, updateProduct]);
|
|
92
|
-
// Create version
|
|
93
|
-
const createVersion = (0, react_1.useCallback)(async (description) => {
|
|
94
|
-
const version = {
|
|
95
|
-
...description,
|
|
96
|
-
version: versions.length + 1,
|
|
97
|
-
created_at: new Date().toISOString(),
|
|
98
|
-
};
|
|
99
|
-
const newVersions = [version, ...versions].slice(0, maxVersions);
|
|
100
|
-
await updateProduct.mutateAsync({
|
|
101
|
-
metadata: {
|
|
102
|
-
...metadata,
|
|
103
|
-
long_description_versions: newVersions,
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
}, [maxVersions, metadata, updateProduct, versions]);
|
|
107
|
-
// Restore version
|
|
108
|
-
const restoreVersion = (0, react_1.useCallback)(async (versionNumber) => {
|
|
109
|
-
const version = versions.find((v) => v.version === versionNumber);
|
|
110
|
-
if (!version) {
|
|
111
|
-
throw new Error(`Version ${versionNumber} not found`);
|
|
112
|
-
}
|
|
113
|
-
const restoredDescription = {
|
|
114
|
-
html: version.html,
|
|
115
|
-
richjson: version.richjson,
|
|
116
|
-
locale: version.locale,
|
|
117
|
-
updated_at: new Date().toISOString(),
|
|
118
|
-
updated_by: "current_user",
|
|
119
|
-
};
|
|
120
|
-
await updateProduct.mutateAsync({
|
|
121
|
-
metadata: {
|
|
122
|
-
...metadata,
|
|
123
|
-
long_description: restoredDescription,
|
|
124
|
-
content_last_updated: new Date().toISOString(),
|
|
125
|
-
content_updated_by: "current_user",
|
|
126
|
-
},
|
|
127
|
-
});
|
|
128
|
-
}, [metadata, updateProduct, versions]);
|
|
129
|
-
// Delete version
|
|
130
|
-
const deleteVersion = (0, react_1.useCallback)(async (versionNumber) => {
|
|
131
|
-
const newVersions = versions.filter((v) => v.version !== versionNumber);
|
|
132
|
-
await updateProduct.mutateAsync({
|
|
133
|
-
metadata: {
|
|
134
|
-
...metadata,
|
|
135
|
-
long_description_versions: newVersions,
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
}, [metadata, updateProduct, versions]);
|
|
139
|
-
// Update metadata
|
|
140
|
-
const updateMetadata = (0, react_1.useCallback)(async (updates) => {
|
|
141
|
-
await updateProduct.mutateAsync({
|
|
142
|
-
metadata: {
|
|
143
|
-
...metadata,
|
|
144
|
-
...updates,
|
|
145
|
-
content_last_updated: new Date().toISOString(),
|
|
146
|
-
content_updated_by: "current_user",
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
}, [metadata, updateProduct]);
|
|
150
|
-
return {
|
|
151
|
-
product,
|
|
152
|
-
isLoading,
|
|
153
|
-
error,
|
|
154
|
-
metadata,
|
|
155
|
-
longDescription,
|
|
156
|
-
specs,
|
|
157
|
-
versions,
|
|
158
|
-
updateLongDescription,
|
|
159
|
-
updateSpecs,
|
|
160
|
-
createVersion,
|
|
161
|
-
restoreVersion,
|
|
162
|
-
deleteVersion,
|
|
163
|
-
updateMetadata,
|
|
164
|
-
};
|
|
165
|
-
}
|
package/dist/admin/lib/sdk.d.ts
DELETED
package/dist/admin/lib/sdk.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.sdk = void 0;
|
|
7
|
-
// @ts-nocheck
|
|
8
|
-
const js_sdk_1 = __importDefault(require("@medusajs/js-sdk"));
|
|
9
|
-
exports.sdk = new js_sdk_1.default({
|
|
10
|
-
baseUrl: import.meta.env.VITE_BACKEND_URL || "/",
|
|
11
|
-
debug: import.meta.env.DEV,
|
|
12
|
-
auth: {
|
|
13
|
-
type: "session",
|
|
14
|
-
},
|
|
15
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Product Content Management Page
|
|
3
|
-
* Main listing page accessible from admin menu
|
|
4
|
-
*/
|
|
5
|
-
import React from "react";
|
|
6
|
-
declare const ProductContentPage: () => React.JSX.Element;
|
|
7
|
-
export declare const config: import("@medusajs/admin-sdk").RouteConfig;
|
|
8
|
-
export default ProductContentPage;
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.config = void 0;
|
|
37
|
-
/**
|
|
38
|
-
* Product Content Management Page
|
|
39
|
-
* Main listing page accessible from admin menu
|
|
40
|
-
*/
|
|
41
|
-
// @ts-nocheck
|
|
42
|
-
const react_1 = __importStar(require("react"));
|
|
43
|
-
const ui_1 = require("@medusajs/ui");
|
|
44
|
-
const icons_1 = require("@medusajs/icons");
|
|
45
|
-
const admin_sdk_1 = require("@medusajs/admin-sdk");
|
|
46
|
-
const sdk_1 = require("../../lib/sdk");
|
|
47
|
-
const ProductContentPage = () => {
|
|
48
|
-
const [products, setProducts] = (0, react_1.useState)([]);
|
|
49
|
-
const [loading, setLoading] = (0, react_1.useState)(true);
|
|
50
|
-
const [error, setError] = (0, react_1.useState)(null);
|
|
51
|
-
const [searchQuery, setSearchQuery] = (0, react_1.useState)("");
|
|
52
|
-
(0, react_1.useEffect)(() => {
|
|
53
|
-
fetchProducts();
|
|
54
|
-
}, []);
|
|
55
|
-
const fetchProducts = async () => {
|
|
56
|
-
setLoading(true);
|
|
57
|
-
setError(null);
|
|
58
|
-
try {
|
|
59
|
-
const response = await sdk_1.sdk.client.fetch("/admin/products?limit=100", {
|
|
60
|
-
credentials: "include",
|
|
61
|
-
});
|
|
62
|
-
if (response.ok) {
|
|
63
|
-
const data = await response.json();
|
|
64
|
-
setProducts(data.products || []);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
setError("Failed to fetch products");
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
setError("Error fetching products");
|
|
72
|
-
console.error("Error fetching products:", err);
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
|
-
setLoading(false);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
const handleManageContent = (productId) => {
|
|
79
|
-
window.location.href = `/app/products/${productId}`;
|
|
80
|
-
};
|
|
81
|
-
const filteredProducts = products.filter((product) => {
|
|
82
|
-
if (!searchQuery)
|
|
83
|
-
return true;
|
|
84
|
-
const query = searchQuery.toLowerCase();
|
|
85
|
-
return (product.title?.toLowerCase().includes(query) ||
|
|
86
|
-
product.handle?.toLowerCase().includes(query));
|
|
87
|
-
});
|
|
88
|
-
const hasContent = (product) => {
|
|
89
|
-
return product.metadata?.long_description || product.metadata?.specs;
|
|
90
|
-
};
|
|
91
|
-
const getContentStatus = (product) => {
|
|
92
|
-
const hasLongDesc = !!product.metadata?.long_description;
|
|
93
|
-
const hasSpecs = !!product.metadata?.specs;
|
|
94
|
-
if (hasLongDesc && hasSpecs)
|
|
95
|
-
return { label: "Complete", color: "green" };
|
|
96
|
-
if (hasLongDesc || hasSpecs)
|
|
97
|
-
return { label: "Partial", color: "orange" };
|
|
98
|
-
return { label: "Empty", color: "grey" };
|
|
99
|
-
};
|
|
100
|
-
if (loading) {
|
|
101
|
-
return (react_1.default.createElement(ui_1.Container, null,
|
|
102
|
-
react_1.default.createElement("div", { className: "flex h-64 items-center justify-center" },
|
|
103
|
-
react_1.default.createElement(ui_1.Text, null, "Loading products..."))));
|
|
104
|
-
}
|
|
105
|
-
if (error) {
|
|
106
|
-
return (react_1.default.createElement(ui_1.Container, null,
|
|
107
|
-
react_1.default.createElement(ui_1.Alert, { variant: "error", dismissible: true }, error)));
|
|
108
|
-
}
|
|
109
|
-
return (react_1.default.createElement(ui_1.Container, null,
|
|
110
|
-
react_1.default.createElement("div", { className: "mb-8" },
|
|
111
|
-
react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
|
|
112
|
-
react_1.default.createElement("div", null,
|
|
113
|
-
react_1.default.createElement(ui_1.Heading, { level: "h1", className: "mb-2" }, "Product Content"),
|
|
114
|
-
react_1.default.createElement(ui_1.Text, { className: "text-ui-fg-subtle" }, "Manage long descriptions and specifications for all products"))),
|
|
115
|
-
react_1.default.createElement("div", { className: "flex items-center gap-4" },
|
|
116
|
-
react_1.default.createElement("div", { className: "relative flex-1 max-w-md" },
|
|
117
|
-
react_1.default.createElement(ui_1.Input, { placeholder: "Search products...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "pl-10" }),
|
|
118
|
-
react_1.default.createElement(icons_1.MagnifyingGlass, { className: "absolute left-3 top-1/2 -translate-y-1/2 text-ui-fg-muted" })))),
|
|
119
|
-
filteredProducts.length === 0 ? (react_1.default.createElement("div", { className: "flex h-64 flex-col items-center justify-center rounded-lg border-2 border-dashed border-ui-border-base" },
|
|
120
|
-
react_1.default.createElement(icons_1.SquareTwoStack, { className: "mb-4 text-ui-fg-subtle", style: { width: "3rem", height: "3rem" } }),
|
|
121
|
-
react_1.default.createElement(ui_1.Text, { className: "mb-2 text-lg font-medium" }, searchQuery ? "No products found" : "No products yet"),
|
|
122
|
-
react_1.default.createElement(ui_1.Text, { className: "mb-4 text-ui-fg-subtle" }, searchQuery
|
|
123
|
-
? "Try adjusting your search query"
|
|
124
|
-
: "Create products to manage their content"))) : (react_1.default.createElement("div", { className: "overflow-hidden rounded-lg border" },
|
|
125
|
-
react_1.default.createElement(ui_1.Table, null,
|
|
126
|
-
react_1.default.createElement(ui_1.Table.Header, null,
|
|
127
|
-
react_1.default.createElement(ui_1.Table.Row, null,
|
|
128
|
-
react_1.default.createElement(ui_1.Table.HeaderCell, null, "Product"),
|
|
129
|
-
react_1.default.createElement(ui_1.Table.HeaderCell, null, "Handle"),
|
|
130
|
-
react_1.default.createElement(ui_1.Table.HeaderCell, null, "Status"),
|
|
131
|
-
react_1.default.createElement(ui_1.Table.HeaderCell, null, "Content Status"),
|
|
132
|
-
react_1.default.createElement(ui_1.Table.HeaderCell, { className: "text-right" }, "Actions"))),
|
|
133
|
-
react_1.default.createElement(ui_1.Table.Body, null, filteredProducts.map((product) => {
|
|
134
|
-
const contentStatus = getContentStatus(product);
|
|
135
|
-
return (react_1.default.createElement(ui_1.Table.Row, { key: product.id },
|
|
136
|
-
react_1.default.createElement(ui_1.Table.Cell, null,
|
|
137
|
-
react_1.default.createElement(ui_1.Text, { className: "font-medium" }, product.title)),
|
|
138
|
-
react_1.default.createElement(ui_1.Table.Cell, null,
|
|
139
|
-
react_1.default.createElement(ui_1.Badge, { color: "blue" }, product.handle || "—")),
|
|
140
|
-
react_1.default.createElement(ui_1.Table.Cell, null,
|
|
141
|
-
react_1.default.createElement(ui_1.Badge, { color: product.status === "published" ? "green" : "grey" }, product.status || "draft")),
|
|
142
|
-
react_1.default.createElement(ui_1.Table.Cell, null,
|
|
143
|
-
react_1.default.createElement("div", { className: "flex items-center gap-2" },
|
|
144
|
-
react_1.default.createElement(ui_1.Badge, { color: contentStatus.color }, contentStatus.label),
|
|
145
|
-
product.metadata?.long_description && (react_1.default.createElement(ui_1.Badge, { color: "green", size: "xsmall" }, "Description")),
|
|
146
|
-
product.metadata?.specs && (react_1.default.createElement(ui_1.Badge, { color: "green", size: "xsmall" }, "Specs")))),
|
|
147
|
-
react_1.default.createElement(ui_1.Table.Cell, null,
|
|
148
|
-
react_1.default.createElement("div", { className: "flex items-center justify-end" },
|
|
149
|
-
react_1.default.createElement(ui_1.Button, { variant: "secondary", size: "small", onClick: () => handleManageContent(product.id) },
|
|
150
|
-
react_1.default.createElement(icons_1.PencilSquare, { className: "mr-1" }),
|
|
151
|
-
"View Product")))));
|
|
152
|
-
})))))));
|
|
153
|
-
};
|
|
154
|
-
exports.config = (0, admin_sdk_1.defineRouteConfig)({
|
|
155
|
-
label: "Product Content",
|
|
156
|
-
icon: icons_1.SquareTwoStack,
|
|
157
|
-
});
|
|
158
|
-
exports.default = ProductContentPage;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Import/Export utility for specifications
|
|
3
|
-
*/
|
|
4
|
-
import { ProductSpecs, ImportValidationResult } from '../../types';
|
|
5
|
-
/**
|
|
6
|
-
* Export specifications to CSV
|
|
7
|
-
*/
|
|
8
|
-
export declare function exportSpecsToCSV(specs: ProductSpecs): string;
|
|
9
|
-
/**
|
|
10
|
-
* Export specifications to JSON
|
|
11
|
-
*/
|
|
12
|
-
export declare function exportSpecsToJSON(specs: ProductSpecs): string;
|
|
13
|
-
/**
|
|
14
|
-
* Import specifications from CSV
|
|
15
|
-
*/
|
|
16
|
-
export declare function importSpecsFromCSV(csvContent: string, defaultLocale?: string): Promise<{
|
|
17
|
-
specs: ProductSpecs | null;
|
|
18
|
-
validation: ImportValidationResult;
|
|
19
|
-
}>;
|
|
20
|
-
/**
|
|
21
|
-
* Import specifications from JSON
|
|
22
|
-
*/
|
|
23
|
-
export declare function importSpecsFromJSON(jsonContent: string): Promise<{
|
|
24
|
-
specs: ProductSpecs | null;
|
|
25
|
-
validation: ImportValidationResult;
|
|
26
|
-
}>;
|
|
27
|
-
/**
|
|
28
|
-
* Merge imported specs with existing specs
|
|
29
|
-
*/
|
|
30
|
-
export declare function mergeSpecs(existing: ProductSpecs, imported: ProductSpecs, strategy?: 'replace' | 'merge' | 'append'): ProductSpecs;
|