Skip to content

Polish File Meta Types UX and defer heavy web bundles#12

Merged
kooksee merged 1 commit into
mainfrom
feat/file-meta-types-polish
Jul 3, 2026
Merged

Polish File Meta Types UX and defer heavy web bundles#12
kooksee merged 1 commit into
mainfrom
feat/file-meta-types-polish

Conversation

@kooksee

@kooksee kooksee commented Jul 3, 2026

Copy link
Copy Markdown

Summary

  • Improve File Meta Types UX: gallery thumbnails, relation search/display/filters, calendar upload, board drag for files, File ID column labels, and calendar row-cap notice.
  • Add file upload dialog with space and folder picker; unify meta type create buttons across database views.
  • Redirect hidden Meta Types space navigation to settings and fix breadcrumb links.
  • Fix TipTap editor mount timing in ActionMenu and defer heavy UI chunks (lazy App, editor, node containers, settings routes, trimmed lowlight).
  • Update docs/file-meta-types.md and docs/roadmap.md.

Test plan

  • npm run build
  • packages/ui tests (49 passed)
  • Manual: meta types list → specific type → meta types returns list (not space settings)
  • Manual: file meta type upload with space/folder picker
  • Manual: page editor opens without TipTap view errors
  • Desktop package smoke test (make:local)

Made with Cursor

Improve file meta type views (gallery thumbnails, relations, calendar upload, folder picker), fix meta types navigation and editor mount timing, and lazy-load large UI chunks to shrink the web entry bundle.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kooksee kooksee merged commit 1e42a0e into main Jul 3, 2026
1 check passed
@kooksee kooksee deleted the feat/file-meta-types-polish branch July 3, 2026 07:48

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces File Meta Types (MVP + Phase 2), generalizing the meta-type system to support both pages and files across database views (board, calendar, gallery, list, and table). It also implements performance optimizations, such as lazy loading key layout and editor components, and optimizing syntax highlighting imports in lowlight. Additionally, a new folder picker utility (buildFolderPickerOptions) is added to resolve nested folder paths. Feedback on the changes highlights a potential infinite loop in the folder path traversal logic if cyclic folder references exist, and suggests implementing a cycle detector using a Set along with corresponding unit tests to ensure robustness.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +15 to +30
const buildPath = (folder: LocalFolderNode): string => {
const parts = [folder.name];
let current = folder;

while (current.parentId !== spaceId) {
const parent = byId.get(current.parentId);
if (!parent) {
break;
}

parts.unshift(parent.name);
current = parent;
}

return parts.join(' / ');
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The while loop resolves folder paths by traversing parent folders. If there is a cyclic reference in the folder structure (e.g., Folder A's parent is Folder B, and Folder B's parent is Folder A), this loop will run infinitely, freezing the browser tab. Implementing a cycle detector using a Set prevents this infinite loop and ensures robust execution.

  const buildPath = (folder: LocalFolderNode): string => {
    const parts = [folder.name];
    let current = folder;
    const visited = new Set<string>([folder.id]);

    while (current.parentId !== spaceId) {
      if (visited.has(current.parentId)) {
        break;
      }
      visited.add(current.parentId);

      const parent = byId.get(current.parentId);
      if (!parent) {
        break;
      }

      parts.unshift(parent.name);
      current = parent;
    }

    return parts.join(' / ');
  };

Comment on lines +21 to +33
describe('buildFolderPickerOptions', () => {
it('builds nested folder paths within a space', () => {
const folders = [
baseFolder({ id: 'folder-a', name: 'Assets', parentId: 'space-1' }),
baseFolder({ id: 'folder-b', name: 'Contracts', parentId: 'folder-a' }),
];

expect(buildFolderPickerOptions(folders, 'space-1')).toEqual([
{ id: 'folder-a', label: 'Assets' },
{ id: 'folder-b', label: 'Assets / Contracts' },
]);
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Add a test case to verify that cyclic folder references are handled gracefully without causing infinite loops, ensuring the robustness of the cycle-safe path building logic.

describe('buildFolderPickerOptions', () => {
  it('builds nested folder paths within a space', () => {
    const folders = [
      baseFolder({ id: 'folder-a', name: 'Assets', parentId: 'space-1' }),
      baseFolder({ id: 'folder-b', name: 'Contracts', parentId: 'folder-a' }),
    ];

    expect(buildFolderPickerOptions(folders, 'space-1')).toEqual([
      { id: 'folder-a', label: 'Assets' },
      { id: 'folder-b', label: 'Assets / Contracts' },
    ]);
  });

  it('handles cyclic folder references gracefully without infinite loops', () => {
    const folders = [
      baseFolder({ id: 'folder-a', name: 'Folder A', parentId: 'folder-b' }),
      baseFolder({ id: 'folder-b', name: 'Folder B', parentId: 'folder-a' }),
    ];

    expect(buildFolderPickerOptions(folders, 'space-1')).toEqual([
      { id: 'folder-a', label: 'Folder A' },
      { id: 'folder-b', label: 'Folder B' },
    ]);
  });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant