fix: proper boundary on the project in the data
This commit is contained in:
@@ -128,19 +128,19 @@ const PostEditor: React.FC<PostEditorProps> = ({ post }) => {
|
||||
window.electronAPI?.posts.hasPublishedVersion(post.id).then(setHasPublishedVersion);
|
||||
}, [post.id]);
|
||||
|
||||
// Load available categories from localStorage
|
||||
// Load available categories from backend (project-scoped)
|
||||
useEffect(() => {
|
||||
const savedCategories = localStorage.getItem('bds-categories');
|
||||
if (savedCategories) {
|
||||
const loadCategories = async () => {
|
||||
try {
|
||||
const parsed = JSON.parse(savedCategories);
|
||||
if (Array.isArray(parsed) && parsed.length > 0) {
|
||||
setAvailableCategories(parsed);
|
||||
const categories = await window.electronAPI?.meta.getCategories();
|
||||
if (categories && categories.length > 0) {
|
||||
setAvailableCategories(categories);
|
||||
}
|
||||
} catch {
|
||||
// Keep defaults
|
||||
}
|
||||
}
|
||||
};
|
||||
loadCategories();
|
||||
}, []);
|
||||
|
||||
// Resolve media URLs in content for display
|
||||
|
||||
@@ -138,13 +138,13 @@ export const SettingsView: React.FC = () => {
|
||||
setCredentials({ ...defaultCredentials, ...JSON.parse(savedCreds) });
|
||||
}
|
||||
|
||||
// Load saved post categories
|
||||
const savedCategories = localStorage.getItem('bds-categories');
|
||||
if (savedCategories) {
|
||||
const categories = JSON.parse(savedCategories);
|
||||
if (Array.isArray(categories) && categories.length > 0) {
|
||||
setPostCategories(categories);
|
||||
}
|
||||
// Load categories from backend (project-scoped)
|
||||
const categories = await window.electronAPI?.meta.getCategories();
|
||||
if (categories && categories.length > 0) {
|
||||
setPostCategories(categories);
|
||||
} else {
|
||||
// Initialize with defaults if no categories exist
|
||||
setPostCategories(DEFAULT_POST_CATEGORIES);
|
||||
}
|
||||
|
||||
// Check Dropbox status
|
||||
@@ -160,7 +160,7 @@ export const SettingsView: React.FC = () => {
|
||||
}
|
||||
};
|
||||
loadSettings();
|
||||
}, []);
|
||||
}, [activeProject?.id]); // Reload when project changes
|
||||
|
||||
const handleSaveDropbox = async () => {
|
||||
try {
|
||||
@@ -343,20 +343,26 @@ export const SettingsView: React.FC = () => {
|
||||
);
|
||||
|
||||
// Handlers for post categories management
|
||||
const handleAddCategory = () => {
|
||||
const handleAddCategory = async () => {
|
||||
const trimmed = newCategoryInput.trim().toLowerCase();
|
||||
if (trimmed && !postCategories.includes(trimmed)) {
|
||||
const updated = [...postCategories, trimmed];
|
||||
setPostCategories(updated);
|
||||
localStorage.setItem('bds-categories', JSON.stringify(updated));
|
||||
setNewCategoryInput('');
|
||||
showToast.success(`Category "${trimmed}" added`);
|
||||
try {
|
||||
const updatedCategories = await window.electronAPI?.meta.addCategory(trimmed);
|
||||
if (updatedCategories) {
|
||||
setPostCategories(updatedCategories);
|
||||
}
|
||||
setNewCategoryInput('');
|
||||
showToast.success(`Category "${trimmed}" added`);
|
||||
} catch (error) {
|
||||
console.error('Failed to add category:', error);
|
||||
showToast.error('Failed to add category');
|
||||
}
|
||||
} else if (postCategories.includes(trimmed)) {
|
||||
showToast.error('Category already exists');
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveCategory = (categoryToRemove: string) => {
|
||||
const handleRemoveCategory = async (categoryToRemove: string) => {
|
||||
if (PROTECTED_CATEGORIES.includes(categoryToRemove)) {
|
||||
showToast.error(`Cannot delete standard category "${categoryToRemove}"`);
|
||||
return;
|
||||
@@ -365,16 +371,39 @@ export const SettingsView: React.FC = () => {
|
||||
showToast.error('Must have at least one category');
|
||||
return;
|
||||
}
|
||||
const updated = postCategories.filter(c => c !== categoryToRemove);
|
||||
setPostCategories(updated);
|
||||
localStorage.setItem('bds-categories', JSON.stringify(updated));
|
||||
showToast.success(`Category "${categoryToRemove}" removed`);
|
||||
try {
|
||||
const updatedCategories = await window.electronAPI?.meta.removeCategory(categoryToRemove);
|
||||
if (updatedCategories) {
|
||||
setPostCategories(updatedCategories);
|
||||
}
|
||||
showToast.success(`Category "${categoryToRemove}" removed`);
|
||||
} catch (error) {
|
||||
console.error('Failed to remove category:', error);
|
||||
showToast.error('Failed to remove category');
|
||||
}
|
||||
};
|
||||
|
||||
const handleResetCategories = () => {
|
||||
setPostCategories(DEFAULT_POST_CATEGORIES);
|
||||
localStorage.setItem('bds-categories', JSON.stringify(DEFAULT_POST_CATEGORIES));
|
||||
showToast.success('Categories reset to defaults');
|
||||
const handleResetCategories = async () => {
|
||||
try {
|
||||
// Remove non-protected categories
|
||||
const currentCategories = await window.electronAPI?.meta.getCategories() || [];
|
||||
for (const cat of currentCategories) {
|
||||
if (!PROTECTED_CATEGORIES.includes(cat)) {
|
||||
await window.electronAPI?.meta.removeCategory(cat);
|
||||
}
|
||||
}
|
||||
// Add any missing default categories
|
||||
for (const cat of DEFAULT_POST_CATEGORIES) {
|
||||
await window.electronAPI?.meta.addCategory(cat);
|
||||
}
|
||||
// Refresh the list
|
||||
const updatedCategories = await window.electronAPI?.meta.getCategories();
|
||||
setPostCategories(updatedCategories || DEFAULT_POST_CATEGORIES);
|
||||
showToast.success('Categories reset to defaults');
|
||||
} catch (error) {
|
||||
console.error('Failed to reset categories:', error);
|
||||
showToast.error('Failed to reset categories');
|
||||
}
|
||||
};
|
||||
|
||||
const renderContentSettings = () => (
|
||||
|
||||
17
src/renderer/types/electron.d.ts
vendored
17
src/renderer/types/electron.d.ts
vendored
@@ -1,5 +1,10 @@
|
||||
// Type definitions for the Electron API exposed via preload
|
||||
|
||||
export interface ProjectMetadata {
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface ProjectData {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -206,6 +211,18 @@ export interface ElectronAPI {
|
||||
openFolder: (folderPath: string) => Promise<string>;
|
||||
showItemInFolder: (itemPath: string) => Promise<void>;
|
||||
};
|
||||
meta: {
|
||||
getTags: () => Promise<string[]>;
|
||||
getCategories: () => Promise<string[]>;
|
||||
addTag: (tag: string) => Promise<string[]>;
|
||||
removeTag: (tag: string) => Promise<string[]>;
|
||||
addCategory: (category: string) => Promise<string[]>;
|
||||
removeCategory: (category: string) => Promise<string[]>;
|
||||
syncOnStartup: () => Promise<{ tags: string[]; categories: string[]; projectMetadata: ProjectMetadata | null }>;
|
||||
getProjectMetadata: () => Promise<ProjectMetadata | null>;
|
||||
setProjectMetadata: (metadata: { name: string; description?: string }) => Promise<ProjectMetadata | null>;
|
||||
updateProjectMetadata: (updates: { name?: string; description?: string }) => Promise<ProjectMetadata | null>;
|
||||
};
|
||||
on: (channel: string, callback: (...args: unknown[]) => void) => () => void;
|
||||
once: (channel: string, callback: (...args: unknown[]) => void) => void;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user