@spree/dashboard-core 6.0.3 → 6.0.4
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/vite/index.js +81 -5
- package/package.json +19 -19
- package/src/api-client.ts +7 -1
- package/src/client.ts +2 -0
- package/src/components/address-form-dialog.tsx +75 -28
- package/src/components/app-shell.tsx +5 -4
- package/src/components/app-sidebar.tsx +2 -1
- package/src/components/bulk-action-bar.tsx +6 -5
- package/src/components/country-state-fields.tsx +3 -0
- package/src/components/currency-select.tsx +6 -4
- package/src/components/developer-inspector-drawer.tsx +322 -0
- package/src/components/file-upload-field.tsx +64 -37
- package/src/components/image-upload-field.tsx +4 -0
- package/src/components/import-wizard-dialog.tsx +14 -12
- package/src/components/invitation-acceptance.tsx +15 -11
- package/src/components/media-editor-dialog.tsx +131 -0
- package/src/components/media-picker-dialog.tsx +866 -0
- package/src/components/media-picker-sheet.tsx +13 -300
- package/src/components/mobile-top-bar.tsx +1 -1
- package/src/components/nav-main.tsx +13 -2
- package/src/components/page-header.tsx +57 -13
- package/src/components/page-tabs.tsx +1 -1
- package/src/components/product-stock-summary.tsx +1 -1
- package/src/components/read-row.tsx +38 -0
- package/src/components/resource-combobox.tsx +1 -1
- package/src/components/resource-image-field.tsx +150 -0
- package/src/components/resource-picker-sheet.tsx +2 -2
- package/src/components/resource-table.tsx +161 -40
- package/src/components/section-heading.tsx +2 -2
- package/src/components/settings-container.tsx +19 -0
- package/src/components/settings-fields.tsx +165 -0
- package/src/components/settings-section.tsx +46 -0
- package/src/components/settings-sidebar.tsx +35 -18
- package/src/components/sheet-top-bar.tsx +7 -8
- package/src/components/sidebar-search.tsx +11 -12
- package/src/components/sidebar-user.tsx +39 -44
- package/src/components/skip-link.tsx +1 -1
- package/src/components/store-switcher.tsx +1 -1
- package/src/components/table-toolbar.tsx +189 -323
- package/src/components/timezone-combobox.tsx +119 -0
- package/src/components/top-bar-breadcrumbs.tsx +1 -1
- package/src/hooks/use-stock-locations.ts +6 -2
- package/src/hooks/use-table-density.ts +50 -0
- package/src/index.ts +19 -2
- package/src/lib/curl.test.ts +18 -0
- package/src/lib/curl.ts +28 -0
- package/src/lib/developer-inspector.test.ts +169 -0
- package/src/lib/developer-inspector.ts +134 -0
- package/src/lib/docs.ts +3 -2
- package/src/lib/fulfillment-items.test.ts +51 -0
- package/src/lib/fulfillment-items.ts +53 -0
- package/src/lib/request-snippets.ts +41 -0
- package/src/lib/table-registry.ts +13 -6
- package/src/lib/timestamp-columns.tsx +1 -1
- package/src/locales/ar.json +120 -14
- package/src/locales/de.json +120 -14
- package/src/locales/en.json +120 -14
- package/src/locales/es.json +120 -14
- package/src/locales/fr.json +120 -14
- package/src/locales/ja.json +120 -14
- package/src/locales/pl.json +120 -14
- package/src/locales/vi.json +120 -14
- package/src/locales/zh-CN.json +120 -14
- package/src/pages/settings-index.tsx +79 -48
- package/src/pages/stock-locations.tsx +14 -6
- package/src/products/digital-asset-edit-sheet.tsx +1 -1
- package/src/products/digital-asset-provider-sheet.tsx +1 -1
- package/src/products/digital-assets-card.tsx +7 -7
- package/src/products/inventory-section.tsx +2 -2
- package/src/products/media-edit-sheet.tsx +136 -133
- package/src/products/product-form-cards.tsx +201 -70
- package/src/products/product-form-mapping.ts +1 -0
- package/src/products/product-schema.ts +8 -0
- package/src/products/product-types.ts +2 -0
- package/src/products/use-product-form-data.ts +30 -3
- package/src/products/variant-edit-sheet.tsx +3 -3
- package/src/products/variants-options-builder.tsx +13 -8
- package/src/products/variants-section.tsx +196 -4
- package/src/providers/auth-provider.tsx +2 -0
- package/src/providers/developer-inspector-provider.tsx +145 -0
- package/src/providers/json-link-resolver-provider.tsx +27 -0
- package/src/sellers/seller-schema.ts +107 -0
- package/src/tables/package-types.tsx +3 -3
- package/src/tables/stock-locations.tsx +15 -14
- package/src/virtual.d.ts +4 -0
- package/src/vite/index.ts +103 -5
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
import { STOCK_LOCATION_KINDS } from '@spree/core'
|
|
1
|
+
import { intlDisplayName, STOCK_LOCATION_KINDS } from '@spree/core'
|
|
2
2
|
import { ActiveBadge, ResourceNameCell } from '@spree/dashboard-ui'
|
|
3
3
|
import { WarehouseIcon } from '@spree/dashboard-ui/icons'
|
|
4
4
|
import i18n from 'i18next'
|
|
5
5
|
import type { PanelStockLocation } from '../api-client'
|
|
6
6
|
import { defineTable } from '../lib/table-registry'
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Where a location is, on one line: street, city, state and country. Sits
|
|
10
|
+
* under the name rather than in a column of its own, since it is what tells
|
|
11
|
+
* two warehouses of a similar name apart.
|
|
12
|
+
*/
|
|
13
|
+
function addressLine(sl: PanelStockLocation): string {
|
|
14
|
+
const country = sl.country_code
|
|
15
|
+
? (intlDisplayName('region', i18n.language, sl.country_code) ?? sl.country_code)
|
|
16
|
+
: null
|
|
17
|
+
return [sl.address1, sl.city, sl.state_text || sl.state_code, country].filter(Boolean).join(', ')
|
|
18
|
+
}
|
|
19
|
+
|
|
8
20
|
defineTable<PanelStockLocation>('stock-locations', {
|
|
9
21
|
docsPath: 'settings/locations',
|
|
10
22
|
description: i18n.t('admin.stock_locations.description'),
|
|
@@ -17,7 +29,7 @@ defineTable<PanelStockLocation>('stock-locations', {
|
|
|
17
29
|
columns: [
|
|
18
30
|
{
|
|
19
31
|
key: 'name',
|
|
20
|
-
label: i18n.t('admin.
|
|
32
|
+
label: i18n.t('admin.stock_locations.columns.location'),
|
|
21
33
|
sortable: true,
|
|
22
34
|
default: true,
|
|
23
35
|
render: (sl) => (
|
|
@@ -25,7 +37,7 @@ defineTable<PanelStockLocation>('stock-locations', {
|
|
|
25
37
|
id={sl.id}
|
|
26
38
|
dataAttr="data-stock-location-id"
|
|
27
39
|
name={sl.name}
|
|
28
|
-
secondary={sl.admin_name}
|
|
40
|
+
secondary={[sl.admin_name, addressLine(sl)].filter(Boolean).join(' · ')}
|
|
29
41
|
/>
|
|
30
42
|
),
|
|
31
43
|
},
|
|
@@ -47,17 +59,6 @@ defineTable<PanelStockLocation>('stock-locations', {
|
|
|
47
59
|
return <span className="capitalize">{label}</span>
|
|
48
60
|
},
|
|
49
61
|
},
|
|
50
|
-
{
|
|
51
|
-
key: 'city',
|
|
52
|
-
label: i18n.t('admin.stock_locations.columns.location'),
|
|
53
|
-
default: true,
|
|
54
|
-
render: (sl) => {
|
|
55
|
-
const parts = [sl.city, sl.state_text || sl.state_code, sl.country_code]
|
|
56
|
-
.filter(Boolean)
|
|
57
|
-
.join(', ')
|
|
58
|
-
return parts || '—'
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
62
|
{
|
|
62
63
|
key: 'pickup_enabled',
|
|
63
64
|
label: i18n.t('admin.stock_locations.columns.pickup'),
|
package/src/virtual.d.ts
CHANGED
|
@@ -3,3 +3,7 @@
|
|
|
3
3
|
// imports @spree/dashboard-core can `import 'virtual:spree-dashboard-plugins'`
|
|
4
4
|
// without its own shim.
|
|
5
5
|
declare module 'virtual:spree-dashboard-plugins'
|
|
6
|
+
|
|
7
|
+
// The host's installed `@spree/*` versions, defined by `spreeDashboardPlugin()`.
|
|
8
|
+
// Undefined in a build without the plugin, so read it behind a typeof check.
|
|
9
|
+
declare const __SPREE_PACKAGES__: Record<string, string> | undefined
|
package/src/vite/index.ts
CHANGED
|
@@ -98,7 +98,103 @@ export interface SpreeDashboardPluginOptions {
|
|
|
98
98
|
* })
|
|
99
99
|
*/
|
|
100
100
|
export function spreeDashboardPlugin(options: SpreeDashboardPluginOptions = {}): PluginOption[] {
|
|
101
|
-
return [
|
|
101
|
+
return [
|
|
102
|
+
dashboardProseMirrorDedupePlugin(),
|
|
103
|
+
dashboardTailwindSourcePlugin(options),
|
|
104
|
+
tailwindcss(),
|
|
105
|
+
dashboardFontPreloadPlugin(),
|
|
106
|
+
dashboardPackagesPlugin(),
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Bakes the host's installed `@spree/*` package versions into the build as
|
|
112
|
+
* `__SPREE_PACKAGES__`, so the diagnostics report can name the dashboard a
|
|
113
|
+
* merchant actually deployed, which the server has no way to know.
|
|
114
|
+
*/
|
|
115
|
+
function dashboardPackagesPlugin(): Plugin {
|
|
116
|
+
return {
|
|
117
|
+
name: 'spree:dashboard-packages',
|
|
118
|
+
config(config) {
|
|
119
|
+
const root = path.resolve(config.root ?? process.cwd())
|
|
120
|
+
return { define: { __SPREE_PACKAGES__: JSON.stringify(installedSpreePackages(root)) } }
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* `@spree/*` packages the host installs, directly or through another Spree
|
|
127
|
+
* package (`@spree/core` comes in with the dashboard), by installed version.
|
|
128
|
+
* Exported for tests.
|
|
129
|
+
*/
|
|
130
|
+
export function installedSpreePackages(root: string): Record<string, string> {
|
|
131
|
+
const versions: Record<string, string> = {}
|
|
132
|
+
const visit = (packageRoot: string, includeDev: boolean) => {
|
|
133
|
+
const manifest = readJson(path.join(packageRoot, 'package.json'))
|
|
134
|
+
const dependencies = {
|
|
135
|
+
...manifest?.dependencies,
|
|
136
|
+
...manifest?.peerDependencies,
|
|
137
|
+
...(includeDev ? manifest?.devDependencies : {}),
|
|
138
|
+
}
|
|
139
|
+
const require = createRequire(path.join(packageRoot, 'package.json'))
|
|
140
|
+
for (const name of Object.keys(dependencies)) {
|
|
141
|
+
if (!name.startsWith('@spree/') || name in versions) continue
|
|
142
|
+
const dependencyRoot = resolvePackageRoot(name, require)
|
|
143
|
+
const dependency = dependencyRoot && readJson(path.join(dependencyRoot, 'package.json'))
|
|
144
|
+
if (!dependencyRoot || !dependency || dependency.private) continue
|
|
145
|
+
versions[name] = dependency.version
|
|
146
|
+
visit(dependencyRoot, false)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
visit(root, true)
|
|
150
|
+
return Object.fromEntries(Object.entries(versions).sort(([a], [b]) => a.localeCompare(b)))
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function readJson(file: string): Record<string, any> | null {
|
|
154
|
+
try {
|
|
155
|
+
return JSON.parse(fs.readFileSync(file, 'utf-8'))
|
|
156
|
+
} catch {
|
|
157
|
+
return null
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The Latin subset of the dashboard's sans font, which nearly every page renders. */
|
|
162
|
+
const PRELOADED_FONT_FILE = 'inter-latin-opsz-normal.woff2'
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Preloads the Latin sans font in production builds. The font is otherwise
|
|
166
|
+
* discovered only after the CSS is downloaded and parsed, so the first paint
|
|
167
|
+
* falls back to the system font. Hosts that replace the font emit no such
|
|
168
|
+
* file and get no tag.
|
|
169
|
+
*/
|
|
170
|
+
function dashboardFontPreloadPlugin(): Plugin {
|
|
171
|
+
let base = '/'
|
|
172
|
+
return {
|
|
173
|
+
name: 'spree:dashboard-font-preload',
|
|
174
|
+
apply: 'build',
|
|
175
|
+
configResolved(config) {
|
|
176
|
+
base = config.base
|
|
177
|
+
},
|
|
178
|
+
transformIndexHtml(_html, ctx) {
|
|
179
|
+
const font = Object.values(ctx.bundle ?? {}).find(
|
|
180
|
+
(file) => file.type === 'asset' && file.names.includes(PRELOADED_FONT_FILE),
|
|
181
|
+
)
|
|
182
|
+
if (!font) return
|
|
183
|
+
return [
|
|
184
|
+
{
|
|
185
|
+
tag: 'link',
|
|
186
|
+
attrs: {
|
|
187
|
+
rel: 'preload',
|
|
188
|
+
href: `${base}${font.fileName}`,
|
|
189
|
+
as: 'font',
|
|
190
|
+
type: 'font/woff2',
|
|
191
|
+
crossorigin: '',
|
|
192
|
+
},
|
|
193
|
+
injectTo: 'head',
|
|
194
|
+
},
|
|
195
|
+
]
|
|
196
|
+
},
|
|
197
|
+
}
|
|
102
198
|
}
|
|
103
199
|
|
|
104
200
|
/**
|
|
@@ -280,12 +376,14 @@ function formatPluginErrorOverlay(errors: PluginError[]): string {
|
|
|
280
376
|
* including ours, don't list it there.
|
|
281
377
|
*/
|
|
282
378
|
function resolvePackageSourceDir(pkg: string, require: NodeJS.Require): string | null {
|
|
379
|
+
const packageRoot = resolvePackageRoot(pkg, require)
|
|
380
|
+
return packageRoot && path.join(packageRoot, 'src')
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function resolvePackageRoot(pkg: string, require: NodeJS.Require): string | null {
|
|
283
384
|
try {
|
|
284
385
|
const entryPath = require.resolve(pkg)
|
|
285
|
-
|
|
286
|
-
const packageRoot = findPackageRoot(entryFile)
|
|
287
|
-
if (!packageRoot) return null
|
|
288
|
-
return path.join(packageRoot, 'src')
|
|
386
|
+
return findPackageRoot(entryPath.startsWith('file:') ? fileURLToPath(entryPath) : entryPath)
|
|
289
387
|
} catch {
|
|
290
388
|
return null
|
|
291
389
|
}
|