astro-tractstack 2.0.0-rc.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/LICENSE +8 -97
  2. package/README.md +7 -5
  3. package/bin/create-tractstack.js +35 -11
  4. package/dist/index.js +106 -29
  5. package/package.json +10 -5
  6. package/templates/css/frontend.css +1 -1
  7. package/templates/custom/minimal/CodeHook.astro +13 -12
  8. package/templates/custom/minimal/CustomRoutes.astro +25 -31
  9. package/templates/custom/with-examples/CodeHook.astro +22 -11
  10. package/templates/custom/with-examples/CustomRoutes.astro +4 -8
  11. package/templates/custom/with-examples/ProductCard.astro +29 -0
  12. package/templates/custom/with-examples/ProductCardWrapper.astro +43 -0
  13. package/templates/custom/with-examples/ProductGrid.astro +64 -0
  14. package/templates/custom/with-examples/pages/Collections.astro +58 -98
  15. package/templates/gitignore +42 -0
  16. package/templates/prettierignore +5 -0
  17. package/templates/prettierrc +19 -0
  18. package/templates/src/client/app.js +127 -0
  19. package/templates/src/client/htmx.min.js +3519 -0
  20. package/templates/src/client/view.js +429 -0
  21. package/templates/src/components/Footer.astro +4 -9
  22. package/templates/src/components/Header.astro +67 -60
  23. package/templates/src/components/Menu.tsx +188 -52
  24. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +2 -2
  25. package/templates/src/components/codehooks/EpinetDurationSelector.tsx +9 -13
  26. package/templates/src/components/codehooks/EpinetTableView.tsx +11 -7
  27. package/templates/src/components/codehooks/EpinetWrapper.tsx +1 -0
  28. package/templates/src/components/codehooks/FeaturedArticle.astro +105 -0
  29. package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +318 -0
  30. package/templates/src/components/codehooks/ListContent.astro +32 -162
  31. package/templates/src/components/codehooks/ListContentSetup.tsx +43 -138
  32. package/templates/src/components/codehooks/ProductCardSetup.tsx +152 -0
  33. package/templates/src/components/codehooks/ProductGridSetup.tsx +274 -0
  34. package/templates/src/components/codehooks/SearchWidget.tsx +453 -0
  35. package/templates/src/components/compositor/Node.tsx +3 -6
  36. package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +21 -11
  37. package/templates/src/components/compositor/elements/BunnyVideo.tsx +21 -20
  38. package/templates/src/components/compositor/nodes/Pane.tsx +51 -21
  39. package/templates/src/components/compositor/nodes/RenderChildren.tsx +6 -1
  40. package/templates/src/components/compositor/nodes/Widget.tsx +16 -2
  41. package/templates/src/components/compositor/preview/FeaturedArticlePreview.tsx +155 -0
  42. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +20 -1
  43. package/templates/src/components/edit/Header.tsx +10 -4
  44. package/templates/src/components/edit/PanelSwitch.tsx +11 -7
  45. package/templates/src/components/edit/SettingsPanel.tsx +29 -18
  46. package/templates/src/components/edit/ToolBar.tsx +1 -28
  47. package/templates/src/components/edit/ToolMode.tsx +45 -32
  48. package/templates/src/components/edit/pane/AddPanePanel_break.tsx +12 -2
  49. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +8 -2
  50. package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +1 -1
  51. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +17 -27
  52. package/templates/src/components/edit/pane/PageGenSelector.tsx +16 -16
  53. package/templates/src/components/edit/pane/PageGenSpecial.tsx +26 -49
  54. package/templates/src/components/edit/pane/PageGen_preview.tsx +17 -2
  55. package/templates/src/components/edit/pane/PanePanel_path.tsx +2 -4
  56. package/templates/src/components/edit/pane/PanePanel_title.tsx +243 -76
  57. package/templates/src/components/edit/panels/StyleBreakPanel.tsx +17 -19
  58. package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +48 -37
  59. package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +60 -55
  60. package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +56 -50
  61. package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +54 -47
  62. package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +54 -44
  63. package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +113 -138
  64. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +54 -40
  65. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +3 -3
  66. package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +56 -49
  67. package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +14 -5
  68. package/templates/src/components/edit/state/SaveModal.tsx +316 -169
  69. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +1 -1
  70. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +56 -55
  71. package/templates/src/components/edit/widgets/BunnyWidget.tsx +538 -59
  72. package/templates/src/components/edit/widgets/InteractiveDisclosureWidget.tsx +656 -0
  73. package/templates/src/components/edit/widgets/ToggleWidget.tsx +9 -16
  74. package/templates/src/components/fields/ArtpackImage.tsx +4 -1
  75. package/templates/src/components/fields/BackgroundImage.tsx +1 -1
  76. package/templates/src/components/fields/BackgroundImageWrapper.tsx +127 -35
  77. package/templates/src/components/fields/ColorPickerCombo.tsx +66 -62
  78. package/templates/src/components/fields/ImageUpload.tsx +1 -1
  79. package/templates/src/components/fields/ViewportComboBox.tsx +59 -42
  80. package/templates/src/components/form/ActionBuilderBeliefSelector.tsx +117 -0
  81. package/templates/src/components/form/ActionBuilderField.tsx +306 -87
  82. package/templates/src/components/search/SearchModal.tsx +420 -0
  83. package/templates/src/components/search/SearchResults.tsx +367 -0
  84. package/templates/src/components/search/SearchWrapper.tsx +46 -0
  85. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +1 -1
  86. package/templates/src/components/storykeep/Dashboard_Analytics.tsx +34 -8
  87. package/templates/src/components/storykeep/Dashboard_Content.tsx +6 -0
  88. package/templates/src/components/storykeep/StoryKeepBackdrop.astro +87 -0
  89. package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +37 -33
  90. package/templates/src/components/storykeep/controls/content/MenuForm.tsx +55 -7
  91. package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +17 -2
  92. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +5 -8
  93. package/templates/src/components/storykeep/state/FetchAnalytics.tsx +274 -228
  94. package/templates/src/components/storykeep/widgets/Wizard.tsx +14 -7
  95. package/templates/src/components/tenant/RegistrationForm.tsx +1 -1
  96. package/templates/src/components/widgets/ImpressionWrapper.tsx +0 -1
  97. package/templates/src/constants/shapes.ts +9 -0
  98. package/templates/src/constants.ts +2121 -16
  99. package/templates/src/hooks/useSearch.ts +228 -0
  100. package/templates/src/layouts/Layout.astro +213 -104
  101. package/templates/src/lib/storyData.ts +4 -1
  102. package/templates/src/pages/[...slug]/edit.astro +14 -14
  103. package/templates/src/pages/[...slug].astro +82 -21
  104. package/templates/src/pages/api/orphan-analysis.ts +0 -1
  105. package/templates/src/pages/api/tailwind.ts +23 -21
  106. package/templates/src/pages/context/[...contextSlug]/edit.astro +14 -14
  107. package/templates/src/pages/context/[...contextSlug].astro +7 -2
  108. package/templates/src/pages/storykeep/advanced.astro +5 -4
  109. package/templates/src/pages/storykeep/branding.astro +5 -4
  110. package/templates/src/pages/storykeep/content.astro +5 -4
  111. package/templates/src/pages/storykeep/init.astro +40 -1
  112. package/templates/src/pages/storykeep/login.astro +1 -1
  113. package/templates/src/pages/storykeep.astro +5 -4
  114. package/templates/src/stores/nodes.ts +59 -88
  115. package/templates/src/stores/orphanAnalysis.ts +19 -21
  116. package/templates/src/stores/storykeep.ts +7 -0
  117. package/templates/src/types/compositorTypes.ts +6 -0
  118. package/templates/src/types/tractstack.ts +17 -0
  119. package/templates/src/utils/actions/lispLexer.ts +2 -2
  120. package/templates/src/utils/actions/preParse_Action.ts +3 -0
  121. package/templates/src/utils/api/beliefHelpers.ts +12 -36
  122. package/templates/src/utils/api/menuHelpers.ts +2 -2
  123. package/templates/src/utils/api.ts +26 -0
  124. package/templates/src/utils/compositor/TemplateNodes.ts +7 -0
  125. package/templates/src/utils/compositor/allowInsert.ts +5 -3
  126. package/templates/src/utils/compositor/nodesHelper.ts +4 -0
  127. package/templates/src/utils/compositor/processMarkdown.ts +16 -2
  128. package/templates/src/utils/compositor/reduceNodesClassNames.ts +4 -0
  129. package/templates/src/utils/compositor/templateMarkdownStyles.ts +13 -13
  130. package/templates/src/utils/compositor/typeGuards.ts +1 -0
  131. package/templates/src/utils/customHelpers.ts +38 -0
  132. package/templates/src/utils/helpers.ts +2 -2
  133. package/templates/src/utils/layout.ts +65 -144
  134. package/utils/inject-files.ts +95 -18
  135. package/templates/src/client/analytics-events.js +0 -207
  136. package/templates/src/client/belief-events.js +0 -191
  137. package/templates/src/client/sse.js +0 -613
  138. package/templates/src/components/codehooks/FeaturedContent.astro +0 -273
  139. package/templates/src/components/codehooks/FeaturedContentSetup.tsx +0 -738
  140. package/templates/src/components/compositor/preview/FeaturedContentPreview.tsx +0 -128
  141. package/templates/src/components/edit/pane/PanePanel_slug.tsx +0 -219
@@ -37,16 +37,14 @@ export default function BeliefForm({
37
37
  onClose,
38
38
  }: BeliefFormProps) {
39
39
  const [customValue, setCustomValue] = useState('');
40
+ const [customValueError, setCustomValueError] = useState<string | null>(null);
40
41
 
41
- // Subscribe to orphan analysis store
42
42
  const orphanState = useStore(orphanAnalysisStore);
43
43
 
44
- // Load orphan analysis on component mount
45
44
  useEffect(() => {
46
45
  loadOrphanAnalysis();
47
46
  }, []);
48
47
 
49
- // Get usage information for this belief
50
48
  const getBeliefUsage = (): string[] => {
51
49
  if (!belief?.id || !orphanState.data || !orphanState.data.beliefs) {
52
50
  return [];
@@ -54,7 +52,6 @@ export default function BeliefForm({
54
52
  return orphanState.data.beliefs[belief.id] || [];
55
53
  };
56
54
 
57
- // Check if belief is in use
58
55
  const isBeliefInUse = (): boolean => {
59
56
  if (isCreate || !belief?.id) return false;
60
57
  return getBeliefUsage().length > 0;
@@ -63,7 +60,6 @@ export default function BeliefForm({
63
60
  const beliefInUse = isBeliefInUse();
64
61
  const usageCount = getBeliefUsage().length;
65
62
 
66
- // Initialize form state
67
63
  const initialState: BeliefNodeState = belief
68
64
  ? convertToLocalState(belief)
69
65
  : {
@@ -85,7 +81,6 @@ export default function BeliefForm({
85
81
  data
86
82
  );
87
83
 
88
- // Call success callback after save (original pattern)
89
84
  setTimeout(() => {
90
85
  onClose?.(true);
91
86
  }, 1000);
@@ -102,23 +97,30 @@ export default function BeliefForm({
102
97
  },
103
98
  });
104
99
 
105
- const handleAddCustomValue = () => {
106
- if (!customValue.trim()) return;
100
+ const handleCustomValueChange = (value: string) => {
101
+ setCustomValue(value);
102
+ const valueRegex = /^[a-zA-Z]([a-zA-Z0-9?!]| (?=[a-zA-Z0-9?!]))*$/;
103
+ if (value && !valueRegex.test(value)) {
104
+ setCustomValueError(
105
+ 'Must start with a letter. No double or trailing spaces.'
106
+ );
107
+ } else {
108
+ setCustomValueError(null);
109
+ }
110
+ };
107
111
 
112
+ const handleAddCustomValue = () => {
113
+ if (!customValue.trim() || customValueError) return;
108
114
  const newState = addCustomValue(formState.state, customValue);
109
115
  formState.updateField('customValues', newState.customValues);
110
116
  setCustomValue('');
111
117
  };
112
118
 
113
119
  const handleRemoveCustomValue = (index: number) => {
114
- // Check if this is a newly added value (not saved yet)
115
120
  const currentValue = formState.state.customValues[index];
116
121
  const originalValues = formState.originalState.customValues || [];
117
122
  const isNewValue = !originalValues.includes(currentValue);
118
123
 
119
- // Allow removal if:
120
- // 1. Belief is not in use, OR
121
- // 2. This is a new value that hasn't been saved yet
122
124
  if (!beliefInUse || isNewValue) {
123
125
  const newState = removeCustomValue(formState.state, index);
124
126
  formState.updateField('customValues', newState.customValues);
@@ -188,7 +190,6 @@ export default function BeliefForm({
188
190
 
189
191
  return (
190
192
  <div className="space-y-8">
191
- {/* Header */}
192
193
  <div className="border-b border-gray-200 pb-4">
193
194
  <h2 className="text-2xl font-bold text-gray-900">
194
195
  {isCreate ? 'Create Belief' : 'Edit Belief'}
@@ -200,10 +201,8 @@ export default function BeliefForm({
200
201
  </p>
201
202
  </div>
202
203
 
203
- {/* Usage Warning */}
204
204
  {renderUsageWarning()}
205
205
 
206
- {/* Info Box */}
207
206
  <div className="rounded-md bg-blue-50 p-4">
208
207
  <div className="text-sm text-blue-700">
209
208
  <p className="font-bold">What are Beliefs?</p>
@@ -225,7 +224,6 @@ export default function BeliefForm({
225
224
  </div>
226
225
  </div>
227
226
 
228
- {/* Basic Fields */}
229
227
  <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
230
228
  <StringInput
231
229
  value={formState.state.title}
@@ -254,7 +252,6 @@ export default function BeliefForm({
254
252
  </div>
255
253
  </div>
256
254
 
257
- {/* Scale Selection */}
258
255
  <div className="space-y-4">
259
256
  <div className="relative">
260
257
  <EnumSelect
@@ -276,7 +273,6 @@ export default function BeliefForm({
276
273
  {renderScalePreview()}
277
274
  </div>
278
275
 
279
- {/* Custom Values Section */}
280
276
  {formState.state.scale === 'custom' && (
281
277
  <div className="space-y-4">
282
278
  <div>
@@ -286,31 +282,41 @@ export default function BeliefForm({
286
282
  </p>
287
283
  </div>
288
284
 
289
- {/* Add Custom Value */}
290
285
  <div className="flex gap-2">
291
286
  <div className="flex-1">
292
- <div className="flex-1">
293
- <input
294
- type="text"
295
- value={customValue}
296
- onChange={(e) => setCustomValue(e.target.value)}
297
- onKeyDown={handleKeyDown}
298
- placeholder="Enter custom value"
299
- className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-cyan-600 sm:text-sm sm:leading-6"
300
- />
301
- </div>
287
+ <input
288
+ type="text"
289
+ value={customValue}
290
+ onChange={(e) => handleCustomValueChange(e.target.value)}
291
+ onKeyDown={handleKeyDown}
292
+ placeholder="Enter custom value"
293
+ className={`block w-full rounded-md border-0 px-3 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset placeholder:text-gray-400 focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 ${
294
+ customValueError
295
+ ? 'ring-red-500 focus:ring-red-600'
296
+ : 'ring-gray-300 focus:ring-cyan-600'
297
+ }`}
298
+ />
302
299
  </div>
303
300
  <button
304
301
  type="button"
305
302
  onClick={handleAddCustomValue}
306
- disabled={!customValue.trim()}
303
+ disabled={!customValue.trim() || !!customValueError}
307
304
  className="inline-flex items-center rounded-md bg-cyan-600 px-3 py-2 text-sm font-bold text-white shadow-sm hover:bg-cyan-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cyan-600 disabled:cursor-not-allowed disabled:opacity-50"
308
305
  >
309
306
  <PlusIcon className="h-4 w-4" />
310
307
  </button>
311
308
  </div>
312
309
 
313
- {/* Custom Values List */}
310
+ {customValueError && (
311
+ <p className="mt-1 text-sm text-red-600">{customValueError}</p>
312
+ )}
313
+
314
+ {formState.errors.customValues && (
315
+ <p className="text-sm text-red-600">
316
+ {formState.errors.customValues}
317
+ </p>
318
+ )}
319
+
314
320
  {formState.state.customValues.length > 0 && (
315
321
  <div className="space-y-2">
316
322
  {formState.state.customValues.map((value, index) => {
@@ -355,7 +361,6 @@ export default function BeliefForm({
355
361
  </div>
356
362
  )}
357
363
 
358
- {/* Save/Cancel Bar */}
359
364
  <UnsavedChangesBar
360
365
  formState={formState}
361
366
  message="You have unsaved belief changes"
@@ -363,7 +368,6 @@ export default function BeliefForm({
363
368
  cancelLabel="Discard Changes"
364
369
  />
365
370
 
366
- {/* Cancel Navigation Button */}
367
371
  <div className="flex justify-start">
368
372
  <button
369
373
  type="button"
@@ -12,6 +12,8 @@ import StringInput from '@/components/form/StringInput';
12
12
  import EnumSelect from '@/components/form/EnumSelect';
13
13
  import ActionBuilderField from '@/components/form/ActionBuilderField';
14
14
  import UnsavedChangesBar from '@/components/form/UnsavedChangesBar';
15
+ import ArrowUpIcon from '@heroicons/react/24/outline/ArrowUpIcon';
16
+ import ArrowDownIcon from '@heroicons/react/24/outline/ArrowDownIcon';
15
17
  import type {
16
18
  MenuNode,
17
19
  MenuNodeState,
@@ -88,6 +90,26 @@ export default function MenuForm({
88
90
  formState.updateField('menuLinks', newState.menuLinks);
89
91
  };
90
92
 
93
+ const handleMoveUp = (index: number) => {
94
+ if (index === 0) return;
95
+ const newMenuLinks = [...formState.state.menuLinks];
96
+ [newMenuLinks[index - 1], newMenuLinks[index]] = [
97
+ newMenuLinks[index],
98
+ newMenuLinks[index - 1],
99
+ ];
100
+ formState.updateField('menuLinks', newMenuLinks);
101
+ };
102
+
103
+ const handleMoveDown = (index: number) => {
104
+ if (index === formState.state.menuLinks.length - 1) return;
105
+ const newMenuLinks = [...formState.state.menuLinks];
106
+ [newMenuLinks[index], newMenuLinks[index + 1]] = [
107
+ newMenuLinks[index + 1],
108
+ newMenuLinks[index],
109
+ ];
110
+ formState.updateField('menuLinks', newMenuLinks);
111
+ };
112
+
91
113
  const handleCancel = () => {
92
114
  onClose?.(false);
93
115
  };
@@ -155,13 +177,39 @@ export default function MenuForm({
155
177
  <h4 className="text-sm font-bold text-gray-900">
156
178
  Link {index + 1}
157
179
  </h4>
158
- <button
159
- type="button"
160
- onClick={() => handleRemoveLink(index)}
161
- className="text-sm font-bold text-red-600 hover:text-red-800"
162
- >
163
- Remove
164
- </button>
180
+ <div className="flex items-center gap-2">
181
+ {/* Reorder buttons */}
182
+ <div className="flex items-center gap-1">
183
+ {index > 0 && (
184
+ <button
185
+ type="button"
186
+ onClick={() => handleMoveUp(index)}
187
+ className="rounded p-1 text-gray-600 hover:bg-gray-100 hover:text-gray-900"
188
+ title="Move up"
189
+ >
190
+ <ArrowUpIcon className="h-4 w-4" />
191
+ </button>
192
+ )}
193
+ {index < formState.state.menuLinks.length - 1 && (
194
+ <button
195
+ type="button"
196
+ onClick={() => handleMoveDown(index)}
197
+ className="rounded p-1 text-gray-600 hover:bg-gray-100 hover:text-gray-900"
198
+ title="Move down"
199
+ >
200
+ <ArrowDownIcon className="h-4 w-4" />
201
+ </button>
202
+ )}
203
+ </div>
204
+ {/* Remove button */}
205
+ <button
206
+ type="button"
207
+ onClick={() => handleRemoveLink(index)}
208
+ className="text-sm font-bold text-red-600 hover:text-red-800"
209
+ >
210
+ Remove
211
+ </button>
212
+ </div>
165
213
  </div>
166
214
 
167
215
  <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
@@ -252,12 +252,26 @@ export default function ResourceForm({
252
252
  />
253
253
  );
254
254
 
255
- case 'image':
255
+ case 'image': {
256
+ let fileUploadValue = ''; // Default to an empty string.
257
+
258
+ if (typeof fieldValue === 'string') {
259
+ // Case 1: The value is a string (Base64 URI).
260
+ fileUploadValue = fieldValue;
261
+ } else if (
262
+ fieldValue &&
263
+ typeof fieldValue === 'object' &&
264
+ fieldValue.src
265
+ ) {
266
+ // already saved, url
267
+ fileUploadValue = fieldValue.src;
268
+ }
269
+
256
270
  return (
257
271
  <FileUpload
258
272
  key={fieldName}
259
273
  label={fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}
260
- value={fieldValue || ''}
274
+ value={fileUploadValue}
261
275
  onChange={(value) => updateOptionsField(fieldName, value)}
262
276
  accept="image/*"
263
277
  showPreview={true}
@@ -265,6 +279,7 @@ export default function ResourceForm({
265
279
  required={!fieldDef.optional}
266
280
  />
267
281
  );
282
+ }
268
283
 
269
284
  default:
270
285
  return (
@@ -7,6 +7,7 @@ import {
7
7
  orphanAnalysisStore,
8
8
  loadOrphanAnalysis,
9
9
  } from '@/stores/orphanAnalysis';
10
+ import { TractStackAPI } from '@/utils/api';
10
11
  import UsageCell from '../UsageCell';
11
12
  import type { FullContentMapItem } from '@/types/tractstack';
12
13
 
@@ -138,17 +139,13 @@ const StoryFragmentTable = ({
138
139
 
139
140
  setIsLoading(true);
140
141
  try {
141
- const response = await fetch(`/api/storyfragments/${id}`, {
142
+ const api = new TractStackAPI(
143
+ window.TRACTSTACK_CONFIG?.tenantId || 'default'
144
+ );
145
+ await api.request(`/api/v1/nodes/storyfragments/${id}`, {
142
146
  method: 'DELETE',
143
- headers: {
144
- 'Content-Type': 'application/json',
145
- },
146
147
  });
147
148
 
148
- if (!response.ok) {
149
- throw new Error('Failed to delete story fragment');
150
- }
151
-
152
149
  // Reload the page to refresh the data
153
150
  window.location.reload();
154
151
  } catch (error) {